2020-05-22 00:21:33 +00:00
|
|
|
use anyhow::Result;
|
2020-05-25 21:51:38 +00:00
|
|
|
use bevy_component_registry::ComponentRegistry;
|
2020-05-25 19:03:50 +00:00
|
|
|
use bevy_property::DynamicProperties;
|
|
|
|
use legion::prelude::World;
|
|
|
|
use serde::Serialize;
|
|
|
|
use std::num::Wrapping;
|
2020-05-24 05:07:17 +00:00
|
|
|
use thiserror::Error;
|
|
|
|
|
2020-05-25 02:36:01 +00:00
|
|
|
#[derive(Default)]
|
2020-05-24 05:07:17 +00:00
|
|
|
pub struct Scene {
|
2020-05-25 19:03:50 +00:00
|
|
|
pub entities: Vec<Entity>,
|
2020-05-22 22:25:31 +00:00
|
|
|
}
|
|
|
|
|
2020-05-25 02:36:01 +00:00
|
|
|
#[derive(Serialize)]
|
2020-05-25 19:03:50 +00:00
|
|
|
pub struct Entity {
|
|
|
|
pub id: u32,
|
2020-05-25 02:36:01 +00:00
|
|
|
pub components: Vec<DynamicProperties>,
|
|
|
|
}
|
|
|
|
|
2020-05-24 05:07:17 +00:00
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum SceneAddError {
|
|
|
|
#[error("Scene contains an unregistered component.")]
|
|
|
|
UnregisteredComponent { type_name: String },
|
2020-05-22 22:25:31 +00:00
|
|
|
}
|
|
|
|
|
2020-05-24 05:07:17 +00:00
|
|
|
impl Scene {
|
|
|
|
pub fn from_world(world: &World, component_registry: &ComponentRegistry) -> Self {
|
|
|
|
let mut scene = Scene::default();
|
|
|
|
for archetype in world.storage().archetypes() {
|
|
|
|
for chunkset in archetype.chunksets() {
|
|
|
|
for component_storage in chunkset.occupied() {
|
|
|
|
let mut entities = Vec::new();
|
|
|
|
for (component_type_id, _component_meta) in archetype.description().components()
|
|
|
|
{
|
|
|
|
if let Some(component_registration) =
|
|
|
|
component_registry.get(component_type_id)
|
|
|
|
{
|
|
|
|
let component_resource_set =
|
|
|
|
component_storage.components(*component_type_id).unwrap();
|
|
|
|
for (index, entity) in component_storage.entities().iter().enumerate() {
|
|
|
|
if index == entities.len() {
|
2020-05-25 19:03:50 +00:00
|
|
|
entities.push(Entity {
|
|
|
|
id: entity.index(),
|
2020-05-24 05:07:17 +00:00
|
|
|
components: Vec::new(),
|
|
|
|
})
|
|
|
|
}
|
2020-05-22 22:25:31 +00:00
|
|
|
|
2020-05-24 05:07:17 +00:00
|
|
|
let properties = (component_registration.component_properties_fn)(
|
|
|
|
&component_resource_set,
|
|
|
|
index,
|
|
|
|
);
|
2020-05-22 00:21:33 +00:00
|
|
|
|
2020-05-24 05:07:17 +00:00
|
|
|
entities[index].components.push(properties.to_dynamic());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-05-22 00:21:33 +00:00
|
|
|
|
2020-05-24 05:07:17 +00:00
|
|
|
scene.entities.extend(entities.drain(..));
|
|
|
|
}
|
|
|
|
}
|
2020-05-22 00:21:33 +00:00
|
|
|
}
|
2020-05-24 05:07:17 +00:00
|
|
|
|
|
|
|
scene
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_to_world(
|
|
|
|
&self,
|
|
|
|
world: &mut World,
|
|
|
|
component_registry: &ComponentRegistry,
|
|
|
|
) -> Result<(), SceneAddError> {
|
|
|
|
world.entity_allocator.push_next_ids(
|
|
|
|
self.entities
|
|
|
|
.iter()
|
2020-05-25 19:03:50 +00:00
|
|
|
.map(|e| legion::prelude::Entity::new(e.id, Wrapping(1))),
|
2020-05-24 05:07:17 +00:00
|
|
|
);
|
|
|
|
for scene_entity in self.entities.iter() {
|
|
|
|
// TODO: use EntityEntry when legion refactor is finished
|
|
|
|
let entity = world.insert((), vec![()])[0];
|
|
|
|
for component in scene_entity.components.iter() {
|
|
|
|
let component_registration = component_registry
|
|
|
|
.get_with_full_name(&component.type_name)
|
|
|
|
.ok_or_else(|| SceneAddError::UnregisteredComponent {
|
|
|
|
type_name: component.type_name.to_string(),
|
|
|
|
})?;
|
|
|
|
(component_registration.component_add_fn)(world, entity, component);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2020-05-22 00:21:33 +00:00
|
|
|
}
|
2020-05-26 00:50:17 +00:00
|
|
|
|
|
|
|
// TODO: move to AssetSaver when it is implemented
|
|
|
|
pub fn serialize_ron(&self) -> Result<String, ron::Error> {
|
|
|
|
let pretty_config = ron::ser::PrettyConfig::default()
|
|
|
|
.with_decimal_floats(true)
|
|
|
|
.with_new_line("\n".to_string());
|
|
|
|
let mut buf = Vec::new();
|
|
|
|
let mut serializer = ron::ser::Serializer::new(&mut buf, Some(pretty_config), true)?;
|
|
|
|
self.serialize(&mut serializer)?;
|
|
|
|
Ok(String::from_utf8(buf).unwrap())
|
|
|
|
}
|
2020-05-22 00:21:33 +00:00
|
|
|
}
|