Skip to main content

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}