mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
can spawn a scene from a ChildBuilder, or directly set its parent when spawning it (#1026)
can spawn a scene from a ChildBuilder, or directly set its parent when spawning one
This commit is contained in:
parent
c54179b182
commit
f53ee54eb6
5 changed files with 85 additions and 9 deletions
|
@ -18,6 +18,7 @@ bevy_app = { path = "../bevy_app", version = "0.3.0" }
|
|||
bevy_asset = { path = "../bevy_asset", version = "0.3.0" }
|
||||
bevy_ecs = { path = "../bevy_ecs", version = "0.3.0" }
|
||||
bevy_reflect = { path = "../bevy_reflect", version = "0.3.0", features = ["bevy"] }
|
||||
bevy_transform = { path = "../bevy_transform", version = "0.3.0" }
|
||||
bevy_utils = { path = "../bevy_utils", version = "0.3.0" }
|
||||
|
||||
# other
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use bevy_asset::Handle;
|
||||
use bevy_ecs::{Command, Commands, Resources, World};
|
||||
use bevy_ecs::{Command, Commands, Entity, Resources, World};
|
||||
use bevy_transform::hierarchy::ChildBuilder;
|
||||
|
||||
use crate::{Scene, SceneSpawner};
|
||||
|
||||
|
@ -23,3 +24,29 @@ impl SpawnSceneCommands for Commands {
|
|||
self.add_command(SpawnScene { scene_handle })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpawnSceneAsChild {
|
||||
scene_handle: Handle<Scene>,
|
||||
parent: Entity,
|
||||
}
|
||||
|
||||
impl Command for SpawnSceneAsChild {
|
||||
fn write(self: Box<Self>, _world: &mut World, resources: &mut Resources) {
|
||||
let mut spawner = resources.get_mut::<SceneSpawner>().unwrap();
|
||||
spawner.spawn_as_child(self.scene_handle, self.parent);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SpawnSceneAsChildCommands {
|
||||
fn spawn_scene(&mut self, scene: Handle<Scene>) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'a> SpawnSceneAsChildCommands for ChildBuilder<'a> {
|
||||
fn spawn_scene(&mut self, scene_handle: Handle<Scene>) -> &mut Self {
|
||||
self.add_command(SpawnSceneAsChild {
|
||||
scene_handle,
|
||||
parent: self.parent_entity(),
|
||||
});
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@ pub use scene_loader::*;
|
|||
pub use scene_spawner::*;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{DynamicScene, Scene, SceneSpawner, SpawnSceneCommands};
|
||||
pub use crate::{
|
||||
DynamicScene, Scene, SceneSpawner, SpawnSceneAsChildCommands, SpawnSceneCommands,
|
||||
};
|
||||
}
|
||||
|
||||
use bevy_app::prelude::*;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::{DynamicScene, Scene};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
||||
use bevy_ecs::{EntityMap, Resources, World};
|
||||
use bevy_ecs::{Entity, EntityMap, Resources, World};
|
||||
use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc};
|
||||
use bevy_transform::prelude::Parent;
|
||||
use bevy_utils::HashMap;
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
@ -28,8 +29,9 @@ pub struct SceneSpawner {
|
|||
spawned_instances: HashMap<InstanceId, InstanceInfo>,
|
||||
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>,
|
||||
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
|
||||
scenes_to_spawn: Vec<Handle<Scene>>,
|
||||
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
|
||||
scenes_to_despawn: Vec<Handle<DynamicScene>>,
|
||||
scenes_with_parent: Vec<(InstanceId, Entity)>,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
@ -50,7 +52,14 @@ impl SceneSpawner {
|
|||
}
|
||||
|
||||
pub fn spawn(&mut self, scene_handle: Handle<Scene>) {
|
||||
self.scenes_to_spawn.push(scene_handle);
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((scene_handle, instance_id));
|
||||
}
|
||||
|
||||
pub fn spawn_as_child(&mut self, scene_handle: Handle<Scene>, parent: Entity) {
|
||||
let instance_id = InstanceId::new();
|
||||
self.scenes_to_spawn.push((scene_handle, instance_id));
|
||||
self.scenes_with_parent.push((instance_id, parent));
|
||||
}
|
||||
|
||||
pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) {
|
||||
|
@ -147,7 +156,16 @@ impl SceneSpawner {
|
|||
resources: &Resources,
|
||||
scene_handle: Handle<Scene>,
|
||||
) -> Result<(), SceneSpawnError> {
|
||||
let instance_id = InstanceId::new();
|
||||
self.spawn_sync_internal(world, resources, scene_handle, InstanceId::new())
|
||||
}
|
||||
|
||||
fn spawn_sync_internal(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
scene_handle: Handle<Scene>,
|
||||
instance_id: InstanceId,
|
||||
) -> Result<(), SceneSpawnError> {
|
||||
let mut instance_info = InstanceInfo {
|
||||
entity_map: EntityMap::default(),
|
||||
};
|
||||
|
@ -256,11 +274,11 @@ impl SceneSpawner {
|
|||
|
||||
let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn);
|
||||
|
||||
for scene_handle in scenes_to_spawn {
|
||||
match self.spawn_sync(world, resources, scene_handle) {
|
||||
for (scene_handle, instance_id) in scenes_to_spawn {
|
||||
match self.spawn_sync_internal(world, resources, scene_handle, instance_id) {
|
||||
Ok(_) => {}
|
||||
Err(SceneSpawnError::NonExistentRealScene { handle }) => {
|
||||
self.scenes_to_spawn.push(handle)
|
||||
self.scenes_to_spawn.push((handle, instance_id))
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
|
@ -268,6 +286,24 @@ impl SceneSpawner {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn set_scene_instance_parent_sync(&mut self, world: &mut World) {
|
||||
let scenes_with_parent = std::mem::take(&mut self.scenes_with_parent);
|
||||
|
||||
for (instance_id, parent) in scenes_with_parent {
|
||||
if let Some(instance) = self.spawned_instances.get(&instance_id) {
|
||||
for entity in instance.entity_map.values() {
|
||||
if let Err(bevy_ecs::ComponentError::MissingComponent(_)) =
|
||||
world.get::<Parent>(entity)
|
||||
{
|
||||
let _ = world.insert_one(entity, Parent(parent));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.scenes_with_parent.push((instance_id, parent));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
||||
|
@ -293,4 +329,5 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
|||
scene_spawner
|
||||
.update_spawned_scenes(world, resources, &updated_spawned_scenes)
|
||||
.unwrap();
|
||||
scene_spawner.set_scene_instance_parent_sync(world);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,10 @@ impl<'a> ChildBuilder<'a> {
|
|||
self.commands.current_entity()
|
||||
}
|
||||
|
||||
pub fn parent_entity(&self) -> Entity {
|
||||
self.push_children.parent
|
||||
}
|
||||
|
||||
pub fn with_bundle(
|
||||
&mut self,
|
||||
components: impl DynamicBundle + Send + Sync + 'static,
|
||||
|
@ -102,6 +106,11 @@ impl<'a> ChildBuilder<'a> {
|
|||
func(current_entity);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
|
||||
self.commands.add_command(command);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait BuildChildren {
|
||||
|
|
Loading…
Reference in a new issue