fyrox_animation/
value.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 module that contains everything related to numeric values of animation tracks. See [`TrackValue`] docs
22//! for more info.
23
24use crate::core::{
25    algebra::{Unit, UnitQuaternion, Vector2, Vector3, Vector4},
26    log::Log,
27    math::lerpf,
28    num_traits::AsPrimitive,
29    reflect::prelude::*,
30    visitor::prelude::*,
31    ImmutableString,
32};
33use std::any::TypeId;
34use std::{
35    any,
36    any::Any,
37    fmt::{Debug, Display, Formatter},
38};
39
40/// An actual type of a property value.
41#[derive(Visit, Reflect, Clone, Copy, Debug, PartialEq, Eq, Hash)]
42pub enum ValueType {
43    /// `bool`
44    Bool,
45    /// `f32`
46    F32,
47    /// `f64`
48    F64,
49    /// `u64`
50    U64,
51    /// `i64`
52    I64,
53    /// `u32`
54    U32,
55    /// `i32`
56    I32,
57    /// `u16`
58    U16,
59    /// `i16`
60    I16,
61    /// `u8`
62    U8,
63    /// `i8`
64    I8,
65
66    /// `Vector2<bool>`
67    Vector2Bool,
68    /// `Vector2<f32>`
69    Vector2F32,
70    /// `Vector2<f64>`
71    Vector2F64,
72    /// `Vector2<u64>`
73    Vector2U64,
74    /// `Vector2<i64>`
75    Vector2I64,
76    /// `Vector2<u32>`
77    Vector2U32,
78    /// `Vector2<i32>`
79    Vector2I32,
80    /// `Vector2<u16>`
81    Vector2U16,
82    /// `Vector2<i16>`
83    Vector2I16,
84    /// `Vector2<u8>`
85    Vector2U8,
86    /// `Vector2<i8>`
87    Vector2I8,
88
89    /// `Vector3<bool>`
90    Vector3Bool,
91    /// `Vector3<f32>`
92    Vector3F32,
93    /// `Vector3<f64>`
94    Vector3F64,
95    /// `Vector3<u64>`
96    Vector3U64,
97    /// `Vector3<i64>`
98    Vector3I64,
99    /// `Vector3<u32>`
100    Vector3U32,
101    /// `Vector3<i32>`
102    Vector3I32,
103    /// `Vector3<u16>`
104    Vector3U16,
105    /// `Vector3<i16>`
106    Vector3I16,
107    /// `Vector3<u8>`
108    Vector3U8,
109    /// `Vector3<i8>`
110    Vector3I8,
111
112    /// `Vector4<bool>`
113    Vector4Bool,
114    /// `Vector4<f32>`
115    Vector4F32,
116    /// `Vector4<f64>`
117    Vector4F64,
118    /// `Vector4<u64>`
119    Vector4U64,
120    /// `Vector4<i64>`
121    Vector4I64,
122    /// `Vector4<u32>`
123    Vector4U32,
124    /// `Vector4<i32>`
125    Vector4I32,
126    /// `Vector4<u16>`
127    Vector4U16,
128    /// `Vector4<i16>`
129    Vector4I16,
130    /// `Vector4<u8>`
131    Vector4U8,
132    /// `Vector4<i8>`
133    Vector4I8,
134
135    /// `UnitQuaternion<f32>`
136    UnitQuaternionF32,
137    /// `UnitQuaternion<f64>`
138    UnitQuaternionF64,
139}
140
141impl ValueType {
142    /// Converts the value type into its respective type id.
143    pub fn into_type_id(self) -> TypeId {
144        match self {
145            ValueType::Bool => TypeId::of::<bool>(),
146            ValueType::F32 => TypeId::of::<f32>(),
147            ValueType::F64 => TypeId::of::<f64>(),
148            ValueType::U64 => TypeId::of::<u64>(),
149            ValueType::I64 => TypeId::of::<i64>(),
150            ValueType::U32 => TypeId::of::<u32>(),
151            ValueType::I32 => TypeId::of::<i32>(),
152            ValueType::U16 => TypeId::of::<u16>(),
153            ValueType::I16 => TypeId::of::<i16>(),
154            ValueType::U8 => TypeId::of::<u8>(),
155            ValueType::I8 => TypeId::of::<i8>(),
156            ValueType::Vector2Bool => TypeId::of::<Vector2<bool>>(),
157            ValueType::Vector2F32 => TypeId::of::<Vector2<f32>>(),
158            ValueType::Vector2F64 => TypeId::of::<Vector2<f64>>(),
159            ValueType::Vector2U64 => TypeId::of::<Vector2<u64>>(),
160            ValueType::Vector2I64 => TypeId::of::<Vector2<i64>>(),
161            ValueType::Vector2U32 => TypeId::of::<Vector2<u32>>(),
162            ValueType::Vector2I32 => TypeId::of::<Vector2<i32>>(),
163            ValueType::Vector2U16 => TypeId::of::<Vector2<u16>>(),
164            ValueType::Vector2I16 => TypeId::of::<Vector2<i16>>(),
165            ValueType::Vector2U8 => TypeId::of::<Vector2<u8>>(),
166            ValueType::Vector2I8 => TypeId::of::<Vector2<i8>>(),
167            ValueType::Vector3Bool => TypeId::of::<Vector3<bool>>(),
168            ValueType::Vector3F32 => TypeId::of::<Vector3<f32>>(),
169            ValueType::Vector3F64 => TypeId::of::<Vector3<f64>>(),
170            ValueType::Vector3U64 => TypeId::of::<Vector3<u64>>(),
171            ValueType::Vector3I64 => TypeId::of::<Vector3<i64>>(),
172            ValueType::Vector3U32 => TypeId::of::<Vector3<u32>>(),
173            ValueType::Vector3I32 => TypeId::of::<Vector3<i32>>(),
174            ValueType::Vector3U16 => TypeId::of::<Vector3<u16>>(),
175            ValueType::Vector3I16 => TypeId::of::<Vector3<i16>>(),
176            ValueType::Vector3U8 => TypeId::of::<Vector3<u8>>(),
177            ValueType::Vector3I8 => TypeId::of::<Vector3<i8>>(),
178            ValueType::Vector4Bool => TypeId::of::<Vector4<bool>>(),
179            ValueType::Vector4F32 => TypeId::of::<Vector4<f32>>(),
180            ValueType::Vector4F64 => TypeId::of::<Vector4<f64>>(),
181            ValueType::Vector4U64 => TypeId::of::<Vector4<u64>>(),
182            ValueType::Vector4I64 => TypeId::of::<Vector4<i64>>(),
183            ValueType::Vector4U32 => TypeId::of::<Vector4<u32>>(),
184            ValueType::Vector4I32 => TypeId::of::<Vector4<i32>>(),
185            ValueType::Vector4U16 => TypeId::of::<Vector4<u16>>(),
186            ValueType::Vector4I16 => TypeId::of::<Vector4<i16>>(),
187            ValueType::Vector4U8 => TypeId::of::<Vector4<u8>>(),
188            ValueType::Vector4I8 => TypeId::of::<Vector4<i8>>(),
189            ValueType::UnitQuaternionF32 => TypeId::of::<UnitQuaternion<f32>>(),
190            ValueType::UnitQuaternionF64 => TypeId::of::<UnitQuaternion<f64>>(),
191        }
192    }
193}
194
195impl Default for ValueType {
196    fn default() -> Self {
197        Self::F32
198    }
199}
200
201/// A real value that can be produced by an animation track. Animations always operate on real numbers (`f32`) for any kind
202/// of machine numeric types (including `bool`). This is needed to be able to blend values; final blending result is then
203/// converted to an actual machine type of a target property.
204#[derive(Clone, Debug, PartialEq)]
205pub enum TrackValue {
206    /// A real number.
207    Real(f32),
208
209    /// A 2-dimensional vector of real values.
210    Vector2(Vector2<f32>),
211
212    /// A 3-dimensional vector of real values.
213    Vector3(Vector3<f32>),
214
215    /// A 4-dimensional vector of real values.
216    Vector4(Vector4<f32>),
217
218    /// A quaternion that represents some rotation.
219    UnitQuaternion(UnitQuaternion<f32>),
220}
221
222impl TrackValue {
223    /// Mixes (blends) the current value with an other value using the given weight. Blending is possible only if the types
224    /// are the same.
225    pub fn blend_with(&mut self, other: &Self, weight: f32) {
226        match (self, other) {
227            (Self::Real(a), Self::Real(b)) => *a = lerpf(*a, *b, weight),
228            (Self::Vector2(a), Self::Vector2(b)) => *a = a.lerp(b, weight),
229            (Self::Vector3(a), Self::Vector3(b)) => *a = a.lerp(b, weight),
230            (Self::Vector4(a), Self::Vector4(b)) => *a = a.lerp(b, weight),
231            (Self::UnitQuaternion(a), Self::UnitQuaternion(b)) => *a = nlerp(*a, b, weight),
232            _ => (),
233        }
234    }
235
236    /// Tries to perform a numeric type casting of the current value to some other and returns a boxed value, that can
237    /// be used to set the value using reflection.
238    pub fn apply_to_any(&self, any: &mut dyn Any, value_type: ValueType) -> bool {
239        fn convert_vec2<T>(vec2: &Vector2<f32>) -> Vector2<T>
240        where
241            f32: AsPrimitive<T>,
242            T: Copy + 'static,
243        {
244            Vector2::new(vec2.x.as_(), vec2.y.as_())
245        }
246
247        fn convert_vec3<T>(vec3: &Vector3<f32>) -> Vector3<T>
248        where
249            f32: AsPrimitive<T>,
250            T: Copy + 'static,
251        {
252            Vector3::new(vec3.x.as_(), vec3.y.as_(), vec3.z.as_())
253        }
254
255        fn convert_vec4<T>(vec4: &Vector4<f32>) -> Vector4<T>
256        where
257            f32: AsPrimitive<T>,
258            T: Copy + 'static,
259        {
260            Vector4::new(vec4.x.as_(), vec4.y.as_(), vec4.z.as_(), vec4.w.as_())
261        }
262
263        fn set<T>(any: &mut dyn Any, value: T) -> bool
264        where
265            T: Any + Copy,
266        {
267            if let Some(any_val) = any.downcast_mut::<T>() {
268                *any_val = value;
269                true
270            } else {
271                Log::err(format!(
272                    "Animation: unable to set value of type {}! Types mismatch!",
273                    any::type_name::<T>()
274                ));
275                false
276            }
277        }
278
279        match self {
280            TrackValue::Real(real) => match value_type {
281                ValueType::Bool => set(any, real.ne(&0.0)),
282                ValueType::F32 => set(any, *real),
283                ValueType::F64 => set(any, *real as f64),
284                ValueType::U64 => set(any, *real as u64),
285                ValueType::I64 => set(any, *real as i64),
286                ValueType::U32 => set(any, *real as u32),
287                ValueType::I32 => set(any, *real as i32),
288                ValueType::U16 => set(any, *real as u16),
289                ValueType::I16 => set(any, *real as i16),
290                ValueType::U8 => set(any, *real as u8),
291                ValueType::I8 => set(any, *real as i8),
292                _ => false,
293            },
294            TrackValue::Vector2(vec2) => match value_type {
295                ValueType::Vector2Bool => set(any, Vector2::new(vec2.x.ne(&0.0), vec2.y.ne(&0.0))),
296                ValueType::Vector2F32 => set(any, *vec2),
297                ValueType::Vector2F64 => set(any, convert_vec2::<f64>(vec2)),
298                ValueType::Vector2U64 => set(any, convert_vec2::<u64>(vec2)),
299                ValueType::Vector2I64 => set(any, convert_vec2::<i64>(vec2)),
300                ValueType::Vector2U32 => set(any, convert_vec2::<u32>(vec2)),
301                ValueType::Vector2I32 => set(any, convert_vec2::<i32>(vec2)),
302                ValueType::Vector2U16 => set(any, convert_vec2::<u16>(vec2)),
303                ValueType::Vector2I16 => set(any, convert_vec2::<i16>(vec2)),
304                ValueType::Vector2U8 => set(any, convert_vec2::<u8>(vec2)),
305                ValueType::Vector2I8 => set(any, convert_vec2::<i8>(vec2)),
306                _ => false,
307            },
308            TrackValue::Vector3(vec3) => match value_type {
309                ValueType::Vector3Bool => set(
310                    any,
311                    Vector3::new(vec3.x.ne(&0.0), vec3.y.ne(&0.0), vec3.z.ne(&0.0)),
312                ),
313                ValueType::Vector3F32 => set(any, *vec3),
314                ValueType::Vector3F64 => set(any, convert_vec3::<f64>(vec3)),
315                ValueType::Vector3U64 => set(any, convert_vec3::<u64>(vec3)),
316                ValueType::Vector3I64 => set(any, convert_vec3::<i64>(vec3)),
317                ValueType::Vector3U32 => set(any, convert_vec3::<u32>(vec3)),
318                ValueType::Vector3I32 => set(any, convert_vec3::<i32>(vec3)),
319                ValueType::Vector3U16 => set(any, convert_vec3::<u16>(vec3)),
320                ValueType::Vector3I16 => set(any, convert_vec3::<i16>(vec3)),
321                ValueType::Vector3U8 => set(any, convert_vec3::<u8>(vec3)),
322                ValueType::Vector3I8 => set(any, convert_vec3::<i8>(vec3)),
323                _ => false,
324            },
325            TrackValue::Vector4(vec4) => match value_type {
326                ValueType::Vector4Bool => set(
327                    any,
328                    Vector4::new(
329                        vec4.x.ne(&0.0),
330                        vec4.y.ne(&0.0),
331                        vec4.z.ne(&0.0),
332                        vec4.w.ne(&0.0),
333                    ),
334                ),
335                ValueType::Vector4F32 => set(any, *vec4),
336                ValueType::Vector4F64 => set(any, convert_vec4::<f64>(vec4)),
337                ValueType::Vector4U64 => set(any, convert_vec4::<u64>(vec4)),
338                ValueType::Vector4I64 => set(any, convert_vec4::<i64>(vec4)),
339                ValueType::Vector4U32 => set(any, convert_vec4::<u32>(vec4)),
340                ValueType::Vector4I32 => set(any, convert_vec4::<i32>(vec4)),
341                ValueType::Vector4U16 => set(any, convert_vec4::<u16>(vec4)),
342                ValueType::Vector4I16 => set(any, convert_vec4::<i16>(vec4)),
343                ValueType::Vector4U8 => set(any, convert_vec4::<u8>(vec4)),
344                ValueType::Vector4I8 => set(any, convert_vec4::<i8>(vec4)),
345                _ => false,
346            },
347            TrackValue::UnitQuaternion(quat) => match value_type {
348                ValueType::UnitQuaternionF32 => set(any, *quat),
349                ValueType::UnitQuaternionF64 => set(any, quat.cast::<f64>()),
350                _ => false,
351            },
352        }
353    }
354}
355
356/// Value binding tells the animation system to which of the many properties to set track's value. It has special
357/// cases for the most used properties and a generic one for arbitrary properties. Arbitrary properties are set using
358/// reflection system, while the special cases handles bindings to standard properties (such as position, scaling, or
359/// rotation) for optimization. Reflection is quite slow to be used as the universal property setting mechanism.  
360#[derive(Default, Clone, Visit, Reflect, Debug, PartialEq, Eq)]
361pub enum ValueBinding {
362    /// A binding to position of a scene node.
363    #[default]
364    Position,
365    /// A binding to scale of a scene node.
366    Scale,
367    /// A binding to rotation of a scene node.
368    Rotation,
369    /// A binding to an arbitrary property of a scene node.
370    Property {
371        /// A path to a property (`foo.bar.baz[1].foobar@EnumVariant.stuff`)
372        name: ImmutableString,
373        /// Actual property type (only numeric properties are supported).
374        value_type: ValueType,
375    },
376}
377
378impl Display for ValueBinding {
379    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
380        match self {
381            ValueBinding::Position => write!(f, "Position"),
382            ValueBinding::Scale => write!(f, "Scale"),
383            ValueBinding::Rotation => write!(f, "Rotation"),
384            ValueBinding::Property { name, .. } => write!(f, "{name}"),
385        }
386    }
387}
388
389/// A value that is bound to a property.
390#[derive(Clone, Debug, PartialEq)]
391pub struct BoundValue {
392    /// A property to which the value is bound to.
393    pub binding: ValueBinding,
394    /// The new value for the property the binding points to.
395    pub value: TrackValue,
396}
397
398impl BoundValue {
399    /// Blends the current value with an other value using the given weight. See [`TrackValue::blend_with`] for
400    /// more info.
401    pub fn blend_with(&mut self, other: &Self, weight: f32) {
402        assert_eq!(self.binding, other.binding);
403        self.value.blend_with(&other.value, weight);
404    }
405
406    /// Sets a property of the given object.
407    pub fn apply_to_object(
408        &self,
409        object: &mut dyn Reflect,
410        property_path: &str,
411        value_type: ValueType,
412    ) {
413        object.as_reflect_mut(&mut |object_ref| {
414            object_ref.resolve_path_mut(property_path, &mut |result| match result {
415                Ok(property) => {
416                    let mut applied = false;
417                    property.as_any_mut(&mut |any| {
418                        applied = self.value.apply_to_any(any, value_type);
419                    });
420                    if applied {
421                        property.as_inheritable_variable_mut(&mut |var| {
422                            if let Some(var) = var {
423                                var.mark_modified();
424                            }
425                        });
426                    }
427                }
428                Err(err) => {
429                    Log::err(format!(
430                        "Failed to set property {property_path}! Reason: {err:?}"
431                    ));
432                }
433            });
434        })
435    }
436}
437
438/// A collection of values that are bounds to some properties.
439#[derive(Clone, Debug, Default, PartialEq)]
440pub struct BoundValueCollection {
441    /// Actual values collection.
442    pub values: Vec<BoundValue>,
443}
444
445impl BoundValueCollection {
446    /// Tries to blend each value of the current collection with a respective (by binding) value in the other collection.
447    /// See [`TrackValue::blend_with`] docs for more info.
448    pub fn blend_with(&mut self, other: &Self, weight: f32) {
449        for value in self.values.iter_mut() {
450            if let Some(other_value) = other.values.iter().find(|v| v.binding == value.binding) {
451                value.blend_with(other_value, weight);
452            }
453        }
454    }
455}
456
457/// Interpolates from `a` to `b` using nlerp, including an additional check to ensure
458/// that the a.dot(b) is positive to prevent the interpolation from going around the long way.
459pub fn nlerp(mut a: UnitQuaternion<f32>, b: &UnitQuaternion<f32>, w: f32) -> UnitQuaternion<f32> {
460    if a.dot(b) < 0.0 {
461        a = negate_unit_quaternion(&a)
462    }
463    a.nlerp(b, w)
464}
465
466/// Negate the given quaternion by negating each of its components.
467pub fn negate_unit_quaternion(a: &UnitQuaternion<f32>) -> UnitQuaternion<f32> {
468    Unit::new_unchecked(-a.as_ref())
469}
470
471#[cfg(test)]
472mod test {
473    use crate::value::{BoundValue, TrackValue, ValueBinding, ValueType};
474    use fyrox_core::{reflect::prelude::*, variable::InheritableVariable};
475
476    #[derive(Reflect, Debug, PartialEq)]
477    struct OtherStruct {
478        field: u32,
479        inheritable_variable: InheritableVariable<u32>,
480    }
481
482    impl Default for OtherStruct {
483        fn default() -> Self {
484            Self {
485                field: 0,
486                inheritable_variable: InheritableVariable::new_non_modified(0),
487            }
488        }
489    }
490
491    #[derive(Default, Reflect, Debug, PartialEq)]
492    struct MyStruct {
493        some_bool: bool,
494        some_property: f32,
495        other_struct: OtherStruct,
496    }
497
498    #[test]
499    fn test_apply_value() {
500        let some_bool_value = BoundValue {
501            binding: ValueBinding::Property {
502                name: "some_bool".into(),
503                value_type: ValueType::Bool,
504            },
505            value: TrackValue::Real(1.0),
506        };
507
508        let some_property_value = BoundValue {
509            binding: ValueBinding::Property {
510                name: "some_property".into(),
511                value_type: ValueType::F32,
512            },
513            value: TrackValue::Real(123.0),
514        };
515
516        let field_value = BoundValue {
517            binding: ValueBinding::Property {
518                name: "field".into(),
519                value_type: ValueType::U32,
520            },
521            value: TrackValue::Real(123.0),
522        };
523
524        let inheritable_variable_value = BoundValue {
525            binding: ValueBinding::Property {
526                name: "inheritable_variable".into(),
527                value_type: ValueType::U32,
528            },
529            value: TrackValue::Real(123.0),
530        };
531
532        let mut object = MyStruct::default();
533
534        some_bool_value.apply_to_object(&mut object, "some_bool", ValueType::Bool);
535        assert!(object.some_bool);
536
537        some_property_value.apply_to_object(&mut object, "some_property", ValueType::F32);
538        assert_eq!(object.some_property, 123.0);
539
540        field_value.apply_to_object(&mut object, "other_struct.field", ValueType::U32);
541        assert_eq!(object.other_struct.field, 123);
542
543        assert!(!object.other_struct.inheritable_variable.is_modified());
544        inheritable_variable_value.apply_to_object(
545            &mut object,
546            "other_struct.inheritable_variable",
547            ValueType::U32,
548        );
549        assert_eq!(object.other_struct.field, 123);
550        assert!(object.other_struct.inheritable_variable.is_modified());
551    }
552}