From 687103dc770d28f3c4888f5816600f0b66ffceed Mon Sep 17 00:00:00 2001 From: s33n Date: Sat, 6 Jan 2024 11:05:27 -0800 Subject: [PATCH 1/2] corrected SceneSpawner::spawn_dynamic_sync to return the InstanceID of the newly-spawned scene --- crates/bevy_scene/src/scene_spawner.rs | 64 +++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 6537333877f53..3b342489478a5 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -198,7 +198,7 @@ impl SceneSpawner { &mut self, world: &mut World, id: impl Into>, - ) -> Result<(), SceneSpawnError> { + ) -> Result { let mut entity_map = EntityHashMap::default(); let id = id.into(); Self::spawn_dynamic_internal(world, id, &mut entity_map)?; @@ -207,7 +207,7 @@ impl SceneSpawner { .insert(instance_id, InstanceInfo { entity_map }); let spawned = self.spawned_dynamic_scenes.entry(id).or_default(); spawned.push(instance_id); - Ok(()) + Ok(instance_id) } fn spawn_dynamic_internal( @@ -434,3 +434,63 @@ pub fn scene_spawner_system(world: &mut World) { scene_spawner.set_scene_instance_parent_sync(world); }); } + + +#[cfg(test)] +mod tests { + use super::*; + use bevy_ecs::{reflect::AppTypeRegistry, world::World}; + use bevy_ecs::component::Component; + use bevy_ecs::entity::Entity; + use bevy_ecs::query::With; + use bevy_ecs::prelude::ReflectComponent; + + use bevy_reflect::Reflect; + use crate::DynamicSceneBuilder; + + #[derive(Reflect, Component, Debug, PartialEq, Eq, Clone, Copy, Default)] + #[reflect(Component)] + struct A(usize); + + #[test] + fn clone_dynamic_entities() { + let mut world = World::default(); + + // setup + let atr = AppTypeRegistry::default(); + atr.write().register::(); + world.insert_resource(atr); + world.insert_resource(Assets::::default()); + + // start test + world.spawn(A(42)); + + assert_eq!(world.query::<&A>().iter(&world).len(), 1); + + // clone only existing entity + let mut scene_spawner = SceneSpawner::default(); + let entity = world.query_filtered::>().single(&world); + let scene = DynamicSceneBuilder::from_world(&world) + .extract_entity(entity) + .build(); + + let scene_id = world.resource_mut::>().add(scene); + let instance_id = scene_spawner.spawn_dynamic_sync(&mut world, scene_id).unwrap(); + + // verify we spawned exactly one new entity with our expected component + assert_eq!(world.query::<&A>().iter(&world).len(), 2); + + // verify that we can get this newly-spawned entity by the instance ID + let new_entity = scene_spawner + .iter_instance_entities(instance_id) + .next() + .unwrap(); + + // verify this is not the original entity + assert_ne!(entity, new_entity); + + // verify this new entity contains the same data as the original entity + let [old_a, new_a] = world.query::<&A>().get_many(&world, [entity, new_entity]).unwrap(); + assert_eq!(old_a, new_a); + } +} From 4fece031ffaaa09f2661ef621404b1a85afab505 Mon Sep 17 00:00:00 2001 From: s33n Date: Sat, 6 Jan 2024 12:03:37 -0800 Subject: [PATCH 2/2] formatting --- crates/bevy_scene/src/scene_spawner.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 3b342489478a5..fc42c522f16ee 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -435,18 +435,17 @@ pub fn scene_spawner_system(world: &mut World) { }); } - #[cfg(test)] mod tests { use super::*; - use bevy_ecs::{reflect::AppTypeRegistry, world::World}; use bevy_ecs::component::Component; use bevy_ecs::entity::Entity; - use bevy_ecs::query::With; use bevy_ecs::prelude::ReflectComponent; + use bevy_ecs::query::With; + use bevy_ecs::{reflect::AppTypeRegistry, world::World}; - use bevy_reflect::Reflect; use crate::DynamicSceneBuilder; + use bevy_reflect::Reflect; #[derive(Reflect, Component, Debug, PartialEq, Eq, Clone, Copy, Default)] #[reflect(Component)] @@ -475,7 +474,9 @@ mod tests { .build(); let scene_id = world.resource_mut::>().add(scene); - let instance_id = scene_spawner.spawn_dynamic_sync(&mut world, scene_id).unwrap(); + let instance_id = scene_spawner + .spawn_dynamic_sync(&mut world, scene_id) + .unwrap(); // verify we spawned exactly one new entity with our expected component assert_eq!(world.query::<&A>().iter(&world).len(), 2); @@ -490,7 +491,10 @@ mod tests { assert_ne!(entity, new_entity); // verify this new entity contains the same data as the original entity - let [old_a, new_a] = world.query::<&A>().get_many(&world, [entity, new_entity]).unwrap(); + let [old_a, new_a] = world + .query::<&A>() + .get_many(&world, [entity, new_entity]) + .unwrap(); assert_eq!(old_a, new_a); } }