use crate::errors::{Error, NativeError};
use crate::scene::{Parent};
use specs::prelude::*;
use super::{load_gltf, GltfResource};
pub enum GltfSceneRoot <'a> {
Index(usize),
NodeList(&'a [usize])
}
pub(crate) fn setup_gltf( world:&mut World, gltf_resource:GltfResource, scene_root:GltfSceneRoot) -> Result<(), Error> {
world.register::<GltfNode>();
create_hierarchy_from_gltf(world, gltf_resource.gltf, scene_root)
}
fn create_hierarchy_from_gltf(world:&mut World, gltf:gltf::Document, scene_root:GltfSceneRoot) -> Result<(), Error> {
let root_nodes = match scene_root {
GltfSceneRoot::NodeList(list) => {
let mut gltf_nodes = Vec::with_capacity(list.len());
for index in list.iter() {
let index = *index;
match gltf.nodes().nth(index) {
Some(node) => gltf_nodes.push(node),
None => return Err(NativeError::NodeMissing(index).into())
}
}
Ok(gltf_nodes)
},
GltfSceneRoot::Index(scene_index) => {
gltf
.scenes()
.nth(scene_index)
.map(|scene| scene.nodes().collect::<Vec<gltf::Node>>())
.ok_or(NativeError::SceneMissing)
}
}?;
_create_hierarchy_from_gltf(root_nodes, None, world)
}
fn _create_hierarchy_from_gltf<'a, I>(level_nodes:I, parent: Option<(&gltf::Node, Entity)>, world:&mut World) -> Result<(), Error>
where
I: IntoIterator<Item = gltf::Node<'a>>
{
for node in level_nodes.into_iter() {
let entity = world.create_entity().build();
world
.write_storage::<GltfNode>()
.insert(entity, GltfNode { index: node.index() })?;
if let Some((parent_node, parent_entity)) = parent {
world
.write_storage::<Parent>()
.insert(entity, Parent {entity: parent_entity})?;
}
let children = node.children();
if children.len() > 0 {
_create_hierarchy_from_gltf(children, Some((&node, entity)), world)?;
}
}
Ok(())
}
pub struct GltfNode {
pub index: usize,
}
impl Component for GltfNode {
type Storage = VecStorage<Self>;
}