fyrox_animation/
track.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//! Track is responsible in animating a property of a single scene node. See [`Track`] docs for more info.
22
23use crate::{
24    container::{TrackDataContainer, TrackValueKind},
25    core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
26    value::{BoundValue, ValueBinding},
27    EntityId,
28};
29use std::fmt::Debug;
30
31/// Track binding contains a handle to a target object that will be animated by an animation track.
32/// Additionally, the binding could be disabled to temporarily prevent animation from affecting the
33/// target.
34#[derive(Debug, Visit, Reflect, Clone, PartialEq)]
35pub struct TrackBinding<T: EntityId> {
36    /// The binding could be disabled to temporarily prevent animation from affecting the target.
37    pub enabled: bool,
38    /// A target bound to a track. The actual track id is stored as a key in hash map of bindings in
39    /// the animation.
40    pub target: T,
41}
42
43impl<T: EntityId> Default for TrackBinding<T> {
44    fn default() -> Self {
45        Self {
46            enabled: true,
47            target: Default::default(),
48        }
49    }
50}
51
52impl<T: EntityId> TrackBinding<T> {
53    /// Creates a new enabled track binding.
54    pub fn new(target: T) -> Self {
55        Self {
56            enabled: true,
57            target,
58        }
59    }
60
61    /// Sets a handle of a node that will be animated.
62    pub fn set_target(&mut self, target: T) {
63        self.target = target;
64    }
65
66    /// Returns a handle of a node that will be animated.
67    pub fn target(&self) -> T {
68        self.target
69    }
70
71    /// Enables or disables the track. Disabled tracks won't animate their nodes/properties.
72    pub fn set_enabled(&mut self, enabled: bool) {
73        self.enabled = enabled;
74    }
75
76    /// Returns `true` if the track is enabled, `false` - otherwise.
77    pub fn is_enabled(&self) -> bool {
78        self.enabled
79    }
80
81    /// Sets target of the track.
82    pub fn with_target(mut self, target: T) -> Self {
83        self.target = target;
84        self
85    }
86}
87
88/// Track is responsible in animating a property of a single scene node. The track consists up to 4 parametric curves
89/// that contains the actual property data. Parametric curves allows the engine to perform various interpolations between
90/// key values.
91#[derive(Debug, Reflect, Clone, PartialEq)]
92pub struct Track {
93    pub(super) binding: ValueBinding,
94    pub(super) frames: TrackDataContainer,
95    pub(super) id: Uuid,
96}
97
98impl Visit for Track {
99    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
100        let mut region = visitor.enter_region(name)?;
101
102        let _ = self.binding.visit("Binding", &mut region); // Backward compatibility
103        let _ = self.id.visit("Id", &mut region); // Backward compatibility
104        let _ = self.frames.visit("Frames", &mut region); // Backward compatibility
105
106        Ok(())
107    }
108}
109
110impl Default for Track {
111    fn default() -> Self {
112        Self {
113            binding: ValueBinding::Position,
114            frames: TrackDataContainer::default(),
115            id: Uuid::new_v4(),
116        }
117    }
118}
119
120impl Track {
121    /// Creates a new track that will animate a property in the given binding. The `container` must have enough parametric
122    /// curves to be able to produces property values.
123    pub fn new(container: TrackDataContainer, binding: ValueBinding) -> Self {
124        Self {
125            frames: container,
126            binding,
127            ..Default::default()
128        }
129    }
130
131    /// Creates a new track that is responsible in animating a position property of a scene node.
132    pub fn new_position() -> Self {
133        Self {
134            frames: TrackDataContainer::new(TrackValueKind::Vector3),
135            binding: ValueBinding::Position,
136            ..Default::default()
137        }
138    }
139
140    /// Creates a new track that is responsible in animating a rotation property of a scene node.
141    pub fn new_rotation() -> Self {
142        Self {
143            frames: TrackDataContainer::new(TrackValueKind::UnitQuaternion),
144            binding: ValueBinding::Rotation,
145            ..Default::default()
146        }
147    }
148
149    /// Creates a new track that is responsible in animating a scaling property of a scene node.
150    pub fn new_scale() -> Self {
151        Self {
152            frames: TrackDataContainer::new(TrackValueKind::Vector3),
153            binding: ValueBinding::Scale,
154            ..Default::default()
155        }
156    }
157
158    /// Sets new track binding. See [`ValueBinding`] docs for more info.
159    pub fn set_value_binding(&mut self, binding: ValueBinding) {
160        self.binding = binding;
161    }
162
163    /// Returns current track binding.
164    pub fn value_binding(&self) -> &ValueBinding {
165        &self.binding
166    }
167
168    /// Returns a reference to the data container.
169    pub fn data_container(&self) -> &TrackDataContainer {
170        &self.frames
171    }
172
173    /// Returns a reference to the data container.
174    pub fn data_container_mut(&mut self) -> &mut TrackDataContainer {
175        &mut self.frames
176    }
177
178    /// Sets new data container and returns the previous one.
179    pub fn set_data_container(&mut self, container: TrackDataContainer) -> TrackDataContainer {
180        std::mem::replace(&mut self.frames, container)
181    }
182
183    /// Tries to get a new property value at a given time position.
184    pub fn fetch(&self, time: f32) -> Option<BoundValue> {
185        self.frames.fetch(time).map(|v| BoundValue {
186            binding: self.binding.clone(),
187            value: v,
188        })
189    }
190
191    /// Returns length of the track in seconds.
192    pub fn time_length(&self) -> f32 {
193        self.frames.time_length()
194    }
195
196    /// Sets a new id for the track.
197    pub fn set_id(&mut self, id: Uuid) {
198        self.id = id;
199    }
200
201    /// Returns the id of the track.
202    pub fn id(&self) -> Uuid {
203        self.id
204    }
205}