use serde::de;
use std::fmt;
use validation::{Checked, Error, Validate};
use {accessor, extensions, scene, Extras, Index, Path, Root};
pub const VALID_INTERPOLATION_ALGORITHMS: &'static [&'static str] = &[
"LINEAR",
"STEP",
"CATMULLROMSPLINE",
"CUBICSPLINE",
];
pub const VALID_TRS_PROPERTIES: &'static [&'static str] = &[
"translation",
"rotation",
"scale",
"weights",
];
#[derive(Clone, Copy, Debug, Deserialize)]
pub enum InterpolationAlgorithm {
Linear = 1,
Step,
CatmullRomSpline,
CubicSpline,
}
#[derive(Clone, Copy, Debug, Deserialize)]
pub enum TrsProperty {
Translation = 1,
Rotation,
Scale,
Weights,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Animation {
#[serde(default)]
pub extensions: extensions::animation::Animation,
#[serde(default)]
pub extras: Extras,
pub channels: Vec<Channel>,
#[cfg(feature = "names")]
pub name: Option<String>,
pub samplers: Vec<Sampler>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Channel {
pub sampler: Index<Sampler>,
pub target: Target,
#[serde(default)]
pub extensions: extensions::animation::Channel,
#[serde(default)]
pub extras: Extras,
}
#[derive(Clone, Debug, Deserialize, Validate)]
pub struct Target {
#[serde(default)]
pub extensions: extensions::animation::Target,
#[serde(default)]
pub extras: Extras,
pub node: Index<scene::Node>,
pub path: Checked<TrsProperty>,
}
#[derive(Clone, Debug, Deserialize, Validate)]
pub struct Sampler {
#[serde(default)]
pub extensions: extensions::animation::Sampler,
#[serde(default)]
pub extras: Extras,
pub input: Index<accessor::Accessor>,
#[serde(default)]
pub interpolation: Checked<InterpolationAlgorithm>,
pub output: Index<accessor::Accessor>,
}
impl Validate for Animation {
fn validate_minimally<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&Fn() -> Path, Error),
{
self.samplers.validate_minimally(root, || path().field("samplers"), report);
for (index, channel) in self.channels.iter().enumerate() {
if channel.sampler.value() as usize >= self.samplers.len() {
let path = || path().field("channels").index(index).field("sampler");
report(&path, Error::IndexOutOfBounds);
}
}
}
}
impl Default for InterpolationAlgorithm {
fn default() -> Self {
InterpolationAlgorithm::Linear
}
}
impl<'de> de::Deserialize<'de> for Checked<InterpolationAlgorithm> {
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<InterpolationAlgorithm>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_INTERPOLATION_ALGORITHMS)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: de::Error
{
use self::InterpolationAlgorithm::*;
use validation::Checked::*;
Ok(match value {
"LINEAR" => Valid(Linear),
"STEP" => Valid(Step),
"CATMULLROMSPLINE" => Valid(CatmullRomSpline),
"CUBICSPLINE" => Valid(CubicSpline),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl<'de> de::Deserialize<'de> for Checked<TrsProperty> {
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<TrsProperty>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_TRS_PROPERTIES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: de::Error
{
use self::TrsProperty::*;
use validation::Checked::*;
Ok(match value {
"translation" => Valid(Translation),
"rotation" => Valid(Rotation),
"scale" => Valid(Scale),
"weights" => Valid(Weights),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}