sticknodes_rs/structs/
polyfill.rs

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    // below methods are commented out because I don't know if they'd be worth existing since there would have to be some kind of special return for if the provided index to insert after/before is invalid.. which kind of defeats the point of the method. At that point just handle the error of the non try versions lol
241    // pub fn try_insert_attached_node_draw_indices_after(&mut self, draw_indices: Vec<DrawOrderIndex>, insert_after_draw_index: DrawOrderIndex, stickfigure: Stickfigure) -> Vec<DrawOrderIndex> {
242    //     let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
243
244    //     let valid_indices: Vec<DrawOrderIndex> = draw_indices.iter().map(|i| *i).filter(|index| !missing_indices.contains(index)).collect();
245
246    //     self.attached_node_draw_indices.splice(insert_after_draw_index + 1..insert_after_draw_index + 1, valid_indices);
247
248    //     missing_indices
249    // }
250
251    // pub fn try_insert_attached_node_draw_indices_before(&mut self, draw_indices: Vec<DrawOrderIndex>, insert_before_draw_index: DrawOrderIndex, stickfigure: Stickfigure) -> Vec<DrawOrderIndex> {
252    //     let missing_indices = stickfigure.missing_draw_indices(&draw_indices);
253
254    //     let valid_indices: Vec<DrawOrderIndex> = draw_indices.iter().map(|i| *i).filter(|index| !missing_indices.contains(index)).collect();
255
256    //     self.attached_node_draw_indices.splice(insert_before_draw_index..insert_before_draw_index, valid_indices);
257
258    //     missing_indices
259    // }
260
261    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}