use rinecs::Resources;
use rin::math::*;
use crate::time::Clock;
use std::collections::HashMap;
use std::borrow::Borrow;
use std::fmt::{self, Debug};
use std::sync::mpsc;
pub trait ActionExt {
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>;
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>;
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>;
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>;
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>;
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> ;
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32>;
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool>;
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool>;
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>;
fn name(&self) -> &str;
fn should_root_motion(&self) -> bool;
fn update(&mut self){}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>);
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionBlend<A1, A2>{
action1: A1,
action2: A2,
weight1: f32,
weight2: f32,
name: String,
}
impl<A1: Clone, A2: Clone> Clone for ActionBlend<A1, A2>{
fn clone(&self) -> ActionBlend<A1, A2>{
ActionBlend{
action1: self.action1.clone(),
action2: self.action2.clone(),
weight1: self.weight1,
weight2: self.weight2,
name: self.name.clone(),
}
}
}
impl<A1: ActionExt, A2: ActionExt> ActionBlend<A1, A2>{
pub fn new(action1: A1, action2: A2, weight: f32) -> ActionBlend<A1, A2>{
ActionBlend{
name: action1.name().to_owned() + "_x_" + action2.name(),
action1,
action2,
weight1: weight,
weight2: 1. - weight,
}
}
pub fn set_weight(&mut self, weight: f32){
self.weight1 = weight;
self.weight2 = 1. - weight;
}
pub fn into_actions(self) -> (A1, A2){
(self.action1, self.action2)
}
pub fn action1(&self) -> &A1{
&self.action1
}
pub fn action2(&self) -> &A2{
&self.action2
}
}
impl<A1: ActionExt, A2: ActionExt> ActionExt for ActionBlend<A1, A2>{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
if self.weight1 == 0. {
self.action1.orientation_at(object, t, current_value)
}else if self.weight1 == 1.{
self.action2.orientation_at(object, t, current_value)
}else{
let q1 = self.action1.borrow().orientation_at(object, t, current_value);
let q2 = self.action2.borrow().orientation_at(object, t, current_value);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1.slerp(&q2, self.weight1))
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
if self.weight1 == 0. {
self.action1.orientation_from_axis_angle_at(object, t, current_value)
}else if self.weight1 == 1.{
self.action2.orientation_from_axis_angle_at(object, t, current_value)
}else{
let q1 = self.action1.borrow().orientation_from_axis_angle_at(object, t, current_value);
let q2 = self.action2.borrow().orientation_from_axis_angle_at(object, t, current_value);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1.slerp(&q2, self.weight1))
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
if self.weight1 == 0. {
self.action1.orientation_from_euler_at(object, t, current_value, rot_order)
}else if self.weight1 == 1.{
self.action2.orientation_from_euler_at(object, t, current_value, rot_order)
}else{
let q1 = self.action1.borrow().orientation_from_euler_at(object, t, current_value, rot_order);
let q2 = self.action2.borrow().orientation_from_euler_at(object, t, current_value, rot_order);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1.slerp(&q2, self.weight1))
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
if self.weight1 == 0. {
self.action1.location_at(object, t, current_value)
}else if self.weight1 == 1.{
self.action2.location_at(object, t, current_value)
}else{
let p1 = self.action1.borrow().location_at(object, t, current_value);
let p2 = self.action2.borrow().location_at(object, t, current_value);
match (p1, p2){
(Some(p1), Some(p2)) => {
Some(lerp(p1.to_vec(), p2.to_vec(), self.weight1).to_pnt())
}
(Some(p1), None) => {
Some(p1 * self.weight2)
}
(None, Some(p2)) => {
Some(p2 * self.weight1)
}
(None, None) => {
None
}
}
}
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
if self.weight1 == 0. {
self.action1.scale_at(object, t, current_value)
}else if self.weight1 == 1.{
self.action2.scale_at(object, t, current_value)
}else{
let s1 = self.action1.borrow().scale_at(object, t, current_value);
let s2 = self.action2.borrow().scale_at(object, t, current_value);
match (s1, s2){
(Some(s1), Some(s2)) => {
Some(lerp(s1, s2, self.weight1))
}
(Some(s1), None) => {
Some(s1 * self.weight2)
}
(None, Some(s2)) => {
Some(s2 * self.weight1)
}
(None, None) => {
None
}
}
}
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
unimplemented!()
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
if self.weight1 == 0. {
self.action1.keyblock_at(keyblock, t)
}else if self.weight1 == 1.{
self.action2.keyblock_at(keyblock, t)
}else{
let k1 = self.action1.borrow().keyblock_at(keyblock, t);
let k2 = self.action2.borrow().keyblock_at(keyblock, t);
match (k1, k2){
(Some(k1), Some(k2)) => {
Some(lerp(k1, k2, self.weight1))
}
(Some(k1), None) => {
Some(k1 * self.weight2)
}
(None, Some(k2)) => {
Some(k2 * self.weight1)
}
(None, None) => {
None
}
}
}
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
if self.weight1 == 0. {
self.action1.hide_view_at(object, t)
}else if self.weight1 == 1.{
self.action2.hide_view_at(object, t)
}else{
let h1 = self.action1.borrow().hide_view_at(object, t);
let h2 = self.action2.borrow().hide_view_at(object, t);
match (h1, h2){
(Some(h1), Some(h2)) => {
Some(if self.weight1 < 0.5 { h1 } else { h2 })
}
(Some(h1), None) => {
Some(h1)
}
(None, Some(h2)) => {
Some(h2)
}
(None, None) => {
None
}
}
}
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
if self.weight1 == 0. {
self.action1.hide_render_at(object, t)
}else if self.weight1 == 1.{
self.action2.hide_render_at(object, t)
}else{
let h1 = self.action1.borrow().hide_render_at(object, t);
let h2 = self.action2.borrow().hide_render_at(object, t);
match (h1, h2){
(Some(h1), Some(h2)) => {
Some(if self.weight1 < 0.5 { h1 } else { h2 })
}
(Some(h1), None) => {
Some(h1)
}
(None, Some(h2)) => {
Some(h2)
}
(None, None) => {
None
}
}
}
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
if self.weight1 == 0. {
self.action2.reset_root_motion_positions(prev_positions);
self.action1.root_motion_location_at(object, t, current_value, prev_positions)
}else if self.weight1 == 1.{
self.action1.reset_root_motion_positions(prev_positions);
self.action2.root_motion_location_at(object, t, current_value, prev_positions)
}else{
let p1 = self.action1.borrow().location_at(object, t, current_value);
let p2 = self.action2.borrow().location_at(object, t, current_value);
let p = match (p1, p2){
(Some(p1), Some(p2)) => {
Some(lerp(p1.to_vec(), p2.to_vec(), self.weight1).to_pnt())
}
(Some(p1), None) => {
Some(p1 * self.weight2)
}
(None, Some(p2)) => {
Some(p2 * self.weight1)
}
(None, None) => {
None
}
};
if let Some(p) = p{
let prev_p1 = prev_positions.get(self.action1.borrow().name()).and_then(|p| *p);
let prev_p2 = prev_positions.get(self.action2.borrow().name()).and_then(|p| *p);
let delta1 = match (p1, prev_p1){
(Some(p1), Some(prev_p1)) => {
Some(p1 - prev_p1)
}
_ => None
};
let delta2 = match (p2, prev_p2){
(Some(p2), Some(prev_p2)) => {
Some(p2 - prev_p2)
}
_ => None
};
let delta = match (delta1, delta2){
(Some(delta1), Some(delta2)) => {
Some(lerp(delta1, delta2, self.weight1))
}
(Some(delta1), None) => {
Some(delta1 * self.weight2)
}
(None, Some(delta2)) => {
Some(delta2 * self.weight1)
}
(None, None) => {
None
}
};
let delta = delta.unwrap_or_else(||{
vec3!(0.)
});
prev_positions.insert(self.action1.borrow().name().to_owned(), p1);
prev_positions.insert(self.action2.borrow().name().to_owned(), p2);
Some((p, delta))
}else{
None
}
}
}
fn name(&self) -> &str{
&self.name
}
fn should_root_motion(&self) -> bool{
if self.weight1 == 0. {
self.action1.should_root_motion()
}else if self.weight1 == 1.{
self.action2.should_root_motion()
}else{
self.action1.should_root_motion() || self.action2.should_root_motion()
}
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
prev_positions.remove(self.action1.name());
prev_positions.remove(self.action2.name());
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ActionMix<A1, A2>{
action1: A1,
action2: A2,
name: String,
}
impl<A1: Clone, A2: Clone> Clone for ActionMix<A1, A2>{
fn clone(&self) -> ActionMix<A1, A2>{
ActionMix{
action1: self.action1.clone(),
action2: self.action2.clone(),
name: self.name.clone(),
}
}
}
impl<A1: ActionExt, A2: ActionExt> ActionMix<A1, A2>{
pub fn new(action1: A1, action2: A2) -> ActionMix<A1, A2>{
ActionMix{
name: action1.name().to_owned() + "_+_" + action2.name(),
action1,
action2,
}
}
}
impl<A1: ActionExt, A2: ActionExt> ActionExt for ActionMix<A1, A2>{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
let q1 = self.action1.orientation_at(object, t, current_value);
let q2 = self.action2.orientation_at(object, t, current_value);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1 * q2)
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
let q1 = self.action1.orientation_from_axis_angle_at(object, t, current_value);
let q2 = self.action2.orientation_from_axis_angle_at(object, t, current_value);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1 * q2)
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
let q1 = self.action1.orientation_from_euler_at(object, t, current_value, rot_order);
let q2 = self.action2.orientation_from_euler_at(object, t, current_value, rot_order);
match (q1, q2){
(Some(q1), Some(q2)) => {
Some(q1 * q2)
}
(Some(q1), None) => {
Some(q1)
}
(None, Some(q2)) => {
Some(q2)
}
(None, None) => {
None
}
}
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
let p1 = self.action1.location_at(object, t, current_value);
let p2 = self.action2.location_at(object, t, current_value);
match (p1, p2){
(Some(p1), Some(p2)) => {
Some(p1 + p2.to_vec())
}
(Some(p1), None) => {
Some(p1)
}
(None, Some(p2)) => {
Some(p2)
}
(None, None) => {
None
}
}
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
let s1 = self.action1.scale_at(object, t, current_value);
let s2 = self.action2.scale_at(object, t, current_value);
match (s1, s2){
(Some(s1), Some(s2)) => {
Some(s1.component_mul(&s2))
}
(Some(s1), None) => {
Some(s1)
}
(None, Some(s2)) => {
Some(s2)
}
(None, None) => {
None
}
}
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
unimplemented!()
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
let k1 = self.action1.keyblock_at(keyblock, t);
let k2 = self.action2.keyblock_at(keyblock, t);
match (k1, k2){
(Some(k1), Some(k2)) => {
unimplemented!()
}
(Some(k1), None) => {
Some(k1)
}
(None, Some(k2)) => {
Some(k2)
}
(None, None) => {
None
}
}
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
let h1 = self.action1.hide_view_at(object, t);
let h2 = self.action2.hide_view_at(object, t);
match (h1, h2){
(Some(h1), Some(h2)) => {
Some(h1 & h2)
}
(Some(h1), None) => {
Some(h1)
}
(None, Some(h2)) => {
Some(h2)
}
(None, None) => {
None
}
}
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
let h1 = self.action1.hide_render_at(object, t);
let h2 = self.action2.hide_render_at(object, t);
match (h1, h2){
(Some(h1), Some(h2)) => {
Some(h1 & h2)
}
(Some(h1), None) => {
Some(h1)
}
(None, Some(h2)) => {
Some(h2)
}
(None, None) => {
None
}
}
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
let p1 = self.action1.location_at(object, t, current_value);
let p2 = self.action2.location_at(object, t, current_value);
let p = match (p1, p2){
(Some(p1), Some(p2)) => {
Some(p1 + p2.to_vec())
}
(Some(p1), None) => {
Some(p1)
}
(None, Some(p2)) => {
Some(p2)
}
(None, None) => {
None
}
};
if let Some(p) = p{
let prev_p1 = prev_positions.get(self.action1.borrow().name()).and_then(|p| *p);
let prev_p2 = prev_positions.get(self.action2.borrow().name()).and_then(|p| *p);
let delta1 = match (p1, prev_p1){
(Some(p1), Some(prev_p1)) => {
Some(p1 - prev_p1)
}
_ => None
};
let delta2 = match (p2, prev_p2){
(Some(p2), Some(prev_p2)) => {
Some(p2 - prev_p2)
}
_ => None
};
let delta = match (delta1, delta2){
(Some(delta1), Some(delta2)) => {
Some(delta1 + delta2)
}
(Some(delta1), None) => {
Some(delta1)
}
(None, Some(delta2)) => {
Some(delta2)
}
(None, None) => {
None
}
};
let delta = delta.unwrap_or(vec3!(0.));
prev_positions.insert(self.action1.borrow().name().to_owned(), p1);
prev_positions.insert(self.action2.borrow().name().to_owned(), p2);
Some((p, delta))
}else{
None
}
}
fn name(&self) -> &str{
&self.name
}
fn should_root_motion(&self) -> bool{
self.action1.should_root_motion() || self.action2.should_root_motion()
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
prev_positions.remove(self.action1.name());
prev_positions.remove(self.action2.name());
}
}
impl ActionExt for rinblender::Action{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.orientation_at(object, t, current_value, false)
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.orientation_from_axis_angle_at(object, t, current_value, false)
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
self.orientation_from_euler_at(object, t, current_value, rot_order, false)
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
self.location_at(object, t, current_value, false)
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
self.scale_at(object, t, current_value, false)
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
self.rotation_at(object, t, current_value, false)
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
self.keyblock_at(keyblock, t, false)
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
self.hide_view_at(object, t, false)
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
self.hide_render_at(object, t, false)
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
let p = self.location_at(object, t, current_value, false);
if let Some(p) = p{
let delta = prev_positions.get(self.borrow().name()).and_then(|p| *p)
.map(|prev_p| p - prev_p)
.unwrap_or(vec3!(0.));
prev_positions.insert(self.borrow().name().to_owned(), Some(p));
Some((p, delta))
}else{
prev_positions.remove(self.borrow().name());
None
}
}
fn name(&self) -> &str{
self.name()
}
fn should_root_motion(&self) -> bool{
false
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
prev_positions.remove(self.name());
}
}
pub struct ActionOffset<A>{
action: A,
offset: f32,
}
impl<A: Clone> Clone for ActionOffset<A>{
fn clone(&self) -> ActionOffset<A>{
ActionOffset{
action: self.action.clone(),
offset: self.offset,
}
}
}
impl<A: ActionExt> ActionOffset<A>{
pub fn new(action: A, offset: f32) -> ActionOffset<A>{
ActionOffset{
action,
offset
}
}
pub fn offset(&self) -> f32{
self.offset
}
}
impl<A: ActionExt> ActionExt for ActionOffset<A>{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.action.orientation_at(object, t + self.offset, current_value)
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.action.orientation_from_axis_angle_at(object, t + self.offset, current_value)
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
self.action.orientation_from_euler_at(object, t + self.offset, current_value, rot_order)
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
self.action.location_at(object, t + self.offset, current_value)
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
self.action.scale_at(object, t + self.offset, current_value)
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
self.action.rotation_at(object, t + self.offset, current_value)
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
self.action.keyblock_at(keyblock, t + self.offset)
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
self.action.hide_view_at(object, t + self.offset)
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
self.action.hide_render_at(object, t + self.offset)
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
self.action.root_motion_location_at(object, t + self.offset, current_value, prev_positions)
}
fn name(&self) -> &str{
self.action.name()
}
fn should_root_motion(&self) -> bool{
self.action.should_root_motion()
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
prev_positions.remove(self.action.name());
}
}
impl<'a, A: ActionExt> ActionExt for &'a A{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
(*self).orientation_at(object, t, current_value)
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
(*self).orientation_from_axis_angle_at(object, t, current_value)
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
(*self).orientation_from_euler_at(object, t, current_value, rot_order)
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
(*self).location_at(object, t, current_value)
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
(*self).scale_at(object, t, current_value)
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
(*self).rotation_at(object, t, current_value)
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
(*self).keyblock_at(keyblock, t)
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
(*self).hide_view_at(object, t)
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
(*self).hide_render_at(object, t)
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
(*self).root_motion_location_at(object, t, current_value, prev_positions)
}
fn name(&self) -> &str{
(*self).name()
}
fn should_root_motion(&self) -> bool{
(*self).should_root_motion()
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
(*self).reset_root_motion_positions(prev_positions)
}
}
pub trait ActionClockExt{
fn update(&mut self, resources: &Resources);
fn try_recv_time(&mut self) -> Option<f64>;
}
pub struct GameClock{
fps: f64,
now: f64,
t: f64,
time_factor: f64,
}
impl GameClock{
pub fn new(fps: f64, time_factor: f64) -> GameClock{
GameClock{
fps,
now: 0.,
t: 0.,
time_factor,
}
}
}
impl ActionClockExt for GameClock{
fn update(&mut self, resources: &Resources){
let delta = resources.get::<Clock>()
.unwrap()
.last_frame_time()
.elapsed_game_time()
.as_seconds();
self.now += delta * self.time_factor;
}
fn try_recv_time(&mut self) -> Option<f64>{
let fixed_step = 1. / self.fps as f64;
if self.now - self.t > fixed_step {
self.t += fixed_step;
Some(self.t)
}else{
None
}
}
}
pub struct LoopClock<C: ActionClockExt>{
start_t: f64,
end_t: f64,
clock: C,
}
impl<C:ActionClockExt> LoopClock<C>{
pub fn new(start_t: f64, end_t: f64, clock: C) -> LoopClock<C>{
LoopClock{
start_t,
end_t,
clock,
}
}
}
impl<C:ActionClockExt> ActionClockExt for LoopClock<C>{
fn update(&mut self, resources: &Resources){
self.clock.update(resources);
}
fn try_recv_time(&mut self) -> Option<f64>{
self.clock.try_recv_time().map(|t|{
let duration = self.end_t - self.start_t;
((t - self.start_t) % duration) + self.start_t
})
}
}
impl<'a> ActionClockExt for rin::events::IterAsync<'a, f64>{
fn update(&mut self, _resources: &Resources){
}
fn try_recv_time(&mut self) -> Option<f64>{
self.next()
}
}
impl ActionClockExt for mpsc::Receiver<f64>{
fn update(&mut self, _resources: &Resources){
}
fn try_recv_time(&mut self) -> Option<f64>{
self.try_recv().ok()
}
}
#[derive(Component)]
#[debug_as_string]
pub struct ActionClock{
clock: Box<dyn ActionClockExt + Send>,
now: f64,
}
impl ActionClock{
pub fn new<C: ActionClockExt + Send + 'static>(clock: C) -> ActionClock{
ActionClock{
clock: Box::new(clock),
now: 0.
}
}
pub fn now(&self) -> f64{
self.now
}
}
impl Debug for ActionClock{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result{
fmt.debug_struct("ActionClock")
.finish()
}
}
impl ActionClockExt for ActionClock{
fn update(&mut self, resources: &Resources){
self.clock.update(resources)
}
fn try_recv_time(&mut self) -> Option<f64>{
if let Some(t) = self.clock.try_recv_time(){
self.now = t;
Some(t)
}else{
None
}
}
}
#[derive(Component)]
#[debug_as_string]
pub struct Action(Box<dyn ActionExt + Send>);
impl Action{
pub fn new<A: ActionExt + Send + 'static>(action: A) -> Action{
Action(Box::new(action))
}
pub fn set<A: ActionExt + Send + 'static>(&mut self, action: A){
self.0 = Box::new(action);
}
}
impl Debug for Action{
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result{
fmt.debug_struct("Action")
.field("action", &self.0.name())
.finish()
}
}
#[derive(Clone, Debug)]
pub struct ActionController{
action: rinblender::Action,
doloop: bool,
doroot_motion: bool,
}
pub struct ActionControllerBuilder{
action: rinblender::Action,
doloop: bool,
doroot_motion: bool,
}
impl ActionControllerBuilder{
pub fn new(action: rinblender::Action) -> ActionControllerBuilder{
ActionControllerBuilder{
action,
doloop: false,
doroot_motion: false,
}
}
pub fn doloop(mut self) -> ActionControllerBuilder{
self.doloop = true;
self
}
pub fn doroot_motion(mut self) -> ActionControllerBuilder{
self.doroot_motion = true;
self
}
pub fn build(self) -> ActionController{
ActionController{
action: self.action,
doroot_motion: self.doroot_motion,
doloop: self.doloop,
}
}
}
impl ActionController{
pub fn doloop(&self) -> bool{
self.doloop
}
pub fn doroot_motion(&self) -> bool{
self.doroot_motion
}
pub fn action(&self) -> &rinblender::Action{
&self.action
}
pub fn into_action(self) -> rinblender::Action{
self.action
}
}
impl ActionExt for ActionController{
fn orientation_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.action.orientation_at(object, t, current_value, self.doloop)
}
fn orientation_from_axis_angle_at(&self, object: &str, t: f32, current_value: &UnitQuat) -> Option<UnitQuat>{
self.action.orientation_from_axis_angle_at(object, t, current_value, self.doloop)
}
fn orientation_from_euler_at(&self, object: &str, t: f32, current_value: &UnitQuat, rot_order: rinblender::RotOrder) -> Option<UnitQuat>{
self.action.orientation_from_euler_at(object, t, current_value, rot_order, self.doloop)
}
fn location_at(&self, object: &str, t: f32, current_value: &Pnt3) -> Option<Pnt3>{
self.action.location_at(object, t, current_value, self.doloop)
}
fn scale_at(&self, object: &str, t: f32, current_value: &Vec3) -> Option<Vec3>{
self.action.scale_at(object, t, current_value, self.doloop)
}
fn rotation_at(&self, object: &str, t: f32, current_value: &rinblender::Rotation) -> Option<rinblender::Rotation> {
self.action.rotation_at(object, t, current_value, self.doloop)
}
fn keyblock_at(&self, keyblock: &str, t: f32) -> Option<f32> {
self.action.keyblock_at(keyblock, t, self.doloop)
}
fn hide_view_at(&self, object: &str, t: f32) -> Option<bool> {
self.action.hide_view_at(object, t, self.doloop)
}
fn hide_render_at(&self, object: &str, t: f32) -> Option<bool> {
self.action.hide_render_at(object, t, self.doloop)
}
fn root_motion_location_at(&self, object: &str, t: f32, current_value: &Pnt3, prev_positions: &mut HashMap<String, Option<Pnt3>>) -> Option<(Pnt3, Vec3)>{
let p = self.action.location_at(object, t, current_value, self.doloop);
if let Some(p) = p{
let delta = prev_positions.get(self.borrow().name()).and_then(|p| *p)
.map(|prev_p| p - prev_p)
.unwrap_or(vec3!(0.));
prev_positions.insert(self.borrow().name().to_owned(), Some(p));
Some((p, delta))
}else{
prev_positions.remove(self.borrow().name());
None
}
}
fn name(&self) -> &str{
self.action.name()
}
fn should_root_motion(&self) -> bool{
self.doroot_motion
}
fn reset_root_motion_positions(&self, prev_positions: &mut HashMap<String, Option<Pnt3>>){
prev_positions.remove(self.action.name());
}
}