fyrox_impl/scene/animation/
absm.rs1use crate::scene::node::constructor::NodeConstructor;
25use crate::{
26 core::{
27 math::aabb::AxisAlignedBoundingBox,
28 pool::Handle,
29 reflect::prelude::*,
30 type_traits::prelude::*,
31 uuid::{uuid, Uuid},
32 variable::InheritableVariable,
33 visitor::prelude::*,
34 },
35 scene::{
36 animation::prelude::*,
37 base::{Base, BaseBuilder},
38 graph::Graph,
39 node::{Node, NodeTrait, UpdateContext},
40 Scene,
41 },
42};
43use fyrox_graph::constructor::ConstructorProvider;
44use fyrox_graph::SceneGraph;
45use std::any::{Any, TypeId};
46use std::ops::{Deref, DerefMut};
47
48pub type RootMotionSettings = crate::generic_animation::RootMotionSettings<Handle<Node>>;
50pub type PoseNode = crate::generic_animation::machine::PoseNode<Handle<Node>>;
52pub type PlayAnimation = crate::generic_animation::machine::node::play::PlayAnimation<Handle<Node>>;
54pub type BlendAnimations =
56 crate::generic_animation::machine::node::blend::BlendAnimations<Handle<Node>>;
57pub type BlendAnimationsByIndex =
59 crate::generic_animation::machine::node::blend::BlendAnimationsByIndex<Handle<Node>>;
60pub type BlendPose = crate::generic_animation::machine::node::blend::BlendPose<Handle<Node>>;
62pub type IndexedBlendInput =
64 crate::generic_animation::machine::node::blend::IndexedBlendInput<Handle<Node>>;
65pub type BlendSpace = crate::generic_animation::machine::node::blendspace::BlendSpace<Handle<Node>>;
67pub type BlendSpacePoint =
69 crate::generic_animation::machine::node::blendspace::BlendSpacePoint<Handle<Node>>;
70pub type LayerMask = crate::generic_animation::machine::mask::LayerMask<Handle<Node>>;
72pub type Event = crate::generic_animation::machine::event::Event<Handle<Node>>;
74pub type Machine = crate::generic_animation::machine::Machine<Handle<Node>>;
76pub type MachineLayer = crate::generic_animation::machine::MachineLayer<Handle<Node>>;
78pub type Transition = crate::generic_animation::machine::transition::Transition<Handle<Node>>;
80pub type State = crate::generic_animation::machine::state::State<Handle<Node>>;
82pub type BasePoseNode = crate::generic_animation::machine::node::BasePoseNode<Handle<Node>>;
84pub type StateAction = crate::generic_animation::machine::state::StateAction<Handle<Node>>;
86pub type StateActionWrapper =
88 crate::generic_animation::machine::state::StateActionWrapper<Handle<Node>>;
89pub type LogicNode = crate::generic_animation::machine::transition::LogicNode<Handle<Node>>;
91pub type AndNode = crate::generic_animation::machine::transition::AndNode<Handle<Node>>;
93pub type XorNode = crate::generic_animation::machine::transition::XorNode<Handle<Node>>;
95pub type OrNode = crate::generic_animation::machine::transition::OrNode<Handle<Node>>;
97pub type NotNode = crate::generic_animation::machine::transition::NotNode<Handle<Node>>;
99pub type LayerAnimationEventsCollection =
101 crate::generic_animation::machine::layer::LayerAnimationEventsCollection<Handle<Node>>;
102pub type AnimationEventsSource =
104 crate::generic_animation::machine::layer::AnimationEventsSource<Handle<Node>>;
105
106pub mod prelude {
108 pub use super::{
109 AndNode, AnimationBlendingStateMachine, AnimationBlendingStateMachineBuilder,
110 AnimationEventsSource, BasePoseNode, BlendAnimations, BlendAnimationsByIndex, BlendPose,
111 BlendSpace, BlendSpacePoint, Event, IndexedBlendInput, LayerAnimationEventsCollection,
112 LayerMask, LogicNode, Machine, MachineLayer, NotNode, OrNode, PlayAnimation, PoseNode,
113 RootMotionSettings, State, StateAction, StateActionWrapper, Transition, XorNode,
114 };
115 pub use crate::generic_animation::machine::{
116 node::AnimationEventCollectionStrategy,
117 parameter::{Parameter, ParameterContainer, ParameterDefinition, PoseWeight},
118 };
119}
120
121pub trait LayerMaskExt {
123 fn from_hierarchy(graph: &Graph, root: Handle<Node>) -> Self;
127}
128
129impl LayerMaskExt for LayerMask {
130 fn from_hierarchy(graph: &Graph, root: Handle<Node>) -> Self {
131 Self::from(
132 graph
133 .traverse_iter(root)
134 .map(|(handle, _)| handle)
135 .collect::<Vec<_>>(),
136 )
137 }
138}
139
140type MachineType = InheritableVariable<Machine>;
141type AnimationPlayerHandle = InheritableVariable<Handle<AnimationPlayer>>;
142type AnimationPlayerUntypedHandle = InheritableVariable<Handle<Node>>;
143
144#[derive(Visit, Reflect, Clone, Debug, Default)]
226#[reflect(derived_type = "Node")]
227pub struct AnimationBlendingStateMachine {
228 base: Base,
229 machine: MachineType,
230 animation_player: AnimationPlayerHandle,
231}
232
233impl ComponentProvider for AnimationBlendingStateMachine {
234 fn query_component_ref(&self, type_id: TypeId) -> Option<&dyn Any> {
235 if type_id == TypeId::of::<Self>() {
236 Some(self)
237 } else if type_id == TypeId::of::<MachineType>() {
238 Some(&self.machine)
239 } else if type_id == TypeId::of::<AnimationPlayerUntypedHandle>() {
240 Some(unsafe {
241 std::mem::transmute::<&AnimationPlayerHandle, &AnimationPlayerUntypedHandle>(
242 &self.animation_player,
243 )
244 })
245 } else {
246 None
247 }
248 }
249
250 fn query_component_mut(&mut self, type_id: TypeId) -> Option<&mut dyn Any> {
251 if type_id == TypeId::of::<Self>() {
252 Some(self)
253 } else if type_id == TypeId::of::<MachineType>() {
254 Some(&mut self.machine)
255 } else if type_id == TypeId::of::<AnimationPlayerUntypedHandle>() {
256 Some(unsafe {
257 std::mem::transmute::<&mut AnimationPlayerHandle, &mut AnimationPlayerUntypedHandle>(
258 &mut self.animation_player,
259 )
260 })
261 } else {
262 None
263 }
264 }
265}
266
267impl AnimationBlendingStateMachine {
268 pub fn set_machine(&mut self, machine: Machine) {
270 self.machine.set_value_and_mark_modified(machine);
271 }
272
273 pub fn machine(&self) -> &InheritableVariable<Machine> {
275 &self.machine
276 }
277
278 pub fn machine_mut(&mut self) -> &mut InheritableVariable<Machine> {
280 &mut self.machine
281 }
282
283 pub fn set_animation_player(&mut self, animation_player: Handle<AnimationPlayer>) {
286 self.animation_player
287 .set_value_and_mark_modified(animation_player);
288 }
289
290 pub fn animation_player(&self) -> Handle<AnimationPlayer> {
292 *self.animation_player
293 }
294}
295
296impl TypeUuidProvider for AnimationBlendingStateMachine {
297 fn type_uuid() -> Uuid {
298 uuid!("4b08c753-2a10-41e3-8fb2-4fd0517e86bc")
299 }
300}
301
302impl Deref for AnimationBlendingStateMachine {
303 type Target = Base;
304
305 fn deref(&self) -> &Self::Target {
306 &self.base
307 }
308}
309
310impl DerefMut for AnimationBlendingStateMachine {
311 fn deref_mut(&mut self) -> &mut Self::Target {
312 &mut self.base
313 }
314}
315
316impl ConstructorProvider<Node, Graph> for AnimationBlendingStateMachine {
317 fn constructor() -> NodeConstructor {
318 NodeConstructor::new::<Self>()
319 .with_variant("Animation Blending State Machine", |_| {
320 let mut machine = Machine::default();
321
322 let mut layer = MachineLayer::new();
323 layer.set_name("Base Layer");
324
325 machine.add_layer(layer);
326
327 AnimationBlendingStateMachineBuilder::new(
328 BaseBuilder::new().with_name("Animation Blending State Machine"),
329 )
330 .with_machine(machine)
331 .build_node()
332 .into()
333 })
334 .with_group("Animation")
335 }
336}
337
338impl NodeTrait for AnimationBlendingStateMachine {
339 fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
340 self.base.local_bounding_box()
341 }
342
343 fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
344 self.base.world_bounding_box()
345 }
346
347 fn id(&self) -> Uuid {
348 Self::type_uuid()
349 }
350
351 fn update(&mut self, context: &mut UpdateContext) {
352 if let Ok(animation_player) = context.nodes.try_get_mut(*self.animation_player) {
353 animation_player.set_auto_apply(false);
356
357 let pose = self.machine.get_value_mut_silent().evaluate_pose(
358 animation_player.animations.get_value_mut_silent(),
359 context.dt,
360 );
361
362 pose.apply_internal(context.nodes);
363 }
364 }
365
366 fn validate(&self, scene: &Scene) -> Result<(), String> {
367 if scene.graph.try_get(*self.animation_player).is_err() {
368 Err(
369 "Animation player is not set or invalid! Animation blending state \
370 machine won't operate! Set the animation player handle in the Inspector."
371 .to_string(),
372 )
373 } else {
374 Ok(())
375 }
376 }
377}
378
379pub struct AnimationBlendingStateMachineBuilder {
381 base_builder: BaseBuilder,
382 machine: Machine,
383 animation_player: Handle<AnimationPlayer>,
384}
385
386impl AnimationBlendingStateMachineBuilder {
387 pub fn new(base_builder: BaseBuilder) -> Self {
389 Self {
390 base_builder,
391 machine: Default::default(),
392 animation_player: Default::default(),
393 }
394 }
395
396 pub fn with_machine(mut self, machine: Machine) -> Self {
398 self.machine = machine;
399 self
400 }
401
402 pub fn with_animation_player(mut self, animation_player: Handle<AnimationPlayer>) -> Self {
404 self.animation_player = animation_player;
405 self
406 }
407
408 pub fn build_node(self) -> Node {
410 Node::new(AnimationBlendingStateMachine {
411 base: self.base_builder.build_base(),
412 machine: self.machine.into(),
413 animation_player: self.animation_player.into(),
414 })
415 }
416
417 pub fn build(self, graph: &mut Graph) -> Handle<AnimationBlendingStateMachine> {
419 graph.add_node(self.build_node()).to_variant()
420 }
421}