2020-10-18 20:48:15 +00:00
|
|
|
use crate::{DynamicScene, Scene};
|
2020-07-17 01:47:51 +00:00
|
|
|
use bevy_app::prelude::*;
|
2020-05-29 19:56:32 +00:00
|
|
|
use bevy_asset::{AssetEvent, Assets, Handle};
|
2020-10-18 20:48:15 +00:00
|
|
|
use bevy_ecs::{EntityMap, Resources, World};
|
2020-11-28 00:39:59 +00:00
|
|
|
use bevy_reflect::{ReflectComponent, ReflectMapEntities, TypeRegistryArc};
|
2020-09-18 00:16:38 +00:00
|
|
|
use bevy_utils::HashMap;
|
2020-05-29 19:56:32 +00:00
|
|
|
use thiserror::Error;
|
2020-05-29 22:51:36 +00:00
|
|
|
use uuid::Uuid;
|
|
|
|
|
2020-10-08 18:43:01 +00:00
|
|
|
#[derive(Debug)]
|
2020-05-29 22:51:36 +00:00
|
|
|
struct InstanceInfo {
|
2020-10-18 20:48:15 +00:00
|
|
|
entity_map: EntityMap,
|
2020-05-29 22:51:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
|
|
|
struct InstanceId(Uuid);
|
|
|
|
|
|
|
|
impl InstanceId {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
InstanceId(Uuid::new_v4())
|
|
|
|
}
|
|
|
|
}
|
2020-06-04 06:53:00 +00:00
|
|
|
|
|
|
|
#[derive(Default)]
|
2020-05-29 19:56:32 +00:00
|
|
|
pub struct SceneSpawner {
|
2020-05-29 22:51:36 +00:00
|
|
|
spawned_scenes: HashMap<Handle<Scene>, Vec<InstanceId>>,
|
2020-10-18 20:48:15 +00:00
|
|
|
spawned_dynamic_scenes: HashMap<Handle<DynamicScene>, Vec<InstanceId>>,
|
2020-05-29 22:51:36 +00:00
|
|
|
spawned_instances: HashMap<InstanceId, InstanceInfo>,
|
2020-10-18 20:48:15 +00:00
|
|
|
scene_asset_event_reader: EventReader<AssetEvent<DynamicScene>>,
|
|
|
|
dynamic_scenes_to_spawn: Vec<Handle<DynamicScene>>,
|
|
|
|
scenes_to_spawn: Vec<Handle<Scene>>,
|
|
|
|
scenes_to_despawn: Vec<Handle<DynamicScene>>,
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum SceneSpawnError {
|
2020-12-02 19:31:16 +00:00
|
|
|
#[error("scene contains an unregistered component")]
|
2020-05-29 19:56:32 +00:00
|
|
|
UnregisteredComponent { type_name: String },
|
2020-12-02 19:31:16 +00:00
|
|
|
#[error("scene does not exist")]
|
2020-10-18 20:48:15 +00:00
|
|
|
NonExistentScene { handle: Handle<DynamicScene> },
|
2020-12-02 19:31:16 +00:00
|
|
|
#[error("scene does not exist")]
|
2020-10-18 20:48:15 +00:00
|
|
|
NonExistentRealScene { handle: Handle<Scene> },
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SceneSpawner {
|
2020-10-18 20:48:15 +00:00
|
|
|
pub fn spawn_dynamic(&mut self, scene_handle: Handle<DynamicScene>) {
|
|
|
|
self.dynamic_scenes_to_spawn.push(scene_handle);
|
|
|
|
}
|
|
|
|
|
2020-09-18 00:16:38 +00:00
|
|
|
pub fn spawn(&mut self, scene_handle: Handle<Scene>) {
|
2020-10-18 20:48:15 +00:00
|
|
|
self.scenes_to_spawn.push(scene_handle);
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
|
2020-10-18 20:48:15 +00:00
|
|
|
pub fn despawn(&mut self, scene_handle: Handle<DynamicScene>) {
|
2020-09-18 00:16:38 +00:00
|
|
|
self.scenes_to_despawn.push(scene_handle);
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
|
2020-09-18 00:16:38 +00:00
|
|
|
pub fn despawn_sync(
|
2020-09-06 20:06:21 +00:00
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
2020-10-18 20:48:15 +00:00
|
|
|
scene_handle: Handle<DynamicScene>,
|
2020-09-06 20:06:21 +00:00
|
|
|
) -> Result<(), SceneSpawnError> {
|
2020-10-18 20:48:15 +00:00
|
|
|
if let Some(instance_ids) = self.spawned_dynamic_scenes.get(&scene_handle) {
|
2020-09-06 20:06:21 +00:00
|
|
|
for instance_id in instance_ids {
|
|
|
|
if let Some(instance) = self.spawned_instances.get(&instance_id) {
|
|
|
|
for entity in instance.entity_map.values() {
|
2020-10-18 20:48:15 +00:00
|
|
|
let _ = world.despawn(entity); // Ignore the result, despawn only cares if it exists.
|
2020-09-06 20:06:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-18 20:48:15 +00:00
|
|
|
self.spawned_dynamic_scenes.remove(&scene_handle);
|
2020-09-06 20:06:21 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-10-18 20:48:15 +00:00
|
|
|
pub fn spawn_dynamic_sync(
|
2020-05-29 22:51:36 +00:00
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
|
|
|
resources: &Resources,
|
2020-10-18 20:48:15 +00:00
|
|
|
scene_handle: &Handle<DynamicScene>,
|
2020-05-29 22:51:36 +00:00
|
|
|
) -> Result<(), SceneSpawnError> {
|
|
|
|
let instance_id = InstanceId::new();
|
|
|
|
let mut instance_info = InstanceInfo {
|
2020-10-18 20:48:15 +00:00
|
|
|
entity_map: EntityMap::default(),
|
2020-05-29 22:51:36 +00:00
|
|
|
};
|
2020-10-18 20:48:15 +00:00
|
|
|
Self::spawn_dynamic_internal(world, resources, scene_handle, &mut instance_info)?;
|
2020-05-29 22:51:36 +00:00
|
|
|
self.spawned_instances.insert(instance_id, instance_info);
|
2020-06-04 03:08:20 +00:00
|
|
|
let spawned = self
|
2020-10-18 20:48:15 +00:00
|
|
|
.spawned_dynamic_scenes
|
|
|
|
.entry(scene_handle.clone())
|
2020-08-16 07:30:04 +00:00
|
|
|
.or_insert_with(Vec::new);
|
2020-05-29 22:51:36 +00:00
|
|
|
spawned.push(instance_id);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-10-18 20:48:15 +00:00
|
|
|
fn spawn_dynamic_internal(
|
2020-05-29 22:51:36 +00:00
|
|
|
world: &mut World,
|
|
|
|
resources: &Resources,
|
2020-10-18 20:48:15 +00:00
|
|
|
scene_handle: &Handle<DynamicScene>,
|
2020-09-18 00:16:38 +00:00
|
|
|
instance_info: &mut InstanceInfo,
|
2020-05-29 19:56:32 +00:00
|
|
|
) -> Result<(), SceneSpawnError> {
|
2020-11-28 00:39:59 +00:00
|
|
|
let type_registry = resources.get::<TypeRegistryArc>().unwrap();
|
|
|
|
let type_registry = type_registry.read();
|
2020-10-18 20:48:15 +00:00
|
|
|
let scenes = resources.get::<Assets<DynamicScene>>().unwrap();
|
2020-05-29 19:56:32 +00:00
|
|
|
let scene = scenes
|
2020-10-18 20:48:15 +00:00
|
|
|
.get(scene_handle)
|
|
|
|
.ok_or_else(|| SceneSpawnError::NonExistentScene {
|
|
|
|
handle: scene_handle.clone_weak(),
|
2020-05-29 19:56:32 +00:00
|
|
|
})?;
|
|
|
|
|
|
|
|
for scene_entity in scene.entities.iter() {
|
2020-09-18 00:16:38 +00:00
|
|
|
let entity = *instance_info
|
|
|
|
.entity_map
|
2020-10-18 20:48:15 +00:00
|
|
|
// TODO: use Entity type directly in scenes to properly encode generation / avoid the need to patch things up?
|
|
|
|
.entry(bevy_ecs::Entity::new(scene_entity.entity))
|
2020-09-18 00:16:38 +00:00
|
|
|
.or_insert_with(|| world.reserve_entity());
|
|
|
|
for component in scene_entity.components.iter() {
|
2020-11-28 00:39:59 +00:00
|
|
|
let registration = type_registry
|
|
|
|
.get_with_name(component.type_name())
|
|
|
|
.ok_or_else(|| SceneSpawnError::UnregisteredComponent {
|
|
|
|
type_name: component.type_name().to_string(),
|
2020-09-18 00:16:38 +00:00
|
|
|
})?;
|
2020-11-28 00:39:59 +00:00
|
|
|
let reflect_component =
|
|
|
|
registration.data::<ReflectComponent>().ok_or_else(|| {
|
|
|
|
SceneSpawnError::UnregisteredComponent {
|
|
|
|
type_name: component.type_name().to_string(),
|
|
|
|
}
|
|
|
|
})?;
|
|
|
|
if world.has_component_type(entity, registration.type_id()) {
|
|
|
|
if registration.short_name() != "Camera" {
|
|
|
|
reflect_component.apply_component(world, entity, &**component);
|
2020-08-03 02:15:41 +00:00
|
|
|
}
|
2020-09-18 00:16:38 +00:00
|
|
|
} else {
|
2020-11-28 00:39:59 +00:00
|
|
|
reflect_component.add_component(world, resources, entity, &**component);
|
2020-08-03 02:15:41 +00:00
|
|
|
}
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-29 22:51:36 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2020-05-29 19:56:32 +00:00
|
|
|
|
2020-10-18 20:48:15 +00:00
|
|
|
pub fn spawn_sync(
|
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
|
|
|
resources: &Resources,
|
|
|
|
scene_handle: Handle<Scene>,
|
|
|
|
) -> Result<(), SceneSpawnError> {
|
|
|
|
let instance_id = InstanceId::new();
|
|
|
|
let mut instance_info = InstanceInfo {
|
|
|
|
entity_map: EntityMap::default(),
|
|
|
|
};
|
2020-11-28 00:39:59 +00:00
|
|
|
let type_registry = resources.get::<TypeRegistryArc>().unwrap();
|
|
|
|
let type_registry = type_registry.read();
|
2020-10-18 20:48:15 +00:00
|
|
|
let scenes = resources.get::<Assets<Scene>>().unwrap();
|
|
|
|
let scene =
|
|
|
|
scenes
|
|
|
|
.get(&scene_handle)
|
|
|
|
.ok_or_else(|| SceneSpawnError::NonExistentRealScene {
|
|
|
|
handle: scene_handle.clone(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
for archetype in scene.world.archetypes() {
|
|
|
|
for scene_entity in archetype.iter_entities() {
|
|
|
|
let entity = *instance_info
|
|
|
|
.entity_map
|
|
|
|
.entry(*scene_entity)
|
|
|
|
.or_insert_with(|| world.reserve_entity());
|
|
|
|
for type_info in archetype.types() {
|
2020-11-28 00:39:59 +00:00
|
|
|
if let Some(registration) = type_registry.get(type_info.id()) {
|
|
|
|
if let Some(component_reflect) = registration.data::<ReflectComponent>() {
|
|
|
|
component_reflect.copy_component(
|
|
|
|
&scene.world,
|
|
|
|
world,
|
|
|
|
resources,
|
|
|
|
*scene_entity,
|
|
|
|
entity,
|
|
|
|
);
|
|
|
|
}
|
2020-10-18 20:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 00:39:59 +00:00
|
|
|
for registration in type_registry.iter() {
|
|
|
|
if let Some(map_entities_reflect) = registration.data::<ReflectMapEntities>() {
|
|
|
|
map_entities_reflect
|
|
|
|
.map_entities(world, &instance_info.entity_map)
|
|
|
|
.unwrap();
|
|
|
|
}
|
2020-10-18 20:48:15 +00:00
|
|
|
}
|
|
|
|
self.spawned_instances.insert(instance_id, instance_info);
|
|
|
|
let spawned = self
|
|
|
|
.spawned_scenes
|
|
|
|
.entry(scene_handle)
|
|
|
|
.or_insert_with(Vec::new);
|
|
|
|
spawned.push(instance_id);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-06-04 03:08:20 +00:00
|
|
|
pub fn update_spawned_scenes(
|
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
|
|
|
resources: &Resources,
|
2020-10-18 20:48:15 +00:00
|
|
|
scene_handles: &[Handle<DynamicScene>],
|
2020-06-04 03:08:20 +00:00
|
|
|
) -> Result<(), SceneSpawnError> {
|
2020-05-29 22:51:36 +00:00
|
|
|
for scene_handle in scene_handles {
|
2020-10-18 20:48:15 +00:00
|
|
|
if let Some(spawned_instances) = self.spawned_dynamic_scenes.get(scene_handle) {
|
2020-05-29 22:51:36 +00:00
|
|
|
for instance_id in spawned_instances.iter() {
|
|
|
|
if let Some(instance_info) = self.spawned_instances.get_mut(instance_id) {
|
2020-10-18 20:48:15 +00:00
|
|
|
Self::spawn_dynamic_internal(
|
|
|
|
world,
|
|
|
|
resources,
|
|
|
|
scene_handle,
|
|
|
|
instance_info,
|
|
|
|
)?;
|
2020-05-29 22:51:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-29 19:56:32 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-09-18 00:16:38 +00:00
|
|
|
pub fn despawn_queued_scenes(&mut self, world: &mut World) -> Result<(), SceneSpawnError> {
|
|
|
|
let scenes_to_despawn = std::mem::take(&mut self.scenes_to_despawn);
|
2020-09-06 20:06:21 +00:00
|
|
|
|
2020-09-18 00:16:38 +00:00
|
|
|
for scene_handle in scenes_to_despawn {
|
|
|
|
self.despawn_sync(world, scene_handle)?;
|
2020-09-06 20:06:21 +00:00
|
|
|
}
|
2020-05-29 22:51:36 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-06-04 03:08:20 +00:00
|
|
|
pub fn spawn_queued_scenes(
|
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
|
|
|
resources: &Resources,
|
|
|
|
) -> Result<(), SceneSpawnError> {
|
2020-10-18 20:48:15 +00:00
|
|
|
let scenes_to_spawn = std::mem::take(&mut self.dynamic_scenes_to_spawn);
|
2020-09-06 20:06:21 +00:00
|
|
|
|
2020-05-29 22:51:36 +00:00
|
|
|
for scene_handle in scenes_to_spawn {
|
2020-10-18 20:48:15 +00:00
|
|
|
match self.spawn_dynamic_sync(world, resources, &scene_handle) {
|
2020-05-29 22:51:36 +00:00
|
|
|
Ok(_) => {}
|
|
|
|
Err(SceneSpawnError::NonExistentScene { .. }) => {
|
2020-10-18 20:48:15 +00:00
|
|
|
self.dynamic_scenes_to_spawn.push(scene_handle)
|
|
|
|
}
|
|
|
|
Err(err) => return Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(SceneSpawnError::NonExistentRealScene { handle }) => {
|
|
|
|
self.scenes_to_spawn.push(handle)
|
2020-05-29 22:51:36 +00:00
|
|
|
}
|
|
|
|
Err(err) => return Err(err),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn scene_spawner_system(world: &mut World, resources: &mut Resources) {
|
|
|
|
let mut scene_spawner = resources.get_mut::<SceneSpawner>().unwrap();
|
2020-10-18 20:48:15 +00:00
|
|
|
let scene_asset_events = resources.get::<Events<AssetEvent<DynamicScene>>>().unwrap();
|
2020-05-29 19:56:32 +00:00
|
|
|
|
2020-05-29 22:51:36 +00:00
|
|
|
let mut updated_spawned_scenes = Vec::new();
|
2020-05-29 19:56:32 +00:00
|
|
|
for event in scene_spawner
|
|
|
|
.scene_asset_event_reader
|
|
|
|
.iter(&scene_asset_events)
|
|
|
|
{
|
|
|
|
if let AssetEvent::Modified { handle } = event {
|
2020-10-18 20:48:15 +00:00
|
|
|
if scene_spawner.spawned_dynamic_scenes.contains_key(handle) {
|
|
|
|
updated_spawned_scenes.push(handle.clone_weak());
|
2020-05-29 22:51:36 +00:00
|
|
|
}
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-18 00:16:38 +00:00
|
|
|
scene_spawner.despawn_queued_scenes(world).unwrap();
|
2020-05-29 22:51:36 +00:00
|
|
|
scene_spawner.spawn_queued_scenes(world, resources).unwrap();
|
2020-06-04 03:08:20 +00:00
|
|
|
scene_spawner
|
|
|
|
.update_spawned_scenes(world, resources, &updated_spawned_scenes)
|
|
|
|
.unwrap();
|
2020-05-29 19:56:32 +00:00
|
|
|
}
|