diff --git a/crates/bevy_ecs/src/identifier/mod.rs b/crates/bevy_ecs/src/identifier/mod.rs index 6018a9f85fca7..56e6270e8c625 100644 --- a/crates/bevy_ecs/src/identifier/mod.rs +++ b/crates/bevy_ecs/src/identifier/mod.rs @@ -6,13 +6,16 @@ #[cfg(feature = "bevy_reflect")] use bevy_reflect::Reflect; -use self::{error::IdentifierError, kinds::IdKind, masks::IdentifierMask}; +use self::masks::IdentifierMask; use std::{hash::Hash, num::NonZero}; pub mod error; pub(crate) mod kinds; pub(crate) mod masks; +pub use self::error::IdentifierError; +pub use self::kinds::IdKind; + /// A unified identifier for all entity and similar IDs. /// /// Has the same size as a `u64` integer, but the layout is split between a 32-bit low diff --git a/crates/bevy_scene/src/dynamic_scene.rs b/crates/bevy_scene/src/dynamic_scene.rs index 7f094ce0167ed..1b51625c08cff 100644 --- a/crates/bevy_scene/src/dynamic_scene.rs +++ b/crates/bevy_scene/src/dynamic_scene.rs @@ -208,13 +208,16 @@ where #[cfg(test)] mod tests { + use bevy_app::App; + use bevy_ecs::observer::Trigger; + use bevy_ecs::world::OnAdd; use bevy_ecs::{ entity::{Entity, EntityHashMap, EntityMapper, MapEntities}, reflect::{AppTypeRegistry, ReflectMapEntitiesResource, ReflectResource}, - system::Resource, + system::{Query, Resource}, world::{Command, World}, }; - use bevy_hierarchy::{AddChild, Parent}; + use bevy_hierarchy::{AddChild, BuildChildren, Children, Parent}; use bevy_reflect::Reflect; use crate::dynamic_scene_builder::DynamicSceneBuilder; @@ -348,4 +351,52 @@ mod tests { "something is wrong with the this test or the code reloading scenes since the relationship between scene entities is broken" ); } + + #[test] + fn observers_should_see_mapped_entities() { + // Testing that Observers don't see the entities from the scene, but rather from the world itself. + + let mut app = App::new(); + app.init_resource::() + .register_type::() + .observe(|trigger: Trigger, query: Query<&Parent>| { + let parent = query + .get(trigger.entity()) + .expect("entity should have a parent"); + + assert_ne!(parent.get(), Entity::PLACEHOLDER); + }); + + let mut scene_world = World::new(); + scene_world.insert_resource(app.world().resource::().clone()); + + for _ in 0..5 { + scene_world.spawn_empty(); + } + + let scene_child = scene_world.spawn_empty().id(); + let scene_parent = scene_world.spawn_empty().add_children(&[scene_child]).id(); + + app.observe( + move |trigger: Trigger, query: Query<&Parent>| { + let parent = query + .get(trigger.entity()) + .expect("entity should have a parent"); + + assert_ne!(parent.get(), scene_parent); + }, + ); + + let scene = DynamicSceneBuilder::from_world(&scene_world) + .allow_component::() + .allow_component::() + .extract_entities([scene_parent, scene_child].into_iter()) + .build(); + + let mut entity_map = EntityHashMap::::default(); + + scene + .write_to_world(app.world_mut(), &mut entity_map) + .expect("write scene to world"); + } } diff --git a/crates/bevy_scene/src/scene.rs b/crates/bevy_scene/src/scene.rs index 5d0cf57639201..5e6ea4a6c0a6d 100644 --- a/crates/bevy_scene/src/scene.rs +++ b/crates/bevy_scene/src/scene.rs @@ -134,3 +134,60 @@ impl Scene { Ok(()) } } + +#[cfg(test)] +mod tests { + use bevy_app::App; + use bevy_ecs::{ + entity::{Entity, EntityHashMap}, + observer::Trigger, + reflect::AppTypeRegistry, + system::Query, + world::{OnAdd, World}, + }; + use bevy_hierarchy::{BuildChildren, Children, Parent}; + + use crate::Scene; + + #[test] + fn observers_should_see_mapped_entities() { + // Testing that Observers don't see the entities from the scene, but rather from the world itself. + + let type_registry = AppTypeRegistry::default(); + { + let mut registry_write = type_registry.write(); + registry_write.register::(); + registry_write.register::(); + } + + let mut app = App::new(); + app.insert_resource(type_registry.clone()); + + let mut scene_world = World::new(); + + for _ in 0..5 { + scene_world.spawn_empty(); + } + + let scene_child = scene_world.spawn_empty().id(); + let scene_parent = scene_world.spawn_empty().add_children(&[scene_child]).id(); + + app.observe( + move |trigger: Trigger, query: Query<&Parent>| { + let parent = query + .get(trigger.entity()) + .expect("entity should have a parent"); + + assert_ne!(parent.get(), scene_parent); + }, + ); + + let mut entity_map = EntityHashMap::::default(); + + let scene = Scene { world: scene_world }; + + scene + .write_to_world_with(app.world_mut(), &mut entity_map, &type_registry) + .expect("write scene to world"); + } +}