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;
pub const VALID_INTERPOLATIONS: &[&str] = &["LINEAR", "STEP", "CUBICSPLINE"];
pub const VALID_PROPERTIES: &[&str] = &["translation", "rotation", "scale", "weights"];
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum Interpolation {
Linear = 1,
Step,
CubicSpline,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum Property {
Translation = 1,
Rotation,
Scale,
MorphTargetWeights,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Animation {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Animation>,
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub channels: Vec<Channel>,
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub samplers: Vec<Sampler>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Channel {
pub sampler: Index<Sampler>,
pub target: Target,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Channel>,
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Target {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Target>,
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
pub node: Index<scene::Node>,
pub path: Checked<Property>,
}
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Sampler {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Sampler>,
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
pub input: Index<accessor::Accessor>,
#[serde(default)]
pub interpolation: Checked<Interpolation>,
pub output: Index<accessor::Accessor>,
}
impl Validate for Animation {
fn validate<P, R>(&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<Interpolation> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Interpolation>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_INTERPOLATIONS)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<Property> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Property>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_PROPERTIES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Property::Translation => "translation",
Property::Rotation => "rotation",
Property::Scale => "scale",
Property::MorphTargetWeights => "weights",
})
}
}