Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 34 additions & 23 deletions crates/bevy_scene/src/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,13 @@ impl WorldSceneExt for World {
let assets = self.resource::<AssetServer>();
let patch = ScenePatch::load(assets, scene);
let handle = assets.add(patch);
self.spawn(ScenePatchInstance(handle))
let mut entity = self.spawn_empty();
let id = entity.id();
entity
.resource_mut::<QueuedScenes>()
.new_scene_entities
.push((id, handle));
entity
}

fn spawn_scene_list<L: SceneList>(
Expand Down Expand Up @@ -501,7 +507,10 @@ impl EntityWorldMutSceneExt for EntityWorldMut<'_> {
let assets = self.resource::<AssetServer>();
let patch = ScenePatch::load(assets, scene);
let handle = assets.add(patch);
self.insert(ScenePatchInstance(handle));
let id = self.id();
self.resource_mut::<QueuedScenes>()
.new_scene_entities
.push((id, handle));
}
}

Expand Down Expand Up @@ -660,7 +669,7 @@ pub fn resolve_scene_patches(
/// A [`Resource`] that tracks entities / scenes that have been queued to spawn.
#[derive(Resource, Default)]
pub struct QueuedScenes {
new_scene_entities: Vec<Entity>,
new_scene_entities: Vec<(Entity, Handle<ScenePatch>)>,
related_scene_list_spawns: Vec<(RelatedSceneListSpawn, Handle<SceneListPatch>)>,
scene_list_spawns: Vec<Handle<SceneListPatch>>,
}
Expand All @@ -682,8 +691,13 @@ pub(crate) struct RelatedSceneListSpawn {
pub fn on_add_scene_patch_instance(
add: On<Add, ScenePatchInstance>,
mut queued_scenes: ResMut<QueuedScenes>,
instances: Query<&ScenePatchInstance>,
) {
queued_scenes.new_scene_entities.push(add.entity);
if let Ok(instance) = instances.get(add.entity) {
queued_scenes
.new_scene_entities
.push((add.entity, instance.0.clone()));
}
}

/// A system that spawns queued scenes when they are loaded.
Expand All @@ -695,22 +709,8 @@ pub fn spawn_queued(
mut reader: Local<MessageCursor<AssetEvent<ScenePatch>>>,
mut list_reader: Local<MessageCursor<AssetEvent<SceneListPatch>>>,
) {
core::mem::swap(&mut *world.resource_mut::<QueuedScenes>(), &mut queued);
world.resource_scope(|world, mut list_patches: Mut<Assets<SceneListPatch>>| {
world.resource_scope(|world, mut waiting: Mut<WaitingScenes>| {
loop {
if queued.is_empty() {
break;
}
queued.spawn_queued(
world,
&mut waiting,
scene_patch_instances,
&mut bundle_scratch,
&list_patches,
);
}

world.resource_scope(|world, events: Mut<Messages<AssetEvent<ScenePatch>>>| {
for event in reader.read(&events) {
let patches = world.resource::<Assets<ScenePatch>>();
Expand Down Expand Up @@ -765,6 +765,20 @@ pub fn spawn_queued(
}
},
);

loop {
core::mem::swap(&mut *world.resource_mut::<QueuedScenes>(), &mut queued);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this loop until after the "asset load event" processing to ensure that we spawn queued scenes that are produced from the spawning of those scene asset loads now rather than waiting a frame.

I've also moved the mem::swap into the loop to ensure we check for newly queued spawns after spawning the current queue.

if queued.is_empty() {
break;
}
queued.spawn_queued(
world,
&mut waiting,
scene_patch_instances,
&mut bundle_scratch,
&list_patches,
);
}
});
});
}
Expand All @@ -784,12 +798,9 @@ impl QueuedScenes {
bundle_scratch: &mut BundleScratch,
list_patches: &Assets<SceneListPatch>,
) {
for entity in core::mem::take(&mut self.new_scene_entities) {
let Ok(handle) = scene_patch_instances.get(world, entity).map(|h| &h.0) else {
continue;
};
for (entity, handle) in core::mem::take(&mut self.new_scene_entities) {
let patches = world.resource::<Assets<ScenePatch>>();
if let Some(resolved) = patches.get(handle).and_then(|p| p.resolved.clone()) {
if let Some(resolved) = patches.get(&handle).and_then(|p| p.resolved.clone()) {
let mut entity_mut = world.get_entity_mut(entity).unwrap();
if let Err(err) = resolved.apply(&mut entity_mut, bundle_scratch) {
let scene_patch_instance = scene_patch_instances.get(world, entity).unwrap();
Expand Down
Loading