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}