11use crate :: { ron, DynamicSceneBuilder , Scene , SceneSpawnError } ;
2+ use bevy_asset:: Asset ;
3+ use bevy_ecs:: reflect:: ReflectResource ;
24use bevy_ecs:: {
3- entity:: { Entity , EntityHashMap } ,
5+ entity:: { Entity , EntityHashMap , SceneEntityMapper } ,
46 reflect:: { AppTypeRegistry , ReflectComponent , ReflectMapEntities } ,
57 world:: World ,
68} ;
79use bevy_reflect:: { PartialReflect , TypePath , TypeRegistry } ;
8- use bevy_utils:: TypeIdMap ;
910
1011#[ cfg( feature = "serialize" ) ]
1112use crate :: serde:: SceneSerializer ;
12- use bevy_asset:: Asset ;
13- use bevy_ecs:: reflect:: { ReflectMapEntitiesResource , ReflectResource } ;
1413#[ cfg( feature = "serialize" ) ]
1514use serde:: Serialize ;
1615
@@ -70,23 +69,26 @@ impl DynamicScene {
7069 ) -> Result < ( ) , SceneSpawnError > {
7170 let type_registry = type_registry. read ( ) ;
7271
73- // For each component types that reference other entities, we keep track
74- // of which entities in the scene use that component.
75- // This is so we can update the scene-internal references to references
76- // of the actual entities in the world.
77- let mut scene_mappings: TypeIdMap < Vec < Entity > > = Default :: default ( ) ;
78-
72+ // First ensure that every entity in the scene has a corresponding world
73+ // entity in the entity map.
7974 for scene_entity in & self . entities {
8075 // Fetch the entity with the given entity id from the `entity_map`
8176 // or spawn a new entity with a transiently unique id if there is
8277 // no corresponding entry.
83- let entity = * entity_map
78+ entity_map
8479 . entry ( scene_entity. entity )
8580 . or_insert_with ( || world. spawn_empty ( ) . id ( ) ) ;
86- let entity_mut = & mut world. entity_mut ( entity) ;
81+ }
82+
83+ for scene_entity in & self . entities {
84+ // Fetch the entity with the given entity id from the `entity_map`.
85+ let entity = * entity_map
86+ . get ( & scene_entity. entity )
87+ . expect ( "should have previously spawned an empty entity" ) ;
8788
8889 // Apply/ add each component to the given entity.
8990 for component in & scene_entity. components {
91+ let mut component = component. clone_value ( ) ;
9092 let type_info = component. get_represented_type_info ( ) . ok_or_else ( || {
9193 SceneSpawnError :: NoRepresentedType {
9294 type_path : component. reflect_type_path ( ) . to_string ( ) ,
@@ -104,39 +106,26 @@ impl DynamicScene {
104106 }
105107 } ) ?;
106108
107- // If this component references entities in the scene, track it
108- // so we can update it to the entity in the world.
109- if registration. data :: < ReflectMapEntities > ( ) . is_some ( ) {
110- scene_mappings
111- . entry ( registration. type_id ( ) )
112- . or_default ( )
113- . push ( entity) ;
109+ // If this component references entities in the scene, update
110+ // them to the entities in the world.
111+ if let Some ( map_entities) = registration. data :: < ReflectMapEntities > ( ) {
112+ SceneEntityMapper :: world_scope ( entity_map, world, |_, mapper| {
113+ map_entities. map_entities ( component. as_partial_reflect_mut ( ) , mapper) ;
114+ } ) ;
114115 }
115116
116- // If the entity already has the given component attached,
117- // just apply the (possibly) new value, otherwise add the
118- // component to the entity.
119117 reflect_component. apply_or_insert (
120- entity_mut,
118+ & mut world . entity_mut ( entity ) ,
121119 component. as_partial_reflect ( ) ,
122120 & type_registry,
123121 ) ;
124122 }
125123 }
126124
127- // Updates references to entities in the scene to entities in the world
128- for ( type_id, entities) in scene_mappings. into_iter ( ) {
129- let registration = type_registry. get ( type_id) . expect (
130- "we should be getting TypeId from this TypeRegistration in the first place" ,
131- ) ;
132- if let Some ( map_entities_reflect) = registration. data :: < ReflectMapEntities > ( ) {
133- map_entities_reflect. map_entities ( world, entity_map, & entities) ;
134- }
135- }
136-
137125 // Insert resources after all entities have been added to the world.
138126 // This ensures the entities are available for the resources to reference during mapping.
139127 for resource in & self . resources {
128+ let mut resource = resource. clone_value ( ) ;
140129 let type_info = resource. get_represented_type_info ( ) . ok_or_else ( || {
141130 SceneSpawnError :: NoRepresentedType {
142131 type_path : resource. reflect_type_path ( ) . to_string ( ) ,
@@ -153,14 +142,17 @@ impl DynamicScene {
153142 }
154143 } ) ?;
155144
145+ // If this component references entities in the scene, update
146+ // them to the entities in the world.
147+ if let Some ( map_entities) = registration. data :: < ReflectMapEntities > ( ) {
148+ SceneEntityMapper :: world_scope ( entity_map, world, |_, mapper| {
149+ map_entities. map_entities ( resource. as_partial_reflect_mut ( ) , mapper) ;
150+ } ) ;
151+ }
152+
156153 // If the world already contains an instance of the given resource
157154 // just apply the (possibly) new value, otherwise insert the resource
158- reflect_resource. apply_or_insert ( world, & * * resource, & type_registry) ;
159-
160- // Map entities in the resource if it implements [`MapEntities`].
161- if let Some ( map_entities_reflect) = registration. data :: < ReflectMapEntitiesResource > ( ) {
162- map_entities_reflect. map_entities ( world, entity_map) ;
163- }
155+ reflect_resource. apply_or_insert ( world, resource. as_partial_reflect ( ) , & type_registry) ;
164156 }
165157
166158 Ok ( ( ) )
@@ -211,10 +203,7 @@ mod tests {
211203 use bevy_ecs:: {
212204 component:: Component ,
213205 entity:: { Entity , EntityHashMap , EntityMapper , MapEntities } ,
214- reflect:: {
215- AppTypeRegistry , ReflectComponent , ReflectMapEntities , ReflectMapEntitiesResource ,
216- ReflectResource ,
217- } ,
206+ reflect:: { AppTypeRegistry , ReflectComponent , ReflectMapEntities , ReflectResource } ,
218207 system:: Resource ,
219208 world:: { Command , World } ,
220209 } ;
@@ -225,7 +214,7 @@ mod tests {
225214 use crate :: dynamic_scene_builder:: DynamicSceneBuilder ;
226215
227216 #[ derive( Resource , Reflect , Debug ) ]
228- #[ reflect( Resource , MapEntitiesResource ) ]
217+ #[ reflect( Resource , MapEntities ) ]
229218 struct TestResource {
230219 entity_a : Entity ,
231220 entity_b : Entity ,
0 commit comments