diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index 6537333877f53..fc42c522f16ee 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,67 @@ 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::component::Component; + use bevy_ecs::entity::Entity; + use bevy_ecs::prelude::ReflectComponent; + use bevy_ecs::query::With; + use bevy_ecs::{reflect::AppTypeRegistry, world::World}; + + use crate::DynamicSceneBuilder; + use bevy_reflect::Reflect; + + #[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); + } +}