fyrox_impl/scene/node/
container.rs1use crate::{
25 core::{
26 pool::PayloadContainer,
27 reflect::prelude::*,
28 uuid::Uuid,
29 visitor::{Visit, VisitError, VisitResult, Visitor},
30 },
31 engine::SerializationContext,
32 scene::{
33 self,
34 camera::Camera,
35 decal::Decal,
36 dim2::{self, rectangle::Rectangle},
37 light::{directional::DirectionalLight, point::PointLight, spot::SpotLight},
38 mesh::Mesh,
39 node::Node,
40 particle_system::ParticleSystem,
41 pivot::Pivot,
42 sound::{listener::Listener, Sound},
43 sprite::Sprite,
44 terrain::Terrain,
45 },
46};
47
48#[derive(Debug, Default, Reflect)]
51pub struct NodeContainer(Option<Node>);
52
53fn read_node(name: &str, visitor: &mut Visitor) -> Result<Node, VisitError> {
54 let node = {
55 let mut kind_id = 0u8;
57 if kind_id.visit("KindId", visitor).is_ok() {
58 let mut node = match kind_id {
59 0 => Node::new(Pivot::default()),
60 1 => {
61 let mut region = visitor.enter_region(name)?;
62
63 let mut light_id = 0u32;
64 light_id.visit("KindId", &mut region)?;
65
66 let mut light_node = match light_id {
67 0 => Node::new(SpotLight::default()),
68 1 => Node::new(PointLight::default()),
69 2 => Node::new(DirectionalLight::default()),
70 _ => {
71 return Err(VisitError::User(format!(
72 "Invalid legacy light kind {light_id}"
73 )))
74 }
75 };
76
77 light_node.visit("Data", &mut region)?;
78
79 return Ok(light_node);
80 }
81 2 => Node::new(Camera::default()),
82 3 => Node::new(Mesh::default()),
83 4 => Node::new(Sprite::default()),
84 5 => Node::new(ParticleSystem::default()),
85 6 => Node::new(Terrain::default()),
86 7 => Node::new(Decal::default()),
87 8 => Node::new(scene::rigidbody::RigidBody::default()),
88 9 => Node::new(scene::collider::Collider::default()),
89 10 => Node::new(scene::joint::Joint::default()),
90 11 => Node::new(Rectangle::default()),
91 12 => Node::new(dim2::rigidbody::RigidBody::default()),
92 13 => Node::new(dim2::collider::Collider::default()),
93 14 => Node::new(dim2::joint::Joint::default()),
94 15 => Node::new(Sound::default()),
95 16 => Node::new(Listener::default()),
96 _ => {
97 return Err(VisitError::User(format!(
98 "Invalid legacy node kind {kind_id}"
99 )))
100 }
101 };
102
103 node.visit(name, visitor)?;
104
105 node
106 } else {
107 let mut region = visitor.enter_region(name)?;
109
110 let mut id = Uuid::default();
111 id.visit("TypeUuid", &mut region)?;
112
113 let serialization_context = region
114 .blackboard
115 .get::<SerializationContext>()
116 .expect("Visitor environment must contain serialization context!");
117
118 let mut node = serialization_context
119 .node_constructors
120 .try_create(&id)
121 .ok_or_else(|| VisitError::User(format!("Unknown node type uuid {id}!")))?;
122
123 node.visit("NodeData", &mut region)?;
124
125 node
126 }
127 };
128
129 Ok(node)
130}
131
132fn write_node(name: &str, node: &mut Node, visitor: &mut Visitor) -> VisitResult {
133 let mut region = visitor.enter_region(name)?;
134
135 let mut id = node.id();
136 id.visit("TypeUuid", &mut region)?;
137
138 node.visit("NodeData", &mut region)?;
139
140 Ok(())
141}
142
143impl Visit for NodeContainer {
144 fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
145 let mut region = visitor.enter_region(name)?;
146
147 let mut is_some = u8::from(self.is_some());
148 is_some.visit("IsSome", &mut region)?;
149
150 if is_some != 0 {
151 if region.is_reading() {
152 *self = NodeContainer(Some(read_node("Data", &mut region)?));
153 } else {
154 write_node("Data", self.0.as_mut().unwrap(), &mut region)?;
155 }
156 }
157
158 Ok(())
159 }
160}
161
162impl PayloadContainer for NodeContainer {
163 type Element = Node;
164
165 fn new_empty() -> Self {
166 Self(None)
167 }
168
169 fn new(element: Self::Element) -> Self {
170 Self(Some(element))
171 }
172
173 fn is_some(&self) -> bool {
174 self.0.is_some()
175 }
176
177 fn as_ref(&self) -> Option<&Self::Element> {
178 self.0.as_ref()
179 }
180
181 fn as_mut(&mut self) -> Option<&mut Self::Element> {
182 self.0.as_mut()
183 }
184
185 fn replace(&mut self, element: Self::Element) -> Option<Self::Element> {
186 self.0.replace(element)
187 }
188
189 fn take(&mut self) -> Option<Self::Element> {
190 self.0.take()
191 }
192}