Skip to content

Commit 58e6789

Browse files
committed
add DynamicSceneBundle
1 parent 286c788 commit 58e6789

File tree

3 files changed

+63
-12
lines changed

3 files changed

+63
-12
lines changed

crates/bevy_scene/src/bundle.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use bevy_ecs::{
44
};
55
use bevy_transform::components::{GlobalTransform, Transform};
66

7-
use crate::{InstanceId, Scene, SceneSpawner};
7+
use crate::{DynamicScene, InstanceId, Scene, SceneSpawner};
88

99
#[derive(Default, Bundle)]
1010
pub struct SceneBundle {
1111
pub scene: Handle<Scene>,
12+
pub instance_id: Option<InstanceId>,
1213
pub transform: Transform,
1314
pub global_transform: GlobalTransform,
14-
pub instance_id: Option<InstanceId>,
1515
}
1616

1717
#[allow(clippy::type_complexity)]
@@ -28,3 +28,28 @@ pub fn scene_bundle_spawner(
2828
}
2929
}
3030
}
31+
32+
#[derive(Default, Bundle)]
33+
pub struct DynamicSceneBundle {
34+
pub scene: Handle<DynamicScene>,
35+
pub instance_id: Option<InstanceId>,
36+
pub transform: Transform,
37+
pub global_transform: GlobalTransform,
38+
}
39+
40+
#[allow(clippy::type_complexity)]
41+
pub fn dynamic_scene_bundle_spawner(
42+
mut dynamic_scene_to_spawn: Query<
43+
(Entity, &Handle<DynamicScene>, &mut Option<InstanceId>),
44+
Changed<Handle<DynamicScene>>,
45+
>,
46+
mut scene_spawner: ResMut<SceneSpawner>,
47+
) {
48+
for (entity, dynamic_scene, mut instance) in dynamic_scene_to_spawn.iter_mut() {
49+
if let Some(id) =
50+
instance.replace(scene_spawner.spawn_dynamic_as_child(dynamic_scene.clone(), entity))
51+
{
52+
scene_spawner.despawn_instance(id);
53+
}
54+
}
55+
}

crates/bevy_scene/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ pub use scene_spawner::*;
1616
pub mod prelude {
1717
#[doc(hidden)]
1818
pub use crate::{
19-
DynamicScene, Scene, SceneBundle, SceneSpawner, SpawnSceneAsChildCommands,
20-
SpawnSceneCommands,
19+
DynamicScene, DynamicSceneBundle, Scene, SceneBundle, SceneSpawner,
20+
SpawnSceneAsChildCommands, SpawnSceneCommands,
2121
};
2222
}
2323

@@ -38,6 +38,8 @@ impl Plugin for ScenePlugin {
3838
CoreStage::PreUpdate,
3939
scene_spawner_system.exclusive_system().at_end(),
4040
)
41-
.add_system_to_stage(CoreStage::PreUpdate, scene_bundle_spawner);
41+
// Systems `*_bundle_spawner` must run before `scene_spawner_system`
42+
.add_system_to_stage(CoreStage::PreUpdate, scene_bundle_spawner)
43+
.add_system_to_stage(CoreStage::PreUpdate, dynamic_scene_bundle_spawner);
4244
}
4345
}

crates/bevy_scene/src/scene_spawner.rs

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct SceneSpawner {
3232
spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>,
3333
spawned_instances: HashMap<InstanceId, InstanceInfo>,
3434
scene_asset_event_reader: ManualEventReader<AssetEvent<DynamicScene>>,
35-
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
35+
dynamic_scenes_to_spawn: Vec<(Handle<DynamicScene>, InstanceId)>,
3636
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
3737
scenes_to_despawn: Vec<Handle<DynamicScene>>,
3838
instances_to_despawn: Vec<InstanceId>,
@@ -53,7 +53,21 @@ pub enum SceneSpawnError {
5353

5454
impl SceneSpawner {
5555
pub fn spawn_dynamic(&mut self, scene_handle: Handle<DynamicScene>) {
56-
self.dynamic_scenes_to_spawn.push(scene_handle);
56+
let instance_id = InstanceId::new();
57+
self.dynamic_scenes_to_spawn
58+
.push((scene_handle, instance_id));
59+
}
60+
61+
pub fn spawn_dynamic_as_child(
62+
&mut self,
63+
scene_handle: Handle<DynamicScene>,
64+
parent: Entity,
65+
) -> InstanceId {
66+
let instance_id = InstanceId::new();
67+
self.dynamic_scenes_to_spawn
68+
.push((scene_handle, instance_id));
69+
self.scenes_with_parent.push((instance_id, parent));
70+
instance_id
5771
}
5872

5973
pub fn spawn(&mut self, scene_handle: Handle<Scene>) -> InstanceId {
@@ -257,12 +271,22 @@ impl SceneSpawner {
257271
pub fn spawn_queued_scenes(&mut self, world: &mut World) -> Result<(), SceneSpawnError> {
258272
let scenes_to_spawn = std::mem::take(&mut self.dynamic_scenes_to_spawn);
259273

260-
for scene_handle in scenes_to_spawn {
261-
match self.spawn_dynamic_sync(world, &scene_handle) {
262-
Ok(_) => {}
263-
Err(SceneSpawnError::NonExistentScene { .. }) => {
264-
self.dynamic_scenes_to_spawn.push(scene_handle)
274+
for (scene_handle, instance_id) in scenes_to_spawn {
275+
let mut entity_map = EntityMap::default();
276+
277+
match Self::spawn_dynamic_internal(world, &scene_handle, &mut entity_map) {
278+
Ok(_) => {
279+
self.spawned_instances
280+
.insert(instance_id, InstanceInfo { entity_map });
281+
let spawned = self
282+
.spawned_dynamic_scenes
283+
.entry(scene_handle.clone())
284+
.or_insert_with(Vec::new);
285+
spawned.push(instance_id);
265286
}
287+
Err(SceneSpawnError::NonExistentScene { .. }) => self
288+
.dynamic_scenes_to_spawn
289+
.push((scene_handle, instance_id)),
266290
Err(err) => return Err(err),
267291
}
268292
}

0 commit comments

Comments
 (0)