Skip to main content

gltf/animation/
mod.rs

1use crate::{accessor, scene, Document};
2
3#[cfg(feature = "utils")]
4use crate::Buffer;
5
6pub use json::animation::{Interpolation, Property};
7#[cfg(feature = "extensions")]
8use serde_json::{Map, Value};
9
10/// Iterators.
11pub mod iter;
12
13/// Utility functions.
14#[cfg(feature = "utils")]
15#[cfg_attr(docsrs, doc(cfg(feature = "utils")))]
16pub mod util;
17
18#[cfg(feature = "utils")]
19#[doc(inline)]
20pub use self::util::Reader;
21
22/// A keyframe animation.
23#[derive(Clone, Debug)]
24pub struct Animation<'a> {
25    /// The parent `Document` struct.
26    document: &'a Document,
27
28    /// The corresponding JSON index.
29    index: usize,
30
31    /// The corresponding JSON struct.
32    json: &'a json::animation::Animation,
33}
34
35/// Targets an animation's sampler at a node's property.
36#[derive(Clone, Debug)]
37pub struct Channel<'a> {
38    /// The parent `Animation` struct.
39    anim: Animation<'a>,
40
41    /// The corresponding JSON index.
42    index: usize,
43
44    /// The corresponding JSON struct.
45    json: &'a json::animation::Channel,
46}
47
48/// Defines a keyframe graph (but not its target).
49#[derive(Clone, Debug)]
50pub struct Sampler<'a> {
51    /// The parent `Animation` struct.
52    anim: Animation<'a>,
53
54    /// The corresponding JSON index.
55    index: usize,
56
57    /// The corresponding JSON struct.
58    json: &'a json::animation::Sampler,
59}
60
61/// The node and TRS property that an animation channel targets.
62#[derive(Clone, Debug)]
63pub struct Target<'a> {
64    /// The parent `Animation` struct.
65    anim: Animation<'a>,
66
67    /// The corresponding JSON struct.
68    json: &'a json::animation::Target,
69}
70
71impl<'a> Animation<'a> {
72    /// Constructs an `Animation`.
73    pub(crate) fn new(
74        document: &'a Document,
75        index: usize,
76        json: &'a json::animation::Animation,
77    ) -> Self {
78        Self {
79            document,
80            index,
81            json,
82        }
83    }
84
85    /// Returns the internal JSON index.
86    pub fn index(&self) -> usize {
87        self.index
88    }
89
90    /// Optional application specific data.
91    pub fn extras(&self) -> &'a json::Extras {
92        &self.json.extras
93    }
94
95    /// Returns an `Iterator` over the animation channels.
96    ///
97    /// Each channel targets an animation's sampler at a node's property.
98    pub fn channels(&self) -> iter::Channels<'a> {
99        iter::Channels {
100            anim: self.clone(),
101            iter: self.json.channels.iter().enumerate(),
102        }
103    }
104
105    /// Optional user-defined name for this object.
106    #[cfg(feature = "names")]
107    pub fn name(&self) -> Option<&'a str> {
108        self.json.name.as_deref()
109    }
110
111    /// Returns an `Iterator` over the animation samplers.
112    ///
113    /// Each sampler combines input and output accessors with an
114    /// interpolation algorithm to define a keyframe graph (but not its target).
115    pub fn samplers(&self) -> iter::Samplers<'a> {
116        iter::Samplers {
117            anim: self.clone(),
118            iter: self.json.samplers.iter().enumerate(),
119        }
120    }
121
122    /// Returns extension data unknown to this crate version.
123    #[cfg(feature = "extensions")]
124    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
125    pub fn extensions(&self) -> Option<&Map<String, Value>> {
126        let ext = self.json.extensions.as_ref()?;
127        Some(&ext.others)
128    }
129
130    /// Queries extension data unknown to this crate version.
131    #[cfg(feature = "extensions")]
132    #[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
133    pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
134        let ext = self.json.extensions.as_ref()?;
135        ext.others.get(ext_name)
136    }
137}
138
139impl<'a> Channel<'a> {
140    /// Constructs a `Channel`.
141    pub(crate) fn new(
142        anim: Animation<'a>,
143        json: &'a json::animation::Channel,
144        index: usize,
145    ) -> Self {
146        Self { anim, json, index }
147    }
148
149    /// Returns the parent `Animation` struct.
150    pub fn animation(&self) -> Animation<'a> {
151        self.anim.clone()
152    }
153
154    /// Returns the sampler in this animation used to compute the value for the
155    /// target.
156    pub fn sampler(&self) -> Sampler<'a> {
157        self.anim.samplers().nth(self.json.sampler.value()).unwrap()
158    }
159
160    /// Returns the node and property to target.
161    pub fn target(&self) -> Target<'a> {
162        Target::new(self.anim.clone(), &self.json.target)
163    }
164
165    /// Constructs an animation channel reader.
166    #[cfg(feature = "utils")]
167    #[cfg_attr(docsrs, doc(cfg(feature = "utils")))]
168    pub fn reader<'s, F>(&self, get_buffer_data: F) -> Reader<'a, 's, F>
169    where
170        F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
171    {
172        Reader {
173            channel: self.clone(),
174            get_buffer_data,
175        }
176    }
177
178    /// Optional application specific data.
179    pub fn extras(&self) -> &'a json::Extras {
180        &self.json.extras
181    }
182
183    /// Returns the internal JSON index.
184    pub fn index(&self) -> usize {
185        self.index
186    }
187}
188
189impl<'a> Target<'a> {
190    /// Constructs a `Target`.
191    pub(crate) fn new(anim: Animation<'a>, json: &'a json::animation::Target) -> Self {
192        Self { anim, json }
193    }
194
195    /// Returns the parent `Animation` struct.
196    pub fn animation(&self) -> Animation<'a> {
197        self.anim.clone()
198    }
199
200    /// Optional application specific data.
201    pub fn extras(&self) -> &'a json::Extras {
202        &self.json.extras
203    }
204
205    /// Returns the target node.
206    pub fn node(&self) -> Option<scene::Node<'a>> {
207        self.anim
208            .document
209            .nodes()
210            .nth(self.json.node.value())
211    }
212
213    /// Returns the node's property to modify or the 'weights' of the morph
214    /// targets it instantiates.
215    pub fn property(&self) -> Property {
216        self.json.path.unwrap()
217    }
218}
219
220impl<'a> Sampler<'a> {
221    /// Constructs a `Sampler`.
222    pub(crate) fn new(
223        anim: Animation<'a>,
224        json: &'a json::animation::Sampler,
225        index: usize,
226    ) -> Self {
227        Self { anim, json, index }
228    }
229
230    /// Returns the parent `Animation` struct.
231    pub fn animation(&self) -> Animation<'a> {
232        self.anim.clone()
233    }
234
235    /// Optional application specific data.
236    pub fn extras(&self) -> &'a json::Extras {
237        &self.json.extras
238    }
239
240    /// Returns the internal JSON index.
241    pub fn index(&self) -> usize {
242        self.index
243    }
244
245    /// Returns the accessor containing the keyframe input values (e.g. time).
246    pub fn input(&self) -> accessor::Accessor<'a> {
247        self.anim
248            .document
249            .accessors()
250            .nth(self.json.input.value())
251            .unwrap()
252    }
253
254    /// Returns the keyframe interpolation algorithm.
255    pub fn interpolation(&self) -> Interpolation {
256        self.json.interpolation.unwrap()
257    }
258
259    /// Returns the accessor containing the keyframe output values.
260    pub fn output(&self) -> accessor::Accessor<'a> {
261        self.anim
262            .document
263            .accessors()
264            .nth(self.json.output.value())
265            .unwrap()
266    }
267}