1use std::collections::hash_map::DefaultHasher;
2use std::collections::HashMap;
3use std::hash::{Hash, Hasher};
4use std::ops::Deref;
5use std::sync::{Arc};
6use serde_json::{Error, Value};
7use tokio::sync::RwLock;
8use crate::core::button::Button;
9use crate::core::{ButtonPanel, Panel, RawButtonPanel, UniqueButton, UniqueButtonMap};
10use crate::font::get_font_names;
11use crate::images::SDSerializedImage;
12use crate::modules::components::{UIFieldType, UIFieldValue, UIPathValue, UIValue};
13
14pub use rusttype;
15
16pub fn make_button_unique(button: Button) -> UniqueButton {
18 Arc::new(RwLock::new(button))
19}
20
21pub async fn serialize_panel(panel: ButtonPanel) -> Result<Value, Error> {
23 let panel = panel_to_raw(&panel).await;
24
25 serialize_panel_raw(panel)
26}
27
28pub fn serialize_panel_raw(panel: RawButtonPanel) -> Result<Value, Error> {
30 serde_json::to_value(panel)
31}
32
33pub fn deserialize_panel(value: Value) -> Result<ButtonPanel, Error> {
35 Ok(make_panel_unique(deserialize_panel_raw(value)?))
36}
37
38pub fn deserialize_panel_raw(value: Value) -> Result<RawButtonPanel, Error> {
40 Ok(serde_json::from_value(value)?)
41}
42
43pub fn make_panel_unique(raw_panel: RawButtonPanel) -> ButtonPanel {
45 Arc::new(RwLock::new(
46 Panel::<UniqueButtonMap> {
47 display_name: raw_panel.display_name,
48 data: raw_panel.data,
49 buttons: raw_panel.buttons.into_iter().map(|(key, button)| (key, make_button_unique(button))).collect()
50 }
51 ))
52}
53
54
55pub async fn panel_to_raw(panel: &ButtonPanel) -> RawButtonPanel {
57 let panel = (*panel.read().await).clone();
58
59 let mut buttons = HashMap::new();
60
61 for (key, button) in panel.buttons {
62 buttons.insert(key, button_to_raw(&button).await);
63 }
64
65 RawButtonPanel {
66 display_name: panel.display_name,
67 data: panel.data,
68 buttons
69 }
70}
71
72pub async fn button_to_raw(button: &UniqueButton) -> Button {
74 button.read().await.deref().clone()
75}
76
77pub fn hash_str(data: &String) -> String {
79 let mut hasher = DefaultHasher::new();
80
81 data.hash(&mut hasher);
82
83 hasher.finish().to_string()
84}
85
86pub fn hash_image(data: &SDSerializedImage) -> String {
88 let mut hasher = DefaultHasher::new();
89
90 data.hash(&mut hasher);
91
92 hasher.finish().to_string()
93}
94
95pub fn hash_value<H: Hasher>(value: &Value, state: &mut H) {
97 match value {
98 Value::Null => 0.hash(state),
99 Value::Bool(b) => b.hash(state),
100 Value::Number(n) => n.hash(state),
101 Value::String(s) => s.hash(state),
102 Value::Array(a) => a.iter().for_each(|x| hash_value(x, state)),
103 Value::Object(o) => o.iter().for_each(|(k, v)| {
104 k.hash(state);
105 hash_value(v, state)
106 }),
107 }
108}
109
110pub fn convert_value_to_path(value: UIValue, current_path: &str) -> UIPathValue {
112 let current_path = if current_path.is_empty() { "".to_string() } else { format!("{}.", current_path) };
113
114 match &value.value {
115 UIFieldValue::Collapsable(m) => {
116 let path = format!("{}{}", current_path, value.name);
117
118 let values: Vec<UIPathValue> = m.clone().into_iter()
119 .map(|x| convert_value_to_path(x, &path))
120 .collect();
121
122 UIPathValue {
123 name: value.name,
124 path,
125 display_name: value.display_name,
126 description: value.description,
127 ty: value.ty,
128 value: UIFieldValue::Collapsable(values)
129 }
130 }
131
132 UIFieldValue::Array(a) => {
133 let path = format!("{}{}", current_path, value.name);
134
135 let values: Vec<Vec<UIPathValue>> = a.clone().into_iter()
136 .enumerate()
137 .map(|(index, x)| x.into_iter()
138 .map(|y| convert_value_to_path(y, &format!("{}.{}", path, index)))
139 .collect())
140 .collect();
141
142 UIPathValue {
143 name: value.name,
144 path,
145 display_name: value.display_name,
146 description: value.description,
147 ty: value.ty,
148 value: UIFieldValue::Array(values)
149 }
150 }
151
152 _ => {
153 let path = format!("{}{}", current_path, value.name);
154
155 UIPathValue {
156 name: value.name,
157 path,
158 display_name: value.display_name,
159 description: value.description,
160 ty: value.ty,
161 value: value.value.into()
162 }
163 }
164 }
165}
166
167pub fn straight_copy(reference: &Button, new_button: &mut Button, component_name: &str) {
169 if let Some(data) = reference.0.get(component_name) {
170 new_button.0.insert(component_name.to_string(), data.clone());
171 }
172}
173
174pub fn change_from_path<T: Fn(&mut UIValue) -> bool>(path: &str, ui_values: Vec<UIValue>, func: &T, keep: bool) -> (Vec<UIValue>, bool) {
176 let mut path = path.split(".");
177
178 let mut changes = vec![];
179 let mut success = false;
180
181 if let Some(path_piece) = path.next() {
182 for mut value in ui_values {
183 if value.name == path_piece {
184 match value.value.clone() {
185 UIFieldValue::Collapsable(submenu) => {
186 let path = path.clone().collect::<Vec<&str>>().join(".");
187
188 let (changed_values, changed_success) = change_from_path(path.as_str(), submenu, func, keep);
189
190 value.value = UIFieldValue::Collapsable(changed_values);
191 success = changed_success;
192
193 changes.push(value);
194 }
195
196 UIFieldValue::Array(array) => {
197 if let Some(path_index) = path.next() {
198 if let Ok(path_index) = path_index.parse::<usize>() {
199 let mut new_array = vec![];
200
201 for (index, item) in array.into_iter().enumerate() {
202 if path_index == index {
203 let path = path.clone().collect::<Vec<&str>>().join(".");
204
205 let (changed_values, changed_success) = change_from_path(path.as_str(), item, func, true);
206 success = changed_success;
207 new_array.push(changed_values);
208 } else {
209 new_array.push(item);
210 }
211 }
212
213 value.value = UIFieldValue::Array(new_array);
214
215 changes.push(value);
216 }
217 } else {
218 success = func(&mut value);
219
220 changes.push(value);
221 }
222 }
223
224 _ => {
225 success = func(&mut value);
226
227 changes.push(value);
228 }
229 }
230 } else {
231 if keep {
232 changes.push(value);
233 }
234 }
235 }
236 }
237
238 (changes, success)
239}
240
241pub fn add_array_function() -> fn(&mut UIValue) -> bool {
243 |x| {
244 if let UIFieldType::Array(template_fields) = &x.ty {
245 let mut new_item = vec![];
246
247 for field in template_fields {
248 new_item.push(UIValue {
249 name: field.name.clone(),
250 display_name: field.display_name.clone(),
251 description: field.description.clone(),
252 ty: field.ty.clone(),
253 value: field.default_value.clone()
254 })
255 }
256
257 if let UIFieldValue::Array(array) = &mut x.value {
258 array.push(new_item);
259 true
260 } else {
261 false
262 }
263 } else {
264 false
265 }
266 }
267}
268
269pub fn remove_array_function(index: usize) -> Box<dyn Fn(&mut UIValue) -> bool> {
271 Box::new(move |x| {
272 if let UIFieldValue::Array(array) = &mut x.value {
273 array.remove(index);
274 true
275 } else {
276 false
277 }
278 })
279}
280
281pub fn set_value_function(value: UIPathValue) -> Box<dyn Fn(&mut UIValue) -> bool> {
283 let fonts = get_font_names();
284
285 Box::new(move |x| {
286 match &x.ty {
287 UIFieldType::Header |
288 UIFieldType::Label |
289 UIFieldType::Collapsable |
290 UIFieldType::Array(_) |
291 UIFieldType::Button { .. } |
292 UIFieldType::ImagePreview => false,
293
294 UIFieldType::Choice(variants) => {
295 if let Ok(variant) = value.value.try_into_string() {
296 if variants.contains(&variant) {
297 x.value = UIFieldValue::Choice(variant);
298 true
299 } else {
300 false
301 }
302 } else {
303 false
304 }
305 }
306
307 UIFieldType::InputFieldFloat => {
308 if let Ok(f) = value.value.try_into_f32() {
309 x.value = UIFieldValue::InputFieldFloat(f);
310 true
311 } else {
312 false
313 }
314 }
315
316 UIFieldType::InputFieldInteger => {
317 if let Ok(i) = value.value.try_into_i32() {
318 x.value = UIFieldValue::InputFieldInteger(i);
319 true
320 } else {
321 false
322 }
323 }
324
325 UIFieldType::InputFieldString => {
326 if let Ok(s) = value.value.try_into_string() {
327 x.value = UIFieldValue::InputFieldString(s);
328 true
329 } else {
330 false
331 }
332 }
333
334 UIFieldType::InputFieldFloat2 => {
335 if let Ok((f1, f2)) = value.value.try_into_f32_f32() {
336 x.value = UIFieldValue::InputFieldFloat2(f1, f2);
337 true
338 } else {
339 false
340 }
341 }
342
343 UIFieldType::InputFieldInteger2 => {
344 if let Ok((i1, i2)) = value.value.try_into_i32_i32() {
345 x.value = UIFieldValue::InputFieldInteger2(i1, i2);
346 true
347 } else {
348 false
349 }
350 }
351
352 UIFieldType::InputFieldUnsignedInteger => {
353 if let Ok(u) = value.value.try_into_u32() {
354 x.value = UIFieldValue::InputFieldUnsignedInteger(u);
355 true
356 } else {
357 false
358 }
359 }
360
361 UIFieldType::ValueSliderFloat(limits) => {
362 if let Ok(f) = value.value.try_into_f32() {
363 if !limits.allow_out_of_bounds {
364 x.value = UIFieldValue::ValueSliderFloat(f.clamp(limits.min_value, limits.max_value));
365 } else {
366 x.value = UIFieldValue::ValueSliderFloat(f);
367 }
368 true
369 } else {
370 false
371 }
372 }
373
374 UIFieldType::ValueSliderInteger(limits) => {
375 if let Ok(i) = value.value.try_into_i32() {
376 if !limits.allow_out_of_bounds {
377 x.value = UIFieldValue::ValueSliderInteger(i.clamp(limits.min_value, limits.max_value));
378 } else {
379 x.value = UIFieldValue::ValueSliderInteger(i);
380 }
381 true
382 } else {
383 false
384 }
385 }
386
387 UIFieldType::Checkbox { .. } => {
388 if let Ok(b) = value.value.try_into_bool() {
389 x.value = UIFieldValue::Checkbox(b);
390 true
391 } else {
392 false
393 }
394 }
395
396 UIFieldType::Color => {
397 if let Ok(b) = value.value.try_into_color() {
398 x.value = UIFieldValue::Color(b.0, b.1, b.2, b.3);
399 true
400 } else {
401 false
402 }
403 }
404
405 UIFieldType::ImageData => {
406 if let Ok(s) = value.value.try_into_string() {
407 x.value = UIFieldValue::ImageData(s);
408 true
409 } else {
410 false
411 }
412 }
413
414 UIFieldType::ExistingImage => {
415 if let Ok(s) = value.value.try_into_string() {
416 x.value = UIFieldValue::ExistingImage(s);
417 true
418 } else {
419 false
420 }
421 }
422 UIFieldType::Font => {
423 if let Ok(s) = value.value.try_into_string() {
424 if fonts.contains(&s) {
425 x.value = UIFieldValue::Font(s);
426 true
427 } else {
428 false
429 }
430 } else {
431 false
432 }
433 }
434 }
435 })
436}