fyrox_animation/machine/node/
mod.rsuse crate::{
core::{
algebra::Vector2,
pool::{Handle, Pool},
reflect::prelude::*,
visitor::prelude::*,
},
machine::{
node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation},
BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State,
},
Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
};
use std::{
cell::Ref,
ops::{Deref, DerefMut},
};
pub mod blend;
pub mod blendspace;
pub mod play;
#[derive(Debug, Visit, Clone, Default, Reflect, PartialEq)]
pub struct BasePoseNode<T: EntityId> {
pub position: Vector2<f32>,
#[reflect(hidden)]
pub parent_state: Handle<State<T>>,
}
#[derive(Debug, Visit, Clone, Reflect, PartialEq)]
pub enum PoseNode<T: EntityId> {
PlayAnimation(PlayAnimation<T>),
BlendAnimations(BlendAnimations<T>),
BlendAnimationsByIndex(BlendAnimationsByIndex<T>),
BlendSpace(BlendSpace<T>),
}
impl<T: EntityId> Default for PoseNode<T> {
fn default() -> Self {
Self::PlayAnimation(Default::default())
}
}
impl<T: EntityId> PoseNode<T> {
pub fn make_play_animation(animation: Handle<Animation<T>>) -> Self {
Self::PlayAnimation(PlayAnimation::new(animation))
}
pub fn make_blend_animations(poses: Vec<BlendPose<T>>) -> Self {
Self::BlendAnimations(BlendAnimations::new(poses))
}
pub fn make_blend_animations_by_index(
index_parameter: String,
inputs: Vec<IndexedBlendInput<T>>,
) -> Self {
Self::BlendAnimationsByIndex(BlendAnimationsByIndex::new(index_parameter, inputs))
}
pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
match self {
Self::PlayAnimation(_) => {
vec![]
}
Self::BlendAnimations(blend_animations) => blend_animations.children(),
Self::BlendAnimationsByIndex(blend_by_index) => blend_by_index.children(),
Self::BlendSpace(blend_space) => blend_space.children(),
}
}
}
macro_rules! static_dispatch {
($self:ident, $func:ident, $($args:expr),*) => {
match $self {
PoseNode::PlayAnimation(v) => v.$func($($args),*),
PoseNode::BlendAnimations(v) => v.$func($($args),*),
PoseNode::BlendAnimationsByIndex(v) => v.$func($($args),*),
PoseNode::BlendSpace(v) => v.$func($($args),*),
}
};
}
impl<T: EntityId> Deref for PoseNode<T> {
type Target = BasePoseNode<T>;
fn deref(&self) -> &Self::Target {
static_dispatch!(self, deref,)
}
}
impl<T: EntityId> DerefMut for PoseNode<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
static_dispatch!(self, deref_mut,)
}
}
#[derive(Copy, Clone, Debug)]
pub enum AnimationEventCollectionStrategy {
All,
MaxWeight,
MinWeight,
}
pub trait AnimationPoseSource<T: EntityId> {
fn eval_pose(
&self,
nodes: &Pool<PoseNode<T>>,
params: &ParameterContainer,
animations: &AnimationContainer<T>,
dt: f32,
) -> Ref<AnimationPose<T>>;
fn pose(&self) -> Ref<AnimationPose<T>>;
fn collect_animation_events(
&self,
nodes: &Pool<PoseNode<T>>,
params: &ParameterContainer,
animations: &AnimationContainer<T>,
strategy: AnimationEventCollectionStrategy,
) -> Vec<(Handle<Animation<T>>, AnimationEvent)>;
}
impl<T: EntityId> AnimationPoseSource<T> for PoseNode<T> {
fn eval_pose(
&self,
nodes: &Pool<PoseNode<T>>,
params: &ParameterContainer,
animations: &AnimationContainer<T>,
dt: f32,
) -> Ref<AnimationPose<T>> {
static_dispatch!(self, eval_pose, nodes, params, animations, dt)
}
fn pose(&self) -> Ref<AnimationPose<T>> {
static_dispatch!(self, pose,)
}
fn collect_animation_events(
&self,
nodes: &Pool<PoseNode<T>>,
params: &ParameterContainer,
animations: &AnimationContainer<T>,
strategy: AnimationEventCollectionStrategy,
) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
static_dispatch!(
self,
collect_animation_events,
nodes,
params,
animations,
strategy
)
}
}