use rinecs::{WriteAndParent, ReadNot, Not};
use super::{DynamicTransformation, Bone };
use rin::graphics::{Node, NodeMut, NodeRef, node};
use na::{one, Pnt3, UnitQuat, Vec3};
use serde::ser::Serialize;
#[derive(Clone, HierarchicalComponent, Debug, Serialize, Deserialize)]
#[debug_custom]
pub struct Transformation{
pub node: Node,
pub parent_bone: Option<String>,
pub is_bone: bool,
has_changed: bool,
}
impl rinecs::DebugParameter for Transformation{
fn debug<S: serde::Serializer>(&self, serializer: S) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>{
#[derive(Serialize)]
struct Position{
x: f32,
y: f32,
z: f32,
}
#[derive(Serialize)]
struct Orientation{
x: f32,
y: f32,
z: f32,
w: f32,
}
#[derive(Serialize)]
struct Scale{
x: f32,
y: f32,
z: f32,
}
#[derive(Serialize)]
struct Transformation{
position: Position,
orientation: Orientation,
scale: Scale,
global_position: Position,
global_orientation: Orientation,
global_scale: Scale,
}
let p = self.position();
let q = self.orientation();
let s = self.scale();
let gp = self.global_position();
let gq = self.global_orientation();
let gs = self.global_scale();
Transformation{
position: Position{
x: p[0], y: p[1], z: p[2]
},
orientation: Orientation{
x: q[0], y: q[1], z: q[2], w: q[3]
},
scale: Scale{
x: s.x, y: s.y, z: s.z
},
global_position: Position{
x: gp[0], y: gp[1], z: gp[2]
},
global_orientation: Orientation{
x: gq[0], y: gq[1], z: gq[2], w: gq[3]
},
global_scale: Scale{
x: gs.x, y: gs.y, z: gs.z
},
}.serialize(serializer)
}
}
impl Default for Transformation{
fn default() -> Transformation{
Transformation{ node: one(), parent_bone: None, is_bone: false, has_changed: false,}
}
}
impl Transformation{
pub fn new(pos: Pnt3, rot: UnitQuat, scale: Vec3) -> Transformation{
Transformation{ node: Node::new(pos, rot, scale), parent_bone: None, is_bone: false, has_changed: false,}
}
pub fn from_position(pos: Pnt3) -> Transformation{
Transformation{ node: Node::new(pos, one(), vec3!(1.)), parent_bone: None, is_bone: false, has_changed: false,}
}
pub fn from_node(node: Node) -> Transformation{
Transformation{ node: node, parent_bone: None, is_bone: false, has_changed: false,}
}
pub fn from_node_parent_bone(node: Node, parent_bone: String) -> Transformation{
Transformation{ node, parent_bone: Some(parent_bone), is_bone: false, has_changed: false,}
}
pub fn has_changed(&self) -> bool{
self.has_changed
}
pub fn into_parameter(&self) -> String{
let pos = self.node.global_position();
let quat = self.node.global_orientation().into_inner();
let scale = self.node.global_scale();
format!("Transformation {{
position: Pnt3 {{
x: {},
y: {},
z: {},
}},
orientation: UnitQuat {{
x: {},
y: {},
z: {},
w: {},
}},
scale: Vec3 {{
x: {},
y: {},
z: {},
}}
}}", pos.x, pos.y, pos.z,
quat.coords.x, quat.coords.y, quat.coords.z, quat.coords.w,
scale.x, scale.y, scale.z)
}
}
impl NodeRef for Transformation{
fn node(&self) -> &Node{
&self.node
}
}
impl NodeMut for Transformation{
fn node_mut(&mut self) -> &mut Node{
&mut self.node
}
fn update_with_parent_flags(&mut self, parent: Option<&Node>, flags: node::Flags) -> bool{
self.has_changed |= self.node.update_with_parent_flags(parent, flags);
self.has_changed
}
}
pub fn update_dynamic(entities: rinecs::Entities, _: rinecs::Resources){
for ((trafo, parent), _) in entities.ordered_iter_for::<(WriteAndParent<Transformation>, ReadNot<DynamicTransformation, Bone>)>(){
trafo.has_changed = false;
trafo.update_with_parent(parent.map(|t| &t.node));
}
}
pub fn update_static(entities: rinecs::Entities, _: rinecs::Resources){
for ((trafo, parent), _) in entities.ordered_iter_for::<(WriteAndParent<Transformation>, Not<DynamicTransformation>)>(){
trafo.has_changed = false;
trafo.update_with_parent(parent.map(|t| &t.node));
}
}
pub fn update_all(entities: rinecs::Entities, _: rinecs::Resources){
for ((trafo, parent), _) in entities.ordered_iter_for::<(WriteAndParent<Transformation>, Not<Bone>)>(){
trafo.has_changed = false;
trafo.update_with_parent(parent.map(|t| &t.node));
}
}