fyrox_animation/machine/
state.rs1use crate::{
24 core::{
25 algebra::Vector2,
26 pool::{Handle, Pool},
27 rand::{self, seq::IteratorRandom},
28 reflect::prelude::*,
29 visitor::prelude::*,
30 },
31 machine::{AnimationPoseSource, ParameterContainer, PoseNode},
32 Animation, AnimationContainer, AnimationPose, EntityId,
33};
34use fxhash::FxHashSet;
35use fyrox_core::pool::PoolError;
36use fyrox_core::uuid::{uuid, Uuid};
37use fyrox_core::{NameProvider, TypeUuidProvider};
38use std::{
39 cell::Ref,
40 ops::{Deref, DerefMut},
41};
42use strum_macros::{AsRefStr, EnumString, VariantNames};
43
44#[doc(hidden)]
45#[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)]
46pub struct StateActionWrapper<T: EntityId>(pub StateAction<T>);
47
48impl<T: EntityId> TypeUuidProvider for StateActionWrapper<T> {
49 fn type_uuid() -> Uuid {
50 uuid!("d686fac8-5cc1-46b1-82a4-7f4438cc078d")
51 }
52}
53
54impl<T: EntityId> Deref for StateActionWrapper<T> {
55 type Target = StateAction<T>;
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62impl<T: EntityId> DerefMut for StateActionWrapper<T> {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.0
65 }
66}
67
68#[derive(Default, Debug, Visit, Reflect, Clone, PartialEq, VariantNames, EnumString, AsRefStr)]
75pub enum StateAction<T: EntityId> {
76 #[default]
78 None,
79 RewindAnimation(Handle<Animation<T>>),
81 EnableAnimation(Handle<Animation<T>>),
83 DisableAnimation(Handle<Animation<T>>),
85 EnableRandomAnimation(Vec<Handle<Animation<T>>>),
90}
91
92impl<T: EntityId> TypeUuidProvider for StateAction<T> {
93 fn type_uuid() -> Uuid {
94 uuid!("c50a15cc-0f63-4409-bbe0-74b9d3e94755")
95 }
96}
97
98impl<T: EntityId> StateAction<T> {
99 pub fn apply(&self, animations: &mut AnimationContainer<T>) {
101 match self {
102 StateAction::None => {}
103 StateAction::RewindAnimation(animation) => {
104 if let Ok(animation) = animations.try_get_mut(*animation) {
105 animation.rewind();
106 }
107 }
108 StateAction::EnableAnimation(animation) => {
109 if let Ok(animation) = animations.try_get_mut(*animation) {
110 animation.set_enabled(true);
111 }
112 }
113 StateAction::DisableAnimation(animation) => {
114 if let Ok(animation) = animations.try_get_mut(*animation) {
115 animation.set_enabled(false);
116 }
117 }
118 StateAction::EnableRandomAnimation(animation_handles) => {
119 if let Some(animation) = animation_handles.iter().choose(&mut rand::thread_rng()) {
120 if let Ok(animation) = animations.try_get_mut(*animation) {
121 animation.set_enabled(true);
122 }
123 }
124 }
125 }
126 }
127}
128
129#[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)]
132pub struct State<T: EntityId> {
133 pub position: Vector2<f32>,
135
136 pub name: String,
138
139 #[visit(optional)]
141 pub on_enter_actions: Vec<StateActionWrapper<T>>,
142
143 #[visit(optional)]
145 pub on_leave_actions: Vec<StateActionWrapper<T>>,
146
147 #[reflect(read_only)]
149 pub root: Handle<PoseNode<T>>,
150}
151
152impl<T: EntityId> NameProvider for State<T> {
153 fn name(&self) -> &str {
154 &self.name
155 }
156}
157
158impl<T: EntityId> State<T> {
159 pub fn new(name: &str, root: Handle<PoseNode<T>>) -> Self {
161 Self {
162 position: Default::default(),
163 name: name.to_owned(),
164 on_enter_actions: Default::default(),
165 on_leave_actions: Default::default(),
166 root,
167 }
168 }
169
170 pub fn pose<'a>(
172 &self,
173 nodes: &'a Pool<PoseNode<T>>,
174 ) -> Result<Ref<'a, AnimationPose<T>>, PoolError> {
175 nodes.try_borrow(self.root).map(|root| root.pose())
176 }
177
178 pub fn collect_animations(
180 &self,
181 nodes: &Pool<PoseNode<T>>,
182 animations: &mut FxHashSet<Handle<Animation<T>>>,
183 ) {
184 if let Ok(root) = nodes.try_borrow(self.root) {
185 root.collect_animations(nodes, animations);
186 }
187 }
188
189 pub(super) fn update(
190 &mut self,
191 nodes: &Pool<PoseNode<T>>,
192 params: &ParameterContainer,
193 animations: &AnimationContainer<T>,
194 dt: f32,
195 ) {
196 if let Ok(root) = nodes.try_borrow(self.root) {
197 root.eval_pose(nodes, params, animations, dt);
198 }
199 }
200}