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::uuid::{uuid, Uuid};
36use fyrox_core::{NameProvider, TypeUuidProvider};
37use std::{
38 cell::Ref,
39 ops::{Deref, DerefMut},
40};
41use strum_macros::{AsRefStr, EnumString, VariantNames};
42
43#[doc(hidden)]
44#[derive(Default, Debug, Visit, Reflect, Clone, PartialEq)]
45pub struct StateActionWrapper<T: EntityId>(pub StateAction<T>);
46
47impl<T: EntityId> TypeUuidProvider for StateActionWrapper<T> {
48 fn type_uuid() -> Uuid {
49 uuid!("d686fac8-5cc1-46b1-82a4-7f4438cc078d")
50 }
51}
52
53impl<T: EntityId> Deref for StateActionWrapper<T> {
54 type Target = StateAction<T>;
55
56 fn deref(&self) -> &Self::Target {
57 &self.0
58 }
59}
60
61impl<T: EntityId> DerefMut for StateActionWrapper<T> {
62 fn deref_mut(&mut self) -> &mut Self::Target {
63 &mut self.0
64 }
65}
66
67#[derive(Default, Debug, Visit, Reflect, Clone, PartialEq, VariantNames, EnumString, AsRefStr)]
74pub enum StateAction<T: EntityId> {
75 #[default]
77 None,
78 RewindAnimation(Handle<Animation<T>>),
80 EnableAnimation(Handle<Animation<T>>),
82 DisableAnimation(Handle<Animation<T>>),
84 EnableRandomAnimation(Vec<Handle<Animation<T>>>),
89}
90
91impl<T: EntityId> TypeUuidProvider for StateAction<T> {
92 fn type_uuid() -> Uuid {
93 uuid!("c50a15cc-0f63-4409-bbe0-74b9d3e94755")
94 }
95}
96
97impl<T: EntityId> StateAction<T> {
98 pub fn apply(&self, animations: &mut AnimationContainer<T>) {
100 match self {
101 StateAction::None => {}
102 StateAction::RewindAnimation(animation) => {
103 if let Some(animation) = animations.try_get_mut(*animation) {
104 animation.rewind();
105 }
106 }
107 StateAction::EnableAnimation(animation) => {
108 if let Some(animation) = animations.try_get_mut(*animation) {
109 animation.set_enabled(true);
110 }
111 }
112 StateAction::DisableAnimation(animation) => {
113 if let Some(animation) = animations.try_get_mut(*animation) {
114 animation.set_enabled(false);
115 }
116 }
117 StateAction::EnableRandomAnimation(animation_handles) => {
118 if let Some(animation) = animation_handles.iter().choose(&mut rand::thread_rng()) {
119 if let Some(animation) = animations.try_get_mut(*animation) {
120 animation.set_enabled(true);
121 }
122 }
123 }
124 }
125 }
126}
127
128#[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)]
131pub struct State<T: EntityId> {
132 pub position: Vector2<f32>,
134
135 pub name: String,
137
138 #[visit(optional)]
140 pub on_enter_actions: Vec<StateActionWrapper<T>>,
141
142 #[visit(optional)]
144 pub on_leave_actions: Vec<StateActionWrapper<T>>,
145
146 #[reflect(read_only)]
148 pub root: Handle<PoseNode<T>>,
149}
150
151impl<T: EntityId> NameProvider for State<T> {
152 fn name(&self) -> &str {
153 &self.name
154 }
155}
156
157impl<T: EntityId> State<T> {
158 pub fn new(name: &str, root: Handle<PoseNode<T>>) -> Self {
160 Self {
161 position: Default::default(),
162 name: name.to_owned(),
163 on_enter_actions: Default::default(),
164 on_leave_actions: Default::default(),
165 root,
166 }
167 }
168
169 pub fn pose<'a>(&self, nodes: &'a Pool<PoseNode<T>>) -> Option<Ref<'a, AnimationPose<T>>> {
171 nodes.try_borrow(self.root).map(|root| root.pose())
172 }
173
174 pub fn collect_animations(
176 &self,
177 nodes: &Pool<PoseNode<T>>,
178 animations: &mut FxHashSet<Handle<Animation<T>>>,
179 ) {
180 if let Some(root) = nodes.try_borrow(self.root) {
181 root.collect_animations(nodes, animations);
182 }
183 }
184
185 pub(super) fn update(
186 &mut self,
187 nodes: &Pool<PoseNode<T>>,
188 params: &ParameterContainer,
189 animations: &AnimationContainer<T>,
190 dt: f32,
191 ) {
192 if let Some(root) = nodes.try_borrow(self.root) {
193 root.eval_pose(nodes, params, animations, dt);
194 }
195 }
196}