1use hashbrown::HashSet;
2use serde::Deserialize;
3use serde::Serialize;
4extern crate alloc;
5use alloc::{format, vec::Vec};
6
7use crate::{color::Color, Stickfigure, StickfigureError};
8
9use super::stickfigure::DrawOrderIndex;
10
11#[derive(Debug, Serialize, Deserialize, Clone)]
12pub struct Polyfill {
13 pub anchor_node_draw_index: DrawOrderIndex,
14 pub color: Color,
15 pub use_polyfill_color: bool,
16 pub attached_node_draw_indices: Vec<DrawOrderIndex>,
17}
18
19#[derive(Debug, Serialize, Deserialize)]
20pub struct PolyfillOptions {
21 pub anchor_node_draw_index: DrawOrderIndex,
22 pub color: Color,
23 pub use_polyfill_color: bool,
24 pub attached_node_draw_indices: Vec<DrawOrderIndex>,
25}
26
27impl Default for Polyfill {
28 fn default() -> Self {
29 Self {
30 anchor_node_draw_index: DrawOrderIndex(0),
31 color: Color::default(),
32 use_polyfill_color: false,
33 attached_node_draw_indices: Vec::new(),
34 }
35 }
36}
37
38impl Default for PolyfillOptions {
39 fn default() -> Self {
40 Self {
41 anchor_node_draw_index: DrawOrderIndex(0),
42 color: Color::default(),
43 use_polyfill_color: false,
44 attached_node_draw_indices: Vec::new(),
45 }
46 }
47}
48
49impl Polyfill {
50 pub fn from_options(
51 options: PolyfillOptions,
52 stickfigure: Stickfigure,
53 ) -> Result<Self, StickfigureError> {
54 let mut indices_to_check = options.attached_node_draw_indices.clone();
55 indices_to_check.insert(0, options.anchor_node_draw_index);
56 let missing_indices = stickfigure.missing_draw_indices(&indices_to_check);
57 if missing_indices.iter().count() > 0 {
58 return Err(StickfigureError::InvalidDrawIndices(
59 format!("{:?}", missing_indices),
60 format!("Cannot create polyfill from invalid draw order indices."),
61 ));
62 }
63
64 if stickfigure.draw_index_is_polyfill_anchor(options.anchor_node_draw_index) {
65 return Err(StickfigureError::NodeIsAlreadyAnchor(
66 options.anchor_node_draw_index.0,
67 format!("Cannot create polyfill with anchor that is already occupied."),
68 ));
69 }
70
71 let mut polyfill = Polyfill::default();
72 polyfill.anchor_node_draw_index = options.anchor_node_draw_index;
73 polyfill.color = options.color;
74 polyfill.use_polyfill_color = options.use_polyfill_color;
75 polyfill.attached_node_draw_indices = options.attached_node_draw_indices;
76
77 return Ok(polyfill);
78 }
79
80 pub fn to_options(&self) -> PolyfillOptions {
81 PolyfillOptions {
82 anchor_node_draw_index: self.anchor_node_draw_index,
83 color: self.color,
84 use_polyfill_color: self.use_polyfill_color,
85 attached_node_draw_indices: self.attached_node_draw_indices.clone(),
86 }
87 }
88
89 pub fn set_attached_node_draw_indices(
90 &mut self,
91 draw_indices: Vec<DrawOrderIndex>,
92 stickfigure: Stickfigure,
93 ) -> Result<(), StickfigureError> {
94 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
95 if missing_indices.iter().count() > 0 {
96 return Err(StickfigureError::InvalidDrawIndices(
97 format!("{:?}", missing_indices),
98 format!("Cannot set attached node draw indices to invalid draw order indices."),
99 ));
100 }
101
102 let mut seen = HashSet::new();
103 let unique_draw_indices: Vec<DrawOrderIndex> = draw_indices
104 .into_iter()
105 .filter(|x| seen.insert(*x))
106 .collect();
107
108 self.attached_node_draw_indices = unique_draw_indices;
109
110 Ok(())
111 }
112
113 pub fn set_anchor_node_draw_index(
114 &mut self,
115 draw_index: DrawOrderIndex,
116 stickfigure: Stickfigure,
117 ) -> Result<(), StickfigureError> {
118 if !stickfigure.draw_index_exists(draw_index) {
119 return Err(StickfigureError::InvalidDrawIndex(
120 draw_index.0,
121 format!("Cannot set anchor node draw index to invalid draw order index."),
122 ));
123 }
124
125 if stickfigure.draw_index_is_polyfill_anchor(draw_index) {
126 return Err(StickfigureError::NodeIsAlreadyAnchor(
127 draw_index.0,
128 format!("Cannot create polyfill with anchor that is already occupied."),
129 ));
130 }
131
132 Ok(self.anchor_node_draw_index = draw_index)
133 }
134
135 pub fn insert_attached_node_draw_indices_after(
136 &mut self,
137 draw_indices: Vec<DrawOrderIndex>,
138 insert_after_draw_index: DrawOrderIndex,
139 stickfigure: Stickfigure,
140 ) -> Result<(), StickfigureError> {
141 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
142 if missing_indices.iter().count() > 0 {
143 return Err(StickfigureError::InvalidDrawIndices(
144 format!("{:?}", missing_indices),
145 format!("Cannot insert attached node draw indices that include invalid draw order indices."),
146 ));
147 }
148
149 if let Some(vec_index) = self
150 .attached_node_draw_indices
151 .iter()
152 .position(|index| *index == insert_after_draw_index)
153 {
154 self.attached_node_draw_indices
155 .splice(vec_index + 1..vec_index + 1, draw_indices);
156 } else {
157 return Err(StickfigureError::InvalidDrawIndex(
158 insert_after_draw_index.0,
159 format!("Cannot insert attached node draw indices after a node draw index that is not an attached node draw index of this polyfill."),
160 ));
161 };
162
163 Ok(())
164 }
165
166 pub fn insert_attached_node_draw_indices_before(
167 &mut self,
168 draw_indices: Vec<DrawOrderIndex>,
169 insert_before_draw_index: DrawOrderIndex,
170 stickfigure: Stickfigure,
171 ) -> Result<(), StickfigureError> {
172 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
173 if missing_indices.iter().count() > 0 {
174 return Err(StickfigureError::InvalidDrawIndices(
175 format!("{:?}", missing_indices),
176 format!("Cannot insert attached node draw indices that include invalid draw order indices."),
177 ));
178 }
179
180 if let Some(vec_index) = self
181 .attached_node_draw_indices
182 .iter()
183 .position(|index| *index == insert_before_draw_index)
184 {
185 self.attached_node_draw_indices
186 .splice(vec_index..vec_index, draw_indices);
187 } else {
188 return Err(StickfigureError::InvalidDrawIndex(
189 insert_before_draw_index.0,
190 format!("Cannot insert attached node draw indices after a node draw index that is not an attached node draw index of this polyfill."),
191 ));
192 };
193
194 Ok(())
195 }
196
197 pub fn remove_attached_node_draw_indices(
198 &mut self,
199 draw_indices: Vec<DrawOrderIndex>,
200 stickfigure: Stickfigure,
201 ) -> Result<(), StickfigureError> {
202 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
203 if missing_indices.iter().count() > 0 {
204 return Err(StickfigureError::InvalidDrawIndices(
205 format!("{:?}", missing_indices),
206 format!("Cannot remove attached node draw indices that include invalid draw order indices."),
207 ));
208 }
209
210 let indices: Vec<DrawOrderIndex> = self
211 .attached_node_draw_indices
212 .iter()
213 .map(|i| *i)
214 .filter(|draw_index| !draw_indices.contains(draw_index))
215 .collect();
216
217 self.attached_node_draw_indices = indices;
218
219 Ok(())
220 }
221
222 pub fn try_set_attached_node_draw_indices(
223 &mut self,
224 draw_indices: Vec<DrawOrderIndex>,
225 stickfigure: Stickfigure,
226 ) -> Vec<DrawOrderIndex> {
227 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
228
229 let valid_indices = draw_indices
230 .iter()
231 .map(|i| *i)
232 .filter(|index| !missing_indices.contains(index))
233 .collect();
234
235 self.attached_node_draw_indices = valid_indices;
236
237 missing_indices
238 }
239
240 pub fn try_remove_attached_node_draw_indices(
262 &mut self,
263 draw_indices: Vec<DrawOrderIndex>,
264 stickfigure: Stickfigure,
265 ) -> Vec<DrawOrderIndex> {
266 let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
267
268 let valid_indices: Vec<DrawOrderIndex> = draw_indices
269 .iter()
270 .map(|i| *i)
271 .filter(|index| !missing_indices.contains(index))
272 .collect();
273
274 let indices: Vec<DrawOrderIndex> = self
275 .attached_node_draw_indices
276 .iter()
277 .map(|i| *i)
278 .filter(|draw_index| !valid_indices.contains(draw_index))
279 .collect();
280
281 self.attached_node_draw_indices = indices;
282
283 missing_indices
284 }
285}