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
					
				| @ -18,6 +18,7 @@ bevy_app = { path = "../bevy_app", version = "0.3.0" } | |||||||
| bevy_asset = { path = "../bevy_asset", version = "0.3.0" } | bevy_asset = { path = "../bevy_asset", version = "0.3.0" } | ||||||
| bevy_ecs = { path = "../bevy_ecs", 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_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" } | bevy_utils = { path = "../bevy_utils", version = "0.3.0" } | ||||||
| 
 | 
 | ||||||
| # other | # other | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| use bevy_asset::Handle; | 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}; | use crate::{Scene, SceneSpawner}; | ||||||
| 
 | 
 | ||||||
| @ -23,3 +24,29 @@ impl SpawnSceneCommands for Commands { | |||||||
|         self.add_command(SpawnScene { scene_handle }) |         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 use scene_spawner::*; | ||||||
| 
 | 
 | ||||||
| pub mod prelude { | pub mod prelude { | ||||||
|     pub use crate::{DynamicScene, Scene, SceneSpawner, SpawnSceneCommands}; |     pub use crate::{ | ||||||
|  |         DynamicScene, Scene, SceneSpawner, SpawnSceneAsChildCommands, SpawnSceneCommands, | ||||||
|  |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| use bevy_app::prelude::*; | use bevy_app::prelude::*; | ||||||
|  | |||||||
| @ -1,8 +1,9 @@ | |||||||
| use crate::{DynamicScene, Scene}; | use crate::{DynamicScene, Scene}; | ||||||
| use bevy_app::prelude::*; | use bevy_app::prelude::*; | ||||||
| use bevy_asset::{AssetEvent, Assets, Handle}; | 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_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc}; | ||||||
|  | use bevy_transform::prelude::Parent; | ||||||
| use bevy_utils::HashMap; | use bevy_utils::HashMap; | ||||||
| use thiserror::Error; | use thiserror::Error; | ||||||
| use uuid::Uuid; | use uuid::Uuid; | ||||||
| @ -28,8 +29,9 @@ pub struct SceneSpawner { | |||||||
|     spawned_instances: HashMap<InstanceId, InstanceInfo>, |     spawned_instances: HashMap<InstanceId, InstanceInfo>, | ||||||
|     scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>, |     scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>, | ||||||
|     dynamic_scenes_to_spawn: Vec<Handle<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_to_despawn: Vec<Handle<DynamicScene>>, | ||||||
|  |     scenes_with_parent: Vec<(InstanceId, Entity)>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Error, Debug)] | #[derive(Error, Debug)] | ||||||
| @ -50,7 +52,14 @@ impl SceneSpawner { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn spawn(&mut self, scene_handle: Handle<Scene>) { |     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>) { |     pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) { | ||||||
| @ -147,7 +156,16 @@ impl SceneSpawner { | |||||||
|         resources: &Resources, |         resources: &Resources, | ||||||
|         scene_handle: Handle<Scene>, |         scene_handle: Handle<Scene>, | ||||||
|     ) -> Result<(), SceneSpawnError> { |     ) -> 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 { |         let mut instance_info = InstanceInfo { | ||||||
|             entity_map: EntityMap::default(), |             entity_map: EntityMap::default(), | ||||||
|         }; |         }; | ||||||
| @ -256,11 +274,11 @@ impl SceneSpawner { | |||||||
| 
 | 
 | ||||||
|         let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn); |         let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn); | ||||||
| 
 | 
 | ||||||
|         for scene_handle in scenes_to_spawn { |         for (scene_handle, instance_id) in scenes_to_spawn { | ||||||
|             match self.spawn_sync(world, resources, scene_handle) { |             match self.spawn_sync_internal(world, resources, scene_handle, instance_id) { | ||||||
|                 Ok(_) => {} |                 Ok(_) => {} | ||||||
|                 Err(SceneSpawnError::NonExistentRealScene { handle }) => { |                 Err(SceneSpawnError::NonExistentRealScene { handle }) => { | ||||||
|                     self.scenes_to_spawn.push(handle) |                     self.scenes_to_spawn.push((handle, instance_id)) | ||||||
|                 } |                 } | ||||||
|                 Err(err) => return Err(err), |                 Err(err) => return Err(err), | ||||||
|             } |             } | ||||||
| @ -268,6 +286,24 @@ impl SceneSpawner { | |||||||
| 
 | 
 | ||||||
|         Ok(()) |         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) { | 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 |     scene_spawner | ||||||
|         .update_spawned_scenes(world, resources, &updated_spawned_scenes) |         .update_spawned_scenes(world, resources, &updated_spawned_scenes) | ||||||
|         .unwrap(); |         .unwrap(); | ||||||
|  |     scene_spawner.set_scene_instance_parent_sync(world); | ||||||
| } | } | ||||||
|  | |||||||
| @ -81,6 +81,10 @@ impl<'a> ChildBuilder<'a> { | |||||||
|         self.commands.current_entity() |         self.commands.current_entity() | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn parent_entity(&self) -> Entity { | ||||||
|  |         self.push_children.parent | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn with_bundle( |     pub fn with_bundle( | ||||||
|         &mut self, |         &mut self, | ||||||
|         components: impl DynamicBundle + Send + Sync + 'static, |         components: impl DynamicBundle + Send + Sync + 'static, | ||||||
| @ -102,6 +106,11 @@ impl<'a> ChildBuilder<'a> { | |||||||
|         func(current_entity); |         func(current_entity); | ||||||
|         self |         self | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self { | ||||||
|  |         self.commands.add_command(command); | ||||||
|  |         self | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait BuildChildren { | pub trait BuildChildren { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 François
						François