1use crate::*;
2
3#[derive(Clone, Debug)]
5pub struct Accessor {
6 pub source: Url,
11 pub count: usize,
13 pub offset: usize,
15 pub stride: usize,
18 pub param: Vec<Param>,
20}
21
22impl Accessor {
23 pub fn new(source: Url, count: usize, param: Vec<Param>) -> Self {
25 Self {
26 source,
27 count,
28 offset: 0,
29 stride: param.len(),
30 param,
31 }
32 }
33}
34
35impl XNode for Accessor {
36 const NAME: &'static str = "accessor";
37 fn parse(element: &Element) -> Result<Self> {
38 debug_assert_eq!(element.name(), Self::NAME);
39 let mut it = element.children().peekable();
40 let res = Accessor {
41 source: parse_attr(element.attr("source"))?.ok_or("missing source attr")?,
42 count: parse_attr(element.attr("count"))?.ok_or("expected 'count' attr")?,
43 offset: parse_attr(element.attr("offset"))?.unwrap_or(0),
44 stride: parse_attr(element.attr("stride"))?.unwrap_or(1),
45 param: Param::parse_list(&mut it)?,
46 };
47 if res.stride < res.param.len() {
48 return Err("accessor stride does not match params".into());
49 }
50 finish(res, it)
51 }
52}
53
54impl XNodeWrite for Accessor {
55 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
56 let mut e = Self::elem();
57 e.print_attr("source", &self.source);
58 e.print_attr("count", self.count);
59 e.def_print_attr("offset", self.offset, 0);
60 e.def_print_attr("stride", self.stride, 1);
61 let e = e.start(w)?;
62 self.param.write_to(w)?;
63 e.end(w)
64 }
65}
66
67fn parse_array_count<T: FromStr>(e: &Element) -> Result<Box<[T]>> {
68 let count: usize = parse_attr(e.attr("count"))?.ok_or("expected 'count' attr")?;
69 let mut vec = Vec::with_capacity(count);
70 for s in get_text(e)
71 .ok_or("expected text node")?
72 .split_ascii_whitespace()
73 {
74 vec.push(s.parse().map_err(|_| "parse error")?)
75 }
76 if vec.len() != count {
77 return Err("'count' does not match array length".into());
78 }
79 Ok(vec.into())
80}
81
82pub trait ArrayKind: HasId + XNode + Deref<Target = [Self::Elem]> + 'static {
84 type Elem: Clone + Display + Debug + 'static;
86 fn from_array_element(elem: &ArrayElement) -> Option<&Self>;
88}
89
90macro_rules! mk_arrays {
91 ($($(#[$doc:meta])* $name:ident($tyname:ident[$ty:ty]) = $s:literal,)*) => {
92 $(
93 $(#[$doc])*
94 #[derive(Clone, Debug)]
95 pub struct $tyname {
96 pub id: Option<String>,
98 pub val: Box<[$ty]>,
100 }
101 impl $tyname {
102 pub fn new(id: impl Into<String>, val: Box<[$ty]>) -> Self {
104 Self {
105 id: Some(id.into()),
106 val,
107 }
108 }
109 }
110 impl From<$tyname> for ArrayElement {
111 fn from(val: $tyname) -> Self {
112 Self::$name(val)
113 }
114 }
115 impl Deref for $tyname {
116 type Target = [$ty];
117
118 fn deref(&self) -> &Self::Target {
119 &self.val
120 }
121 }
122 impl XNode for $tyname {
123 const NAME: &'static str = $s;
124 fn parse(element: &Element) -> Result<Self> {
125 debug_assert_eq!(element.name(), Self::NAME);
126 Ok(Self {
127 id: element.attr("id").map(Into::into),
128 val: parse_array_count(element)?,
129 })
130 }
131 }
132 impl XNodeWrite for $tyname {
133 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
134 let mut e = Self::elem();
135 e.opt_attr("id", &self.id);
136 e.print_attr("count", self.val.len());
137 let e = e.start(w)?;
138 print_arr(&self.val, w)?;
139 e.end(w)
140 }
141 }
142 impl CollectLocalMaps for $tyname {
143 fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
144 maps.insert(self)
145 }
146 }
147 impl ArrayKind for $tyname {
148 type Elem = $ty;
149 fn from_array_element(elem: &ArrayElement) -> Option<&Self> {
150 match elem {
151 ArrayElement::$name(arr) => Some(arr),
152 _ => None,
153 }
154 }
155 }
156 )*
157
158 #[derive(Clone, Debug)]
160 pub enum ArrayElement {
161 $($(#[$doc])* $name($tyname),)*
162 }
163
164 impl XNodeWrite for ArrayElement {
165 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
166 match self {
167 $(Self::$name(e) => e.write_to(w),)*
168 }
169 }
170 }
171
172 impl CollectLocalMaps for ArrayElement {
173 fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
174 match self {
175 $(Self::$name(arr) => arr.collect_local_maps(maps),)*
176 }
177 }
178 }
179
180 impl ArrayElement {
181 pub fn parse(e: &Element) -> Result<Option<Self>> {
183 Ok(Some(match e.name() {
184 $($tyname::NAME => Self::$name($tyname::parse(e)?),)*
185 _ => return Ok(None),
186 }))
187 }
188
189 pub fn id(&self) -> Option<&str> {
191 match self {
192 $(ArrayElement::$name(arr) => arr.id.as_deref(),)*
193 }
194 }
195
196 pub fn len(&self) -> usize {
198 match self {
199 $(ArrayElement::$name(arr) => arr.len(),)*
200 }
201 }
202
203 pub fn is_empty(&self) -> bool {
205 self.len() == 0
206 }
207 }
208 }
209}
210
211mk_arrays! {
212 IdRef(IdRefArray[String]) = "IDREF_array",
214 Name(NameArray[String]) = "Name_array",
216 Bool(BoolArray[bool]) = "bool_array",
218 Float(FloatArray[f32]) = "float_array",
220 Int(IntArray[u32]) = "int_array",
222}
223
224#[derive(Clone, Debug)]
226pub struct Param {
227 pub sid: Option<String>,
230 pub name: Option<String>,
232 pub ty: String,
234 pub semantic: Option<Semantic>,
236}
237
238impl Param {
239 pub fn new(name: impl Into<String>, ty: impl Into<String>) -> Self {
241 Self {
242 sid: None,
243 name: Some(name.into()),
244 ty: ty.into(),
245 semantic: None,
246 }
247 }
248
249 pub fn new_xyz() -> Vec<Self> {
251 vec![
252 Self::new("X", "float"),
253 Self::new("Y", "float"),
254 Self::new("Z", "float"),
255 ]
256 }
257
258 pub fn new_st() -> Vec<Self> {
260 vec![Self::new("S", "float"), Self::new("T", "float")]
261 }
262}
263
264impl XNode for Param {
265 const NAME: &'static str = "param";
266 fn parse(element: &Element) -> Result<Self> {
267 debug_assert_eq!(element.name(), Self::NAME);
268 Ok(Param {
269 sid: element.attr("sid").map(Into::into),
270 name: element.attr("name").map(Into::into),
271 ty: element.attr("type").ok_or("expecting 'type' attr")?.into(),
272 semantic: parse_attr(element.attr("semantic"))?,
273 })
274 }
275}
276
277impl XNodeWrite for Param {
278 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
279 let mut e = Self::elem();
280 e.opt_attr("sid", &self.sid);
281 e.opt_attr("name", &self.name);
282 e.attr("type", &self.ty);
283 e.opt_print_attr("semantic", &self.semantic);
284 e.end(w)
285 }
286}
287
288#[derive(Clone, Debug)]
291pub struct Source {
292 pub id: Option<String>,
294 pub name: Option<String>,
296 pub asset: Option<Box<Asset>>,
298 pub array: Option<ArrayElement>,
300 pub accessor: Accessor,
302 pub technique: Vec<Technique>,
304}
305
306impl Source {
307 pub fn new_local(
309 id: impl Into<String>,
310 param: Vec<Param>,
311 array: impl Into<ArrayElement>,
312 ) -> Self {
313 let id = id.into();
314 let array = array.into();
315 assert!(!param.is_empty());
316 let count = array.len() / param.len();
317 assert!(param.len() * count == array.len());
318 Self {
319 accessor: Accessor::new(
320 Url::Fragment(array.id().expect("array requires id").into()),
321 count,
322 param,
323 ),
324 id: Some(id),
325 name: None,
326 asset: None,
327 array: Some(array),
328 technique: vec![],
329 }
330 }
331}
332
333impl XNode for Source {
334 const NAME: &'static str = "source";
335 fn parse(element: &Element) -> Result<Self> {
336 debug_assert_eq!(element.name(), Self::NAME);
337 let mut it = element.children().peekable();
338 let res = Source {
339 id: element.attr("id").map(Into::into),
340 name: element.attr("name").map(Into::into),
341 asset: Asset::parse_opt_box(&mut it)?,
342 array: parse_opt_many(&mut it, ArrayElement::parse)?,
343 accessor: parse_one(Technique::COMMON, &mut it, |e| {
344 let mut it = e.children().peekable();
345 finish(Accessor::parse_one(&mut it)?, it)
346 })?,
347 technique: Technique::parse_list(&mut it)?,
348 };
349 if let Some(arr) = &res.array {
350 if arr.len() < res.accessor.offset + res.accessor.stride * res.accessor.count {
351 return Err("array is too short for accessor".into());
352 }
353 }
354 finish(res, it)
355 }
356}
357
358impl XNodeWrite for Source {
359 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
360 let mut e = Self::elem();
361 e.opt_attr("id", &self.id);
362 e.opt_attr("name", &self.name);
363 let e = e.start(w)?;
364 self.asset.write_to(w)?;
365 self.array.write_to(w)?;
366 let common = ElemBuilder::new(Technique::COMMON).start(w)?;
367 self.accessor.write_to(w)?;
368 common.end(w)?;
369 self.technique.write_to(w)?;
370 e.end(w)
371 }
372}
373
374impl CollectLocalMaps for Source {
375 fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
376 maps.insert(self);
377 self.array.collect_local_maps(maps);
378 }
379}
380
381impl Traversable for Source {
382 fn traverse<'a, E>(
383 doc: &'a Document,
384 mut f: impl FnMut(&'a Self) -> Result<(), E>,
385 ) -> Result<(), E>
386 where
387 Self: 'a,
388 {
389 doc.library.iter().try_for_each(|elem| match elem {
390 LibraryElement::Animations(lib) => lib
391 .items
392 .iter()
393 .try_for_each(|anim| anim.source.iter().try_for_each(&mut f)),
394 LibraryElement::Controllers(lib) => lib
395 .items
396 .iter()
397 .try_for_each(|con| con.element.sources().iter().try_for_each(&mut f)),
398 LibraryElement::Geometries(lib) => lib
399 .items
400 .iter()
401 .try_for_each(|geom| geom.element.sources().iter().try_for_each(&mut f)),
402 _ => Ok(()),
403 })
404 }
405}
406
407#[derive(Clone, Debug)]
410pub struct Input {
411 pub semantic: Semantic,
413 pub source: Url,
418}
419
420impl XNode for Input {
421 const NAME: &'static str = "input";
422 fn parse(element: &Element) -> Result<Self> {
423 debug_assert_eq!(element.name(), Self::NAME);
424 Ok(Input {
425 semantic: parse_attr(element.attr("semantic"))?.ok_or("missing semantic attr")?,
426 source: parse_attr(element.attr("source"))?.ok_or("missing source attr")?,
427 })
428 }
429}
430
431impl XNodeWrite for Input {
432 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
433 let mut e = Self::elem();
434 e.print_attr("semantic", &self.semantic);
435 e.print_attr("source", &self.source);
436 e.end(w)
437 }
438}
439
440impl Input {
441 pub fn new(semantic: Semantic, source: Url) -> Self {
443 Self { semantic, source }
444 }
445
446 pub fn source_as_source(&self) -> &UrlRef<Source> {
450 debug_assert!(!matches!(self.semantic, Semantic::Vertex));
451 ref_cast::RefCast::ref_cast(&self.source)
452 }
453
454 pub fn source_as_vertices(&self) -> &UrlRef<Vertices> {
458 debug_assert!(matches!(self.semantic, Semantic::Vertex));
459 ref_cast::RefCast::ref_cast(&self.source)
460 }
461}
462
463#[derive(Clone, Debug)]
466pub struct InputS {
467 pub input: Input,
469 pub offset: u32,
474 pub set: Option<u32>,
477}
478
479impl InputS {
480 pub fn new(semantic: Semantic, source: Url, offset: u32, set: Option<u32>) -> Self {
482 Self {
483 input: Input { semantic, source },
484 offset,
485 set,
486 }
487 }
488}
489
490impl Deref for InputS {
491 type Target = Input;
492 fn deref(&self) -> &Self::Target {
493 &self.input
494 }
495}
496
497impl XNode for InputS {
498 const NAME: &'static str = "input";
499 fn parse(element: &Element) -> Result<Self> {
500 Ok(InputS {
501 input: Input::parse(element)?,
502 offset: parse_attr(element.attr("offset"))?.ok_or("missing offset attr")?,
503 set: parse_attr(element.attr("set"))?,
504 })
505 }
506}
507
508impl XNodeWrite for InputS {
509 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
510 let mut e = Self::elem();
511 e.print_attr("semantic", &self.semantic);
512 e.print_attr("source", &self.source);
513 e.print_attr("offset", self.offset);
514 e.opt_print_attr("set", &self.set);
515 e.end(w)
516 }
517}
518
519#[derive(Clone, Default, Debug)]
521pub struct InputList {
522 pub inputs: Vec<InputS>,
524 pub stride: usize,
527}
528
529impl Deref for InputList {
530 type Target = Vec<InputS>;
531
532 fn deref(&self) -> &Self::Target {
533 &self.inputs
534 }
535}
536
537impl From<Vec<InputS>> for InputList {
538 fn from(inputs: Vec<InputS>) -> Self {
539 Self::new(inputs)
540 }
541}
542
543impl InputList {
544 pub fn new(inputs: Vec<InputS>) -> Self {
546 let stride = inputs.iter().map(|i| i.offset).max().map_or(0, |n| n + 1) as usize;
547 Self { inputs, stride }
548 }
549
550 pub(crate) fn parse<const N: usize>(it: &mut ElementIter<'_>) -> Result<Self> {
551 Ok(InputList::new(InputS::parse_list_n::<N>(it)?))
552 }
553
554 pub(crate) fn check_prim<const MIN: usize>(&self, data: &[u32]) -> bool {
555 self.stride != 0 && data.len() < self.stride * MIN && data.len() % self.stride == 0
556 }
557}
558
559mk_extensible_enum! {
560 pub enum Semantic {
563 Binormal = "BINORMAL",
565 Color = "COLOR",
567 Continuity = "CONTINUITY",
569 Image = "IMAGE",
571 Input = "INPUT",
573 InTangent = "IN_TANGENT",
575 Interpolation = "INTERPOLATION",
577 InvBindMatrix = "INV_BIND_MATRIX",
579 Joint = "JOINT",
581 LinearSteps = "LINEAR_STEPS",
584 MorphTarget = "MORPH_TARGET",
586 MorphWeight = "MORPH_WEIGHT",
588 Normal = "NORMAL",
590 Output = "OUTPUT",
592 OutTangent = "OUT_TANGENT",
594 Position = "POSITION",
596 Tangent = "TANGENT",
598 TexBinormal = "TEXBINORMAL",
600 TexCoord = "TEXCOORD",
602 TexTangent = "TEXTANGENT",
604 UV = "UV",
606 Vertex = "VERTEX",
608 Weight = "WEIGHT",
610 }
611}