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_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 New Issue
	
	Block a user
	 François
						François