Skip to content

Commit 1a490c9

Browse files
Fishrock123mrk-its
authored andcommitted
SceneSpawner: add unload() and unload_sync() (bevyengine#339)
This allows you to unload scenes. Refs: bevyengine#255
1 parent b8d9009 commit 1a490c9

File tree

1 file changed

+41
-8
lines changed

1 file changed

+41
-8
lines changed

crates/bevy_scene/src/scene_spawner.rs

+41-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct SceneSpawner {
2828
scene_asset_event_reader: EventReader<AssetEvent<Scene>>,
2929
scenes_to_spawn: Vec<Handle<Scene>>,
3030
scenes_to_load: Vec<Handle<Scene>>,
31+
scenes_to_unload: Vec<Handle<Scene>>,
3132
}
3233

3334
#[derive(Error, Debug)]
@@ -47,6 +48,10 @@ impl SceneSpawner {
4748
self.scenes_to_load.push(scene_handle);
4849
}
4950

51+
pub fn unload(&mut self, scene_handle: Handle<Scene>) {
52+
self.scenes_to_unload.push(scene_handle);
53+
}
54+
5055
pub fn load_sync(
5156
&mut self,
5257
world: &mut World,
@@ -58,6 +63,26 @@ impl SceneSpawner {
5863
Ok(())
5964
}
6065

66+
pub fn unload_sync(
67+
&mut self,
68+
world: &mut World,
69+
scene_handle: Handle<Scene>,
70+
) -> Result<(), SceneSpawnError> {
71+
if let Some(instance_ids) = self.spawned_scenes.get(&scene_handle) {
72+
for instance_id in instance_ids {
73+
if let Some(instance) = self.spawned_instances.get(&instance_id) {
74+
for entity in instance.entity_map.values() {
75+
let _ = world.despawn(*entity); // Ignore the result, unload only cares if it exists.
76+
}
77+
}
78+
}
79+
80+
self.loaded_scenes.remove(&scene_handle);
81+
self.spawned_scenes.remove(&scene_handle);
82+
}
83+
Ok(())
84+
}
85+
6186
pub fn spawn_sync(
6287
&mut self,
6388
world: &mut World,
@@ -152,19 +177,27 @@ impl SceneSpawner {
152177
world: &mut World,
153178
resources: &Resources,
154179
) -> Result<(), SceneSpawnError> {
155-
let scenes_to_load = self.scenes_to_load.drain(..).collect::<Vec<_>>();
156-
let mut non_existent_scenes = Vec::new();
180+
let scenes_to_load = std::mem::take(&mut self.scenes_to_load);
181+
157182
for scene_handle in scenes_to_load {
158183
match self.load_sync(world, resources, scene_handle) {
159184
Ok(_) => {}
160185
Err(SceneSpawnError::NonExistentScene { .. }) => {
161-
non_existent_scenes.push(scene_handle)
186+
self.scenes_to_load.push(scene_handle)
162187
}
163188
Err(err) => return Err(err),
164189
}
165190
}
166191

167-
self.scenes_to_load = non_existent_scenes;
192+
Ok(())
193+
}
194+
195+
pub fn unload_queued_scenes(&mut self, world: &mut World) -> Result<(), SceneSpawnError> {
196+
let scenes_to_unload = std::mem::take(&mut self.scenes_to_unload);
197+
198+
for scene_handle in scenes_to_unload {
199+
self.unload_sync(world, scene_handle)?;
200+
}
168201
Ok(())
169202
}
170203

@@ -173,19 +206,18 @@ impl SceneSpawner {
173206
world: &mut World,
174207
resources: &Resources,
175208
) -> Result<(), SceneSpawnError> {
176-
let scenes_to_spawn = self.scenes_to_spawn.drain(..).collect::<Vec<_>>();
177-
let mut non_existent_scenes = Vec::new();
209+
let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn);
210+
178211
for scene_handle in scenes_to_spawn {
179212
match self.spawn_sync(world, resources, scene_handle) {
180213
Ok(_) => {}
181214
Err(SceneSpawnError::NonExistentScene { .. }) => {
182-
non_existent_scenes.push(scene_handle)
215+
self.scenes_to_spawn.push(scene_handle)
183216
}
184217
Err(err) => return Err(err),
185218
}
186219
}
187220

188-
self.scenes_to_spawn = non_existent_scenes;
189221
Ok(())
190222
}
191223
}
@@ -209,6 +241,7 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
209241
}
210242
}
211243

244+
scene_spawner.unload_queued_scenes(world).unwrap();
212245
scene_spawner.load_queued_scenes(world, resources).unwrap();
213246
scene_spawner.spawn_queued_scenes(world, resources).unwrap();
214247
scene_spawner

0 commit comments

Comments
 (0)