fyrox_animation/
track.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! Track is responsible in animating a property of a single scene node. See [`Track`] docs for more info.

use crate::{
    container::{TrackDataContainer, TrackValueKind},
    core::{reflect::prelude::*, uuid::Uuid, visitor::prelude::*},
    value::{BoundValue, ValueBinding},
    EntityId,
};
use std::fmt::Debug;

/// Track is responsible in animating a property of a single scene node. The track consists up to 4 parametric curves
/// that contains the actual property data. Parametric curves allows the engine to perform various interpolations between
/// key values.
#[derive(Debug, Reflect, Clone, PartialEq)]
pub struct Track<T: EntityId> {
    binding: ValueBinding,
    frames: TrackDataContainer,
    enabled: bool,
    target: T,
    id: Uuid,
}

impl<T: EntityId> Visit for Track<T> {
    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
        let mut region = visitor.enter_region(name)?;

        self.target.visit("Node", &mut region)?;
        self.enabled.visit("Enabled", &mut region)?;

        let _ = self.binding.visit("Binding", &mut region); // Backward compatibility
        let _ = self.id.visit("Id", &mut region); // Backward compatibility
        let _ = self.frames.visit("Frames", &mut region); // Backward compatibility

        Ok(())
    }
}

impl<T: EntityId> Default for Track<T> {
    fn default() -> Self {
        Self {
            binding: ValueBinding::Position,
            frames: TrackDataContainer::default(),
            enabled: true,
            target: Default::default(),
            id: Uuid::new_v4(),
        }
    }
}

impl<T: EntityId> Track<T> {
    /// Creates a new track that will animate a property in the given binding. The `container` must have enough parametric
    /// curves to be able to produces property values.
    pub fn new(container: TrackDataContainer, binding: ValueBinding) -> Self {
        Self {
            frames: container,
            binding,
            ..Default::default()
        }
    }

    /// Creates a new track that is responsible in animating a position property of a scene node.
    pub fn new_position() -> Self {
        Self {
            frames: TrackDataContainer::new(TrackValueKind::Vector3),
            binding: ValueBinding::Position,
            ..Default::default()
        }
    }

    /// Creates a new track that is responsible in animating a rotation property of a scene node.
    pub fn new_rotation() -> Self {
        Self {
            frames: TrackDataContainer::new(TrackValueKind::UnitQuaternion),
            binding: ValueBinding::Rotation,
            ..Default::default()
        }
    }

    /// Creates a new track that is responsible in animating a scaling property of a scene node.
    pub fn new_scale() -> Self {
        Self {
            frames: TrackDataContainer::new(TrackValueKind::Vector3),
            binding: ValueBinding::Scale,
            ..Default::default()
        }
    }

    /// Sets target of the track.
    pub fn with_target(mut self, target: T) -> Self {
        self.target = target;
        self
    }

    /// Sets new track binding. See [`ValueBinding`] docs for more info.
    pub fn set_binding(&mut self, binding: ValueBinding) {
        self.binding = binding;
    }

    /// Returns current track binding.
    pub fn binding(&self) -> &ValueBinding {
        &self.binding
    }

    /// Sets a handle of a node that will be animated.
    pub fn set_target(&mut self, target: T) {
        self.target = target;
    }

    /// Returns a handle of a node that will be animated.
    pub fn target(&self) -> T {
        self.target
    }

    /// Returns a reference to the data container.
    pub fn data_container(&self) -> &TrackDataContainer {
        &self.frames
    }

    /// Returns a reference to the data container.
    pub fn data_container_mut(&mut self) -> &mut TrackDataContainer {
        &mut self.frames
    }

    /// Sets new data container and returns the previous one.
    pub fn set_data_container(&mut self, container: TrackDataContainer) -> TrackDataContainer {
        std::mem::replace(&mut self.frames, container)
    }

    /// Tries to get a new property value at a given time position.
    pub fn fetch(&self, time: f32) -> Option<BoundValue> {
        self.frames.fetch(time).map(|v| BoundValue {
            binding: self.binding.clone(),
            value: v,
        })
    }

    /// Enables or disables the track. Disabled tracks won't animate their nodes/properties.
    pub fn set_enabled(&mut self, enabled: bool) {
        self.enabled = enabled;
    }

    /// Returns `true` if the track is enabled, `false` - otherwise.
    pub fn is_enabled(&self) -> bool {
        self.enabled
    }

    /// Returns length of the track in seconds.
    pub fn time_length(&self) -> f32 {
        self.frames.time_length()
    }

    /// Sets a new id for the track.
    pub fn set_id(&mut self, id: Uuid) {
        self.id = id;
    }

    /// Returns the id of the track.
    pub fn id(&self) -> Uuid {
        self.id
    }
}