use crate::*;
#[cfg(feature = "nalgebra")]
use nalgebra::Matrix4;
#[derive(Clone, Default, Debug)]
pub struct Scene {
pub instance_physics_scene: Vec<Instance<PhysicsScene>>,
pub instance_visual_scene: Option<Instance<VisualScene>>,
pub extra: Vec<Extra>,
}
impl Scene {
pub fn new(instance_visual_scene: Instance<VisualScene>) -> Self {
Self {
instance_physics_scene: vec![],
instance_visual_scene: Some(instance_visual_scene),
extra: vec![],
}
}
}
impl XNode for Scene {
const NAME: &'static str = "scene";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
Ok(Scene {
instance_physics_scene: Instance::parse_list(&mut it)?,
instance_visual_scene: Instance::parse_opt(&mut it)?,
extra: Extra::parse_many(it)?,
})
}
}
impl XNodeWrite for Scene {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let e = Self::elem().start(w)?;
self.instance_physics_scene.write_to(w)?;
self.instance_visual_scene.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct VisualScene {
pub id: Option<String>,
pub name: Option<String>,
pub asset: Option<Box<Asset>>,
pub nodes: Vec<Node>,
pub evaluate_scene: Vec<EvaluateScene>,
pub extra: Vec<Extra>,
}
impl VisualScene {
pub fn new(id: impl Into<String>, name: Option<String>) -> Self {
Self {
id: Some(id.into()),
name,
asset: None,
nodes: vec![],
evaluate_scene: vec![],
extra: vec![],
}
}
}
impl XNode for VisualScene {
const NAME: &'static str = "visual_scene";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
Ok(VisualScene {
id: element.attr("id").map(Into::into),
name: element.attr("name").map(Into::into),
asset: Asset::parse_opt_box(&mut it)?,
nodes: Node::parse_list(&mut it)?,
evaluate_scene: EvaluateScene::parse_list(&mut it)?,
extra: Extra::parse_many(it)?,
})
}
}
impl XNodeWrite for VisualScene {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("id", &self.id);
e.opt_attr("name", &self.name);
let e = e.start(w)?;
self.asset.write_to(w)?;
self.nodes.write_to(w)?;
self.evaluate_scene.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
#[derive(Clone, Debug)]
pub struct Node {
pub id: Option<String>,
pub name: Option<String>,
pub sid: Option<String>,
pub ty: NodeType,
pub layer: Vec<String>,
pub asset: Option<Box<Asset>>,
pub transforms: Vec<Transform>,
pub instance_camera: Vec<Instance<Camera>>,
pub instance_controller: Vec<Instance<Controller>>,
pub instance_geometry: Vec<Instance<Geometry>>,
pub instance_light: Vec<Instance<Light>>,
pub instance_node: Vec<Instance<Node>>,
pub children: Vec<Node>,
pub extra: Vec<Extra>,
}
impl XNode for Node {
const NAME: &'static str = "node";
#[allow(clippy::eval_order_dependence)]
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
let extra;
Ok(Node {
id: element.attr("id").map(Into::into),
name: element.attr("name").map(Into::into),
sid: element.attr("sid").map(Into::into),
ty: parse_attr(element.attr("type"))?.unwrap_or_default(),
layer: element.attr("layer").map_or_else(Vec::new, |s| {
s.split_ascii_whitespace().map(|s| s.to_owned()).collect()
}),
asset: Asset::parse_opt_box(&mut it)?,
transforms: parse_list_many(&mut it, Transform::parse)?,
instance_camera: Instance::parse_list(&mut it)?,
instance_controller: Instance::parse_list(&mut it)?,
instance_geometry: Instance::parse_list(&mut it)?,
instance_light: Instance::parse_list(&mut it)?,
instance_node: Instance::parse_list(&mut it)?,
children: {
extra = Extra::parse_list(&mut it)?;
Node::parse_list(&mut it)?
},
extra: Extra::parse_append_many(extra, it)?,
})
}
}
impl XNodeWrite for Node {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("id", &self.id);
e.opt_attr("name", &self.name);
e.opt_attr("sid", &self.sid);
e.def_print_attr("type", self.ty, Default::default());
if let Some(s) = arr_to_string(&self.layer) {
e.attr("layer", &s)
}
if self.is_empty() {
e.end(w)
} else {
let e = e.start(w)?;
self.asset.write_to(w)?;
self.transforms.write_to(w)?;
self.instance_camera.write_to(w)?;
self.instance_controller.write_to(w)?;
self.instance_geometry.write_to(w)?;
self.instance_light.write_to(w)?;
self.instance_node.write_to(w)?;
self.children.write_to(w)?;
self.extra.write_to(w)?;
e.end(w)
}
}
}
impl CollectLocalMaps for Node {
fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
maps.insert(self);
self.children.collect_local_maps(maps);
}
}
impl Node {
pub fn new(id: impl Into<String>, name: Option<String>) -> Self {
Self {
id: Some(id.into()),
name,
sid: Default::default(),
ty: Default::default(),
layer: Default::default(),
asset: Default::default(),
transforms: Default::default(),
instance_camera: Default::default(),
instance_controller: Default::default(),
instance_geometry: Default::default(),
instance_light: Default::default(),
instance_node: Default::default(),
children: Default::default(),
extra: Default::default(),
}
}
pub fn push_transform(&mut self, transform: impl Into<Transform>) {
self.transforms.push(transform.into())
}
fn on_children<'a, E>(
&'a self,
f: &mut impl FnMut(&'a Self) -> Result<(), E>,
) -> Result<(), E> {
f(self)?;
for child in &self.children {
child.on_children(f)?
}
Ok(())
}
pub fn is_empty(&self) -> bool {
self.asset.is_none()
&& self.transforms.is_empty()
&& self.instance_camera.is_empty()
&& self.instance_controller.is_empty()
&& self.instance_geometry.is_empty()
&& self.instance_light.is_empty()
&& self.instance_node.is_empty()
&& self.children.is_empty()
&& self.extra.is_empty()
}
}
impl Traversable for Node {
fn traverse<'a, E>(
doc: &'a Document,
mut f: impl FnMut(&'a Node) -> Result<(), E>,
) -> Result<(), E> {
doc.library.iter().try_for_each(|elem| match elem {
LibraryElement::Nodes(lib) => lib.items.iter().try_for_each(|e| e.on_children(&mut f)),
LibraryElement::VisualScenes(lib) => lib
.items
.iter()
.try_for_each(|e| e.nodes.iter().try_for_each(|e| e.on_children(&mut f))),
_ => Ok(()),
})
}
}
#[cfg(feature = "nalgebra")]
impl Node {
pub fn prepend_transforms(&self, mat: &mut Matrix4<f32>) {
for t in &self.transforms {
t.prepend_to_matrix(mat)
}
}
pub fn append_transforms(&self, mat: &mut Matrix4<f32>) {
for t in self.transforms.iter().rev() {
t.append_to_matrix(mat)
}
}
pub fn transform_as_matrix(&self) -> Matrix4<f32> {
let mut mat = Matrix4::identity();
self.prepend_transforms(&mut mat);
mat
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum NodeType {
Node,
Joint,
}
impl Default for NodeType {
fn default() -> Self {
Self::Node
}
}
impl FromStr for NodeType {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"NODE" => Ok(Self::Node),
"JOINT" => Ok(Self::Joint),
_ => Err(()),
}
}
}
impl NodeType {
pub fn to_str(self) -> &'static str {
match self {
Self::Node => "NODE",
Self::Joint => "JOINT",
}
}
}
impl Display for NodeType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(self.to_str(), f)
}
}
#[derive(Clone, Debug)]
pub struct EvaluateScene {
pub name: Option<String>,
pub render: Vec<Render>,
}
impl EvaluateScene {
pub fn new(render: Vec<Render>) -> Self {
assert!(!render.is_empty());
Self { name: None, render }
}
}
impl XNode for EvaluateScene {
const NAME: &'static str = "evaluate_scene";
fn parse(element: &Element) -> Result<Self> {
debug_assert_eq!(element.name(), Self::NAME);
let mut it = element.children().peekable();
let res = EvaluateScene {
name: element.attr("name").map(Into::into),
render: Render::parse_list_n::<1>(&mut it)?,
};
finish(res, it)
}
}
impl XNodeWrite for EvaluateScene {
fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
let mut e = Self::elem();
e.opt_attr("name", &self.name);
let e = e.start(w)?;
self.render.write_to(w)?;
e.end(w)
}
}