fyrox_animation/machine/node/
mod.rs1use crate::{
25 core::{
26 algebra::Vector2,
27 pool::{Handle, Pool},
28 reflect::prelude::*,
29 visitor::prelude::*,
30 },
31 machine::{
32 node::{blend::BlendAnimations, blendspace::BlendSpace, play::PlayAnimation},
33 BlendAnimationsByIndex, BlendPose, IndexedBlendInput, ParameterContainer, State,
34 },
35 Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
36};
37use fxhash::FxHashSet;
38use std::{
39 cell::Ref,
40 ops::{Deref, DerefMut},
41};
42
43pub mod blend;
44pub mod blendspace;
45pub mod play;
46
47#[derive(Debug, Visit, Clone, Default, Reflect, PartialEq)]
49pub struct BasePoseNode<T: EntityId> {
50 pub position: Vector2<f32>,
52
53 #[reflect(hidden)]
55 pub parent_state: Handle<State<T>>,
56}
57
58#[derive(Debug, Visit, Clone, Reflect, PartialEq)]
60pub enum PoseNode<T: EntityId> {
61 PlayAnimation(PlayAnimation<T>),
63
64 BlendAnimations(BlendAnimations<T>),
66
67 BlendAnimationsByIndex(BlendAnimationsByIndex<T>),
69
70 BlendSpace(BlendSpace<T>),
72}
73
74impl<T: EntityId> Default for PoseNode<T> {
75 fn default() -> Self {
76 Self::PlayAnimation(Default::default())
77 }
78}
79
80impl<T: EntityId> PoseNode<T> {
81 pub fn make_play_animation(animation: Handle<Animation<T>>) -> Self {
83 Self::PlayAnimation(PlayAnimation::new(animation))
84 }
85
86 pub fn make_blend_animations(poses: Vec<BlendPose<T>>) -> Self {
88 Self::BlendAnimations(BlendAnimations::new(poses))
89 }
90
91 pub fn make_blend_animations_by_index(
94 index_parameter: String,
95 inputs: Vec<IndexedBlendInput<T>>,
96 ) -> Self {
97 Self::BlendAnimationsByIndex(BlendAnimationsByIndex::new(index_parameter, inputs))
98 }
99
100 pub fn children(&self) -> Vec<Handle<PoseNode<T>>> {
102 match self {
103 Self::PlayAnimation(_) => {
104 vec![]
106 }
107 Self::BlendAnimations(blend_animations) => blend_animations.children(),
108 Self::BlendAnimationsByIndex(blend_by_index) => blend_by_index.children(),
109 Self::BlendSpace(blend_space) => blend_space.children(),
110 }
111 }
112
113 pub fn collect_animations(
115 &self,
116 nodes: &Pool<PoseNode<T>>,
117 animations: &mut FxHashSet<Handle<Animation<T>>>,
118 ) {
119 match self {
120 PoseNode::PlayAnimation(play_animation) => {
121 animations.insert(play_animation.animation);
122 }
123 PoseNode::BlendAnimations(blend_animations) => {
124 for input in blend_animations.pose_sources.iter() {
125 if let Ok(source) = nodes.try_borrow(input.pose_source) {
126 source.collect_animations(nodes, animations)
127 }
128 }
129 }
130 PoseNode::BlendAnimationsByIndex(blend_animations_by_index) => {
131 for input in blend_animations_by_index.inputs.iter() {
132 if let Ok(source) = nodes.try_borrow(input.pose_source) {
133 source.collect_animations(nodes, animations)
134 }
135 }
136 }
137 PoseNode::BlendSpace(blend_space) => {
138 for point in blend_space.points() {
139 if let Ok(source) = nodes.try_borrow(point.pose_source) {
140 source.collect_animations(nodes, animations)
141 }
142 }
143 }
144 }
145 }
146}
147
148macro_rules! static_dispatch {
149 ($self:ident, $func:ident, $($args:expr),*) => {
150 match $self {
151 PoseNode::PlayAnimation(v) => v.$func($($args),*),
152 PoseNode::BlendAnimations(v) => v.$func($($args),*),
153 PoseNode::BlendAnimationsByIndex(v) => v.$func($($args),*),
154 PoseNode::BlendSpace(v) => v.$func($($args),*),
155 }
156 };
157}
158
159impl<T: EntityId> Deref for PoseNode<T> {
160 type Target = BasePoseNode<T>;
161
162 fn deref(&self) -> &Self::Target {
163 static_dispatch!(self, deref,)
164 }
165}
166
167impl<T: EntityId> DerefMut for PoseNode<T> {
168 fn deref_mut(&mut self) -> &mut Self::Target {
169 static_dispatch!(self, deref_mut,)
170 }
171}
172
173#[derive(Copy, Clone, Debug)]
175pub enum AnimationEventCollectionStrategy {
176 All,
178 MaxWeight,
180 MinWeight,
182}
183
184pub trait AnimationPoseSource<T: EntityId> {
186 fn eval_pose(
188 &self,
189 nodes: &Pool<PoseNode<T>>,
190 params: &ParameterContainer,
191 animations: &AnimationContainer<T>,
192 dt: f32,
193 ) -> Ref<AnimationPose<T>>;
194
195 fn pose(&self) -> Ref<AnimationPose<T>>;
197
198 fn collect_animation_events(
200 &self,
201 nodes: &Pool<PoseNode<T>>,
202 params: &ParameterContainer,
203 animations: &AnimationContainer<T>,
204 strategy: AnimationEventCollectionStrategy,
205 ) -> Vec<(Handle<Animation<T>>, AnimationEvent)>;
206}
207
208impl<T: EntityId> AnimationPoseSource<T> for PoseNode<T> {
209 fn eval_pose(
210 &self,
211 nodes: &Pool<PoseNode<T>>,
212 params: &ParameterContainer,
213 animations: &AnimationContainer<T>,
214 dt: f32,
215 ) -> Ref<AnimationPose<T>> {
216 static_dispatch!(self, eval_pose, nodes, params, animations, dt)
217 }
218
219 fn pose(&self) -> Ref<AnimationPose<T>> {
220 static_dispatch!(self, pose,)
221 }
222
223 fn collect_animation_events(
224 &self,
225 nodes: &Pool<PoseNode<T>>,
226 params: &ParameterContainer,
227 animations: &AnimationContainer<T>,
228 strategy: AnimationEventCollectionStrategy,
229 ) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
230 static_dispatch!(
231 self,
232 collect_animation_events,
233 nodes,
234 params,
235 animations,
236 strategy
237 )
238 }
239}