fyrox_animation/machine/node/play.rs
1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! A simplest pose node that extracts pose from a specific animation and prepares it for further use.
22
23use crate::{
24 core::{
25 pool::{Handle, Pool},
26 reflect::prelude::*,
27 visitor::prelude::*,
28 },
29 machine::{
30 node::AnimationEventCollectionStrategy,
31 node::{AnimationPoseSource, BasePoseNode},
32 ParameterContainer, PoseNode,
33 },
34 Animation, AnimationContainer, AnimationEvent, AnimationPose, EntityId,
35};
36use std::{
37 cell::{Ref, RefCell},
38 ops::{Deref, DerefMut},
39};
40
41/// A simplest pose node that extracts pose from a specific animation and prepares it for further use.
42/// Animation handle should point to an animation in some animation container see [`AnimationContainer`] docs
43/// for more info.
44#[derive(Default, Debug, Visit, Clone, Reflect, PartialEq)]
45pub struct PlayAnimation<T: EntityId> {
46 /// Base node.
47 pub base: BasePoseNode<T>,
48
49 /// A handle to animation.
50 pub animation: Handle<Animation<T>>,
51
52 /// Output pose, it contains a filtered (see [`crate::machine::LayerMask`] for more info) pose from
53 /// the animation specified by the `animation` field.
54 #[visit(skip)]
55 #[reflect(hidden)]
56 pub output_pose: RefCell<AnimationPose<T>>,
57}
58
59impl<T: EntityId> Deref for PlayAnimation<T> {
60 type Target = BasePoseNode<T>;
61
62 fn deref(&self) -> &Self::Target {
63 &self.base
64 }
65}
66
67impl<T: EntityId> DerefMut for PlayAnimation<T> {
68 fn deref_mut(&mut self) -> &mut Self::Target {
69 &mut self.base
70 }
71}
72
73impl<T: EntityId> PlayAnimation<T> {
74 /// Creates new PlayAnimation node with given animation handle.
75 pub fn new(animation: Handle<Animation<T>>) -> Self {
76 Self {
77 base: Default::default(),
78 animation,
79 output_pose: Default::default(),
80 }
81 }
82}
83
84impl<T: EntityId> AnimationPoseSource<T> for PlayAnimation<T> {
85 fn eval_pose(
86 &self,
87 _nodes: &Pool<PoseNode<T>>,
88 _params: &ParameterContainer,
89 animations: &AnimationContainer<T>,
90 _dt: f32,
91 ) -> Ref<AnimationPose<T>> {
92 if let Ok(animation) = animations.try_get(self.animation) {
93 let mut output_pose = self.output_pose.borrow_mut();
94 animation.pose().clone_into(&mut output_pose);
95 // Pass the root motion (if any) so it will be blended correctly.
96 output_pose.set_root_motion(animation.root_motion().cloned());
97 }
98 self.output_pose.borrow()
99 }
100
101 fn pose(&self) -> Ref<AnimationPose<T>> {
102 self.output_pose.borrow()
103 }
104
105 fn collect_animation_events(
106 &self,
107 _nodes: &Pool<PoseNode<T>>,
108 _params: &ParameterContainer,
109 animations: &AnimationContainer<T>,
110 _strategy: AnimationEventCollectionStrategy,
111 ) -> Vec<(Handle<Animation<T>>, AnimationEvent)> {
112 animations
113 .try_get(self.animation)
114 .map(|a| {
115 a.events_ref()
116 .iter()
117 .map(|e| (self.animation, e.clone()))
118 .collect()
119 })
120 .unwrap_or_default()
121 }
122}