1use gltf_derive::Validate;
2use serde_derive::{Deserialize, Serialize};
3#[cfg(feature = "extensions")]
4use serde_json::{Map, Value};
5
6#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
17pub struct Node {
18 #[cfg(feature = "KHR_lights_punctual")]
19 #[serde(
20 default,
21 rename = "KHR_lights_punctual",
22 skip_serializing_if = "Option::is_none"
23 )]
24 pub khr_lights_punctual: Option<khr_lights_punctual::KhrLightsPunctual>,
25
26 #[cfg(feature = "extensions")]
27 #[serde(default, flatten)]
28 pub others: Map<String, Value>,
29}
30
31#[cfg(feature = "KHR_lights_punctual")]
32pub mod khr_lights_punctual {
33 use crate::validation::{Checked, Error};
34 use crate::{Extras, Index, Path, Root};
35 use gltf_derive::Validate;
36 use serde::{de, ser};
37 use serde_derive::{Deserialize, Serialize};
38 use std::fmt;
39
40 pub const VALID_TYPES: &[&str] = &["directional", "point", "spot"];
42
43 #[derive(Clone, Debug, Deserialize, Serialize, Validate)]
44 pub struct KhrLightsPunctual {
45 pub light: Index<Light>,
46 }
47
48 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
50 pub enum Type {
51 Directional = 1,
58
59 Point,
66
67 Spot,
77 }
78
79 #[derive(Clone, Debug, Deserialize, Serialize, Validate)]
80 #[gltf(validate_hook = "light_validate_hook")]
81 pub struct Light {
82 #[serde(default = "color_default")]
84 pub color: [f32; 3],
85
86 #[serde(default, skip_serializing_if = "Option::is_none")]
88 pub extensions: Option<std::boxed::Box<serde_json::value::RawValue>>,
89
90 #[serde(default)]
92 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
93 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
94 pub extras: Extras,
95
96 #[serde(default = "intensity_default")]
99 pub intensity: f32,
100
101 #[cfg(feature = "names")]
103 #[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
104 pub name: Option<String>,
105
106 #[serde(default, skip_serializing_if = "Option::is_none")]
109 pub range: Option<f32>,
110
111 #[serde(default, skip_serializing_if = "Option::is_none")]
113 pub spot: Option<Spot>,
114
115 #[serde(rename = "type")]
117 pub type_: Checked<Type>,
118 }
119
120 fn light_validate_hook<P, R>(light: &Light, _root: &Root, path: P, report: &mut R)
121 where
122 P: Fn() -> Path,
123 R: FnMut(&dyn Fn() -> Path, Error),
124 {
125 if let Checked::Valid(ty) = light.type_.as_ref() {
126 if *ty == Type::Spot && light.spot.is_none() {
127 report(&|| path().field("spot"), Error::Missing);
128 }
129 }
130 }
131
132 fn color_default() -> [f32; 3] {
133 [1.0, 1.0, 1.0]
134 }
135
136 fn intensity_default() -> f32 {
137 1.0
138 }
139
140 #[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
142 #[serde(rename_all = "camelCase")]
143 pub struct Spot {
144 #[serde(default)]
146 pub inner_cone_angle: f32,
147
148 #[serde(default = "outer_cone_angle_default")]
150 pub outer_cone_angle: f32,
151 }
152
153 fn outer_cone_angle_default() -> f32 {
154 std::f32::consts::FRAC_PI_4
155 }
156
157 impl<'de> de::Deserialize<'de> for Checked<Type> {
158 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
159 where
160 D: de::Deserializer<'de>,
161 {
162 struct Visitor;
163 impl<'de> de::Visitor<'de> for Visitor {
164 type Value = Checked<Type>;
165
166 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 write!(f, "any of: {:?}", VALID_TYPES)
168 }
169
170 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
171 where
172 E: de::Error,
173 {
174 use self::Type::*;
175 use crate::validation::Checked::*;
176 Ok(match value {
177 "directional" => Valid(Directional),
178 "point" => Valid(Point),
179 "spot" => Valid(Spot),
180 _ => Invalid,
181 })
182 }
183 }
184 deserializer.deserialize_str(Visitor)
185 }
186 }
187
188 impl ser::Serialize for Type {
189 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
190 where
191 S: ser::Serializer,
192 {
193 serializer.serialize_str(match *self {
194 Type::Directional => "directional",
195 Type::Point => "point",
196 Type::Spot => "spot",
197 })
198 }
199 }
200}
201
202#[cfg(feature = "KHR_materials_variants")]
203pub mod khr_materials_variants {
204 use crate::validation::{Error, Validate};
205 use crate::{Path, Root};
206 use serde_derive::{Deserialize, Serialize};
207
208 #[derive(Clone, Debug, Deserialize, Serialize)]
209 pub struct Variant {
210 pub name: String,
211 }
212
213 impl Validate for Variant {
214 fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
215 where
216 P: Fn() -> Path,
217 R: FnMut(&dyn Fn() -> Path, Error),
218 {
219 self.name.validate(root, || path().field("name"), report);
220 }
221 }
222}
223
224#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
226pub struct Scene {
227 #[cfg(feature = "extensions")]
228 #[serde(default, flatten)]
229 pub others: Map<String, Value>,
230}