Skip to content

Commit 99ba787

Browse files
committed
add DynamicSceneBundle
1 parent 273f968 commit 99ba787

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
@@ -33,7 +33,7 @@ pub struct SceneSpawner {
3333
spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>,
3434
spawned_instances: HashMap<InstanceId, InstanceInfo>,
3535
scene_asset_event_reader: ManualEventReader<AssetEvent<DynamicScene>>,
36-
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
36+
dynamic_scenes_to_spawn: Vec<(Handle<DynamicScene>, InstanceId)>,
3737
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
3838
scenes_to_despawn: Vec<Handle<DynamicScene>>,
3939
instances_to_despawn: Vec<InstanceId>,
@@ -54,7 +54,21 @@ pub enum SceneSpawnError {
5454

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

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

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

0 commit comments

Comments
 (0)