diff --git a/crates/bevy_scene2/src/lib.rs b/crates/bevy_scene2/src/lib.rs index cb8ed3e0c7de2..5116eca6dcfff 100644 --- a/crates/bevy_scene2/src/lib.rs +++ b/crates/bevy_scene2/src/lib.rs @@ -32,8 +32,10 @@ pub struct ScenePlugin; impl Plugin for ScenePlugin { fn build(&self, app: &mut App) { app.init_resource::() + .init_resource::() .init_asset::() - .add_systems(Update, (resolve_scene_patches, spawn_queued).chain()); + .add_systems(Update, (resolve_scene_patches, spawn_queued).chain()) + .add_observer(on_add_scene_patch_instance); } } diff --git a/crates/bevy_scene2/src/spawn.rs b/crates/bevy_scene2/src/spawn.rs index 70aa5ff5f91f9..82e16320cb38b 100644 --- a/crates/bevy_scene2/src/spawn.rs +++ b/crates/bevy_scene2/src/spawn.rs @@ -62,39 +62,51 @@ pub struct QueuedScenes { waiting_entities: HashMap, Vec>, } +#[derive(Resource, Default)] +pub struct NewScenes { + entities: Vec, +} + +pub fn on_add_scene_patch_instance( + trigger: On, + mut new_scenes: ResMut, +) { + new_scenes.entities.push(trigger.target()); +} + pub fn spawn_queued( world: &mut World, - handles: &mut QueryState<(Entity, &ScenePatchInstance), Added>, + handles: &mut QueryState<&ScenePatchInstance>, mut reader: Local>>, ) { world.resource_scope(|world, mut patches: Mut>| { world.resource_scope(|world, mut queued: Mut| { world.resource_scope(|world, events: Mut>>| { - for (entity, id) in handles - .iter(world) - .map(|(e, h)| (e, h.id())) - .collect::>() - { - if let Some(scene) = patches.get_mut(id).and_then(|p| p.resolved.as_mut()) { - let mut entity_mut = world.get_entity_mut(entity).unwrap(); - scene.spawn(&mut entity_mut).unwrap(); - } else { - let entities = queued.waiting_entities.entry(id).or_default(); - entities.push(entity); + loop { + let mut new_scenes = world.resource_mut::(); + if new_scenes.entities.is_empty() { + break; + } + for entity in core::mem::take(&mut new_scenes.entities) { + if let Ok(id) = handles.get(world, entity).map(|h| h.id()) { + if let Some(scene) = + patches.get_mut(id).and_then(|p| p.resolved.as_mut()) + { + let mut entity_mut = world.get_entity_mut(entity).unwrap(); + scene.spawn(&mut entity_mut).unwrap(); + } else { + let entities = queued.waiting_entities.entry(id).or_default(); + entities.push(entity); + } + } } } for event in reader.read(&events) { - if let AssetEvent::LoadedWithDependencies { id } = event { - let Some(scene) = patches.get_mut(*id).and_then(|p| p.resolved.as_mut()) - else { - continue; - }; - - let Some(entities) = queued.waiting_entities.remove(id) else { - continue; - }; - + if let AssetEvent::LoadedWithDependencies { id } = event + && let Some(scene) = patches.get_mut(*id).and_then(|p| p.resolved.as_mut()) + && let Some(entities) = queued.waiting_entities.remove(id) + { for entity in entities { if let Ok(mut entity_mut) = world.get_entity_mut(entity) { scene.spawn(&mut entity_mut).unwrap();