mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
can spawn a scene from a ChildBuilder, or directly set its parent when spawning it (#1026)
can spawn a scene from a ChildBuilder, or directly set its parent when spawning one
This commit is contained in:
parent
c54179b182
commit
f53ee54eb6
5 changed files with 85 additions and 9 deletions
|
@ -18,6 +18,7 @@ bevy_app = { path = "../bevy_app", version = "0.3.0" }
|
||||||
bevy_asset = { path = "../bevy_asset", version = "0.3.0" }
|
bevy_asset = { path = "../bevy_asset", version = "0.3.0" }
|
||||||
bevy_ecs = { path = "../bevy_ecs", 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_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" }
|
bevy_utils = { path = "../bevy_utils", version = "0.3.0" }
|
||||||
|
|
||||||
# other
|
# other
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use bevy_asset::Handle;
|
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};
|
use crate::{Scene, SceneSpawner};
|
||||||
|
|
||||||
|
@ -23,3 +24,29 @@ impl SpawnSceneCommands for Commands {
|
||||||
self.add_command(SpawnScene { scene_handle })
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ pub use scene_loader::*;
|
||||||
pub use scene_spawner::*;
|
pub use scene_spawner::*;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{DynamicScene, Scene, SceneSpawner, SpawnSceneCommands};
|
pub use crate::{
|
||||||
|
DynamicScene, Scene, SceneSpawner, SpawnSceneAsChildCommands, SpawnSceneCommands,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{DynamicScene, Scene};
|
use crate::{DynamicScene, Scene};
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
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_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc};
|
||||||
|
use bevy_transform::prelude::Parent;
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -28,8 +29,9 @@ pub struct SceneSpawner {
|
||||||
spawned_instances: HashMap<InstanceId, InstanceInfo>,
|
spawned_instances: HashMap<InstanceId, InstanceInfo>,
|
||||||
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>,
|
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>,
|
||||||
dynamic_scenes_to_spawn: Vec<Handle<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_to_despawn: Vec<Handle<DynamicScene>>,
|
||||||
|
scenes_with_parent: Vec<(InstanceId, Entity)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -50,7 +52,14 @@ impl SceneSpawner {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(&mut self, scene_handle: Handle<Scene>) {
|
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>) {
|
pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) {
|
||||||
|
@ -147,7 +156,16 @@ impl SceneSpawner {
|
||||||
resources: &Resources,
|
resources: &Resources,
|
||||||
scene_handle: Handle<Scene>,
|
scene_handle: Handle<Scene>,
|
||||||
) -> Result<(), SceneSpawnError> {
|
) -> 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 {
|
let mut instance_info = InstanceInfo {
|
||||||
entity_map: EntityMap::default(),
|
entity_map: EntityMap::default(),
|
||||||
};
|
};
|
||||||
|
@ -256,11 +274,11 @@ impl SceneSpawner {
|
||||||
|
|
||||||
let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn);
|
let scenes_to_spawn = std::mem::take(&mut self.scenes_to_spawn);
|
||||||
|
|
||||||
for scene_handle in scenes_to_spawn {
|
for (scene_handle, instance_id) in scenes_to_spawn {
|
||||||
match self.spawn_sync(world, resources, scene_handle) {
|
match self.spawn_sync_internal(world, resources, scene_handle, instance_id) {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(SceneSpawnError::NonExistentRealScene { handle }) => {
|
Err(SceneSpawnError::NonExistentRealScene { handle }) => {
|
||||||
self.scenes_to_spawn.push(handle)
|
self.scenes_to_spawn.push((handle, instance_id))
|
||||||
}
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
}
|
}
|
||||||
|
@ -268,6 +286,24 @@ impl SceneSpawner {
|
||||||
|
|
||||||
Ok(())
|
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) {
|
pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
||||||
|
@ -293,4 +329,5 @@ pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
||||||
scene_spawner
|
scene_spawner
|
||||||
.update_spawned_scenes(world, resources, &updated_spawned_scenes)
|
.update_spawned_scenes(world, resources, &updated_spawned_scenes)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
scene_spawner.set_scene_instance_parent_sync(world);
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,10 @@ impl<'a> ChildBuilder<'a> {
|
||||||
self.commands.current_entity()
|
self.commands.current_entity()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent_entity(&self) -> Entity {
|
||||||
|
self.push_children.parent
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_bundle(
|
pub fn with_bundle(
|
||||||
&mut self,
|
&mut self,
|
||||||
components: impl DynamicBundle + Send + Sync + 'static,
|
components: impl DynamicBundle + Send + Sync + 'static,
|
||||||
|
@ -102,6 +106,11 @@ impl<'a> ChildBuilder<'a> {
|
||||||
func(current_entity);
|
func(current_entity);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
|
||||||
|
self.commands.add_command(command);
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait BuildChildren {
|
pub trait BuildChildren {
|
||||||
|
|
Loading…
Reference in a new issue