1use crate::*;
2
3#[derive(Clone, Debug)]
5pub struct Shape {
6 pub hollow: Option<bool>,
8 pub mass: Option<f32>,
11 pub density: Option<f32>,
14 pub physics_material: Option<Box<DefInstance<PhysicsMaterial>>>,
16 pub geom: ShapeGeom,
18 pub transform: Vec<RigidTransform>,
21 pub extra: Vec<Extra>,
23}
24
25impl Shape {
26 pub fn new(geom: impl Into<ShapeGeom>) -> Self {
28 Self {
29 hollow: Default::default(),
30 mass: Default::default(),
31 density: Default::default(),
32 physics_material: Default::default(),
33 geom: geom.into(),
34 transform: Default::default(),
35 extra: Default::default(),
36 }
37 }
38}
39
40impl XNode for Shape {
41 const NAME: &'static str = "shape";
42 fn parse(element: &Element) -> Result<Self> {
43 debug_assert_eq!(element.name(), Self::NAME);
44 let mut it = element.children().peekable();
45 Ok(Shape {
46 hollow: parse_opt("hollow", &mut it, parse_elem)?,
47 mass: parse_opt("mass", &mut it, parse_elem)?,
48 density: parse_opt("density", &mut it, parse_elem)?,
49 physics_material: parse_opt_many(&mut it, DefInstance::parse)?.map(Box::new),
50 transform: parse_list_many(&mut it, RigidTransform::parse)?,
51 geom: parse_one_many(&mut it, ShapeGeom::parse)?,
52 extra: Extra::parse_many(it)?,
53 })
54 }
55}
56
57impl XNodeWrite for Shape {
58 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
59 let e = Self::elem().start(w)?;
60 ElemBuilder::opt_print("hollow", &self.hollow, w)?;
61 ElemBuilder::opt_print("mass", &self.mass, w)?;
62 ElemBuilder::opt_print("density", &self.density, w)?;
63 self.physics_material.write_to(w)?;
64 self.geom.write_to(w)?;
65 self.transform.write_to(w)?;
66 self.extra.write_to(w)?;
67 e.end(w)
68 }
69}
70
71impl CollectLocalMaps for Shape {
72 fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
73 self.physics_material.collect_local_maps(maps);
74 }
75}
76
77#[derive(Clone, Debug)]
81pub enum ShapeGeom {
82 Plane(Plane),
84 Box(BoxShape),
86 Sphere(Sphere),
88 Cylinder(Cylinder),
90 TaperedCylinder(TaperedCylinder),
92 Capsule(Capsule),
94 TaperedCapsule(TaperedCapsule),
96 Geom(Instance<Geometry>),
99}
100
101impl From<Plane> for ShapeGeom {
102 fn from(v: Plane) -> Self {
103 Self::Plane(v)
104 }
105}
106
107impl From<BoxShape> for ShapeGeom {
108 fn from(v: BoxShape) -> Self {
109 Self::Box(v)
110 }
111}
112
113impl From<Sphere> for ShapeGeom {
114 fn from(v: Sphere) -> Self {
115 Self::Sphere(v)
116 }
117}
118
119impl From<Cylinder> for ShapeGeom {
120 fn from(v: Cylinder) -> Self {
121 Self::Cylinder(v)
122 }
123}
124
125impl From<TaperedCylinder> for ShapeGeom {
126 fn from(v: TaperedCylinder) -> Self {
127 Self::TaperedCylinder(v)
128 }
129}
130
131impl From<Capsule> for ShapeGeom {
132 fn from(v: Capsule) -> Self {
133 Self::Capsule(v)
134 }
135}
136
137impl From<TaperedCapsule> for ShapeGeom {
138 fn from(v: TaperedCapsule) -> Self {
139 Self::TaperedCapsule(v)
140 }
141}
142
143impl From<Instance<Geometry>> for ShapeGeom {
144 fn from(v: Instance<Geometry>) -> Self {
145 Self::Geom(v)
146 }
147}
148
149impl ShapeGeom {
150 pub fn parse(e: &Element) -> Result<Option<Self>> {
152 match e.name() {
153 Plane::NAME => Ok(Some(Self::Plane(Plane::parse(e)?))),
154 BoxShape::NAME => Ok(Some(Self::Box(BoxShape::parse(e)?))),
155 Sphere::NAME => Ok(Some(Self::Sphere(Sphere::parse(e)?))),
156 Cylinder::NAME => Ok(Some(Self::Cylinder(Cylinder::parse(e)?))),
157 TaperedCylinder::NAME => Ok(Some(Self::TaperedCylinder(TaperedCylinder::parse(e)?))),
158 Capsule::NAME => Ok(Some(Self::Capsule(Capsule::parse(e)?))),
159 TaperedCapsule::NAME => Ok(Some(Self::TaperedCapsule(TaperedCapsule::parse(e)?))),
160 Geometry::INSTANCE => Ok(Some(Self::Geom(Instance::parse(e)?))),
161 _ => Ok(None),
162 }
163 }
164}
165
166impl XNodeWrite for ShapeGeom {
167 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
168 match self {
169 Self::Plane(e) => e.write_to(w),
170 Self::Box(e) => e.write_to(w),
171 Self::Sphere(e) => e.write_to(w),
172 Self::Cylinder(e) => e.write_to(w),
173 Self::TaperedCylinder(e) => e.write_to(w),
174 Self::Capsule(e) => e.write_to(w),
175 Self::TaperedCapsule(e) => e.write_to(w),
176 Self::Geom(e) => e.write_to(w),
177 }
178 }
179}
180
181#[derive(Clone, Debug)]
183pub struct Plane {
184 pub equation: [f32; 4],
186 pub extra: Vec<Extra>,
188}
189
190impl Plane {
191 pub fn new(equation: [f32; 4]) -> Self {
193 Self {
194 equation,
195 extra: vec![],
196 }
197 }
198}
199
200impl XNode for Plane {
201 const NAME: &'static str = "plane";
202 fn parse(element: &Element) -> Result<Self> {
203 debug_assert_eq!(element.name(), Self::NAME);
204 let mut it = element.children().peekable();
205 Ok(Plane {
206 equation: *parse_one("equation", &mut it, parse_array_n)?,
207 extra: Extra::parse_many(it)?,
208 })
209 }
210}
211
212impl XNodeWrite for Plane {
213 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
214 let e = Self::elem().start(w)?;
215 ElemBuilder::print_arr("equation", &self.equation, w)?;
216 self.extra.write_to(w)?;
217 e.end(w)
218 }
219}
220
221#[derive(Clone, Debug)]
224pub struct BoxShape {
225 pub half_extents: [f32; 3],
227 pub extra: Vec<Extra>,
229}
230
231impl BoxShape {
232 pub fn new(half_extents: [f32; 3]) -> Self {
234 Self {
235 half_extents,
236 extra: vec![],
237 }
238 }
239}
240
241impl XNode for BoxShape {
242 const NAME: &'static str = "box";
243 fn parse(element: &Element) -> Result<Self> {
244 debug_assert_eq!(element.name(), Self::NAME);
245 let mut it = element.children().peekable();
246 Ok(BoxShape {
247 half_extents: *parse_one("half_extents", &mut it, parse_array_n)?,
248 extra: Extra::parse_many(it)?,
249 })
250 }
251}
252
253impl XNodeWrite for BoxShape {
254 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
255 let e = Self::elem().start(w)?;
256 ElemBuilder::print_arr("half_extents", &self.half_extents, w)?;
257 self.extra.write_to(w)?;
258 e.end(w)
259 }
260}
261
262#[derive(Clone, Debug)]
264pub struct Sphere {
265 pub radius: f32,
267 pub extra: Vec<Extra>,
269}
270
271impl Sphere {
272 pub fn new(radius: f32) -> Self {
274 Self {
275 radius,
276 extra: vec![],
277 }
278 }
279}
280
281impl XNode for Sphere {
282 const NAME: &'static str = "sphere";
283 fn parse(element: &Element) -> Result<Self> {
284 debug_assert_eq!(element.name(), Self::NAME);
285 let mut it = element.children().peekable();
286 Ok(Sphere {
287 radius: parse_one("radius", &mut it, parse_elem)?,
288 extra: Extra::parse_many(it)?,
289 })
290 }
291}
292
293impl XNodeWrite for Sphere {
294 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
295 let e = Self::elem().start(w)?;
296 ElemBuilder::print("radius", &self.radius, w)?;
297 self.extra.write_to(w)?;
298 e.end(w)
299 }
300}
301
302#[derive(Clone, Debug)]
304pub struct Cylinder {
305 pub height: f32,
307 pub radius: [f32; 2],
309 pub extra: Vec<Extra>,
311}
312
313impl Cylinder {
314 pub fn new(height: f32, radius: [f32; 2]) -> Self {
316 Self {
317 height,
318 radius,
319 extra: vec![],
320 }
321 }
322}
323
324impl XNode for Cylinder {
325 const NAME: &'static str = "cylinder";
326 fn parse(element: &Element) -> Result<Self> {
327 debug_assert_eq!(element.name(), Self::NAME);
328 let mut it = element.children().peekable();
329 Ok(Cylinder {
330 height: parse_one("height", &mut it, parse_elem)?,
331 radius: *parse_one("radius", &mut it, parse_array_n)?,
332 extra: Extra::parse_many(it)?,
333 })
334 }
335}
336
337impl XNodeWrite for Cylinder {
338 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
339 let e = Self::elem().start(w)?;
340 ElemBuilder::print("height", &self.height, w)?;
341 ElemBuilder::print_arr("radius", &self.radius, w)?;
342 self.extra.write_to(w)?;
343 e.end(w)
344 }
345}
346
347#[derive(Clone, Debug)]
349pub struct TaperedCylinder {
350 pub height: f32,
352 pub radius1: [f32; 2],
355 pub radius2: [f32; 2],
358 pub extra: Vec<Extra>,
360}
361
362impl TaperedCylinder {
363 pub fn new(height: f32, radius1: [f32; 2], radius2: [f32; 2]) -> Self {
365 Self {
366 height,
367 radius1,
368 radius2,
369 extra: vec![],
370 }
371 }
372}
373
374impl XNode for TaperedCylinder {
375 const NAME: &'static str = "tapered_cylinder";
376 fn parse(element: &Element) -> Result<Self> {
377 debug_assert_eq!(element.name(), Self::NAME);
378 let mut it = element.children().peekable();
379 Ok(TaperedCylinder {
380 height: parse_one("height", &mut it, parse_elem)?,
381 radius1: *parse_one("radius1", &mut it, parse_array_n)?,
382 radius2: *parse_one("radius2", &mut it, parse_array_n)?,
383 extra: Extra::parse_many(it)?,
384 })
385 }
386}
387
388impl XNodeWrite for TaperedCylinder {
389 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
390 let e = Self::elem().start(w)?;
391 ElemBuilder::print("height", &self.height, w)?;
392 ElemBuilder::print_arr("radius1", &self.radius1, w)?;
393 ElemBuilder::print_arr("radius2", &self.radius2, w)?;
394 self.extra.write_to(w)?;
395 e.end(w)
396 }
397}
398
399#[derive(Clone, Debug)]
401pub struct Capsule {
402 pub height: f32,
404 pub radius: [f32; 2],
406 pub extra: Vec<Extra>,
408}
409
410impl Capsule {
411 pub fn new(height: f32, radius: [f32; 2]) -> Self {
413 Self {
414 height,
415 radius,
416 extra: vec![],
417 }
418 }
419}
420
421impl XNode for Capsule {
422 const NAME: &'static str = "capsule";
423 fn parse(element: &Element) -> Result<Self> {
424 debug_assert_eq!(element.name(), Self::NAME);
425 let mut it = element.children().peekable();
426 Ok(Capsule {
427 height: parse_one("height", &mut it, parse_elem)?,
428 radius: *parse_one("radius", &mut it, parse_array_n)?,
429 extra: Extra::parse_many(it)?,
430 })
431 }
432}
433
434impl XNodeWrite for Capsule {
435 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
436 let e = Self::elem().start(w)?;
437 ElemBuilder::print("height", &self.height, w)?;
438 ElemBuilder::print_arr("radius", &self.radius, w)?;
439 self.extra.write_to(w)?;
440 e.end(w)
441 }
442}
443
444#[derive(Clone, Debug)]
446pub struct TaperedCapsule {
447 pub height: f32,
449 pub radius1: [f32; 2],
452 pub radius2: [f32; 2],
455 pub extra: Vec<Extra>,
457}
458
459impl TaperedCapsule {
460 pub fn new(height: f32, radius1: [f32; 2], radius2: [f32; 2]) -> Self {
462 Self {
463 height,
464 radius1,
465 radius2,
466 extra: vec![],
467 }
468 }
469}
470
471impl XNode for TaperedCapsule {
472 const NAME: &'static str = "tapered_capsule";
473 fn parse(element: &Element) -> Result<Self> {
474 debug_assert_eq!(element.name(), Self::NAME);
475 let mut it = element.children().peekable();
476 Ok(TaperedCapsule {
477 height: parse_one("height", &mut it, parse_elem)?,
478 radius1: *parse_one("radius1", &mut it, parse_array_n)?,
479 radius2: *parse_one("radius2", &mut it, parse_array_n)?,
480 extra: Extra::parse_many(it)?,
481 })
482 }
483}
484
485impl XNodeWrite for TaperedCapsule {
486 fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
487 let e = Self::elem().start(w)?;
488 ElemBuilder::print("height", &self.height, w)?;
489 ElemBuilder::print_arr("radius1", &self.radius1, w)?;
490 ElemBuilder::print_arr("radius2", &self.radius2, w)?;
491 self.extra.write_to(w)?;
492 e.end(w)
493 }
494}