Change SceneSpawner::spawn_dynamic_sync to return InstanceID (#11239)

# Objective

`SceneSpawner::spawn_dynamic_sync` currently returns `()` on success,
which is inconsistent with the other `SceneSpawner::spawn_` methods that
all return an `InstanceId`. We need this ID to do useful work with the
newly-created data.

## Solution

Updated `SceneSpawner::spawn_dynamic_sync` to return `Result<InstanceId,
SceneSpawnError>` instead of `Result<(), SceneSpawnError>`
This commit is contained in:
thebluefish 2024-01-06 14:26:32 -08:00 committed by GitHub
parent 0349809420
commit cfcb6885e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -198,7 +198,7 @@ impl SceneSpawner {
&mut self,
world: &mut World,
id: impl Into<AssetId<DynamicScene>>,
) -> Result<(), SceneSpawnError> {
) -> Result<InstanceId, SceneSpawnError> {
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::<A>();
world.insert_resource(atr);
world.insert_resource(Assets::<DynamicScene>::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::<Entity, With<A>>().single(&world);
let scene = DynamicSceneBuilder::from_world(&world)
.extract_entity(entity)
.build();
let scene_id = world.resource_mut::<Assets<DynamicScene>>().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);
}
}