1use core::cell::RefCell;
2use std::collections::HashMap;
3
4use alloc::rc::Rc;
5use glam::{Vec3, Mat3};
6use serde::{Serialize, Deserialize};
7
8use crate::rcs::{Position, WorldObj, PointRef, Point};
9
10#[derive(Clone, Debug, Serialize, Deserialize)]
11struct PositionDes {
12 pub pos : [f32; 3],
13 pub ori : Option<[[f32; 3]; 3]>
14}
15
16impl From<Position> for PositionDes {
17 fn from(pos : Position) -> Self {
18 PositionDes {
19 pos: pos.pos.to_array(),
20 ori: Some(pos.ori.to_cols_array_2d())
21 }
22 }
23}
24
25impl Into<Position> for PositionDes {
26 fn into(self) -> Position {
27 if let Some(ori) = &self.ori {
28 Position::new_ori(
29 Vec3::from(self.pos),
30 Mat3::from_cols_array_2d(ori)
31 )
32 } else {
33 Position::from_vec3(
34 Vec3::from(self.pos)
35 )
36 }
37 }
38}
39
40impl Serialize for Position {
41 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42 where
43 S: serde::Serializer {
44 let pos = PositionDes::from(self.clone());
45 pos.serialize(serializer)
46 }
47}
48
49impl<'de> Deserialize<'de> for Position {
50 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51 where
52 D: serde::Deserializer<'de> {
53 Ok(PositionDes::deserialize(deserializer)?.into())
54 }
55}
56
57#[derive(Serialize, Deserialize)]
58#[serde(untagged)]
59enum PointEnum {
60 Pos { ori : Option<[[f32; 3]; 3]>, pos : [f32; 3] },
61 Wo { pos : Position, sub : HashMap<String, PointRef> },
62 WoDir { pos: [f32; 3], sub : HashMap<String, PointRef> }
63}
64
65impl From<PointRef> for PointEnum {
66 fn from(value: PointRef) -> Self {
67 let poi = value.borrow();
68
69 if let Some(wo) = poi.as_wo() {
70 if wo.pos.ori == Mat3::IDENTITY {
71 Self::WoDir { pos: wo.pos.pos().to_array(), sub: wo.sub.clone() }
72 } else {
73 Self::Wo { pos: wo.pos.clone(), sub: wo.sub.clone() }
74 }
75 } else if let Some(pos) = poi.as_pos() {
76 if pos.ori == Mat3::IDENTITY {
77 Self::Pos { pos: pos.pos.to_array(), ori: None }
78 } else {
79 Self::Pos { ori: Some(pos.ori.to_cols_array_2d()), pos: pos.pos.to_array() }
80 }
81 } else {
82 panic!("Bad implementation of the trait 'Point'!")
83 }
84 }
85}
86
87impl Serialize for PointRef {
88 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
89 where
90 S: serde::Serializer {
91 PointEnum::from(self.clone()).serialize(serializer)
92 }
93}
94
95impl<'de> Deserialize<'de> for PointRef {
96 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
97 where
98 D: serde::Deserializer<'de> {
99 let point = PointEnum::deserialize(deserializer)?;
100
101 Ok(match point {
102 PointEnum::Pos { ori, pos } =>
103 PointRef(Rc::new(RefCell::new(Position::new_ori(Vec3::from(pos), if let Some(o) = &ori {
104 Mat3::from_cols_array_2d(o)
105 } else {
106 Mat3::IDENTITY
107 })))),
108 PointEnum::Wo { pos, sub } =>
109 PointRef(Rc::new(RefCell::new(WorldObj::from_pos_sub(pos, sub)))),
110 PointEnum::WoDir { pos, sub } =>
111 PointRef(Rc::new(RefCell::new(WorldObj::from_pos_sub(Position::from_vec3(Vec3::from(pos)), sub))))
112 })
113 }
114}