Skip to content

Commit df1bd8e

Browse files
committed
SceneSpawner: add unload() and unload_sync()
This allows you to unload scenes. Refs: bevyengine#255
1 parent 2dadc86 commit df1bd8e

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

crates/bevy_scene/src/scene_spawner.rs

+50-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.retain(|handle| handle.id != scene_handle.id);
81+
self.spawned_scenes.retain(|handle, _| handle.id != scene_handle.id);
82+
}
83+
Ok(())
84+
}
85+
6186
pub fn spawn_sync(
6287
&mut self,
6388
world: &mut World,
@@ -152,19 +177,35 @@ 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 mut scenes_to_load = Vec::new();
181+
std::mem::swap(&mut self.scenes_to_load, &mut scenes_to_load);
182+
157183
for scene_handle in scenes_to_load {
158184
match self.load_sync(world, resources, scene_handle) {
159185
Ok(_) => {}
160186
Err(SceneSpawnError::NonExistentScene { .. }) => {
161-
non_existent_scenes.push(scene_handle)
187+
self.scenes_to_spawn.push(scene_handle)
162188
}
163189
Err(err) => return Err(err),
164190
}
165191
}
166192

167-
self.scenes_to_load = non_existent_scenes;
193+
Ok(())
194+
}
195+
196+
pub fn unload_queued_scenes(
197+
&mut self,
198+
world: &mut World,
199+
) -> Result<(), SceneSpawnError> {
200+
let mut scenes_to_unload = Vec::new();
201+
std::mem::swap(&mut self.scenes_to_unload, &mut scenes_to_unload);
202+
203+
for scene_handle in scenes_to_unload {
204+
match self.unload_sync(world, scene_handle) {
205+
Ok(_) => {},
206+
Err(err) => return Err(err),
207+
}
208+
}
168209
Ok(())
169210
}
170211

@@ -173,19 +214,19 @@ impl SceneSpawner {
173214
world: &mut World,
174215
resources: &Resources,
175216
) -> Result<(), SceneSpawnError> {
176-
let scenes_to_spawn = self.scenes_to_spawn.drain(..).collect::<Vec<_>>();
177-
let mut non_existent_scenes = Vec::new();
217+
let mut scenes_to_spawn = Vec::new();
218+
std::mem::swap(&mut self.scenes_to_spawn, &mut scenes_to_spawn);
219+
178220
for scene_handle in scenes_to_spawn {
179221
match self.spawn_sync(world, resources, scene_handle) {
180222
Ok(_) => {}
181223
Err(SceneSpawnError::NonExistentScene { .. }) => {
182-
non_existent_scenes.push(scene_handle)
224+
self.scenes_to_spawn.push(scene_handle)
183225
}
184226
Err(err) => return Err(err),
185227
}
186228
}
187229

188-
self.scenes_to_spawn = non_existent_scenes;
189230
Ok(())
190231
}
191232
}
@@ -209,6 +250,7 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
209250
}
210251
}
211252

253+
scene_spawner.unload_queued_scenes(world).unwrap();
212254
scene_spawner.load_queued_scenes(world, resources).unwrap();
213255
scene_spawner.spawn_queued_scenes(world, resources).unwrap();
214256
scene_spawner

0 commit comments

Comments
 (0)