Skip to content

Commit

Permalink
can spawn a scene from a ChildBuilder, or directly set its parent whe…
Browse files Browse the repository at this point in the history
…n spawning it (#1026)

can spawn a scene from a ChildBuilder, or directly set its parent when spawning one
  • Loading branch information
mockersf authored Dec 9, 2020
1 parent c54179b commit f53ee54
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 9 deletions.
1 change: 1 addition & 0 deletions crates/bevy_scene/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ bevy_app = { path = "../bevy_app", version = "0.3.0" }
bevy_asset = { path = "../bevy_asset", version = "0.3.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.3.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.3.0", features = ["bevy"] }
bevy_transform = { path = "../bevy_transform", version = "0.3.0" }
bevy_utils = { path = "../bevy_utils", version = "0.3.0" }

# other
Expand Down
29 changes: 28 additions & 1 deletion crates/bevy_scene/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use bevy_asset::Handle;
use bevy_ecs::{Command, Commands, Resources, World};
use bevy_ecs::{Command, Commands, Entity, Resources, World};
use bevy_transform::hierarchy::ChildBuilder;

use crate::{Scene, SceneSpawner};

Expand All @@ -23,3 +24,29 @@ impl SpawnSceneCommands for Commands {
self.add_command(SpawnScene { scene_handle })
}
}

pub struct SpawnSceneAsChild {
scene_handle: Handle<Scene>,
parent: Entity,
}

impl Command for SpawnSceneAsChild {
fn write(self: Box<Self>, _world: &mut World, resources: &mut Resources) {
let mut spawner = resources.get_mut::<SceneSpawner>().unwrap();
spawner.spawn_as_child(self.scene_handle, self.parent);
}
}

pub trait SpawnSceneAsChildCommands {
fn spawn_scene(&mut self, scene: Handle<Scene>) -> &mut Self;
}

impl<'a> SpawnSceneAsChildCommands for ChildBuilder<'a> {
fn spawn_scene(&mut self, scene_handle: Handle<Scene>) -> &mut Self {
self.add_command(SpawnSceneAsChild {
scene_handle,
parent: self.parent_entity(),
});
self
}
}
4 changes: 3 additions & 1 deletion crates/bevy_scene/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ pub use scene_loader::*;
pub use scene_spawner::*;

pub mod prelude {
pub use crate::{DynamicScene, Scene, SceneSpawner, SpawnSceneCommands};
pub use crate::{
DynamicScene, Scene, SceneSpawner, SpawnSceneAsChildCommands, SpawnSceneCommands,
};
}

use bevy_app::prelude::*;
Expand Down
51 changes: 44 additions & 7 deletions crates/bevy_scene/src/scene_spawner.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::{DynamicScene, Scene};
use bevy_app::prelude::*;
use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_ecs::{EntityMap, Resources, World};
use bevy_ecs::{Entity, EntityMap, Resources, World};
use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc};
use bevy_transform::prelude::Parent;
use bevy_utils::HashMap;
use thiserror::Error;
use uuid::Uuid;
Expand All @@ -28,8 +29,9 @@ pub struct SceneSpawner {
spawned_instances: HashMap<InstanceId, InstanceInfo>,
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>,
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
scenes_to_spawn: Vec<Handle<Scene>>,
scenes_to_spawn: Vec<(Handle<Scene>, InstanceId)>,
scenes_to_despawn: Vec<Handle<DynamicScene>>,
scenes_with_parent: Vec<(InstanceId, Entity)>,
}

#[derive(Error, Debug)]
Expand All @@ -50,7 +52,14 @@ impl SceneSpawner {
}

pub fn spawn(&mut self, scene_handle: Handle<Scene>) {
self.scenes_to_spawn.push(scene_handle);
let instance_id = InstanceId::new();
self.scenes_to_spawn.push((scene_handle, instance_id));
}

pub fn spawn_as_child(&mut self, scene_handle: Handle<Scene>, parent: Entity) {
let instance_id = InstanceId::new();
self.scenes_to_spawn.push((scene_handle, instance_id));
self.scenes_with_parent.push((instance_id, parent));
}

pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) {
Expand Down Expand Up @@ -147,7 +156,16 @@ impl SceneSpawner {
resources: &Resources,
scene_handle: Handle<Scene>,
) -> Result<(), SceneSpawnError> {
let instance_id = InstanceId::new();
self.spawn_sync_internal(world, resources, scene_handle, InstanceId::new())
}

fn spawn_sync_internal(
&mut self,
world: &mut World,
resources: &Resources,
scene_handle: Handle<Scene>,
instance_id: InstanceId,
) -> Result<(), SceneSpawnError> {
let mut instance_info = InstanceInfo {
entity_map: EntityMap::default(),
};
Expand Down Expand Up @@ -256,18 +274,36 @@ impl SceneSpawner {

let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn);

for scene_handle in scenes_to_spawn {
match self.spawn_sync(world, resources, scene_handle) {
for (scene_handle, instance_id) in scenes_to_spawn {
match self.spawn_sync_internal(world, resources, scene_handle, instance_id) {
Ok(_) => {}
Err(SceneSpawnError::NonExistentRealScene { handle }) => {
self.scenes_to_spawn.push(handle)
self.scenes_to_spawn.push((handle, instance_id))
}
Err(err) => return Err(err),
}
}

Ok(())
}

pub(crate) fn set_scene_instance_parent_sync(&mut self, world: &mut World) {
let scenes_with_parent = std::mem::take(&mut self.scenes_with_parent);

for (instance_id, parent) in scenes_with_parent {
if let Some(instance) = self.spawned_instances.get(&instance_id) {
for entity in instance.entity_map.values() {
if let Err(bevy_ecs::ComponentError::MissingComponent(_)) =
world.get::<Parent>(entity)
{
let _ = world.insert_one(entity, Parent(parent));
}
}
} else {
self.scenes_with_parent.push((instance_id, parent));
}
}
}
}

pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
Expand All @@ -293,4 +329,5 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
scene_spawner
.update_spawned_scenes(world, resources, &updated_spawned_scenes)
.unwrap();
scene_spawner.set_scene_instance_parent_sync(world);
}
9 changes: 9 additions & 0 deletions crates/bevy_transform/src/hierarchy/child_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ impl<'a> ChildBuilder<'a> {
self.commands.current_entity()
}

pub fn parent_entity(&self) -> Entity {
self.push_children.parent
}

pub fn with_bundle(
&mut self,
components: impl DynamicBundle + Send + Sync + 'static,
Expand All @@ -102,6 +106,11 @@ impl<'a> ChildBuilder<'a> {
func(current_entity);
self
}

pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
self.commands.add_command(command);
self
}
}

pub trait BuildChildren {
Expand Down

0 comments on commit f53ee54

Please sign in to comment.