use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Node {
#[cfg(feature = "KHR_lights_punctual")]
#[serde(
default,
rename = "KHR_lights_punctual",
skip_serializing_if = "Option::is_none"
)]
pub khr_lights_punctual: Option<khr_lights_punctual::KhrLightsPunctual>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
#[cfg(feature = "KHR_lights_punctual")]
pub mod khr_lights_punctual {
use crate::validation::{Checked, Error, Validate};
use crate::{Extras, Index, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
pub const VALID_TYPES: &[&str] = &["directional", "point", "spot"];
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct KhrLightsPunctual {
pub light: Index<Light>,
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Type {
Directional = 1,
Point,
Spot,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Light {
#[serde(default = "color_default")]
pub color: [f32; 3],
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<std::boxed::Box<serde_json::value::RawValue>>,
#[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(default = "intensity_default")]
pub intensity: f32,
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub range: Option<f32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spot: Option<Spot>,
#[serde(rename = "type")]
pub type_: Checked<Type>,
}
impl Validate for Light {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if let Checked::Valid(ty) = self.type_.as_ref() {
if *ty == Type::Spot && self.spot.is_none() {
report(&|| path().field("spot"), Error::Missing);
}
}
self.type_.validate(root, || path().field("type"), report);
self.extensions
.validate(root, || path().field("extensions"), report);
self.extras
.validate(root, || path().field("extras"), report);
}
}
fn color_default() -> [f32; 3] {
[1.0, 1.0, 1.0]
}
fn intensity_default() -> f32 {
1.0
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct Spot {
#[serde(default)]
pub inner_cone_angle: f32,
#[serde(default = "outer_cone_angle_default")]
pub outer_cone_angle: f32,
}
fn outer_cone_angle_default() -> f32 {
std::f32::consts::FRAC_PI_4
}
impl<'de> de::Deserialize<'de> for Checked<Type> {
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<Type>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_TYPES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Type::*;
use crate::validation::Checked::*;
Ok(match value {
"directional" => Valid(Directional),
"point" => Valid(Point),
"spot" => Valid(Spot),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Type {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Type::Directional => "directional",
Type::Point => "point",
Type::Spot => "spot",
})
}
}
}
#[cfg(feature = "KHR_materials_variants")]
pub mod khr_materials_variants {
use crate::validation::{Error, Validate};
use crate::{Path, Root};
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Variant {
pub name: String,
}
impl Validate for Variant {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
self.name.validate(root, || path().field("name"), report);
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Scene {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}