1use petgraph::graph::NodeIndex;
2use petgraph::Graph;
3use serde::Deserialize;
4use serde::Serialize;
5
6use crate::color::Color;
7
8use super::stickfigure::DrawOrderIndex;
9
10use core::cell::RefCell;
11extern crate alloc;
12use alloc::{rc::Rc, vec::Vec};
13
14#[derive(Debug, Clone)]
15pub struct Node {
16 pub node_type: NodeType,
17 pub(crate) draw_order_index: DrawOrderIndex,
18 pub is_static: bool,
19 pub is_stretchy: bool,
20 pub is_smart_stretch: bool,
21 pub do_not_apply_smart_stretch: bool,
22 pub use_segment_color: bool,
23 pub use_circle_outline: bool,
24 pub circle_is_hollow: bool,
25 pub use_gradient: bool,
26 pub reverse_gradient: bool,
27 pub gradient_mode: i16,
28 pub use_segment_scale: bool,
29 pub local_x: f32,
30 pub local_y: f32,
31 pub scale: f32,
32 pub default_length: f32,
33 pub length: f32,
34 pub default_thickness: i32,
35 pub thickness: i32,
36 pub segment_curve_radius_and_default_curve_radius: i32,
37 pub curve_circulization: bool,
38 pub segment_curve_polyfill_precision: i16,
39 pub half_arc: bool,
40 pub right_triangle_direction: i16,
41 pub triangle_upside_down: bool,
42 pub trapezoid_top_thickness_ratio: f32,
43 pub num_polygon_vertices: i16,
44 pub default_local_angle: f32,
45 pub local_angle: f32,
46 pub default_angle: f32,
47 pub color: Color,
48 pub gradient_color: Color,
49 pub circle_outline_color: Color,
50}
51
52impl Default for Node {
53 fn default() -> Self {
54 Self {
55 node_type: NodeType::default(),
56 draw_order_index: DrawOrderIndex(0),
57 is_static: false,
58 is_stretchy: false,
59 is_smart_stretch: false,
60 do_not_apply_smart_stretch: false,
61 use_segment_color: false,
62 use_circle_outline: false,
63 circle_is_hollow: false,
64 use_gradient: false,
65 reverse_gradient: false,
66 gradient_mode: 0,
67 use_segment_scale: false,
68 local_x: 0.0,
69 local_y: 0.0,
70 scale: 1.0,
71 default_length: 0.0,
72 length: 0.0,
73 default_thickness: 0,
74 thickness: 0,
75 segment_curve_radius_and_default_curve_radius: 0,
76 curve_circulization: false,
77 segment_curve_polyfill_precision: 0,
78 half_arc: false,
79 right_triangle_direction: 0,
80 triangle_upside_down: false,
81 trapezoid_top_thickness_ratio: 0.0,
82 num_polygon_vertices: 0,
83 default_local_angle: 0.0,
84 local_angle: 0.0,
85 default_angle: 0.0,
86 color: Color::default(),
87 gradient_color: Color::default(),
88 circle_outline_color: Color::default(),
89 }
90 }
91}
92
93#[derive(Serialize, Deserialize, Clone, Debug)]
94pub struct SerializableNode {
95 pub draw_order_index: DrawOrderIndex,
96 pub node_type: NodeType,
97 pub is_static: bool,
98 pub is_stretchy: bool,
99 pub is_smart_stretch: bool,
100 pub do_not_apply_smart_stretch: bool,
101 pub use_segment_color: bool,
102 pub use_circle_outline: bool,
103 pub circle_is_hollow: bool,
104 pub use_gradient: bool,
105 pub reverse_gradient: bool,
106 pub gradient_mode: i16,
107 pub use_segment_scale: bool,
108 pub local_x: f32,
109 pub local_y: f32,
110 pub scale: f32,
111 pub default_length: f32,
112 pub length: f32,
113 pub default_thickness: i32,
114 pub thickness: i32,
115 pub segment_curve_radius_and_default_curve_radius: i32,
116 pub curve_circulization: bool,
117 pub segment_curve_polyfill_precision: i16,
118 pub half_arc: bool,
119 pub right_triangle_direction: i16,
120 pub triangle_upside_down: bool,
121 pub trapezoid_top_thickness_ratio: f32,
122 pub num_polygon_vertices: i16,
123 pub default_local_angle: f32,
124 pub local_angle: f32,
125 pub default_angle: f32,
126 pub color: Color,
127 pub gradient_color: Color,
128 pub circle_outline_color: Color,
129 pub children: Vec<SerializableNode>,
130}
131
132#[derive(Debug, Serialize, Deserialize)]
133pub struct NodeOptions {
134 pub node_type: NodeType,
135 pub is_static: bool,
136 pub is_stretchy: bool,
137 pub is_smart_stretch: bool,
138 pub do_not_apply_smart_stretch: bool,
139 pub use_segment_color: bool,
140 pub use_circle_outline: bool,
141 pub circle_is_hollow: bool,
142 pub use_gradient: bool,
143 pub reverse_gradient: bool,
144 pub gradient_mode: i16,
145 pub use_segment_scale: bool,
146 pub local_x: f32,
147 pub local_y: f32,
148 pub scale: f32,
149 pub default_length: f32,
150 pub length: f32,
151 pub default_thickness: i32,
152 pub thickness: i32,
153 pub segment_curve_radius_and_default_curve_radius: i32,
154 pub curve_circulization: bool,
155 pub segment_curve_polyfill_precision: i16,
156 pub half_arc: bool,
157 pub right_triangle_direction: i16,
158 pub triangle_upside_down: bool,
159 pub trapezoid_top_thickness_ratio: f32,
160 pub num_polygon_vertices: i16,
161 pub default_local_angle: f32,
162 pub local_angle: f32,
163 pub default_angle: f32,
164 pub color: Color,
165 pub gradient_color: Color,
166 pub circle_outline_color: Color,
167}
168
169impl Default for NodeOptions {
170 fn default() -> Self {
171 Self {
172 node_type: NodeType::default(),
173 is_static: false,
174 is_stretchy: false,
175 is_smart_stretch: false,
176 do_not_apply_smart_stretch: false,
177 use_segment_color: false,
178 use_circle_outline: false,
179 circle_is_hollow: false,
180 use_gradient: false,
181 reverse_gradient: false,
182 gradient_mode: 0,
183 use_segment_scale: false,
184 local_x: 0.0,
185 local_y: 0.0,
186 scale: 1.0,
187 default_length: 0.0,
188 length: 0.0,
189 default_thickness: 0,
190 thickness: 0,
191 segment_curve_radius_and_default_curve_radius: 0,
192 curve_circulization: false,
193 segment_curve_polyfill_precision: 0,
194 half_arc: false,
195 right_triangle_direction: 0,
196 triangle_upside_down: false,
197 trapezoid_top_thickness_ratio: 0.0,
198 num_polygon_vertices: 0,
199 default_local_angle: 0.0,
200 local_angle: 0.0,
201 default_angle: 0.0,
202 color: Color::default(),
203 gradient_color: Color::default(),
204 circle_outline_color: Color::default(),
205 }
206 }
207}
208
209impl Node {
210 pub fn new() -> Self {
212 Node::default()
213 }
214
215 pub fn from_options(options: NodeOptions) -> Self {
216 let mut node_type = options.node_type.clone();
217 if options.node_type.to_integer() == NodeType::RootNode.to_integer() {
218 node_type = NodeType::RoundedSegment;
219 }
220 Self {
221 node_type: node_type,
222 is_static: options.is_static,
223 is_stretchy: options.is_stretchy,
224 is_smart_stretch: options.is_smart_stretch,
225 do_not_apply_smart_stretch: options.do_not_apply_smart_stretch,
226 use_segment_color: options.use_segment_color,
227 use_circle_outline: options.use_circle_outline,
228 circle_is_hollow: options.circle_is_hollow,
229 use_gradient: options.use_gradient,
230 reverse_gradient: options.reverse_gradient,
231 gradient_mode: options.gradient_mode,
232 use_segment_scale: options.use_segment_scale,
233 local_x: options.local_x,
234 local_y: options.local_y,
235 scale: options.scale,
236 default_length: options.default_length,
237 length: options.length,
238 default_thickness: options.default_thickness,
239 thickness: options.thickness,
240 segment_curve_radius_and_default_curve_radius: options
241 .segment_curve_radius_and_default_curve_radius,
242 curve_circulization: options.curve_circulization,
243 segment_curve_polyfill_precision: options.segment_curve_polyfill_precision,
244 half_arc: options.half_arc,
245 right_triangle_direction: options.right_triangle_direction,
246 triangle_upside_down: options.triangle_upside_down,
247 trapezoid_top_thickness_ratio: options.trapezoid_top_thickness_ratio,
248 num_polygon_vertices: options.num_polygon_vertices,
249 default_local_angle: options.default_local_angle,
250 local_angle: options.local_angle,
251 default_angle: options.default_angle,
252 color: options.color,
253 gradient_color: options.gradient_color,
254 circle_outline_color: options.circle_outline_color,
255 ..Default::default()
256 }
257 }
258
259 pub fn to_options(&self) -> NodeOptions {
260 NodeOptions {
261 node_type: self.node_type.clone(),
262 is_static: self.is_static,
263 is_stretchy: self.is_stretchy,
264 is_smart_stretch: self.is_smart_stretch,
265 do_not_apply_smart_stretch: self.do_not_apply_smart_stretch,
266 use_segment_color: self.use_segment_color,
267 use_circle_outline: self.use_circle_outline,
268 circle_is_hollow: self.circle_is_hollow,
269 use_gradient: self.use_gradient,
270 reverse_gradient: self.reverse_gradient,
271 gradient_mode: self.gradient_mode,
272 use_segment_scale: self.use_segment_scale,
273 local_x: self.local_x,
274 local_y: self.local_y,
275 scale: self.scale,
276 default_length: self.default_length,
277 length: self.length,
278 default_thickness: self.default_thickness,
279 thickness: self.thickness,
280 segment_curve_radius_and_default_curve_radius: self
281 .segment_curve_radius_and_default_curve_radius,
282 curve_circulization: self.curve_circulization,
283 segment_curve_polyfill_precision: self.segment_curve_polyfill_precision,
284 half_arc: self.half_arc,
285 right_triangle_direction: self.right_triangle_direction,
286 triangle_upside_down: self.triangle_upside_down,
287 trapezoid_top_thickness_ratio: self.trapezoid_top_thickness_ratio,
288 num_polygon_vertices: self.num_polygon_vertices,
289 default_local_angle: self.default_local_angle,
290 local_angle: self.local_angle,
291 default_angle: self.default_angle,
292 color: self.color,
293 gradient_color: self.gradient_color,
294 circle_outline_color: self.circle_outline_color,
295 }
296 }
297
298 pub fn build_serializable_tree(
299 &self,
300 graph: &Graph<Rc<RefCell<Node>>, ()>,
301 current: NodeIndex,
302 ) -> SerializableNode {
303 let node = graph.node_weight(current).expect("Bug with library. NodeIndex passed to build_serializable_tree in Node is not valid.").borrow().clone();
304 let mut children = Vec::new();
305
306 for neighbor in graph.neighbors_directed(current, petgraph::Direction::Outgoing) {
307 children.push(self.build_serializable_tree(graph, neighbor));
308 }
309
310 SerializableNode {
311 draw_order_index: node.get_draw_order_index(),
312 children,
313 node_type: node.node_type.clone(),
314 is_static: node.is_static,
315 is_stretchy: node.is_stretchy,
316 is_smart_stretch: node.is_smart_stretch,
317 do_not_apply_smart_stretch: node.do_not_apply_smart_stretch,
318 use_segment_color: node.use_segment_color,
319 use_circle_outline: node.use_circle_outline,
320 circle_is_hollow: node.circle_is_hollow,
321 use_gradient: node.use_gradient,
322 reverse_gradient: node.reverse_gradient,
323 gradient_mode: node.gradient_mode,
324 use_segment_scale: node.use_segment_scale,
325 local_x: node.local_x,
326 local_y: node.local_y,
327 scale: node.scale,
328 default_length: node.default_length,
329 length: node.length,
330 default_thickness: node.default_thickness,
331 thickness: node.thickness,
332 segment_curve_radius_and_default_curve_radius: node
333 .segment_curve_radius_and_default_curve_radius,
334 curve_circulization: node.curve_circulization,
335 segment_curve_polyfill_precision: node.segment_curve_polyfill_precision,
336 half_arc: node.half_arc,
337 right_triangle_direction: node.right_triangle_direction,
338 triangle_upside_down: node.triangle_upside_down,
339 trapezoid_top_thickness_ratio: node.trapezoid_top_thickness_ratio,
340 num_polygon_vertices: node.num_polygon_vertices,
341 default_local_angle: node.default_local_angle,
342 local_angle: node.local_angle,
343 default_angle: node.default_angle,
344 color: node.color,
345 gradient_color: node.gradient_color,
346 circle_outline_color: node.circle_outline_color,
347 }
348 }
349
350 pub fn get_draw_order_index(&self) -> DrawOrderIndex {
351 return self.draw_order_index;
352 }
353
354 pub fn update<F>(rc_node: &Rc<RefCell<Self>>, f: F)
355 where
356 F: FnOnce(&mut Self),
357 {
358 let mut inner = rc_node.borrow_mut();
359 f(&mut *inner);
360 }
361}
362
363#[derive(Clone, Debug, Default, Serialize, Deserialize)]
364pub enum NodeType {
365 RootNode = -1,
367 #[default]
368 RoundedSegment = 0,
369 Segment = 1,
370 Circle = 2,
371 Triangle = 3,
372 FilledCircle = 4,
373 Ellipse = 5,
374 Trapezoid = 6,
375 Polygon = 7,
376}
377
378impl NodeType {
379 pub fn from_integer(int: i8) -> Option<Self> {
380 match int {
381 -1 => Some(NodeType::RootNode),
382 0 => Some(NodeType::RoundedSegment),
383 1 => Some(NodeType::Segment),
384 2 => Some(NodeType::Circle),
385 3 => Some(NodeType::Triangle),
386 4 => Some(NodeType::FilledCircle),
387 5 => Some(NodeType::Ellipse),
388 6 => Some(NodeType::Trapezoid),
389 7 => Some(NodeType::Polygon),
390 _ => None,
391 }
392 }
393 pub fn to_integer(&self) -> i8 {
394 self.clone() as i8
395 }
396}