use crate::validation::{Checked, Error, Validate}; use crate::{accessor, extensions, scene, Extras, Index, Path, Root}; use gltf_derive::Validate; use serde::{de, ser}; use serde_derive::{Deserialize, Serialize}; use std::fmt; /// All valid animation interpolation algorithms. pub const VALID_INTERPOLATIONS: &[&str] = &["LINEAR", "STEP", "CUBICSPLINE"]; /// All valid animation property names. pub const VALID_PROPERTIES: &[&str] = &["translation", "rotation", "scale", "weights"]; /// Specifies an interpolation algorithm. #[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)] pub enum Interpolation { /// Linear interpolation. /// /// The animated values are linearly interpolated between keyframes. /// When targeting a rotation, spherical linear interpolation (slerp) should be /// used to interpolate quaternions. The number output of elements must equal /// the number of input elements. Linear = 1, /// Step interpolation. /// /// The animated values remain constant to the output of the first keyframe, /// until the next keyframe. The number of output elements must equal the number /// of input elements. Step, /// Cubic spline interpolation. /// /// The animation's interpolation is computed using a cubic spline with specified /// tangents. The number of output elements must equal three times the number of /// input elements. For each input element, the output stores three elements, an /// in-tangent, a spline vertex, and an out-tangent. There must be at least two /// keyframes when using this interpolation CubicSpline, } /// Specifies a property to animate. #[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)] pub enum Property { /// XYZ translation vector. Translation = 1, /// XYZW rotation quaternion. Rotation, /// XYZ scale vector. Scale, /// Weights of morph targets. MorphTargetWeights, } /// A keyframe animation. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Animation { /// Extension specific data. #[serde(default, skip_serializing_if = "Option::is_none")] pub extensions: Option, /// Optional application specific data. #[serde(default)] #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))] #[cfg_attr(not(feature = "extras"), serde(skip_serializing))] pub extras: Extras, /// An array of channels, each of which targets an animation's sampler at a /// node's property. /// /// Different channels of the same animation must not have equal targets. #[serde(skip_serializing_if = "Vec::is_empty")] pub channels: Vec, /// Optional user-defined name for this object. #[cfg(feature = "names")] #[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))] pub name: Option, /// An array of samplers that combine input and output accessors with an /// interpolation algorithm to define a keyframe graph (but not its target). #[serde(skip_serializing_if = "Vec::is_empty")] pub samplers: Vec, } /// Targets an animation's sampler at a node's property. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Channel { /// The index of a sampler in this animation used to compute the value for the /// target. pub sampler: Index, /// The index of the node and TRS property to target. pub target: Target, /// Extension specific data. #[serde(default, skip_serializing_if = "Option::is_none")] pub extensions: Option, /// Optional application specific data. #[serde(default)] #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))] #[cfg_attr(not(feature = "extras"), serde(skip_serializing))] pub extras: Extras, } /// The index of the node and TRS property that an animation channel targets. #[derive(Clone, Debug, Deserialize, Serialize, Validate)] pub struct Target { /// Extension specific data. #[serde(default, skip_serializing_if = "Option::is_none")] pub extensions: Option, /// Optional application specific data. #[serde(default)] #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))] #[cfg_attr(not(feature = "extras"), serde(skip_serializing))] pub extras: Extras, /// The index of the node to target. pub node: Index, /// The name of the node's property to modify or the 'weights' of the /// morph targets it instantiates. pub path: Checked, } /// Defines a keyframe graph but not its target. #[derive(Clone, Debug, Deserialize, Serialize, Validate)] pub struct Sampler { /// Extension specific data. #[serde(default, skip_serializing_if = "Option::is_none")] pub extensions: Option, /// Optional application specific data. #[serde(default)] #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))] #[cfg_attr(not(feature = "extras"), serde(skip_serializing))] pub extras: Extras, /// The index of an accessor containing keyframe input values, e.g., time. pub input: Index, /// The interpolation algorithm. #[serde(default)] pub interpolation: Checked, /// The index of an accessor containing keyframe output values. pub output: Index, } impl Validate for Animation { fn validate(&self, root: &Root, path: P, report: &mut R) where P: Fn() -> Path, R: FnMut(&dyn Fn() -> Path, Error), { self.samplers .validate(root, || path().field("samplers"), report); for (index, channel) in self.channels.iter().enumerate() { if channel.sampler.value() >= self.samplers.len() { let path = || path().field("channels").index(index).field("sampler"); report(&path, Error::IndexOutOfBounds); } } } } impl Default for Interpolation { fn default() -> Self { Interpolation::Linear } } impl<'de> de::Deserialize<'de> for Checked { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { struct Visitor; impl<'de> de::Visitor<'de> for Visitor { type Value = Checked; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "any of: {:?}", VALID_INTERPOLATIONS) } fn visit_str(self, value: &str) -> Result where E: de::Error, { use self::Interpolation::*; use crate::validation::Checked::*; Ok(match value { "LINEAR" => Valid(Linear), "STEP" => Valid(Step), "CUBICSPLINE" => Valid(CubicSpline), _ => Invalid, }) } } deserializer.deserialize_str(Visitor) } } impl ser::Serialize for Interpolation { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer, { serializer.serialize_str(match *self { Interpolation::Linear => "LINEAR", Interpolation::Step => "STEP", Interpolation::CubicSpline => "CUBICSPLINE", }) } } impl<'de> de::Deserialize<'de> for Checked { fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de>, { struct Visitor; impl<'de> de::Visitor<'de> for Visitor { type Value = Checked; fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "any of: {:?}", VALID_PROPERTIES) } fn visit_str(self, value: &str) -> Result where E: de::Error, { use self::Property::*; use crate::validation::Checked::*; Ok(match value { "translation" => Valid(Translation), "rotation" => Valid(Rotation), "scale" => Valid(Scale), "weights" => Valid(MorphTargetWeights), _ => Invalid, }) } } deserializer.deserialize_str(Visitor) } } impl ser::Serialize for Property { fn serialize(&self, serializer: S) -> Result where S: ser::Serializer, { serializer.serialize_str(match *self { Property::Translation => "translation", Property::Rotation => "rotation", Property::Scale => "scale", Property::MorphTargetWeights => "weights", }) } }