1use eframe::{
23 Result,
24 emath::Rect,
25 epaint::{Stroke, textures::TextureOptions},
26};
27use egui::{
28 Color32, ColorImage, Context, CursorIcon, FontData, FontDefinitions, FontFamily, FontId,
29 Galley, Id, ImageSource, Key, OpenUrl, PointerButton, Pos2, Sense, StrokeKind, TextureHandle,
30 Ui, Vec2, text::CCursor,
31};
32use std::{
33 any::Any,
34 error::Error,
35 fmt::{Debug, Display, Formatter},
36 fs::{File, read},
37 io::Read,
38 sync::Arc,
39 time::Instant,
40 vec::Vec,
41};
42
43pub trait RustConstructorResource: Debug {
45 fn name(&self) -> &str;
47
48 fn expose_type(&self) -> &str;
50
51 fn active(&self) -> bool;
53
54 fn modify_active(&mut self, active: bool);
56
57 fn as_any(&self) -> &dyn Any;
59
60 fn as_any_mut(&mut self) -> &mut dyn Any;
62}
63
64pub trait BasicFrontResource: RustConstructorResource {
66 fn display_size(&self) -> [f32; 2];
68
69 fn display_position(&self) -> [f32; 2];
71
72 fn display_offset(&self) -> [f32; 2];
74
75 fn display_clip_rect(&self) -> &Option<PositionConfig>;
77
78 fn display_panel_name(&self) -> &str;
80
81 fn display_panel_layout(&self) -> &Option<(PanelLocation, PanelLayout)>;
83
84 fn display_center_display(&self) -> &(HorizontalAlign, VerticalAlign);
86
87 fn display_allow_scrolling(&self) -> [bool; 2];
89
90 fn modify_size(&mut self, width: f32, height: f32);
92
93 fn modify_position(&mut self, x: f32, y: f32);
95
96 fn modify_offset(&mut self, x: f32, y: f32);
98
99 fn modify_clip_rect(&mut self, clip_rect: &Option<PositionConfig>);
101
102 fn modify_panel_name(&mut self, panel_name: &str);
104
105 fn modify_panel_layout(&mut self, panel_layout: &Option<(PanelLocation, PanelLayout)>);
107
108 fn modify_center_display(
110 &mut self,
111 horizontal_align: &HorizontalAlign,
112 vertical_align: &VerticalAlign,
113 );
114
115 fn modify_allow_scrolling(&mut self, horizontal: bool, vertical: bool);
117}
118
119#[derive(Debug, Clone, PartialEq, PartialOrd)]
121pub struct PositionConfig {
122 pub origin_position: [f32; 2],
124 pub origin_size: [f32; 2],
126 pub x_location_grid: [u32; 2],
128 pub y_location_grid: [u32; 2],
130 pub x_size_grid: [u32; 2],
132 pub y_size_grid: [u32; 2],
134 pub center_display: (HorizontalAlign, VerticalAlign),
136 pub offset: [f32; 2],
138}
139
140impl Default for PositionConfig {
141 fn default() -> Self {
142 PositionConfig {
143 origin_position: [0_f32, 0_f32],
144 origin_size: [100_f32, 100_f32],
145 x_location_grid: [0, 0],
146 y_location_grid: [0, 0],
147 x_size_grid: [0, 0],
148 y_size_grid: [0, 0],
149 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
150 offset: [0_f32, 0_f32],
151 }
152 }
153}
154
155impl PositionConfig {
156 pub fn from_image(image: &Image) -> Self {
157 Self {
158 origin_position: image.origin_position,
159 origin_size: image.origin_size,
160 x_size_grid: image.x_size_grid,
161 y_size_grid: image.y_size_grid,
162 x_location_grid: image.x_location_grid,
163 y_location_grid: image.y_location_grid,
164 center_display: image.center_display,
165 offset: image.offset,
166 }
167 }
168
169 pub fn from_image_config(image_config: &ImageConfig) -> Self {
170 Self {
171 origin_position: image_config.origin_position,
172 origin_size: image_config.origin_size,
173 x_size_grid: image_config.x_size_grid,
174 y_size_grid: image_config.y_size_grid,
175 x_location_grid: image_config.x_location_grid,
176 y_location_grid: image_config.y_location_grid,
177 center_display: image_config.center_display,
178 offset: image_config.offset,
179 }
180 }
181
182 pub fn from_custom_rect(custom_rect: &CustomRect) -> Self {
183 Self {
184 origin_position: custom_rect.origin_position,
185 origin_size: custom_rect.origin_size,
186 x_size_grid: custom_rect.x_size_grid,
187 y_size_grid: custom_rect.y_size_grid,
188 x_location_grid: custom_rect.x_location_grid,
189 y_location_grid: custom_rect.y_location_grid,
190 center_display: custom_rect.center_display,
191 offset: custom_rect.offset,
192 }
193 }
194
195 pub fn from_custom_rect_config(custom_rect_config: &CustomRectConfig) -> Self {
196 Self {
197 origin_position: custom_rect_config.origin_position,
198 origin_size: custom_rect_config.origin_size,
199 x_size_grid: custom_rect_config.x_size_grid,
200 y_size_grid: custom_rect_config.y_size_grid,
201 x_location_grid: custom_rect_config.x_location_grid,
202 y_location_grid: custom_rect_config.y_location_grid,
203 center_display: custom_rect_config.center_display,
204 offset: custom_rect_config.offset,
205 }
206 }
207
208 pub fn from_text(text: &Text) -> Self {
209 Self {
210 origin_position: text.origin_position,
211 origin_size: text.origin_size,
212 x_size_grid: text.x_size_grid,
213 y_size_grid: text.y_size_grid,
214 x_location_grid: text.x_location_grid,
215 y_location_grid: text.y_location_grid,
216 center_display: text.center_display,
217 offset: text.offset,
218 }
219 }
220
221 pub fn from_text_config(text_config: &TextConfig) -> Self {
222 Self {
223 origin_position: text_config.origin_position,
224 origin_size: text_config.origin_size,
225 x_size_grid: text_config.x_size_grid,
226 y_size_grid: text_config.y_size_grid,
227 x_location_grid: text_config.x_location_grid,
228 y_location_grid: text_config.y_location_grid,
229 center_display: text_config.center_display,
230 offset: text_config.offset,
231 }
232 }
233
234 pub fn from_mouse_detector(mouse_detector: &MouseDetector) -> Self {
235 Self {
236 origin_position: mouse_detector.origin_position,
237 origin_size: mouse_detector.origin_size,
238 x_size_grid: mouse_detector.x_size_grid,
239 y_size_grid: mouse_detector.y_size_grid,
240 x_location_grid: mouse_detector.x_location_grid,
241 y_location_grid: mouse_detector.y_location_grid,
242 center_display: mouse_detector.center_display,
243 offset: mouse_detector.offset,
244 }
245 }
246
247 pub fn from_resource_panel(resource_panel: &ResourcePanel) -> Self {
248 Self {
249 origin_position: resource_panel.origin_position,
250 origin_size: resource_panel.origin_size,
251 x_size_grid: resource_panel.x_size_grid,
252 y_size_grid: resource_panel.y_size_grid,
253 x_location_grid: resource_panel.x_location_grid,
254 y_location_grid: resource_panel.y_location_grid,
255 center_display: resource_panel.center_display,
256 offset: resource_panel.offset,
257 }
258 }
259
260 #[inline]
261 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
262 self.origin_position = [x, y];
263 self
264 }
265
266 #[inline]
267 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
268 self.origin_size = [width, height];
269 self
270 }
271
272 #[inline]
273 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
274 self.x_size_grid = [fetch, total];
275 self
276 }
277
278 #[inline]
279 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
280 self.y_size_grid = [fetch, total];
281 self
282 }
283
284 #[inline]
285 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
286 self.x_location_grid = [fetch, total];
287 self
288 }
289
290 #[inline]
291 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
292 self.y_location_grid = [fetch, total];
293 self
294 }
295
296 #[inline]
297 pub fn center_display(
298 mut self,
299 horizontal_align: HorizontalAlign,
300 vertical_align: VerticalAlign,
301 ) -> Self {
302 self.center_display = (horizontal_align, vertical_align);
303 self
304 }
305
306 #[inline]
307 pub fn offset(mut self, x: f32, y: f32) -> Self {
308 self.offset = [x, y];
309 self
310 }
311}
312
313#[derive(Debug, Clone, PartialEq, PartialOrd)]
315pub struct ReportState {
316 pub current_page: String,
318 pub current_total_runtime: f32,
320 pub current_page_runtime: f32,
322}
323
324#[derive(Debug, Clone, PartialEq, PartialOrd)]
326pub struct Problem {
327 pub severity_level: SeverityLevel,
329 pub problem: String,
331 pub annotation: String,
333 pub report_state: ReportState,
335 pub problem_type: RustConstructorError,
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
341pub enum SeverityLevel {
342 MildWarning,
344 SevereWarning,
346 Error,
348}
349
350#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
352pub enum PanelLayout {
353 Vertical(f32, f32, f32, f32, bool),
355 Horizontal(f32, f32, f32, f32, bool),
357 None(f32, f32, f32, f32, bool),
359}
360
361#[derive(Debug, Clone, PartialEq, PartialOrd)]
363pub enum PanelLocation {
364 Absolute(f32, f32),
366 Relative([[u32; 2]; 2]),
368}
369
370#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
372pub struct PageData {
373 pub discern_type: String,
374 pub name: String,
375 pub active: bool,
376 pub forced_update: bool,
378 pub change_page_updated: bool,
380 pub enter_page_updated: bool,
382}
383
384impl RustConstructorResource for PageData {
385 fn name(&self) -> &str {
386 &self.name
387 }
388
389 fn expose_type(&self) -> &str {
390 &self.discern_type
391 }
392
393 fn active(&self) -> bool {
394 self.active
395 }
396
397 fn modify_active(&mut self, active: bool) {
398 self.active = active;
399 }
400
401 fn as_any(&self) -> &dyn Any {
402 self
403 }
404
405 fn as_any_mut(&mut self) -> &mut dyn Any {
406 self
407 }
408}
409
410impl Default for PageData {
411 fn default() -> Self {
412 PageData {
413 discern_type: String::from("PageData"),
414 name: String::from("PageData"),
415 active: false,
416 forced_update: true,
417 change_page_updated: false,
418 enter_page_updated: false,
419 }
420 }
421}
422
423impl PageData {
424 #[inline]
425 pub fn name(mut self, name: &str) -> Self {
426 self.name = name.to_string();
427 self
428 }
429
430 #[inline]
431 pub fn forced_update(mut self, forced_update: bool) -> Self {
432 self.forced_update = forced_update;
433 self
434 }
435}
436
437#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
439pub struct Timer {
440 pub start_time: f32,
442 pub total_time: f32,
444 pub timer: Instant,
446 pub now_time: f32,
448}
449
450impl Default for Timer {
451 fn default() -> Self {
452 Timer {
453 start_time: 0_f32,
454 total_time: 0_f32,
455 timer: Instant::now(),
456 now_time: 0_f32,
457 }
458 }
459}
460
461#[derive(Clone, PartialEq, Eq, Hash)]
463pub struct DebugTextureHandle(TextureHandle);
464
465impl Debug for DebugTextureHandle {
466 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
467 f.debug_struct("DebugTextureHandle").finish()
469 }
470}
471
472impl DebugTextureHandle {
473 pub fn new(texture_handle: TextureHandle) -> Self {
474 Self(texture_handle)
475 }
476}
477
478#[derive(Debug, Clone, PartialEq)]
480pub struct ImageTexture {
481 pub discern_type: String,
482 pub name: String,
483 pub active: bool,
484 pub texture: Option<DebugTextureHandle>,
486 pub cite_path: String,
488 pub flip: [bool; 2],
490 pub ctx: Context,
492}
493
494impl RustConstructorResource for ImageTexture {
495 fn name(&self) -> &str {
496 &self.name
497 }
498
499 fn expose_type(&self) -> &str {
500 &self.discern_type
501 }
502
503 fn active(&self) -> bool {
504 self.active
505 }
506
507 fn modify_active(&mut self, active: bool) {
508 self.active = active;
509 }
510
511 fn as_any(&self) -> &dyn Any {
512 self
513 }
514
515 fn as_any_mut(&mut self) -> &mut dyn Any {
516 self
517 }
518}
519
520impl Default for ImageTexture {
521 fn default() -> Self {
522 ImageTexture {
523 discern_type: String::from("ImageTexture"),
524 name: String::from("ImageTexture"),
525 active: false,
526 texture: None,
527 cite_path: String::from(""),
528 flip: [false, false],
529 ctx: Context::default(),
530 }
531 }
532}
533
534impl ImageTexture {
535 #[inline]
536 pub fn name(mut self, name: &str) -> Self {
537 self.name = name.to_string();
538 self
539 }
540
541 #[inline]
542 pub fn cite_path(mut self, cite_path: &str) -> Self {
543 self.cite_path = cite_path.to_string();
544 self
545 }
546
547 #[inline]
548 pub fn flip(mut self, horizontal_flip: bool, vertical_flip: bool) -> Self {
549 self.flip = [horizontal_flip, vertical_flip];
550 self
551 }
552
553 #[inline]
554 pub fn ctx(mut self, ctx: &Context) -> Self {
555 self.ctx = ctx.clone();
556 self
557 }
558}
559
560#[derive(Debug, Clone, PartialEq, PartialOrd)]
562pub struct CustomRectConfig {
563 pub origin_size: [f32; 2],
565 pub x_size_grid: [u32; 2],
567 pub y_size_grid: [u32; 2],
569 pub rounding: f32,
571 pub x_location_grid: [u32; 2],
573 pub y_location_grid: [u32; 2],
575 pub center_display: (HorizontalAlign, VerticalAlign),
577 pub offset: [f32; 2],
579 pub color: [u8; 4],
581 pub border_width: f32,
583 pub border_color: [u8; 4],
585 pub origin_position: [f32; 2],
587 pub clip_rect: Option<PositionConfig>,
589 pub panel_name: String,
591 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
593 pub allow_scrolling: [bool; 2],
595}
596
597impl Default for CustomRectConfig {
598 fn default() -> Self {
599 Self {
600 origin_size: [100_f32, 100_f32],
601 x_size_grid: [0, 0],
602 y_size_grid: [0, 0],
603 rounding: 2_f32,
604 x_location_grid: [0, 0],
605 y_location_grid: [0, 0],
606 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
607 offset: [0_f32, 0_f32],
608 color: [255, 255, 255, 255],
609 border_width: 2_f32,
610 border_color: [0, 0, 0, 255],
611 origin_position: [0_f32, 0_f32],
612 clip_rect: None,
613 panel_name: String::new(),
614 panel_layout: None,
615 allow_scrolling: [false, false],
616 }
617 }
618}
619
620impl CustomRectConfig {
621 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
622 self.origin_position = position_config.origin_position;
623 self.origin_size = position_config.origin_size;
624 self.x_size_grid = position_config.x_size_grid;
625 self.y_size_grid = position_config.y_size_grid;
626 self.x_location_grid = position_config.x_location_grid;
627 self.y_location_grid = position_config.y_location_grid;
628 self.center_display = position_config.center_display;
629 self.offset = position_config.offset;
630 self
631 }
632
633 pub fn from_custom_rect(custom_rect: &CustomRect) -> Self {
634 Self {
635 origin_size: custom_rect.origin_size,
636 x_size_grid: custom_rect.x_size_grid,
637 y_size_grid: custom_rect.y_size_grid,
638 rounding: custom_rect.rounding,
639 x_location_grid: custom_rect.x_location_grid,
640 y_location_grid: custom_rect.y_location_grid,
641 center_display: custom_rect.center_display,
642 offset: custom_rect.offset,
643 color: custom_rect.color,
644 border_width: custom_rect.border_width,
645 border_color: custom_rect.border_color,
646 origin_position: custom_rect.origin_position,
647 clip_rect: custom_rect.clip_rect.clone(),
648 panel_name: custom_rect.panel_name.clone(),
649 panel_layout: custom_rect.panel_layout.clone(),
650 allow_scrolling: custom_rect.allow_scrolling,
651 }
652 }
653
654 #[inline]
655 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
656 self.origin_size = [width, height];
657 self
658 }
659
660 #[inline]
661 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
662 self.x_size_grid = [fetch, total];
663 self
664 }
665
666 #[inline]
667 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
668 self.y_size_grid = [fetch, total];
669 self
670 }
671
672 #[inline]
673 pub fn rounding(mut self, rounding: f32) -> Self {
674 self.rounding = rounding;
675 self
676 }
677
678 #[inline]
679 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
680 self.x_location_grid = [fetch, total];
681 self
682 }
683
684 #[inline]
685 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
686 self.y_location_grid = [fetch, total];
687 self
688 }
689
690 #[inline]
691 pub fn center_display(
692 mut self,
693 horizontal_align: HorizontalAlign,
694 vertical_align: VerticalAlign,
695 ) -> Self {
696 self.center_display = (horizontal_align, vertical_align);
697 self
698 }
699
700 #[inline]
701 pub fn offset(mut self, x: f32, y: f32) -> Self {
702 self.offset = [x, y];
703 self
704 }
705
706 #[inline]
707 pub fn color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
708 self.color = [r, g, b, a];
709 self
710 }
711
712 #[inline]
713 pub fn border_width(mut self, border_width: f32) -> Self {
714 self.border_width = border_width;
715 self
716 }
717
718 #[inline]
719 pub fn border_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
720 self.border_color = [r, g, b, a];
721 self
722 }
723
724 #[inline]
725 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
726 self.origin_position = [x, y];
727 self
728 }
729
730 #[inline]
731 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
732 self.clip_rect = clip_rect;
733 self
734 }
735
736 #[inline]
737 pub fn panel_name(mut self, panel_name: &str) -> Self {
738 self.panel_name = panel_name.to_string();
739 self
740 }
741
742 #[inline]
743 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
744 self.panel_layout = panel_layout;
745 self
746 }
747
748 #[inline]
749 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
750 self.allow_scrolling = [horizontal, vertical];
751 self
752 }
753}
754
755#[derive(Debug, Clone, PartialEq, PartialOrd)]
757pub struct CustomRect {
758 pub discern_type: String,
759 pub name: String,
760 pub active: bool,
761 pub position: [f32; 2],
763 pub size: [f32; 2],
765 pub origin_size: [f32; 2],
767 pub x_size_grid: [u32; 2],
769 pub y_size_grid: [u32; 2],
771 pub rounding: f32,
773 pub x_location_grid: [u32; 2],
775 pub y_location_grid: [u32; 2],
777 pub center_display: (HorizontalAlign, VerticalAlign),
779 pub offset: [f32; 2],
781 pub color: [u8; 4],
783 pub border_width: f32,
785 pub border_color: [u8; 4],
787 pub origin_position: [f32; 2],
789 pub clip_rect: Option<PositionConfig>,
791 pub panel_name: String,
793 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
795 pub allow_scrolling: [bool; 2],
797}
798
799impl RustConstructorResource for CustomRect {
800 fn name(&self) -> &str {
801 &self.name
802 }
803
804 fn expose_type(&self) -> &str {
805 &self.discern_type
806 }
807
808 fn active(&self) -> bool {
809 self.active
810 }
811
812 fn modify_active(&mut self, active: bool) {
813 self.active = active;
814 }
815
816 fn as_any(&self) -> &dyn Any {
817 self
818 }
819
820 fn as_any_mut(&mut self) -> &mut dyn Any {
821 self
822 }
823}
824
825impl BasicFrontResource for CustomRect {
826 fn display_position(&self) -> [f32; 2] {
827 self.position
828 }
829
830 fn display_size(&self) -> [f32; 2] {
831 self.size
832 }
833
834 fn display_offset(&self) -> [f32; 2] {
835 self.offset
836 }
837
838 fn display_clip_rect(&self) -> &Option<PositionConfig> {
839 &self.clip_rect
840 }
841
842 fn display_panel_name(&self) -> &str {
843 &self.panel_name
844 }
845
846 fn display_panel_layout(&self) -> &Option<(PanelLocation, PanelLayout)> {
847 &self.panel_layout
848 }
849
850 fn display_center_display(&self) -> &(HorizontalAlign, VerticalAlign) {
851 &self.center_display
852 }
853
854 fn display_allow_scrolling(&self) -> [bool; 2] {
855 self.allow_scrolling
856 }
857
858 fn modify_position(&mut self, x: f32, y: f32) {
859 self.origin_position = [x, y];
860 }
861
862 fn modify_size(&mut self, width: f32, height: f32) {
863 self.origin_size = [width, height];
864 }
865
866 fn modify_offset(&mut self, x: f32, y: f32) {
867 self.offset = [x, y];
868 }
869
870 fn modify_clip_rect(&mut self, clip_rect: &Option<PositionConfig>) {
871 self.clip_rect = clip_rect.clone();
872 }
873
874 fn modify_panel_name(&mut self, panel_name: &str) {
875 self.panel_name = panel_name.to_string();
876 }
877
878 fn modify_panel_layout(&mut self, panel_layout: &Option<(PanelLocation, PanelLayout)>) {
879 self.panel_layout = panel_layout.clone();
880 }
881
882 fn modify_center_display(
883 &mut self,
884 horizontal_align: &HorizontalAlign,
885 vertical_align: &VerticalAlign,
886 ) {
887 self.center_display = (*horizontal_align, *vertical_align);
888 }
889
890 fn modify_allow_scrolling(&mut self, horizontal: bool, vertical: bool) {
891 self.allow_scrolling = [horizontal, vertical];
892 }
893}
894
895impl Default for CustomRect {
896 fn default() -> Self {
897 Self {
898 discern_type: String::from("CustomRect"),
899 name: String::from("CustomRect"),
900 active: false,
901 position: [0_f32, 0_f32],
902 size: [100_f32, 100_f32],
903 origin_size: [100_f32, 100_f32],
904 x_size_grid: [0, 0],
905 y_size_grid: [0, 0],
906 rounding: 2_f32,
907 x_location_grid: [0, 0],
908 y_location_grid: [0, 0],
909 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
910 offset: [0_f32, 0_f32],
911 color: [255, 255, 255, 255],
912 border_width: 2_f32,
913 border_color: [0, 0, 0, 255],
914 origin_position: [0_f32, 0_f32],
915 clip_rect: None,
916 panel_name: String::new(),
917 panel_layout: None,
918 allow_scrolling: [false, false],
919 }
920 }
921}
922
923impl CustomRect {
924 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
925 self.origin_position = position_config.origin_position;
926 self.origin_size = position_config.origin_size;
927 self.x_size_grid = position_config.x_size_grid;
928 self.y_size_grid = position_config.y_size_grid;
929 self.x_location_grid = position_config.x_location_grid;
930 self.y_location_grid = position_config.y_location_grid;
931 self.center_display = position_config.center_display;
932 self.offset = position_config.offset;
933 self
934 }
935
936 pub fn from_config(mut self, config: &CustomRectConfig) -> Self {
937 self.origin_size = config.origin_size;
938 self.x_size_grid = config.x_size_grid;
939 self.y_size_grid = config.y_size_grid;
940 self.rounding = config.rounding;
941 self.x_location_grid = config.x_location_grid;
942 self.y_location_grid = config.y_location_grid;
943 self.center_display = config.center_display;
944 self.offset = config.offset;
945 self.color = config.color;
946 self.border_width = config.border_width;
947 self.border_color = config.border_color;
948 self.origin_position = config.origin_position;
949 self.clip_rect = config.clip_rect.clone();
950 self.panel_name = config.panel_name.clone();
951 self.panel_layout = config.panel_layout.clone();
952 self.allow_scrolling = config.allow_scrolling;
953 self
954 }
955
956 #[inline]
957 pub fn name(mut self, name: &str) -> Self {
958 self.name = name.to_string();
959 self
960 }
961
962 #[inline]
963 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
964 self.origin_size = [width, height];
965 self
966 }
967
968 #[inline]
969 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
970 self.x_size_grid = [fetch, total];
971 self
972 }
973
974 #[inline]
975 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
976 self.y_size_grid = [fetch, total];
977 self
978 }
979
980 #[inline]
981 pub fn rounding(mut self, rounding: f32) -> Self {
982 self.rounding = rounding;
983 self
984 }
985
986 #[inline]
987 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
988 self.x_location_grid = [fetch, total];
989 self
990 }
991
992 #[inline]
993 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
994 self.y_location_grid = [fetch, total];
995 self
996 }
997
998 #[inline]
999 pub fn center_display(
1000 mut self,
1001 horizontal_align: HorizontalAlign,
1002 vertical_align: VerticalAlign,
1003 ) -> Self {
1004 self.center_display = (horizontal_align, vertical_align);
1005 self
1006 }
1007
1008 #[inline]
1009 pub fn offset(mut self, x: f32, y: f32) -> Self {
1010 self.offset = [x, y];
1011 self
1012 }
1013
1014 #[inline]
1015 pub fn color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1016 self.color = [r, g, b, a];
1017 self
1018 }
1019
1020 #[inline]
1021 pub fn border_width(mut self, border_width: f32) -> Self {
1022 self.border_width = border_width;
1023 self
1024 }
1025
1026 #[inline]
1027 pub fn border_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1028 self.border_color = [r, g, b, a];
1029 self
1030 }
1031
1032 #[inline]
1033 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
1034 self.origin_position = [x, y];
1035 self
1036 }
1037
1038 #[inline]
1039 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
1040 self.clip_rect = clip_rect;
1041 self
1042 }
1043
1044 #[inline]
1045 pub fn panel_name(mut self, panel_name: &str) -> Self {
1046 self.panel_name = panel_name.to_string();
1047 self
1048 }
1049
1050 #[inline]
1051 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
1052 self.panel_layout = panel_layout;
1053 self
1054 }
1055
1056 #[inline]
1057 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
1058 self.allow_scrolling = [horizontal, vertical];
1059 self
1060 }
1061}
1062
1063#[derive(Debug, Clone, PartialEq, PartialOrd)]
1065pub struct ImageConfig {
1066 pub origin_size: [f32; 2],
1068 pub x_size_grid: [u32; 2],
1070 pub y_size_grid: [u32; 2],
1072 pub x_location_grid: [u32; 2],
1074 pub y_location_grid: [u32; 2],
1076 pub center_display: (HorizontalAlign, VerticalAlign),
1078 pub offset: [f32; 2],
1080 pub alpha: u8,
1082 pub overlay_color: [u8; 4],
1084 pub background_color: [u8; 4],
1086 pub rotate_angle: f32,
1088 pub rotate_center: [f32; 2],
1090 pub origin_position: [f32; 2],
1092 pub cite_texture: String,
1094 pub clip_rect: Option<PositionConfig>,
1096 pub panel_name: String,
1098 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
1100 pub allow_scrolling: [bool; 2],
1102}
1103
1104impl Default for ImageConfig {
1105 fn default() -> Self {
1106 Self {
1107 origin_size: [100_f32, 100_f32],
1108 x_size_grid: [0, 0],
1109 y_size_grid: [0, 0],
1110 x_location_grid: [0, 0],
1111 y_location_grid: [0, 0],
1112 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
1113 offset: [0_f32, 0_f32],
1114 alpha: 255,
1115 overlay_color: [255, 255, 255, 255],
1116 background_color: [0, 0, 0, 0],
1117 rotate_angle: 0_f32,
1118 rotate_center: [0_f32, 0_f32],
1119 origin_position: [0_f32, 0_f32],
1120 cite_texture: String::from("ImageTexture"),
1121 clip_rect: None,
1122 panel_name: String::new(),
1123 panel_layout: None,
1124 allow_scrolling: [false, false],
1125 }
1126 }
1127}
1128
1129impl ImageConfig {
1130 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
1131 self.origin_position = position_config.origin_position;
1132 self.origin_size = position_config.origin_size;
1133 self.x_size_grid = position_config.x_size_grid;
1134 self.y_size_grid = position_config.y_size_grid;
1135 self.x_location_grid = position_config.x_location_grid;
1136 self.y_location_grid = position_config.y_location_grid;
1137 self.center_display = position_config.center_display;
1138 self.offset = position_config.offset;
1139 self
1140 }
1141
1142 pub fn from_image(image: &Image) -> Self {
1143 Self {
1144 origin_size: image.origin_size,
1145 x_size_grid: image.x_size_grid,
1146 y_size_grid: image.y_size_grid,
1147 x_location_grid: image.x_location_grid,
1148 y_location_grid: image.y_location_grid,
1149 center_display: image.center_display,
1150 offset: image.offset,
1151 alpha: image.alpha,
1152 overlay_color: image.overlay_color,
1153 background_color: image.background_color,
1154 rotate_angle: image.rotate_angle,
1155 rotate_center: image.rotate_center,
1156 cite_texture: image.cite_texture.clone(),
1157 origin_position: image.origin_position,
1158 clip_rect: image.clip_rect.clone(),
1159 panel_name: image.panel_name.clone(),
1160 panel_layout: image.panel_layout.clone(),
1161 allow_scrolling: image.allow_scrolling,
1162 }
1163 }
1164
1165 #[inline]
1166 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
1167 self.origin_position = [x, y];
1168 self
1169 }
1170
1171 #[inline]
1172 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
1173 self.origin_size = [width, height];
1174 self
1175 }
1176
1177 #[inline]
1178 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
1179 self.x_size_grid = [fetch, total];
1180 self
1181 }
1182
1183 #[inline]
1184 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
1185 self.y_size_grid = [fetch, total];
1186 self
1187 }
1188
1189 #[inline]
1190 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
1191 self.x_location_grid = [fetch, total];
1192 self
1193 }
1194
1195 #[inline]
1196 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
1197 self.y_location_grid = [fetch, total];
1198 self
1199 }
1200
1201 #[inline]
1202 pub fn center_display(
1203 mut self,
1204 horizontal_align: HorizontalAlign,
1205 vertical_align: VerticalAlign,
1206 ) -> Self {
1207 self.center_display = (horizontal_align, vertical_align);
1208 self
1209 }
1210
1211 #[inline]
1212 pub fn offset(mut self, x: f32, y: f32) -> Self {
1213 self.offset = [x, y];
1214 self
1215 }
1216
1217 #[inline]
1218 pub fn alpha(mut self, alpha: u8) -> Self {
1219 self.alpha = alpha;
1220 self
1221 }
1222
1223 #[inline]
1224 pub fn overlay_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1225 self.overlay_color = [r, g, b, a];
1226 self
1227 }
1228
1229 #[inline]
1230 pub fn background_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1231 self.background_color = [r, g, b, a];
1232 self
1233 }
1234
1235 #[inline]
1236 pub fn rotate_angle(mut self, rotate_angle: f32) -> Self {
1237 self.rotate_angle = rotate_angle;
1238 self
1239 }
1240
1241 #[inline]
1242 pub fn rotate_center(mut self, x: f32, y: f32) -> Self {
1243 self.rotate_center = [x, y];
1244 self
1245 }
1246
1247 #[inline]
1248 pub fn cite_texture(mut self, cite_texture: &str) -> Self {
1249 self.cite_texture = cite_texture.to_string();
1250 self
1251 }
1252
1253 #[inline]
1254 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
1255 self.clip_rect = clip_rect;
1256 self
1257 }
1258
1259 #[inline]
1260 pub fn panel_name(mut self, panel_name: &str) -> Self {
1261 self.panel_name = panel_name.to_string();
1262 self
1263 }
1264
1265 #[inline]
1266 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
1267 self.panel_layout = panel_layout;
1268 self
1269 }
1270
1271 #[inline]
1272 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
1273 self.allow_scrolling = [horizontal, vertical];
1274 self
1275 }
1276}
1277
1278#[derive(Debug, Clone, PartialEq)]
1280pub struct Image {
1281 pub discern_type: String,
1282 pub name: String,
1283 pub active: bool,
1284 pub texture: Option<DebugTextureHandle>,
1286 pub position: [f32; 2],
1288 pub size: [f32; 2],
1290 pub origin_size: [f32; 2],
1292 pub x_size_grid: [u32; 2],
1294 pub y_size_grid: [u32; 2],
1296 pub x_location_grid: [u32; 2],
1298 pub y_location_grid: [u32; 2],
1300 pub center_display: (HorizontalAlign, VerticalAlign),
1302 pub offset: [f32; 2],
1304 pub alpha: u8,
1306 pub overlay_color: [u8; 4],
1308 pub background_color: [u8; 4],
1310 pub rotate_angle: f32,
1312 pub rotate_center: [f32; 2],
1314 pub origin_position: [f32; 2],
1316 pub cite_texture: String,
1318 pub last_frame_cite_texture: String,
1320 pub clip_rect: Option<PositionConfig>,
1322 pub panel_name: String,
1324 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
1326 pub allow_scrolling: [bool; 2],
1328}
1329
1330impl RustConstructorResource for Image {
1331 fn name(&self) -> &str {
1332 &self.name
1333 }
1334
1335 fn expose_type(&self) -> &str {
1336 &self.discern_type
1337 }
1338
1339 fn active(&self) -> bool {
1340 self.active
1341 }
1342
1343 fn modify_active(&mut self, active: bool) {
1344 self.active = active;
1345 }
1346
1347 fn as_any(&self) -> &dyn Any {
1348 self
1349 }
1350
1351 fn as_any_mut(&mut self) -> &mut dyn Any {
1352 self
1353 }
1354}
1355
1356impl BasicFrontResource for Image {
1357 fn display_position(&self) -> [f32; 2] {
1358 self.position
1359 }
1360
1361 fn display_size(&self) -> [f32; 2] {
1362 self.size
1363 }
1364
1365 fn display_offset(&self) -> [f32; 2] {
1366 self.offset
1367 }
1368
1369 fn display_clip_rect(&self) -> &Option<PositionConfig> {
1370 &self.clip_rect
1371 }
1372
1373 fn display_panel_name(&self) -> &str {
1374 &self.panel_name
1375 }
1376
1377 fn display_panel_layout(&self) -> &Option<(PanelLocation, PanelLayout)> {
1378 &self.panel_layout
1379 }
1380
1381 fn display_center_display(&self) -> &(HorizontalAlign, VerticalAlign) {
1382 &self.center_display
1383 }
1384
1385 fn display_allow_scrolling(&self) -> [bool; 2] {
1386 self.allow_scrolling
1387 }
1388
1389 fn modify_position(&mut self, x: f32, y: f32) {
1390 self.origin_position = [x, y];
1391 }
1392
1393 fn modify_size(&mut self, width: f32, height: f32) {
1394 self.origin_size = [width, height];
1395 }
1396
1397 fn modify_offset(&mut self, x: f32, y: f32) {
1398 self.offset = [x, y];
1399 }
1400
1401 fn modify_clip_rect(&mut self, clip_rect: &Option<PositionConfig>) {
1402 self.clip_rect = clip_rect.clone();
1403 }
1404
1405 fn modify_panel_name(&mut self, panel_name: &str) {
1406 self.panel_name = panel_name.to_string();
1407 }
1408
1409 fn modify_panel_layout(&mut self, panel_layout: &Option<(PanelLocation, PanelLayout)>) {
1410 self.panel_layout = panel_layout.clone();
1411 }
1412
1413 fn modify_center_display(
1414 &mut self,
1415 horizontal_align: &HorizontalAlign,
1416 vertical_align: &VerticalAlign,
1417 ) {
1418 self.center_display = (*horizontal_align, *vertical_align);
1419 }
1420
1421 fn modify_allow_scrolling(&mut self, horizontal: bool, vertical: bool) {
1422 self.allow_scrolling = [horizontal, vertical];
1423 }
1424}
1425
1426impl Default for Image {
1427 fn default() -> Self {
1428 Self {
1429 discern_type: String::from("Image"),
1430 name: String::from("Image"),
1431 active: false,
1432 texture: None,
1433 position: [0_f32, 0_f32],
1434 size: [100_f32, 100_f32],
1435 origin_size: [100_f32, 100_f32],
1436 x_size_grid: [0, 0],
1437 y_size_grid: [0, 0],
1438 x_location_grid: [0, 0],
1439 y_location_grid: [0, 0],
1440 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
1441 offset: [0_f32, 0_f32],
1442 alpha: 255,
1443 overlay_color: [255, 255, 255, 255],
1444 background_color: [0, 0, 0, 0],
1445 rotate_angle: 0_f32,
1446 rotate_center: [0_f32, 0_f32],
1447 origin_position: [0_f32, 0_f32],
1448 cite_texture: String::from("ImageTexture"),
1449 last_frame_cite_texture: String::from("ImageTexture"),
1450 clip_rect: None,
1451 panel_name: String::new(),
1452 panel_layout: None,
1453 allow_scrolling: [false, false],
1454 }
1455 }
1456}
1457
1458impl Image {
1459 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
1460 self.origin_position = position_config.origin_position;
1461 self.origin_size = position_config.origin_size;
1462 self.x_size_grid = position_config.x_size_grid;
1463 self.y_size_grid = position_config.y_size_grid;
1464 self.x_location_grid = position_config.x_location_grid;
1465 self.y_location_grid = position_config.y_location_grid;
1466 self.center_display = position_config.center_display;
1467 self.offset = position_config.offset;
1468 self
1469 }
1470
1471 pub fn from_config(mut self, config: &ImageConfig) -> Self {
1472 self.origin_size = config.origin_size;
1473 self.x_size_grid = config.x_size_grid;
1474 self.y_size_grid = config.y_size_grid;
1475 self.x_location_grid = config.x_location_grid;
1476 self.y_location_grid = config.y_location_grid;
1477 self.center_display = config.center_display;
1478 self.offset = config.offset;
1479 self.alpha = config.alpha;
1480 self.overlay_color = config.overlay_color;
1481 self.background_color = config.background_color;
1482 self.rotate_angle = config.rotate_angle;
1483 self.rotate_center = config.rotate_center;
1484 self.origin_position = config.origin_position;
1485 self.cite_texture = config.cite_texture.clone();
1486 self.clip_rect = config.clip_rect.clone();
1487 self.panel_name = config.panel_name.clone();
1488 self.panel_layout = config.panel_layout.clone();
1489 self.allow_scrolling = config.allow_scrolling;
1490 self
1491 }
1492
1493 #[inline]
1494 pub fn name(mut self, name: &str) -> Self {
1495 self.name = name.to_string();
1496 self
1497 }
1498
1499 #[inline]
1500 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
1501 self.origin_position = [x, y];
1502 self
1503 }
1504
1505 #[inline]
1506 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
1507 self.origin_size = [width, height];
1508 self
1509 }
1510
1511 #[inline]
1512 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
1513 self.x_size_grid = [fetch, total];
1514 self
1515 }
1516
1517 #[inline]
1518 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
1519 self.y_size_grid = [fetch, total];
1520 self
1521 }
1522
1523 #[inline]
1524 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
1525 self.x_location_grid = [fetch, total];
1526 self
1527 }
1528
1529 #[inline]
1530 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
1531 self.y_location_grid = [fetch, total];
1532 self
1533 }
1534
1535 #[inline]
1536 pub fn center_display(
1537 mut self,
1538 horizontal_align: HorizontalAlign,
1539 vertical_align: VerticalAlign,
1540 ) -> Self {
1541 self.center_display = (horizontal_align, vertical_align);
1542 self
1543 }
1544
1545 #[inline]
1546 pub fn offset(mut self, x: f32, y: f32) -> Self {
1547 self.offset = [x, y];
1548 self
1549 }
1550
1551 #[inline]
1552 pub fn alpha(mut self, alpha: u8) -> Self {
1553 self.alpha = alpha;
1554 self
1555 }
1556
1557 #[inline]
1558 pub fn overlay_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1559 self.overlay_color = [r, g, b, a];
1560 self
1561 }
1562
1563 #[inline]
1564 pub fn background_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1565 self.background_color = [r, g, b, a];
1566 self
1567 }
1568
1569 #[inline]
1570 pub fn rotate_angle(mut self, rotate_angle: f32) -> Self {
1571 self.rotate_angle = rotate_angle;
1572 self
1573 }
1574
1575 #[inline]
1576 pub fn rotate_center(mut self, x: f32, y: f32) -> Self {
1577 self.rotate_center = [x, y];
1578 self
1579 }
1580
1581 #[inline]
1582 pub fn cite_texture(mut self, cite_texture: &str) -> Self {
1583 self.cite_texture = cite_texture.to_string();
1584 self
1585 }
1586
1587 #[inline]
1588 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
1589 self.clip_rect = clip_rect;
1590 self
1591 }
1592
1593 #[inline]
1594 pub fn panel_name(mut self, panel_name: &str) -> Self {
1595 self.panel_name = panel_name.to_string();
1596 self
1597 }
1598
1599 #[inline]
1600 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
1601 self.panel_layout = panel_layout;
1602 self
1603 }
1604
1605 #[inline]
1606 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
1607 self.allow_scrolling = [horizontal, vertical];
1608 self
1609 }
1610}
1611
1612#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1614pub enum HyperlinkSelectMethod {
1615 All(String),
1617 Segment(Vec<(usize, String)>),
1619}
1620
1621#[derive(Debug, Clone, PartialEq, PartialOrd)]
1623pub struct TextConfig {
1624 pub content: String,
1626 pub font_size: f32,
1628 pub color: [u8; 4],
1630 pub center_display: (HorizontalAlign, VerticalAlign),
1632 pub offset: [f32; 2],
1634 pub background_color: [u8; 4],
1636 pub background_rounding: f32,
1638 pub origin_size: [f32; 2],
1640 pub x_size_grid: [u32; 2],
1642 pub y_size_grid: [u32; 2],
1644 pub x_location_grid: [u32; 2],
1646 pub y_location_grid: [u32; 2],
1648 pub origin_position: [f32; 2],
1650 pub font: String,
1652 pub selectable: bool,
1654 pub hyperlink_text: Vec<(String, HyperlinkSelectMethod)>,
1656 pub truncate: bool,
1658 pub clip_rect: Option<PositionConfig>,
1660 pub panel_name: String,
1662 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
1664 pub allow_scrolling: [bool; 2],
1666}
1667
1668impl Default for TextConfig {
1669 fn default() -> Self {
1670 Self {
1671 content: String::from("Hello world"),
1672 font_size: 16_f32,
1673 origin_size: [0_f32, 0_f32],
1674 x_size_grid: [0, 0],
1675 y_size_grid: [0, 0],
1676 color: [255, 255, 255, 255],
1677 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
1678 offset: [0_f32, 0_f32],
1679 background_color: [0, 0, 0, 0],
1680 background_rounding: 2_f32,
1681 x_location_grid: [0, 0],
1682 y_location_grid: [0, 0],
1683 origin_position: [0_f32, 0_f32],
1684 font: String::new(),
1685 selectable: true,
1686 hyperlink_text: Vec::new(),
1687 truncate: false,
1688 clip_rect: None,
1689 panel_name: String::new(),
1690 panel_layout: None,
1691 allow_scrolling: [false, false],
1692 }
1693 }
1694}
1695
1696impl TextConfig {
1697 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
1698 self.origin_position = position_config.origin_position;
1699 self.origin_size = position_config.origin_size;
1700 self.x_size_grid = position_config.x_size_grid;
1701 self.y_size_grid = position_config.y_size_grid;
1702 self.x_location_grid = position_config.x_location_grid;
1703 self.y_location_grid = position_config.y_location_grid;
1704 self.center_display = position_config.center_display;
1705 self.offset = position_config.offset;
1706 self
1707 }
1708
1709 pub fn from_text(text: &Text) -> Self {
1710 Self {
1711 content: text.content.clone(),
1712 font_size: text.font_size,
1713 origin_size: text.origin_size,
1714 x_size_grid: text.x_size_grid,
1715 y_size_grid: text.y_size_grid,
1716 color: text.color,
1717 center_display: text.center_display,
1718 offset: text.offset,
1719 background_color: text.background_color,
1720 background_rounding: text.background_rounding,
1721 x_location_grid: text.x_location_grid,
1722 y_location_grid: text.y_location_grid,
1723 origin_position: text.origin_position,
1724 font: text.font.clone(),
1725 selectable: text.selectable,
1726 hyperlink_text: text.hyperlink_text.clone(),
1727 truncate: text.truncate,
1728 clip_rect: text.clip_rect.clone(),
1729 panel_name: text.panel_name.clone(),
1730 panel_layout: text.panel_layout.clone(),
1731 allow_scrolling: text.allow_scrolling,
1732 }
1733 }
1734
1735 #[inline]
1736 pub fn content(mut self, content: &str) -> Self {
1737 self.content = content.to_string();
1738 self
1739 }
1740
1741 #[inline]
1742 pub fn font_size(mut self, font_size: f32) -> Self {
1743 self.font_size = font_size;
1744 self
1745 }
1746
1747 #[inline]
1748 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
1749 self.origin_size = [width, height];
1750 self
1751 }
1752
1753 #[inline]
1754 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
1755 self.x_size_grid = [fetch, total];
1756 self
1757 }
1758
1759 #[inline]
1760 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
1761 self.y_size_grid = [fetch, total];
1762 self
1763 }
1764
1765 #[inline]
1766 pub fn color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1767 self.color = [r, g, b, a];
1768 self
1769 }
1770
1771 #[inline]
1772 pub fn center_display(
1773 mut self,
1774 horizontal_align: HorizontalAlign,
1775 vertical_align: VerticalAlign,
1776 ) -> Self {
1777 self.center_display = (horizontal_align, vertical_align);
1778 self
1779 }
1780
1781 #[inline]
1782 pub fn offset(mut self, x: f32, y: f32) -> Self {
1783 self.offset = [x, y];
1784 self
1785 }
1786
1787 #[inline]
1788 pub fn background_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
1789 self.background_color = [r, g, b, a];
1790 self
1791 }
1792
1793 #[inline]
1794 pub fn background_rounding(mut self, background_rounding: f32) -> Self {
1795 self.background_rounding = background_rounding;
1796 self
1797 }
1798
1799 #[inline]
1800 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
1801 self.x_location_grid = [fetch, total];
1802 self
1803 }
1804
1805 #[inline]
1806 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
1807 self.y_location_grid = [fetch, total];
1808 self
1809 }
1810
1811 #[inline]
1812 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
1813 self.origin_position = [x, y];
1814 self
1815 }
1816
1817 #[inline]
1818 pub fn font(mut self, font: &str) -> Self {
1819 self.font = font.to_string();
1820 self
1821 }
1822
1823 #[inline]
1824 pub fn selectable(mut self, selectable: bool) -> Self {
1825 self.selectable = selectable;
1826 self
1827 }
1828
1829 #[inline]
1830 pub fn hyperlink_text(
1831 mut self,
1832 target_text: &str,
1833 select_method: HyperlinkSelectMethod,
1834 ) -> Self {
1835 self.hyperlink_text
1836 .push((target_text.to_string(), select_method));
1837 self
1838 }
1839
1840 #[inline]
1841 pub fn truncate(mut self, truncate: bool) -> Self {
1842 self.truncate = truncate;
1843 self
1844 }
1845
1846 #[inline]
1847 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
1848 self.clip_rect = clip_rect;
1849 self
1850 }
1851
1852 #[inline]
1853 pub fn panel_name(mut self, panel_name: &str) -> Self {
1854 self.panel_name = panel_name.to_string();
1855 self
1856 }
1857
1858 #[inline]
1859 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
1860 self.panel_layout = panel_layout;
1861 self
1862 }
1863
1864 #[inline]
1865 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
1866 self.allow_scrolling = [horizontal, vertical];
1867 self
1868 }
1869}
1870
1871#[derive(Debug, Clone, PartialEq, PartialOrd)]
1873pub struct Text {
1874 pub discern_type: String,
1875 pub name: String,
1876 pub active: bool,
1877 pub content: String,
1879 pub font_size: f32,
1881 pub actual_size: [f32; 2],
1883 pub origin_size: [f32; 2],
1885 pub x_size_grid: [u32; 2],
1887 pub y_size_grid: [u32; 2],
1889 pub color: [u8; 4],
1891 pub position: [f32; 2],
1893 pub center_display: (HorizontalAlign, VerticalAlign),
1895 pub offset: [f32; 2],
1897 pub background_color: [u8; 4],
1899 pub background_rounding: f32,
1901 pub x_location_grid: [u32; 2],
1903 pub y_location_grid: [u32; 2],
1905 pub origin_position: [f32; 2],
1907 pub font: String,
1909 pub selection: Option<(usize, usize)>,
1911 pub selectable: bool,
1913 pub hyperlink_text: Vec<(String, HyperlinkSelectMethod)>,
1915 pub hyperlink_index: Vec<(usize, usize, String)>,
1917 pub last_frame_content: String,
1919 pub size: [f32; 2],
1921 pub truncate: bool,
1923 pub clip_rect: Option<PositionConfig>,
1925 pub panel_name: String,
1927 pub panel_layout: Option<(PanelLocation, PanelLayout)>,
1929 pub allow_scrolling: [bool; 2],
1931}
1932
1933impl RustConstructorResource for Text {
1934 fn name(&self) -> &str {
1935 &self.name
1936 }
1937
1938 fn expose_type(&self) -> &str {
1939 &self.discern_type
1940 }
1941
1942 fn active(&self) -> bool {
1943 self.active
1944 }
1945
1946 fn modify_active(&mut self, active: bool) {
1947 self.active = active;
1948 }
1949
1950 fn as_any(&self) -> &dyn Any {
1951 self
1952 }
1953
1954 fn as_any_mut(&mut self) -> &mut dyn Any {
1955 self
1956 }
1957}
1958
1959impl BasicFrontResource for Text {
1960 fn display_position(&self) -> [f32; 2] {
1961 self.position
1962 }
1963
1964 fn display_size(&self) -> [f32; 2] {
1965 self.actual_size
1966 }
1967
1968 fn display_offset(&self) -> [f32; 2] {
1969 self.offset
1970 }
1971
1972 fn display_clip_rect(&self) -> &Option<PositionConfig> {
1973 &self.clip_rect
1974 }
1975
1976 fn display_panel_name(&self) -> &str {
1977 &self.panel_name
1978 }
1979
1980 fn display_panel_layout(&self) -> &Option<(PanelLocation, PanelLayout)> {
1981 &self.panel_layout
1982 }
1983
1984 fn display_center_display(&self) -> &(HorizontalAlign, VerticalAlign) {
1985 &self.center_display
1986 }
1987
1988 fn display_allow_scrolling(&self) -> [bool; 2] {
1989 self.allow_scrolling
1990 }
1991
1992 fn modify_position(&mut self, x: f32, y: f32) {
1993 self.origin_position = [x, y];
1994 }
1995
1996 fn modify_size(&mut self, width: f32, height: f32) {
1997 self.origin_size = [width, height];
1998 }
1999
2000 fn modify_offset(&mut self, x: f32, y: f32) {
2001 self.offset = [x, y];
2002 }
2003
2004 fn modify_clip_rect(&mut self, clip_rect: &Option<PositionConfig>) {
2005 self.clip_rect = clip_rect.clone();
2006 }
2007
2008 fn modify_panel_name(&mut self, panel_name: &str) {
2009 self.panel_name = panel_name.to_string();
2010 }
2011
2012 fn modify_panel_layout(&mut self, panel_layout: &Option<(PanelLocation, PanelLayout)>) {
2013 self.panel_layout = panel_layout.clone();
2014 }
2015
2016 fn modify_center_display(
2017 &mut self,
2018 horizontal_align: &HorizontalAlign,
2019 vertical_align: &VerticalAlign,
2020 ) {
2021 self.center_display = (*horizontal_align, *vertical_align);
2022 }
2023
2024 fn modify_allow_scrolling(&mut self, horizontal: bool, vertical: bool) {
2025 self.allow_scrolling = [horizontal, vertical];
2026 }
2027}
2028
2029impl Default for Text {
2030 fn default() -> Self {
2031 Self {
2032 discern_type: String::from("Text"),
2033 name: String::from("Text"),
2034 active: false,
2035 content: String::from("Hello world"),
2036 font_size: 16_f32,
2037 actual_size: [0_f32, 0_f32],
2038 origin_size: [100_f32, 100_f32],
2039 x_size_grid: [0, 0],
2040 y_size_grid: [0, 0],
2041 color: [255, 255, 255, 255],
2042 position: [0_f32, 0_f32],
2043 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
2044 offset: [0_f32, 0_f32],
2045 background_color: [0, 0, 0, 0],
2046 background_rounding: 2_f32,
2047 x_location_grid: [0, 0],
2048 y_location_grid: [0, 0],
2049 origin_position: [0_f32, 0_f32],
2050 font: String::new(),
2051 selection: None,
2052 selectable: true,
2053 hyperlink_text: Vec::new(),
2054 hyperlink_index: Vec::new(),
2055 last_frame_content: String::from(""),
2056 size: [100_f32, 100_f32],
2057 truncate: false,
2058 clip_rect: None,
2059 panel_name: String::new(),
2060 panel_layout: None,
2061 allow_scrolling: [false, false],
2062 }
2063 }
2064}
2065
2066impl Text {
2067 pub fn from_position_config(mut self, position_config: &PositionConfig) -> Self {
2068 self.origin_position = position_config.origin_position;
2069 self.origin_size = position_config.origin_size;
2070 self.x_location_grid = position_config.x_location_grid;
2071 self.y_location_grid = position_config.y_location_grid;
2072 self.x_size_grid = position_config.x_size_grid;
2073 self.y_size_grid = position_config.y_size_grid;
2074 self.center_display = position_config.center_display;
2075 self.offset = position_config.offset;
2076 self
2077 }
2078
2079 pub fn from_config(mut self, config: &TextConfig) -> Self {
2080 self.content = config.content.clone();
2081 self.font_size = config.font_size;
2082 self.origin_size = config.origin_size;
2083 self.x_size_grid = config.x_size_grid;
2084 self.y_size_grid = config.y_size_grid;
2085 self.color = config.color;
2086 self.center_display = config.center_display;
2087 self.offset = config.offset;
2088 self.background_color = config.background_color;
2089 self.background_rounding = config.background_rounding;
2090 self.x_location_grid = config.x_location_grid;
2091 self.y_location_grid = config.y_location_grid;
2092 self.origin_position = config.origin_position;
2093 self.font = config.font.clone();
2094 self.selectable = config.selectable;
2095 self.hyperlink_text = config.hyperlink_text.clone();
2096 self.clip_rect = config.clip_rect.clone();
2097 self.truncate = config.truncate;
2098 self.panel_name = config.panel_name.clone();
2099 self.panel_layout = config.panel_layout.clone();
2100 self.allow_scrolling = config.allow_scrolling;
2101 self
2102 }
2103
2104 #[inline]
2105 pub fn name(mut self, name: &str) -> Self {
2106 self.name = name.to_string();
2107 self
2108 }
2109
2110 #[inline]
2111 pub fn content(mut self, content: &str) -> Self {
2112 self.content = content.to_string();
2113 self
2114 }
2115
2116 #[inline]
2117 pub fn font_size(mut self, font_size: f32) -> Self {
2118 self.font_size = font_size;
2119 self
2120 }
2121
2122 #[inline]
2123 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
2124 self.origin_size = [width, height];
2125 self
2126 }
2127
2128 #[inline]
2129 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
2130 self.x_size_grid = [fetch, total];
2131 self
2132 }
2133
2134 #[inline]
2135 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
2136 self.y_size_grid = [fetch, total];
2137 self
2138 }
2139
2140 #[inline]
2141 pub fn color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
2142 self.color = [r, g, b, a];
2143 self
2144 }
2145
2146 #[inline]
2147 pub fn center_display(
2148 mut self,
2149 horizontal_align: HorizontalAlign,
2150 vertical_align: VerticalAlign,
2151 ) -> Self {
2152 self.center_display = (horizontal_align, vertical_align);
2153 self
2154 }
2155
2156 #[inline]
2157 pub fn offset(mut self, x: f32, y: f32) -> Self {
2158 self.offset = [x, y];
2159 self
2160 }
2161
2162 #[inline]
2163 pub fn background_color(mut self, r: u8, g: u8, b: u8, a: u8) -> Self {
2164 self.background_color = [r, g, b, a];
2165 self
2166 }
2167
2168 #[inline]
2169 pub fn background_rounding(mut self, background_rounding: f32) -> Self {
2170 self.background_rounding = background_rounding;
2171 self
2172 }
2173
2174 #[inline]
2175 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
2176 self.x_location_grid = [fetch, total];
2177 self
2178 }
2179
2180 #[inline]
2181 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
2182 self.y_location_grid = [fetch, total];
2183 self
2184 }
2185
2186 #[inline]
2187 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
2188 self.origin_position = [x, y];
2189 self
2190 }
2191
2192 #[inline]
2193 pub fn font(mut self, font: &str) -> Self {
2194 self.font = font.to_string();
2195 self
2196 }
2197
2198 #[inline]
2199 pub fn selectable(mut self, selectable: bool) -> Self {
2200 self.selectable = selectable;
2201 self
2202 }
2203
2204 #[inline]
2205 pub fn hyperlink_text(
2206 mut self,
2207 target_text: &str,
2208 select_method: HyperlinkSelectMethod,
2209 ) -> Self {
2210 self.hyperlink_text
2211 .push((target_text.to_string(), select_method));
2212 self
2213 }
2214
2215 #[inline]
2216 pub fn truncate(mut self, truncate: bool) -> Self {
2217 self.truncate = truncate;
2218 self
2219 }
2220
2221 #[inline]
2222 pub fn clip_rect(mut self, clip_rect: Option<PositionConfig>) -> Self {
2223 self.clip_rect = clip_rect;
2224 self
2225 }
2226
2227 #[inline]
2228 pub fn panel_name(mut self, panel_name: &str) -> Self {
2229 self.panel_name = panel_name.to_string();
2230 self
2231 }
2232
2233 #[inline]
2234 pub fn panel_layout(mut self, panel_layout: Option<(PanelLocation, PanelLayout)>) -> Self {
2235 self.panel_layout = panel_layout;
2236 self
2237 }
2238
2239 #[inline]
2240 pub fn allow_scrolling(mut self, horizontal: bool, vertical: bool) -> Self {
2241 self.allow_scrolling = [horizontal, vertical];
2242 self
2243 }
2244}
2245
2246#[derive(Debug, Clone, PartialEq, PartialOrd)]
2248pub struct Variable<T> {
2249 pub discern_type: String,
2250 pub name: String,
2251 pub active: bool,
2252 pub value: Option<T>,
2254}
2255
2256impl<T: Debug + 'static> RustConstructorResource for Variable<T> {
2257 fn name(&self) -> &str {
2258 &self.name
2259 }
2260
2261 fn expose_type(&self) -> &str {
2262 &self.discern_type
2263 }
2264
2265 fn active(&self) -> bool {
2266 self.active
2267 }
2268
2269 fn modify_active(&mut self, active: bool) {
2270 self.active = active;
2271 }
2272
2273 fn as_any(&self) -> &dyn Any {
2274 self
2275 }
2276
2277 fn as_any_mut(&mut self) -> &mut dyn Any {
2278 self
2279 }
2280}
2281
2282impl<T> Default for Variable<T> {
2283 fn default() -> Self {
2284 Variable {
2285 discern_type: String::from("Variable"),
2286 name: String::from("Variable"),
2287 active: false,
2288 value: None,
2289 }
2290 }
2291}
2292
2293impl<T> Variable<T> {
2294 #[inline]
2295 pub fn name(mut self, name: &str) -> Self {
2296 self.name = name.to_string();
2297 self
2298 }
2299
2300 #[inline]
2301 pub fn value(mut self, value: Option<T>) -> Self {
2302 self.value = value;
2303 self
2304 }
2305}
2306
2307#[derive(Debug, Clone, PartialEq)]
2309pub struct Font {
2310 pub name: String,
2311 pub discern_type: String,
2312 pub active: bool,
2313 pub font_definitions: FontDefinitions,
2315 pub path: String,
2317}
2318
2319impl RustConstructorResource for Font {
2320 fn name(&self) -> &str {
2321 &self.name
2322 }
2323
2324 fn expose_type(&self) -> &str {
2325 &self.discern_type
2326 }
2327
2328 fn active(&self) -> bool {
2329 self.active
2330 }
2331
2332 fn modify_active(&mut self, active: bool) {
2333 self.active = active;
2334 }
2335
2336 fn as_any(&self) -> &dyn Any {
2337 self
2338 }
2339
2340 fn as_any_mut(&mut self) -> &mut dyn Any {
2341 self
2342 }
2343}
2344
2345impl Default for Font {
2346 fn default() -> Self {
2347 Self {
2348 discern_type: String::from("Font"),
2349 name: String::from("Font"),
2350 active: false,
2351 font_definitions: FontDefinitions::default(),
2352 path: String::from(""),
2353 }
2354 }
2355}
2356
2357impl Font {
2358 #[inline]
2359 pub fn name(mut self, name: &str) -> Self {
2360 self.name = name.to_string();
2361 self
2362 }
2363
2364 #[inline]
2365 pub fn path(mut self, path: &str) -> Self {
2366 self.path = path.to_string();
2367 self
2368 }
2369}
2370
2371#[derive(Debug, Clone, PartialEq, PartialOrd)]
2373pub struct SplitTime {
2374 pub discern_type: String,
2375 pub name: String,
2376 pub active: bool,
2377 pub time: [f32; 2],
2379}
2380
2381impl RustConstructorResource for SplitTime {
2382 fn name(&self) -> &str {
2383 &self.name
2384 }
2385
2386 fn expose_type(&self) -> &str {
2387 &self.discern_type
2388 }
2389
2390 fn active(&self) -> bool {
2391 self.active
2392 }
2393
2394 fn modify_active(&mut self, active: bool) {
2395 self.active = active;
2396 }
2397
2398 fn as_any(&self) -> &dyn Any {
2399 self
2400 }
2401
2402 fn as_any_mut(&mut self) -> &mut dyn Any {
2403 self
2404 }
2405}
2406
2407impl Default for SplitTime {
2408 fn default() -> Self {
2409 Self {
2410 discern_type: String::from("SplitTime"),
2411 name: String::from("SplitTime"),
2412 active: false,
2413 time: [0_f32, 0_f32],
2414 }
2415 }
2416}
2417
2418impl SplitTime {
2419 #[inline]
2420 pub fn name(mut self, name: &str) -> Self {
2421 self.name = name.to_string();
2422 self
2423 }
2424}
2425
2426#[derive(Debug, Clone, PartialEq, PartialOrd)]
2428pub struct SwitchAppearance {
2429 pub image_config: ImageConfig,
2431 pub custom_rect_config: CustomRectConfig,
2433 pub text_config: TextConfig,
2435 pub texture: String,
2437 pub hint_text: String,
2439}
2440
2441#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2443pub struct SwitchClickAction {
2444 pub click_method: PointerButton,
2446 pub action: bool,
2448}
2449
2450#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2452pub struct SwitchData {
2453 pub switched: bool,
2455 pub last_time_clicked_index: usize,
2457 pub state: u32,
2459}
2460
2461#[derive(Debug, Clone, PartialEq)]
2463pub struct Switch {
2464 pub discern_type: String,
2465 pub name: String,
2466 pub active: bool,
2467 pub appearance: Vec<SwitchAppearance>,
2469 pub fill_resource_name: String,
2471 pub fill_resource_type: String,
2473 pub enable_hover_click_fill_resource: [bool; 2],
2475 pub state: u32,
2477 pub click_method: Vec<SwitchClickAction>,
2479 pub last_time_hovered: bool,
2481 pub last_time_clicked: bool,
2483 pub last_time_clicked_index: usize,
2485 pub animation_count: u32,
2487 pub hint_text_name: String,
2489 pub text_name: String,
2491 pub text_origin_position: [f32; 2],
2493 pub switched: bool,
2495}
2496
2497impl RustConstructorResource for Switch {
2498 fn name(&self) -> &str {
2499 &self.name
2500 }
2501
2502 fn expose_type(&self) -> &str {
2503 &self.discern_type
2504 }
2505
2506 fn active(&self) -> bool {
2507 self.active
2508 }
2509
2510 fn modify_active(&mut self, active: bool) {
2511 self.active = active;
2512 }
2513
2514 fn as_any(&self) -> &dyn Any {
2515 self
2516 }
2517
2518 fn as_any_mut(&mut self) -> &mut dyn Any {
2519 self
2520 }
2521}
2522
2523impl Default for Switch {
2524 fn default() -> Self {
2525 Self {
2526 discern_type: String::from("Switch"),
2527 name: String::from("Switch"),
2528 active: false,
2529 appearance: vec![],
2530 fill_resource_name: String::from("FillResource"),
2531 fill_resource_type: String::from("Image"),
2532 enable_hover_click_fill_resource: [false, false],
2533 state: 0,
2534 click_method: vec![],
2535 last_time_hovered: false,
2536 last_time_clicked: false,
2537 last_time_clicked_index: 5,
2538 animation_count: 0,
2539 hint_text_name: String::new(),
2540 text_name: String::new(),
2541 text_origin_position: [0_f32, 0_f32],
2542 switched: false,
2543 }
2544 }
2545}
2546
2547impl Switch {
2548 #[inline]
2549 pub fn name(mut self, name: &str) -> Self {
2550 self.name = name.to_string();
2551 self
2552 }
2553
2554 #[inline]
2555 pub fn appearance(mut self, appearance: Vec<SwitchAppearance>) -> Self {
2556 self.appearance = appearance;
2557 self
2558 }
2559
2560 #[inline]
2561 pub fn fill_resource_name(mut self, fill_resource_name: &str) -> Self {
2562 self.fill_resource_name = fill_resource_name.to_string();
2563 self
2564 }
2565
2566 #[inline]
2567 pub fn fill_resource_type(mut self, fill_resource_type: &str) -> Self {
2568 self.fill_resource_type = fill_resource_type.to_string();
2569 self
2570 }
2571
2572 #[inline]
2573 pub fn enable_hover_click_fill_resource(
2574 mut self,
2575 enable_hover_fill_resource: bool,
2576 enable_click_fill_resource: bool,
2577 ) -> Self {
2578 self.enable_hover_click_fill_resource =
2579 [enable_hover_fill_resource, enable_click_fill_resource];
2580 self
2581 }
2582
2583 #[inline]
2584 pub fn click_method(mut self, click_method: Vec<SwitchClickAction>) -> Self {
2585 self.click_method = click_method;
2586 self
2587 }
2588
2589 #[inline]
2590 pub fn text_name(mut self, text_name: &str) -> Self {
2591 self.text_name = text_name.to_string();
2592 self
2593 }
2594}
2595
2596#[derive(Debug, Clone, PartialEq, PartialOrd)]
2598pub struct MessageBox {
2599 pub discern_type: String,
2600 pub name: String,
2601 pub active: bool,
2602 pub size: [f32; 2],
2604 pub content_name: String,
2606 pub title_name: String,
2608 pub image_name: String,
2610 pub keep_existing: bool,
2612 pub existing_time: f32,
2614 pub exist: bool,
2616 pub speed: f32,
2618 pub restore_speed: f32,
2620 pub memory_offset: f32,
2622 pub close_switch_fill_resource_name: String,
2624 pub close_switch_fill_resource_type: String,
2626}
2627
2628impl RustConstructorResource for MessageBox {
2629 fn name(&self) -> &str {
2630 &self.name
2631 }
2632
2633 fn expose_type(&self) -> &str {
2634 &self.discern_type
2635 }
2636
2637 fn active(&self) -> bool {
2638 self.active
2639 }
2640
2641 fn modify_active(&mut self, active: bool) {
2642 self.active = active;
2643 }
2644
2645 fn as_any(&self) -> &dyn Any {
2646 self
2647 }
2648
2649 fn as_any_mut(&mut self) -> &mut dyn Any {
2650 self
2651 }
2652}
2653
2654impl Default for MessageBox {
2655 fn default() -> Self {
2656 Self {
2657 discern_type: String::from("MessageBox"),
2658 name: String::from("MessageBox"),
2659 active: false,
2660 size: [100_f32, 100_f32],
2661 content_name: String::from("Content"),
2662 title_name: String::from("Title"),
2663 image_name: String::from("Image"),
2664 keep_existing: false,
2665 existing_time: 3_f32,
2666 exist: true,
2667 speed: 30_f32,
2668 restore_speed: 10_f32,
2669 memory_offset: 0_f32,
2670 close_switch_fill_resource_name: String::from("CloseSwitch"),
2671 close_switch_fill_resource_type: String::from("Image"),
2672 }
2673 }
2674}
2675
2676impl MessageBox {
2677 #[inline]
2678 pub fn name(mut self, name: &str) -> Self {
2679 self.name = name.to_string();
2680 self
2681 }
2682
2683 #[inline]
2684 pub fn size(mut self, width: f32, height: f32) -> Self {
2685 self.size = [width, height];
2686 self
2687 }
2688
2689 #[inline]
2690 pub fn content_name(mut self, content_name: &str) -> Self {
2691 self.content_name = content_name.to_string();
2692 self
2693 }
2694
2695 #[inline]
2696 pub fn title_name(mut self, title_name: &str) -> Self {
2697 self.title_name = title_name.to_string();
2698 self
2699 }
2700
2701 #[inline]
2702 pub fn image_name(mut self, image_name: &str) -> Self {
2703 self.image_name = image_name.to_string();
2704 self
2705 }
2706
2707 #[inline]
2708 pub fn keep_existing(mut self, keep_existing: bool) -> Self {
2709 self.keep_existing = keep_existing;
2710 self
2711 }
2712
2713 #[inline]
2714 pub fn existing_time(mut self, existing_time: f32) -> Self {
2715 self.existing_time = existing_time;
2716 self
2717 }
2718
2719 #[inline]
2720 pub fn speed(mut self, speed: f32) -> Self {
2721 self.speed = speed;
2722 self
2723 }
2724
2725 #[inline]
2726 pub fn restore_speed(mut self, restore_speed: f32) -> Self {
2727 self.restore_speed = restore_speed;
2728 self
2729 }
2730
2731 #[inline]
2732 pub fn close_switch_fill_resource_name(
2733 mut self,
2734 close_switch_fill_resource_name: &str,
2735 ) -> Self {
2736 self.close_switch_fill_resource_name = close_switch_fill_resource_name.to_string();
2737 self
2738 }
2739
2740 #[inline]
2741 pub fn close_switch_fill_resource_type(
2742 mut self,
2743 close_switch_fill_resource_type: &str,
2744 ) -> Self {
2745 self.close_switch_fill_resource_type = close_switch_fill_resource_type.to_string();
2746 self
2747 }
2748}
2749
2750#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2752pub enum MouseDetectorLevel {
2753 Lite,
2755 #[default]
2757 Default,
2758 Pro,
2760}
2761
2762#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
2764pub struct MouseDetectResult {
2765 pub clicked: bool,
2767 pub contains_pointer: bool,
2769 pub secondary_clicked: Option<bool>,
2771 pub middle_clicked: Option<bool>,
2773 pub clicked_by_extra_button: Option<[bool; 2]>,
2775 pub long_touched: Option<bool>,
2777 pub double_clicked: Option<bool>,
2779 pub triple_clicked: Option<bool>,
2781 pub double_clicked_by: Option<[bool; 5]>,
2783 pub triple_clicked_by: Option<[bool; 5]>,
2785 pub clicked_elsewhere: Option<bool>,
2787 pub hovered: Option<bool>,
2789 pub drag_started: Option<bool>,
2791 pub drag_started_by: Option<[bool; 5]>,
2793 pub dragged: Option<bool>,
2795 pub dragged_by: Option<[bool; 5]>,
2797 pub drag_stopped: Option<bool>,
2799 pub deag_stopped_by: Option<[bool; 5]>,
2801 pub drag_delta: Option<[f32; 2]>,
2803 pub total_drag_delta: Option<Option<[f32; 2]>>,
2805 pub drag_motion: Option<[f32; 2]>,
2807 pub interact_pointer_pos: Option<Option<[f32; 2]>>,
2809 pub hover_pos: Option<Option<[f32; 2]>>,
2811 pub is_pointer_button_down_on: Option<bool>,
2813 pub raw_scroll_delta: Option<[f32; 2]>,
2815 pub smooth_scroll_delta: Option<[f32; 2]>,
2817}
2818
2819#[derive(Debug, Clone, PartialEq, PartialOrd)]
2821pub struct MouseDetector {
2822 pub discern_type: String,
2823 pub name: String,
2824 pub active: bool,
2825 pub position: [f32; 2],
2827 pub origin_position: [f32; 2],
2829 pub size: [f32; 2],
2831 pub origin_size: [f32; 2],
2833 pub x_size_grid: [u32; 2],
2835 pub y_size_grid: [u32; 2],
2837 pub x_location_grid: [u32; 2],
2839 pub y_location_grid: [u32; 2],
2841 pub center_display: (HorizontalAlign, VerticalAlign),
2843 pub offset: [f32; 2],
2845 pub detect_result: MouseDetectResult,
2847}
2848
2849impl RustConstructorResource for MouseDetector {
2850 fn name(&self) -> &str {
2851 &self.name
2852 }
2853
2854 fn expose_type(&self) -> &str {
2855 &self.discern_type
2856 }
2857
2858 fn active(&self) -> bool {
2859 self.active
2860 }
2861
2862 fn modify_active(&mut self, active: bool) {
2863 self.active = active;
2864 }
2865
2866 fn as_any(&self) -> &dyn Any {
2867 self
2868 }
2869
2870 fn as_any_mut(&mut self) -> &mut dyn Any {
2871 self
2872 }
2873}
2874
2875impl Default for MouseDetector {
2876 fn default() -> Self {
2877 Self {
2878 discern_type: String::from("MouseDetector"),
2879 name: String::from("MouseDetector"),
2880 active: false,
2881 position: [0_f32, 0_f32],
2882 origin_position: [0_f32, 0_f32],
2883 size: [100_f32, 100_f32],
2884 origin_size: [100_f32, 100_f32],
2885 x_size_grid: [0, 0],
2886 y_size_grid: [0, 0],
2887 x_location_grid: [0, 0],
2888 y_location_grid: [0, 0],
2889 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
2890 offset: [0_f32, 0_f32],
2891 detect_result: MouseDetectResult::default(),
2892 }
2893 }
2894}
2895
2896impl MouseDetector {
2897 pub fn from_position_config(mut self, position_config: PositionConfig) -> Self {
2898 self.origin_position = position_config.origin_position;
2899 self.origin_size = position_config.origin_size;
2900 self.x_size_grid = position_config.x_size_grid;
2901 self.y_size_grid = position_config.y_size_grid;
2902 self.x_location_grid = position_config.x_location_grid;
2903 self.y_location_grid = position_config.y_location_grid;
2904 self.center_display = position_config.center_display;
2905 self.offset = position_config.offset;
2906 self
2907 }
2908
2909 #[inline]
2910 pub fn name(mut self, name: &str) -> Self {
2911 self.name = name.to_string();
2912 self
2913 }
2914
2915 #[inline]
2916 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
2917 self.origin_position = [x, y];
2918 self
2919 }
2920
2921 #[inline]
2922 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
2923 self.origin_size = [width, height];
2924 self
2925 }
2926
2927 #[inline]
2928 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
2929 self.x_size_grid = [fetch, total];
2930 self
2931 }
2932
2933 #[inline]
2934 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
2935 self.y_size_grid = [fetch, total];
2936 self
2937 }
2938
2939 #[inline]
2940 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
2941 self.x_location_grid = [fetch, total];
2942 self
2943 }
2944
2945 #[inline]
2946 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
2947 self.y_location_grid = [fetch, total];
2948 self
2949 }
2950
2951 #[inline]
2952 pub fn center_display(
2953 mut self,
2954 horizontal_align: HorizontalAlign,
2955 vertical_align: VerticalAlign,
2956 ) -> Self {
2957 self.center_display = (horizontal_align, vertical_align);
2958 self
2959 }
2960
2961 #[inline]
2962 pub fn offset(mut self, x: f32, y: f32) -> Self {
2963 self.offset = [x, y];
2964 self
2965 }
2966}
2967
2968#[derive(Debug, Default, Clone, Copy, PartialEq, PartialOrd)]
2970pub enum ScrollLengthMethod {
2971 Fixed(f32),
2973 #[default]
2975 AutoFit,
2976}
2977
2978#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2980pub enum ClickAim {
2981 #[default]
2982 Move,
2984 TopResize,
2986 BottomResize,
2988 LeftResize,
2990 RightResize,
2992 LeftTopResize,
2994 RightTopResize,
2996 LeftBottomResize,
2998 RightBottomResize,
3000}
3001
3002#[derive(Debug, Clone, PartialEq, PartialOrd)]
3004pub struct ResourcePanel {
3005 pub discern_type: String,
3006 pub name: String,
3007 pub active: bool,
3008 pub size: [f32; 2],
3010 pub position: [f32; 2],
3012 pub origin_position: [f32; 2],
3014 pub origin_size: [f32; 2],
3016 pub x_location_grid: [u32; 2],
3018 pub y_location_grid: [u32; 2],
3020 pub x_size_grid: [u32; 2],
3022 pub y_size_grid: [u32; 2],
3024 pub center_display: (HorizontalAlign, VerticalAlign),
3026 pub offset: [f32; 2],
3028 pub resizable: [bool; 4],
3030 pub display_rect: Option<CustomRectConfig>,
3032 pub last_frame_mouse_status: Option<([f32; 2], ClickAim, [f32; 2])>,
3034 pub min_size: [f32; 2],
3036 pub max_size: Option<[f32; 2]>,
3038 pub movable: [bool; 2],
3040 pub scroll_length_method: [Option<ScrollLengthMethod>; 2],
3042 pub scroll_length: [f32; 2],
3044 pub scroll_progress: [f32; 2],
3046 pub scroll_sensitivity: f32,
3048 pub use_smooth_scroll_delta: bool,
3050 pub last_frame_scroll_progress: [f32; 2],
3052}
3053
3054impl RustConstructorResource for ResourcePanel {
3055 fn name(&self) -> &str {
3056 &self.name
3057 }
3058
3059 fn expose_type(&self) -> &str {
3060 &self.discern_type
3061 }
3062
3063 fn active(&self) -> bool {
3064 self.active
3065 }
3066
3067 fn modify_active(&mut self, active: bool) {
3068 self.active = active;
3069 }
3070
3071 fn as_any(&self) -> &dyn Any {
3072 self
3073 }
3074
3075 fn as_any_mut(&mut self) -> &mut dyn Any {
3076 self
3077 }
3078}
3079
3080impl Default for ResourcePanel {
3081 fn default() -> Self {
3082 Self {
3083 discern_type: String::from("ResourcePanel"),
3084 name: String::from("ResourcePanel"),
3085 active: false,
3086 size: [100_f32, 100_f32],
3087 position: [0_f32, 0_f32],
3088 origin_position: [0_f32, 0_f32],
3089 origin_size: [100_f32, 100_f32],
3090 x_location_grid: [0, 0],
3091 y_location_grid: [0, 0],
3092 x_size_grid: [0, 0],
3093 y_size_grid: [0, 0],
3094 center_display: (HorizontalAlign::default(), VerticalAlign::default()),
3095 offset: [0_f32, 0_f32],
3096 resizable: [true, true, true, true],
3097 display_rect: None,
3098 last_frame_mouse_status: None,
3099 min_size: [10_f32, 10_f32],
3100 max_size: None,
3101 movable: [true, true],
3102 scroll_length_method: [None, None],
3103 scroll_length: [0_f32, 0_f32],
3104 scroll_progress: [0_f32, 0_f32],
3105 scroll_sensitivity: 0_f32,
3106 use_smooth_scroll_delta: true,
3107 last_frame_scroll_progress: [0_f32, 0_f32],
3108 }
3109 }
3110}
3111
3112impl ResourcePanel {
3113 pub fn from_position_config(mut self, position_config: PositionConfig) -> Self {
3114 self.center_display = position_config.center_display;
3115 self.offset = position_config.offset;
3116 self.origin_position = position_config.origin_position;
3117 self.origin_size = position_config.origin_size;
3118 self.x_size_grid = position_config.x_size_grid;
3119 self.y_size_grid = position_config.y_size_grid;
3120 self.x_location_grid = position_config.x_location_grid;
3121 self.y_location_grid = position_config.y_location_grid;
3122 self
3123 }
3124
3125 #[inline]
3126 pub fn name(mut self, name: &str) -> Self {
3127 self.name = name.to_string();
3128 self
3129 }
3130
3131 #[inline]
3132 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
3133 self.origin_position = [x, y];
3134 self
3135 }
3136
3137 #[inline]
3138 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
3139 self.origin_size = [width, height];
3140 self
3141 }
3142
3143 #[inline]
3144 pub fn x_location_grid(mut self, fetch: u32, total: u32) -> Self {
3145 self.x_location_grid = [fetch, total];
3146 self
3147 }
3148
3149 #[inline]
3150 pub fn y_location_grid(mut self, fetch: u32, total: u32) -> Self {
3151 self.y_location_grid = [fetch, total];
3152 self
3153 }
3154
3155 #[inline]
3156 pub fn x_size_grid(mut self, fetch: u32, total: u32) -> Self {
3157 self.x_size_grid = [fetch, total];
3158 self
3159 }
3160
3161 #[inline]
3162 pub fn y_size_grid(mut self, fetch: u32, total: u32) -> Self {
3163 self.y_size_grid = [fetch, total];
3164 self
3165 }
3166
3167 #[inline]
3168 pub fn center_display(
3169 mut self,
3170 horizontal_align: HorizontalAlign,
3171 vertical_align: VerticalAlign,
3172 ) -> Self {
3173 self.center_display = (horizontal_align, vertical_align);
3174 self
3175 }
3176
3177 #[inline]
3178 pub fn offset(mut self, x: f32, y: f32) -> Self {
3179 self.offset = [x, y];
3180 self
3181 }
3182
3183 #[inline]
3184 pub fn resizable(mut self, top: bool, bottom: bool, left: bool, right: bool) -> Self {
3185 self.resizable = [top, bottom, left, right];
3186 self
3187 }
3188
3189 #[inline]
3190 pub fn display_rect(mut self, display_rect: Option<CustomRectConfig>) -> Self {
3191 self.display_rect = display_rect;
3192 self
3193 }
3194
3195 #[inline]
3196 pub fn min_size(mut self, width: f32, height: f32) -> Self {
3197 self.min_size = [width, height];
3198 self
3199 }
3200
3201 #[inline]
3202 pub fn max_size(mut self, max_size: Option<[f32; 2]>) -> Self {
3203 self.max_size = max_size;
3204 self
3205 }
3206
3207 #[inline]
3208 pub fn movable(mut self, horizontal: bool, vertical: bool) -> Self {
3209 self.movable = [horizontal, vertical];
3210 self
3211 }
3212
3213 #[inline]
3214 pub fn scroll_length_method(
3215 mut self,
3216 horizontal: Option<ScrollLengthMethod>,
3217 vertical: Option<ScrollLengthMethod>,
3218 ) -> Self {
3219 self.scroll_length_method = [horizontal, vertical];
3220 self
3221 }
3222
3223 #[inline]
3224 pub fn scroll_sensitivity(mut self, scroll_sensitivity: f32) -> Self {
3225 self.scroll_sensitivity = scroll_sensitivity;
3226 self
3227 }
3228
3229 #[inline]
3230 pub fn use_smooth_scroll_delta(mut self, use_smooth_scroll_delta: bool) -> Self {
3231 self.use_smooth_scroll_delta = use_smooth_scroll_delta;
3232 self
3233 }
3234}
3235
3236#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
3238pub enum RustConstructorError {
3239 ResourceNameRepetition {
3241 resource_name: String,
3242 resource_type: String,
3243 },
3244 ImageGetFailed { image_path: String },
3246 ImageNotFound { image_name: String },
3248 ImageTextureNotFound { image_texture_name: String },
3250 TextNotFound { text_name: String },
3252 VariableNotFound { variable_name: String },
3254 VariableTypeMismatch { variable_name: String },
3256 SplitTimeNotFound { split_time_name: String },
3258 SwitchAppearanceMismatch { switch_name: String, differ: u32 },
3260 SwitchFillResourceMismatch {
3262 switch_name: String,
3263 fill_resource_name: String,
3264 fill_resource_type: String,
3265 },
3266 SwitchNotFound { switch_name: String },
3268 MessageBoxAlreadyExists { message_box_name: String },
3270 MouseDetectorNotFound { mouse_detector_name: String },
3272 FontGetFailed { font_path: String },
3274 FontNotFound { font_name: String },
3276 RectNotFound { rect_name: String },
3278 ResourcePanelNotFound { resource_panel_name: String },
3280 ResourceNotFound {
3282 resource_name: String,
3283 resource_type: String,
3284 },
3285 ResourceUntitled { resource_type: String },
3287 PageNotFound { page_name: String },
3289 CustomError {
3291 error_name: String,
3292 error_message: String,
3293 error_annotation: String,
3294 },
3295}
3296
3297impl Display for RustConstructorError {
3298 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
3299 Debug::fmt(self, f)
3300 }
3301}
3302
3303impl Error for RustConstructorError {}
3304
3305impl Default for RustConstructorError {
3306 fn default() -> Self {
3307 RustConstructorError::ImageGetFailed {
3308 image_path: "".to_string(),
3309 }
3310 }
3311}
3312
3313#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
3315pub enum HorizontalAlign {
3316 #[default]
3318 Left,
3319 Center,
3321 Right,
3323}
3324
3325#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
3327pub enum VerticalAlign {
3328 #[default]
3330 Top,
3331 Center,
3333 Bottom,
3335}
3336
3337#[derive(Debug)]
3339pub struct App {
3340 pub strict_mode: bool,
3342 pub safe_mode: bool,
3344 pub rust_constructor_resource: Vec<Box<dyn RustConstructorResource>>,
3346 pub problem_list: Vec<Problem>,
3348 pub tick_interval: f32,
3350 pub current_page: String,
3352 pub timer: Timer,
3354 pub frame_times: Vec<f32>,
3356 pub last_frame_time: Option<f64>,
3358 pub basic_front_resource_list: Vec<String>,
3360}
3361
3362impl Default for App {
3363 fn default() -> Self {
3364 App {
3365 strict_mode: false,
3366 safe_mode: true,
3367 rust_constructor_resource: Vec::new(),
3368 problem_list: Vec::new(),
3369 tick_interval: 0.05,
3370 current_page: String::new(),
3371 timer: Timer::default(),
3372 frame_times: Vec::new(),
3373 last_frame_time: None,
3374 basic_front_resource_list: vec![
3375 String::from("Image"),
3376 String::from("Text"),
3377 String::from("CustomRect"),
3378 ],
3379 }
3380 }
3381}
3382
3383impl App {
3384 #[inline]
3385 pub fn strict_mode(mut self, strict_mode: bool) -> Self {
3386 self.strict_mode = strict_mode;
3387 self
3388 }
3389
3390 #[inline]
3391 pub fn safe_mode(mut self, safe_mode: bool) -> Self {
3392 self.safe_mode = safe_mode;
3393 self
3394 }
3395
3396 #[inline]
3397 pub fn tick_interval(mut self, tick_interval: f32) -> Self {
3398 self.tick_interval = tick_interval;
3399 self
3400 }
3401
3402 #[inline]
3403 pub fn current_page(mut self, current_page: &str) -> Self {
3404 self.current_page = current_page.to_string();
3405 self
3406 }
3407
3408 pub fn print_resource_active_info(&self, display_complex_info: bool, format: bool) -> String {
3410 let mut text = String::from("Resource Active Info:\n");
3411 for rcr in &self.rust_constructor_resource {
3412 if rcr.active() {
3413 if display_complex_info {
3414 text += &if format {
3415 format!(
3416 "\nName: {:?}\nType: {:?}\nDetail: {:#?}\n",
3417 rcr.name(),
3418 rcr.expose_type(),
3419 rcr
3420 )
3421 } else {
3422 format!(
3423 "\nName: {:?}\nType: {:?}\nDetail: {:?}\n",
3424 rcr.name(),
3425 rcr.expose_type(),
3426 rcr
3427 )
3428 };
3429 } else {
3430 text += &format!("\nName: {:?}\nType: {:?}\n", rcr.name(), rcr.expose_type());
3431 };
3432 };
3433 }
3434 text
3435 }
3436
3437 pub fn add_resource<T: RustConstructorResource + 'static>(
3439 &mut self,
3440 mut resource: T,
3441 safe_mode: Option<bool>,
3442 ) -> Result<(), RustConstructorError> {
3443 if safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode {
3444 if self.check_resource_exists(resource.name(), resource.expose_type()) {
3445 self.problem_report_custom(
3446 RustConstructorError::ResourceNameRepetition {
3447 resource_name: resource.name().to_string(),
3448 resource_type: resource.expose_type().to_string(),
3449 },
3450 SeverityLevel::SevereWarning,
3451 self.problem_list.clone(),
3452 );
3453 return Err(RustConstructorError::ResourceNameRepetition {
3454 resource_name: resource.name().to_string(),
3455 resource_type: resource.expose_type().to_string(),
3456 });
3457 };
3458 if resource.name().is_empty() {
3459 self.problem_report_custom(
3460 RustConstructorError::ResourceUntitled {
3461 resource_type: resource.expose_type().to_string(),
3462 },
3463 SeverityLevel::SevereWarning,
3464 self.problem_list.clone(),
3465 );
3466 return Err(RustConstructorError::ResourceUntitled {
3467 resource_type: resource.expose_type().to_string(),
3468 });
3469 };
3470 };
3471 match resource.expose_type() {
3472 "PageData" => {}
3473 "CustomRect" => {}
3474 "Text" => {}
3475 "Variable" => {}
3476 "MouseDetector" => {}
3477 "SplitTime" => {
3478 let split_time = resource.as_any_mut().downcast_mut::<SplitTime>().unwrap();
3479 split_time.time = [self.timer.now_time, self.timer.total_time];
3480 }
3481 "ResourcePanel" => {
3482 let resource_panel = resource
3483 .as_any_mut()
3484 .downcast_mut::<ResourcePanel>()
3485 .unwrap();
3486 if resource_panel.display_rect.is_some() {
3487 self.add_resource(
3488 CustomRect::default().name(&format!("{}DisplayRect", resource_panel.name)),
3489 safe_mode,
3490 )
3491 .unwrap();
3492 };
3493 }
3494 "ImageTexture" => {
3495 let image_texture = resource
3496 .as_any_mut()
3497 .downcast_mut::<ImageTexture>()
3498 .unwrap();
3499 if let Ok(mut file) = File::open(image_texture.cite_path.clone()) {
3500 let mut buffer = Vec::new();
3501 file.read_to_end(&mut buffer).unwrap();
3502 let img_bytes = buffer;
3503 let img = image::load_from_memory(&img_bytes).unwrap();
3504 let color_data = match image_texture.flip {
3505 [true, true] => img.fliph().flipv().into_rgba8(),
3506 [true, false] => img.fliph().into_rgba8(),
3507 [false, true] => img.flipv().into_rgba8(),
3508 _ => img.into_rgba8(),
3509 };
3510 let (w, h) = (color_data.width(), color_data.height());
3511 let raw_data: Vec<u8> = color_data.into_raw();
3512
3513 let color_image =
3514 ColorImage::from_rgba_unmultiplied([w as usize, h as usize], &raw_data);
3515 let loaded_image_texture = image_texture.ctx.load_texture(
3516 image_texture.name.clone(),
3517 color_image,
3518 TextureOptions::LINEAR,
3519 );
3520 image_texture.texture = Some(DebugTextureHandle::new(loaded_image_texture));
3521 image_texture.cite_path = image_texture.cite_path.to_string();
3522 } else {
3523 self.problem_report_custom(
3524 RustConstructorError::ImageGetFailed {
3525 image_path: image_texture.cite_path.to_string(),
3526 },
3527 SeverityLevel::SevereWarning,
3528 self.problem_list.clone(),
3529 );
3530 };
3531 }
3532 "Image" => {
3533 let image = resource.as_any_mut().downcast_mut::<Image>().unwrap();
3534 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3535 && !self.check_resource_exists(&image.cite_texture, "ImageTexture")
3536 {
3537 self.problem_report_custom(
3538 RustConstructorError::ImageTextureNotFound {
3539 image_texture_name: image.cite_texture.clone(),
3540 },
3541 SeverityLevel::SevereWarning,
3542 self.problem_list.clone(),
3543 );
3544 return Err(RustConstructorError::ImageTextureNotFound {
3545 image_texture_name: image.cite_texture.clone(),
3546 });
3547 };
3548 let image_texture = self
3549 .get_resource::<ImageTexture>(&image.cite_texture, "ImageTexture")
3550 .unwrap()
3551 .unwrap();
3552 image.texture = image_texture.texture.clone();
3553 image.last_frame_cite_texture = image_texture.name.clone();
3554 }
3555 "Font" => {
3556 let font = resource.as_any_mut().downcast_mut::<Font>().unwrap();
3557 let mut fonts = FontDefinitions::default();
3558 if let Ok(font_read_data) = read(font.path.clone()) {
3559 let font_data: Arc<Vec<u8>> = Arc::new(font_read_data);
3560 fonts.font_data.insert(
3561 font.name.to_owned(),
3562 Arc::new(FontData::from_owned(
3563 Arc::try_unwrap(font_data).ok().unwrap(),
3564 )),
3565 );
3566
3567 fonts
3569 .families
3570 .entry(FontFamily::Proportional)
3571 .or_default()
3572 .insert(0, font.name.to_owned());
3573
3574 fonts
3575 .families
3576 .entry(FontFamily::Monospace)
3577 .or_default()
3578 .insert(0, font.name.to_owned());
3579
3580 font.font_definitions = fonts;
3581 } else {
3582 self.problem_report_custom(
3583 RustConstructorError::FontGetFailed {
3584 font_path: font.path.to_string(),
3585 },
3586 SeverityLevel::SevereWarning,
3587 self.problem_list.clone(),
3588 );
3589 return Err(RustConstructorError::FontGetFailed {
3590 font_path: font.path.to_string(),
3591 });
3592 }
3593 }
3594 "Switch" => {
3595 let switch = resource.as_any_mut().downcast_mut::<Switch>().unwrap();
3596 let mut count = 1;
3597 if switch.enable_hover_click_fill_resource[0] {
3598 count += 1;
3599 };
3600 if switch.enable_hover_click_fill_resource[1] {
3601 count += 1;
3602 };
3603 if switch.appearance.len() < count {
3604 self.problem_report_custom(
3605 RustConstructorError::SwitchAppearanceMismatch {
3606 switch_name: switch.name.clone(),
3607 differ: count as u32 - switch.appearance.len() as u32,
3608 },
3609 SeverityLevel::SevereWarning,
3610 self.problem_list.clone(),
3611 );
3612 return Err(RustConstructorError::SwitchAppearanceMismatch {
3613 switch_name: switch.name.clone(),
3614 differ: count as u32 - switch.appearance.len() as u32,
3615 });
3616 };
3617 for _ in 0..switch.appearance.len() % count {
3618 switch.appearance.pop();
3619 }
3620 if self.check_resource_exists(&switch.text_name, "Text") {
3621 let t = self
3622 .get_resource_mut::<Text>(&switch.text_name, "Text")
3623 .unwrap()
3624 .unwrap();
3625 switch.text_origin_position = t.origin_position;
3626 t.center_display = (HorizontalAlign::Center, VerticalAlign::Center);
3627 t.x_location_grid = [0, 0];
3628 t.y_location_grid = [0, 0];
3629 } else if !switch.text_name.is_empty() {
3630 switch.text_name = String::new();
3631 self.problem_report_custom(
3632 RustConstructorError::TextNotFound {
3633 text_name: switch.text_name.clone(),
3634 },
3635 SeverityLevel::SevereWarning,
3636 self.problem_list.clone(),
3637 );
3638 };
3639 if self
3640 .check_resource_exists(&switch.fill_resource_name, &switch.fill_resource_type)
3641 {
3642 match switch.fill_resource_type.as_str() {
3643 "Image" | "CustomRect" => {
3644 switch.fill_resource_name = switch.fill_resource_name.clone();
3645 switch.fill_resource_type = switch.fill_resource_type.clone();
3646 }
3647 _ => {
3648 self.problem_report_custom(
3649 RustConstructorError::SwitchFillResourceMismatch {
3650 switch_name: switch.name.clone(),
3651 fill_resource_name: switch.fill_resource_name.clone(),
3652 fill_resource_type: switch.fill_resource_type.clone(),
3653 },
3654 SeverityLevel::SevereWarning,
3655 self.problem_list.clone(),
3656 );
3657 return Err(RustConstructorError::SwitchFillResourceMismatch {
3658 switch_name: switch.name.clone(),
3659 fill_resource_name: switch.fill_resource_name.clone(),
3660 fill_resource_type: switch.fill_resource_type.clone(),
3661 });
3662 }
3663 };
3664 } else {
3665 self.problem_report_custom(
3666 RustConstructorError::ResourceNotFound {
3667 resource_name: switch.fill_resource_name.clone(),
3668 resource_type: switch.fill_resource_type.clone(),
3669 },
3670 SeverityLevel::SevereWarning,
3671 self.problem_list.clone(),
3672 );
3673 return Err(RustConstructorError::ResourceNotFound {
3674 resource_name: switch.fill_resource_name.clone(),
3675 resource_type: switch.fill_resource_type.clone(),
3676 });
3677 };
3678 if switch
3679 .appearance
3680 .iter()
3681 .filter(|x| !x.hint_text.is_empty())
3682 .count()
3683 > 0
3684 {
3685 switch.hint_text_name = format!("{}Hint", switch.name);
3686 self.add_resource(
3687 Text::default()
3688 .name(&format!("{}Hint", switch.name))
3689 .content("")
3690 .origin_position(0_f32, 0_f32)
3691 .font_size(25_f32)
3692 .origin_size(300_f32, 0_f32)
3693 .background_rounding(10_f32)
3694 .color(255, 255, 255, 0)
3695 .background_color(0, 0, 0, 255)
3696 .center_display(HorizontalAlign::Left, VerticalAlign::Top)
3697 .selectable(false),
3698 safe_mode,
3699 )
3700 .unwrap();
3701 self.add_resource(
3702 SplitTime::default().name(&format!("{}StartHoverTime", switch.name)),
3703 safe_mode,
3704 )
3705 .unwrap();
3706 self.add_resource(
3707 SplitTime::default().name(&format!("{}HintFadeAnimation", switch.name)),
3708 safe_mode,
3709 )
3710 .unwrap();
3711 };
3712 switch.animation_count = count as u32;
3713 }
3714 "MessageBox" => {
3715 let message_box = resource.as_any_mut().downcast_mut::<MessageBox>().unwrap();
3716 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3717 && self.check_resource_exists(&message_box.name, "MessageBox")
3718 {
3719 self.problem_report_custom(
3720 RustConstructorError::MessageBoxAlreadyExists {
3721 message_box_name: message_box.name.clone(),
3722 },
3723 SeverityLevel::SevereWarning,
3724 self.problem_list.clone(),
3725 );
3726 return Err(RustConstructorError::MessageBoxAlreadyExists {
3727 message_box_name: message_box.name.clone(),
3728 });
3729 };
3730 message_box.exist = true;
3731 message_box.memory_offset = 0_f32;
3732
3733 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3734 && !self.check_resource_exists(&message_box.image_name, "Image")
3735 {
3736 self.problem_report_custom(
3737 RustConstructorError::ImageNotFound {
3738 image_name: message_box.image_name.clone(),
3739 },
3740 SeverityLevel::SevereWarning,
3741 self.problem_list.clone(),
3742 );
3743 return Err(RustConstructorError::ImageNotFound {
3744 image_name: message_box.image_name.clone(),
3745 });
3746 };
3747 let im = self
3748 .get_resource_mut::<Image>(&message_box.image_name, "Image")
3749 .unwrap()
3750 .unwrap();
3751 im.origin_size = [message_box.size[1] - 15_f32, message_box.size[1] - 15_f32];
3752 im.center_display = (HorizontalAlign::Left, VerticalAlign::Center);
3753 im.x_location_grid = [1, 1];
3754 im.y_location_grid = [0, 1];
3755 im.x_size_grid = [0, 0];
3756 im.y_size_grid = [0, 0];
3757 im.name = format!("MessageBox{}", im.name);
3758 message_box.image_name = im.name.to_string();
3759
3760 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3761 && !self.check_resource_exists(&message_box.title_name, "Text")
3762 {
3763 self.problem_report_custom(
3764 RustConstructorError::TextNotFound {
3765 text_name: message_box.title_name.clone(),
3766 },
3767 SeverityLevel::SevereWarning,
3768 self.problem_list.clone(),
3769 );
3770 return Err(RustConstructorError::TextNotFound {
3771 text_name: message_box.title_name.clone(),
3772 });
3773 };
3774 let t = self
3775 .get_resource_mut::<Text>(&message_box.title_name, "Text")
3776 .unwrap()
3777 .unwrap();
3778 t.x_location_grid = [1, 1];
3779 t.y_location_grid = [0, 1];
3780 t.x_size_grid = [0, 0];
3781 t.y_size_grid = [0, 0];
3782 t.center_display = (HorizontalAlign::Left, VerticalAlign::Top);
3783 t.origin_size[0] = message_box.size[0] - message_box.size[1] + 5_f32;
3784 t.name = format!("MessageBox{}", t.name);
3785 message_box.title_name = t.name.to_string();
3786
3787 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3788 && !self.check_resource_exists(&message_box.content_name, "Text")
3789 {
3790 self.problem_report_custom(
3791 RustConstructorError::TextNotFound {
3792 text_name: message_box.content_name.clone(),
3793 },
3794 SeverityLevel::SevereWarning,
3795 self.problem_list.clone(),
3796 );
3797 return Err(RustConstructorError::TextNotFound {
3798 text_name: message_box.content_name.clone(),
3799 });
3800 };
3801 let t = self
3802 .get_resource_mut::<Text>(&message_box.content_name, "Text")
3803 .unwrap()
3804 .unwrap();
3805 t.center_display = (HorizontalAlign::Left, VerticalAlign::Top);
3806 t.x_location_grid = [1, 1];
3807 t.y_location_grid = [0, 1];
3808 t.x_size_grid = [0, 0];
3809 t.y_size_grid = [0, 0];
3810 t.origin_size[0] = message_box.size[0] - message_box.size[1] + 5_f32;
3811 t.name = format!("MessageBox{}", t.name);
3812 message_box.content_name = t.name.to_string();
3813
3814 if !message_box.keep_existing {
3815 self.add_resource(
3816 SplitTime::default().name(&format!("MessageBox{}", message_box.name)),
3817 safe_mode,
3818 )
3819 .unwrap();
3820 };
3821
3822 self.add_resource(
3823 SplitTime::default().name(&format!("MessageBox{}Animation", message_box.name)),
3824 safe_mode,
3825 )
3826 .unwrap();
3827
3828 self.add_resource(
3829 CustomRect::default()
3830 .name(&format!("MessageBox{}", message_box.name))
3831 .origin_position(0_f32, 0_f32)
3832 .origin_size(message_box.size[0], message_box.size[1])
3833 .rounding(20_f32)
3834 .x_location_grid(1, 1)
3835 .y_location_grid(0, 1)
3836 .center_display(HorizontalAlign::Left, VerticalAlign::Top)
3837 .color(100, 100, 100, 125)
3838 .border_width(0_f32),
3839 safe_mode,
3840 )
3841 .unwrap();
3842
3843 if safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode {
3844 match message_box.close_switch_fill_resource_type.as_str() {
3845 "Image" | "CustomRect" => {}
3846 _ => {
3847 self.problem_report_custom(
3848 RustConstructorError::SwitchFillResourceMismatch {
3849 switch_name: format!("MessageBox{}Close", message_box.name),
3850 fill_resource_name: message_box
3851 .close_switch_fill_resource_name
3852 .clone(),
3853 fill_resource_type: message_box
3854 .close_switch_fill_resource_type
3855 .clone(),
3856 },
3857 SeverityLevel::SevereWarning,
3858 self.problem_list.clone(),
3859 );
3860 return Err(RustConstructorError::SwitchFillResourceMismatch {
3861 switch_name: format!("MessageBox{}Close", message_box.name),
3862 fill_resource_name: message_box
3863 .close_switch_fill_resource_name
3864 .clone(),
3865 fill_resource_type: message_box
3866 .close_switch_fill_resource_type
3867 .clone(),
3868 });
3869 }
3870 };
3871 };
3872
3873 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
3874 && !self.check_resource_exists(
3875 &message_box.close_switch_fill_resource_name,
3876 &message_box.close_switch_fill_resource_type,
3877 )
3878 {
3879 self.problem_report_custom(
3880 RustConstructorError::ResourceNotFound {
3881 resource_name: message_box.close_switch_fill_resource_name.clone(),
3882 resource_type: message_box.close_switch_fill_resource_type.clone(),
3883 },
3884 SeverityLevel::SevereWarning,
3885 self.problem_list.clone(),
3886 );
3887 return Err(RustConstructorError::ResourceNotFound {
3888 resource_name: message_box.close_switch_fill_resource_name.clone(),
3889 resource_type: message_box.close_switch_fill_resource_type.clone(),
3890 });
3891 };
3892
3893 let (texture, image_config, custom_rect_config, color, border_color) =
3894 match message_box.close_switch_fill_resource_type.as_str() {
3895 "Image" => {
3896 let im = self
3897 .get_resource_mut::<Image>(
3898 &message_box.close_switch_fill_resource_name,
3899 "Image",
3900 )
3901 .unwrap()
3902 .unwrap();
3903 im.name = format!(
3904 "MessageBox{}Close",
3905 message_box.close_switch_fill_resource_name
3906 );
3907 (
3908 im.cite_texture.clone(),
3909 ImageConfig::from_image(im)
3910 .origin_size(30_f32, 30_f32)
3911 .center_display(HorizontalAlign::Center, VerticalAlign::Center),
3912 CustomRectConfig::default(),
3913 im.overlay_color,
3914 [0, 0, 0, 0],
3915 )
3916 }
3917 "CustomRect" => {
3918 let cr = self
3919 .get_resource_mut::<CustomRect>(
3920 &message_box.close_switch_fill_resource_name,
3921 "CustomRect",
3922 )
3923 .unwrap()
3924 .unwrap();
3925 cr.name = format!(
3926 "MessageBox{}Close",
3927 message_box.close_switch_fill_resource_name
3928 );
3929 (
3930 String::new(),
3931 ImageConfig::default(),
3932 CustomRectConfig::from_custom_rect(cr)
3933 .origin_size(30_f32, 30_f32)
3934 .center_display(HorizontalAlign::Center, VerticalAlign::Center),
3935 cr.color,
3936 cr.border_color,
3937 )
3938 }
3939 _ => {
3940 self.problem_report_custom(
3941 RustConstructorError::SwitchFillResourceMismatch {
3942 switch_name: format!("MessageBox{}Close", message_box.name),
3943 fill_resource_name: message_box
3944 .close_switch_fill_resource_name
3945 .clone(),
3946 fill_resource_type: message_box
3947 .close_switch_fill_resource_type
3948 .clone(),
3949 },
3950 SeverityLevel::SevereWarning,
3951 self.problem_list.clone(),
3952 );
3953 return Err(RustConstructorError::SwitchFillResourceMismatch {
3954 switch_name: format!("MessageBox{}Close", message_box.name),
3955 fill_resource_name: message_box
3956 .close_switch_fill_resource_name
3957 .clone(),
3958 fill_resource_type: message_box
3959 .close_switch_fill_resource_type
3960 .clone(),
3961 });
3962 }
3963 };
3964
3965 self.add_resource(
3966 Switch::default()
3967 .name(&format!("MessageBox{}Close", message_box.name))
3968 .appearance(vec![
3969 SwitchAppearance {
3970 image_config: image_config
3971 .clone()
3972 .overlay_color(color[0], color[1], color[2], 0),
3973 custom_rect_config: custom_rect_config
3974 .clone()
3975 .color(color[0], color[1], color[2], 0)
3976 .border_color(
3977 border_color[0],
3978 border_color[1],
3979 border_color[2],
3980 0,
3981 ),
3982 text_config: TextConfig::default(),
3983 texture: texture.clone(),
3984 hint_text: String::new(),
3985 },
3986 SwitchAppearance {
3987 image_config: image_config.clone().overlay_color(
3988 (color[0] as u32 * 180 / 255) as u8,
3989 (color[1] as u32 * 180 / 255) as u8,
3990 (color[2] as u32 * 180 / 255) as u8,
3991 255,
3992 ),
3993 custom_rect_config: custom_rect_config
3994 .clone()
3995 .color(
3996 (color[0] as u32 * 180 / 255) as u8,
3997 (color[1] as u32 * 180 / 255) as u8,
3998 (color[2] as u32 * 180 / 255) as u8,
3999 255,
4000 )
4001 .border_color(
4002 (border_color[0] as u32 * 180 / 255) as u8,
4003 (border_color[1] as u32 * 180 / 255) as u8,
4004 (border_color[2] as u32 * 180 / 255) as u8,
4005 255,
4006 ),
4007 text_config: TextConfig::default(),
4008 texture: texture.clone(),
4009 hint_text: String::new(),
4010 },
4011 SwitchAppearance {
4012 image_config: image_config.clone().overlay_color(0, 0, 0, 0),
4013 custom_rect_config: custom_rect_config
4014 .clone()
4015 .color(0, 0, 0, 0)
4016 .border_color(0, 0, 0, 0),
4017 text_config: TextConfig::default(),
4018 texture: texture.clone(),
4019 hint_text: String::new(),
4020 },
4021 SwitchAppearance {
4022 image_config: image_config.overlay_color(0, 0, 0, 0),
4023 custom_rect_config: custom_rect_config
4024 .color(0, 0, 0, 0)
4025 .border_color(0, 0, 0, 0),
4026 text_config: TextConfig::default(),
4027 texture,
4028 hint_text: String::new(),
4029 },
4030 ])
4031 .enable_hover_click_fill_resource(false, true)
4032 .click_method(vec![SwitchClickAction {
4033 click_method: PointerButton::Primary,
4034 action: true,
4035 }])
4036 .fill_resource_name(&format!(
4037 "MessageBox{}Close",
4038 message_box.close_switch_fill_resource_name
4039 ))
4040 .fill_resource_type(&message_box.close_switch_fill_resource_type)
4041 .text_name(""),
4042 safe_mode,
4043 )
4044 .unwrap();
4045 }
4046 _ => {}
4047 };
4048 self.rust_constructor_resource.push(Box::new(resource));
4049 Ok(())
4050 }
4051
4052 pub fn page_data(
4054 &mut self,
4055 ctx: &Context,
4056 safe_mode: Option<bool>,
4057 ) -> Result<(), RustConstructorError> {
4058 self.update_frame_stats(ctx);
4060 for rcr in &mut self.rust_constructor_resource {
4062 rcr.modify_active(false);
4063 }
4064 self.update_timer();
4066 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4067 && !self.check_resource_exists(&self.current_page, "PageData")
4068 {
4069 self.problem_report_custom(
4070 RustConstructorError::PageNotFound {
4071 page_name: self.current_page.clone(),
4072 },
4073 SeverityLevel::MildWarning,
4074 self.problem_list.clone(),
4075 );
4076 return Err(RustConstructorError::PageNotFound {
4077 page_name: self.current_page.clone(),
4078 });
4079 };
4080 let page_data = self
4081 .get_resource_mut::<PageData>(&self.current_page.clone(), "PageData")
4082 .unwrap()
4083 .unwrap();
4084 page_data.modify_active(true);
4085 if page_data.forced_update {
4086 ctx.request_repaint();
4087 };
4088 Ok(())
4089 }
4090
4091 pub fn switch_page(
4093 &mut self,
4094 name: &str,
4095 safe_mode: Option<bool>,
4096 ) -> Result<(), RustConstructorError> {
4097 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4098 && !self.check_resource_exists(name, "PageData")
4099 {
4100 self.problem_report_custom(
4101 RustConstructorError::PageNotFound {
4102 page_name: name.to_string(),
4103 },
4104 SeverityLevel::SevereWarning,
4105 self.problem_list.clone(),
4106 );
4107 return Err(RustConstructorError::PageNotFound {
4108 page_name: name.to_string(),
4109 });
4110 };
4111 self.current_page = name.to_string();
4112 let pd = self
4113 .get_resource_mut::<PageData>(name, "PageData")
4114 .unwrap()
4115 .unwrap();
4116 pd.enter_page_updated = false;
4117 self.timer.start_time = self.timer.total_time;
4118 self.update_timer();
4119 Ok(())
4120 }
4121
4122 pub fn replace_resource<T>(
4124 &mut self,
4125 name: &str,
4126 discern_type: &str,
4127 resource: T,
4128 ) -> Result<(), RustConstructorError>
4129 where
4130 T: RustConstructorResource + 'static,
4131 {
4132 if let Some(index) = self
4133 .rust_constructor_resource
4134 .iter()
4135 .position(|x| x.name() == name && x.expose_type() == discern_type)
4136 {
4137 self.rust_constructor_resource[index] = Box::new(resource);
4138 Ok(())
4139 } else {
4140 self.problem_report_custom(
4141 RustConstructorError::ResourceNotFound {
4142 resource_name: name.to_string(),
4143 resource_type: discern_type.to_string(),
4144 },
4145 SeverityLevel::SevereWarning,
4146 self.problem_list.clone(),
4147 );
4148 Err(RustConstructorError::ResourceNotFound {
4149 resource_name: name.to_string(),
4150 resource_type: discern_type.to_string(),
4151 })
4152 }
4153 }
4154
4155 pub fn get_resource<T>(
4157 &self,
4158 name: &str,
4159 discern_type: &str,
4160 ) -> Result<Option<&T>, RustConstructorError>
4161 where
4162 T: RustConstructorResource + 'static,
4163 {
4164 if self.check_resource_exists(name, discern_type) {
4165 Ok(self
4166 .rust_constructor_resource
4167 .iter()
4168 .find(|resource| resource.name() == name && resource.expose_type() == discern_type)
4169 .and_then(|resource| resource.as_any().downcast_ref::<T>()))
4170 } else {
4171 self.problem_report_custom(
4172 RustConstructorError::ResourceNotFound {
4173 resource_name: name.to_string(),
4174 resource_type: discern_type.to_string(),
4175 },
4176 SeverityLevel::SevereWarning,
4177 self.problem_list.clone(),
4178 );
4179 Err(RustConstructorError::ResourceNotFound {
4180 resource_name: name.to_string(),
4181 resource_type: discern_type.to_string(),
4182 })
4183 }
4184 }
4185
4186 pub fn get_resource_mut<T>(
4188 &mut self,
4189 name: &str,
4190 discern_type: &str,
4191 ) -> Result<Option<&mut T>, RustConstructorError>
4192 where
4193 T: RustConstructorResource + 'static,
4194 {
4195 if self.check_resource_exists(name, discern_type) {
4196 Ok(self
4197 .rust_constructor_resource
4198 .iter_mut()
4199 .find(|resource| resource.name() == name && resource.expose_type() == discern_type)
4200 .and_then(|resource| resource.as_any_mut().downcast_mut::<T>()))
4201 } else {
4202 self.problem_report_custom(
4203 RustConstructorError::ResourceNotFound {
4204 resource_name: name.to_string(),
4205 resource_type: discern_type.to_string(),
4206 },
4207 SeverityLevel::SevereWarning,
4208 self.problem_list.clone(),
4209 );
4210 Err(RustConstructorError::ResourceNotFound {
4211 resource_name: name.to_string(),
4212 resource_type: discern_type.to_string(),
4213 })
4214 }
4215 }
4216
4217 pub fn check_resource_exists(&self, name: &str, discern_type: &str) -> bool {
4219 self.rust_constructor_resource
4220 .iter()
4221 .any(|x| x.name() == name && x.expose_type() == discern_type)
4222 }
4223
4224 pub fn font(
4226 &mut self,
4227 name: &str,
4228 safe_mode: Option<bool>,
4229 ) -> Result<FontDefinitions, RustConstructorError> {
4230 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4231 && !self.check_resource_exists(name, "Font")
4232 {
4233 self.problem_report_custom(
4234 RustConstructorError::FontNotFound {
4235 font_name: name.to_string(),
4236 },
4237 SeverityLevel::SevereWarning,
4238 self.problem_list.clone(),
4239 );
4240 return Err(RustConstructorError::FontNotFound {
4241 font_name: name.to_string(),
4242 });
4243 };
4244 let f = self
4245 .get_resource_mut::<Font>(name, "Font")
4246 .unwrap()
4247 .unwrap();
4248 f.modify_active(true);
4249 Ok(f.font_definitions.clone())
4250 }
4251
4252 pub fn register_all_fonts(&mut self, ctx: &Context, safe_mode: Option<bool>) {
4254 let mut font_definitions = FontDefinitions::default();
4255 let mut font_resources = Vec::new();
4256 for i in 0..self.rust_constructor_resource.len() {
4257 if let Some(f) = self.rust_constructor_resource[i]
4258 .as_any()
4259 .downcast_ref::<Font>()
4260 {
4261 font_resources.push(f.clone());
4262 };
4263 }
4264 for i in &font_resources {
4265 let font_name = i.name.clone();
4266 if let Ok(font_def) = self.font(&font_name, safe_mode) {
4268 if let Some(font_data) = font_def.font_data.get(&font_name) {
4270 font_definitions
4271 .font_data
4272 .insert(font_name.clone(), Arc::clone(font_data));
4273 font_definitions
4274 .families
4275 .entry(FontFamily::Name(font_name.clone().into()))
4276 .or_default()
4277 .push(font_name.clone());
4278 };
4279
4280 font_definitions
4282 .families
4283 .entry(FontFamily::Proportional)
4284 .or_default()
4285 .insert(0, font_name.to_owned());
4286
4287 font_definitions
4288 .families
4289 .entry(FontFamily::Monospace)
4290 .or_default()
4291 .insert(0, font_name.to_owned());
4292 };
4293 }
4294 ctx.set_fonts(font_definitions);
4295 }
4296
4297 pub fn problem_processor(
4299 &self,
4300 problem_type: RustConstructorError,
4301 severity_level: SeverityLevel,
4302 ) -> (String, String) {
4303 let (problem, annotation) = match problem_type.clone() {
4304 RustConstructorError::ResourceNameRepetition { resource_name, resource_type } => (
4305 format!(
4306 "Resource name repetition({:?}): {}({})",
4307 severity_level, resource_name, resource_type
4308 ),
4309 "Please check whether the resource name is repeated.".to_string(),
4310 ),
4311
4312 RustConstructorError::FontGetFailed { font_path } => (
4313 format!("Font get failed({:?}): {}", severity_level, font_path,),
4314 "Please check if the font file exists and the path is correct.".to_string(),
4315 ),
4316 RustConstructorError::FontNotFound { font_name } => (
4317 format!("Font not found({:?}): {}", severity_level, font_name,),
4318 "Please check whether the font has been added.".to_string(),
4319 ),
4320 RustConstructorError::ImageGetFailed { image_path } => (
4321 format!("Image get failed({:?}): {}", severity_level, image_path,),
4322 "Please check whether the image path is correct and whether the image has been added.".to_string(),
4323 ),
4324 RustConstructorError::ImageNotFound { image_name } => (
4325 format!("Image not found({:?}): {}", severity_level, image_name,),
4326 "Please check whether the image has been added.".to_string(),
4327 ),
4328 RustConstructorError::ImageTextureNotFound { image_texture_name } => (
4329 format!("Image texture not found({:?}): {}", severity_level, image_texture_name,),
4330 "Please check whether the image texture has been added.".to_string(),
4331 ),
4332 RustConstructorError::TextNotFound { text_name } => (
4333 format!("Text not found({:?}): {}", severity_level, text_name,),
4334 "Please check whether the text has been added.".to_string(),
4335 ),
4336 RustConstructorError::MessageBoxAlreadyExists { message_box_name } => (
4337 format!("Message box already exists({:?}): {}", severity_level, message_box_name,),
4338 "Please check whether the code for generating the message box has been accidentally called multiple times.".to_string(),
4339 ),
4340 RustConstructorError::MouseDetectorNotFound { mouse_detector_name } => (
4341 format!("Mouse detector not found({:?}): {}", severity_level, mouse_detector_name,),
4342 "Please check whether the mouse detector has been added.".to_string(),
4343 ),
4344 RustConstructorError::SplitTimeNotFound { split_time_name } => (
4345 format!("Split time not found({:?}): {}", severity_level, split_time_name,),
4346 "Please check whether the split time has been added.".to_string(),
4347 ),
4348 RustConstructorError::SwitchAppearanceMismatch {
4349 switch_name,
4350 differ,
4351 } => (
4352 format!(
4353 "Switch appearance list's number of items is large / small {} more({:?}): {}",
4354 differ, severity_level, switch_name
4355 ),
4356 "Please check whether the number of appearance list items matches the number of enabled animations.".to_string(),
4357 ),
4358 RustConstructorError::SwitchNotFound { switch_name } => (
4359 format!("Switch not found({:?}): {}", severity_level, switch_name,),
4360 "Please check whether the switch has been added.".to_string(),
4361 ),
4362 RustConstructorError::SwitchFillResourceMismatch { switch_name, fill_resource_name, fill_resource_type } => (
4363 format!("Switch fill resource mismatch({:?}): Resource {} of switch {} is not of type {}", severity_level, fill_resource_name, switch_name, fill_resource_type,),
4364 "Please check whether the imported fill resource is correctly typed.".to_string(),
4365 ),
4366 RustConstructorError::PageNotFound { page_name } => (
4367 format!("Page not found({:?}): {}", severity_level, page_name,),
4368 "Please check whether the page has been added.".to_string(),
4369 ),
4370 RustConstructorError::VariableNotFound { variable_name } => (
4371 format!("Variable not found({:?}): {}", severity_level, variable_name,),
4372 "Please check whether the variable has been added.".to_string(),
4373 ),
4374 RustConstructorError::VariableTypeMismatch { variable_name } => (
4375 format!("Variable type mismatch({:?}): {}", severity_level, variable_name,),
4376 "Please check whether the generics used for matching are filled correctly.".to_string(),
4377 ),
4378 RustConstructorError::RectNotFound { rect_name } => (
4379 format!("Rect not found({:?}): {}", severity_level, rect_name,),
4380 "Please check whether the rect has been added.".to_string(),
4381 ),
4382 RustConstructorError::ResourcePanelNotFound { resource_panel_name } => (
4383 format!("Resource panel not found({:?}): {}", severity_level, resource_panel_name,),
4384 "Please check whether the resource panel has been added.".to_string(),
4385 ),
4386 RustConstructorError::ResourceNotFound {
4387 resource_name,
4388 resource_type,
4389 } => (
4390 format!(
4391 "Resource not found({:?}): {}(\"{}\")",
4392 severity_level, resource_type, resource_name,
4393 ),
4394 "Please check whether the resource has been added.".to_string(),
4395 ),
4396 RustConstructorError::ResourceUntitled { resource_type } => (
4397 format!("Resource untitled({:?}): {}", severity_level, resource_type,),
4398 "Resources must have names.".to_string(),
4399 ),
4400 RustConstructorError::CustomError { error_name, error_message, error_annotation } => (
4401 format!("Custom error({}, {:?}): {}", error_name, severity_level, error_message),
4402 error_annotation
4403 )
4404 };
4405 if self.strict_mode {
4407 panic!(
4408 "Rust Constructor Error({:?}): {}\nnote: {}",
4409 problem_type, problem, annotation
4410 );
4411 };
4412 (problem, annotation)
4413 }
4414
4415 pub fn problem_report(
4417 &mut self,
4418 problem_type: RustConstructorError,
4419 severity_level: SeverityLevel,
4420 ) {
4421 let (problem, annotation) = self.problem_processor(problem_type.clone(), severity_level);
4422 self.problem_list.push(Problem {
4423 severity_level,
4424 problem,
4425 annotation,
4426 report_state: ReportState {
4427 current_page: self.current_page.clone(),
4428 current_total_runtime: self.timer.total_time,
4429 current_page_runtime: self.timer.now_time,
4430 },
4431 problem_type: problem_type.clone(),
4432 });
4433 }
4434
4435 pub fn problem_report_custom(
4437 &self,
4438 problem_type: RustConstructorError,
4439 severity_level: SeverityLevel,
4440 mut problem_storage: Vec<Problem>,
4441 ) {
4442 let (problem, annotation) = self.problem_processor(problem_type.clone(), severity_level);
4443 problem_storage.push(Problem {
4444 severity_level,
4445 problem,
4446 annotation,
4447 report_state: ReportState {
4448 current_page: self.current_page.clone(),
4449 current_total_runtime: self.timer.total_time,
4450 current_page_runtime: self.timer.now_time,
4451 },
4452 problem_type: problem_type.clone(),
4453 });
4454 }
4455
4456 pub fn position_size_processor(
4458 &self,
4459 position_config: PositionConfig,
4460 ctx: &Context,
4461 ) -> [[f32; 2]; 2] {
4462 let mut position = [0_f32, 0_f32];
4463 let mut size = [0_f32, 0_f32];
4464 size[0] = match position_config.x_size_grid[0] {
4465 0 => position_config.origin_size[0],
4466 _ => {
4467 (ctx.available_rect().width() as f64 / position_config.x_size_grid[1] as f64
4468 * position_config.x_size_grid[0] as f64) as f32
4469 + position_config.origin_size[0]
4470 }
4471 };
4472 size[1] = match position_config.y_size_grid[0] {
4473 0 => position_config.origin_size[1],
4474 _ => {
4475 (ctx.available_rect().height() as f64 / position_config.y_size_grid[1] as f64
4476 * position_config.y_size_grid[0] as f64) as f32
4477 + position_config.origin_size[1]
4478 }
4479 };
4480 position[0] = match position_config.x_location_grid[1] {
4481 0 => position_config.origin_position[0],
4482 _ => {
4483 (ctx.available_rect().width() as f64 / position_config.x_location_grid[1] as f64
4484 * position_config.x_location_grid[0] as f64) as f32
4485 + position_config.origin_position[0]
4486 }
4487 };
4488 position[1] = match position_config.y_location_grid[1] {
4489 0 => position_config.origin_position[1],
4490 _ => {
4491 (ctx.available_rect().height() as f64 / position_config.y_location_grid[1] as f64
4492 * position_config.y_location_grid[0] as f64) as f32
4493 + position_config.origin_position[1]
4494 }
4495 };
4496 match position_config.center_display.0 {
4497 HorizontalAlign::Left => {}
4498 HorizontalAlign::Center => position[0] -= size[0] / 2.0,
4499 HorizontalAlign::Right => position[0] -= size[0],
4500 };
4501 match position_config.center_display.1 {
4502 VerticalAlign::Top => {}
4503 VerticalAlign::Center => position[1] -= size[1] / 2.0,
4504 VerticalAlign::Bottom => position[1] -= size[1],
4505 };
4506 position[0] += position_config.offset[0];
4507 position[1] += position_config.offset[1];
4508 [position, size]
4509 }
4510
4511 pub fn check_updated(
4513 &mut self,
4514 name: &str,
4515 safe_mode: Option<bool>,
4516 ) -> Result<bool, RustConstructorError> {
4517 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4518 && !self.check_resource_exists(name, "PageData")
4519 {
4520 self.problem_report_custom(
4521 RustConstructorError::PageNotFound {
4522 page_name: name.to_string(),
4523 },
4524 SeverityLevel::SevereWarning,
4525 self.problem_list.clone(),
4526 );
4527 return Err(RustConstructorError::PageNotFound {
4528 page_name: name.to_string(),
4529 });
4530 };
4531 let pd = self
4532 .get_resource::<PageData>(name, "PageData")
4533 .unwrap()
4534 .unwrap()
4535 .clone();
4536 if !pd.change_page_updated {
4537 self.new_page_update(name, safe_mode).unwrap();
4538 };
4539 Ok(pd.change_page_updated)
4540 }
4541
4542 pub fn check_enter_updated(
4544 &mut self,
4545 name: &str,
4546 safe_mode: Option<bool>,
4547 ) -> Result<bool, RustConstructorError> {
4548 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4549 && !self.check_resource_exists(name, "PageData")
4550 {
4551 self.problem_report_custom(
4552 RustConstructorError::PageNotFound {
4553 page_name: name.to_string(),
4554 },
4555 SeverityLevel::SevereWarning,
4556 self.problem_list.clone(),
4557 );
4558 return Err(RustConstructorError::PageNotFound {
4559 page_name: name.to_string(),
4560 });
4561 };
4562 let pd = self
4563 .get_resource_mut::<PageData>(name, "PageData")
4564 .unwrap()
4565 .unwrap();
4566 let return_value = pd.enter_page_updated;
4567 pd.enter_page_updated = true;
4568 Ok(return_value)
4569 }
4570
4571 pub fn new_page_update(
4573 &mut self,
4574 name: &str,
4575 safe_mode: Option<bool>,
4576 ) -> Result<(), RustConstructorError> {
4577 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4578 && !self.check_resource_exists(name, "PageData")
4579 {
4580 self.problem_report_custom(
4581 RustConstructorError::PageNotFound {
4582 page_name: name.to_string(),
4583 },
4584 SeverityLevel::SevereWarning,
4585 self.problem_list.clone(),
4586 );
4587 return Err(RustConstructorError::PageNotFound {
4588 page_name: name.to_string(),
4589 });
4590 }
4591 self.timer.start_time = self.timer.total_time;
4592 self.update_timer();
4593 let pd = self
4594 .get_resource_mut::<PageData>(name, "PageData")
4595 .unwrap()
4596 .unwrap();
4597 pd.change_page_updated = true;
4598 Ok(())
4599 }
4600
4601 pub fn update_frame_stats(&mut self, ctx: &Context) {
4603 let current_time = ctx.input(|i| i.time);
4604 if let Some(last) = self.last_frame_time {
4605 let delta = (current_time - last) as f32;
4606 self.frame_times.push(delta);
4607 const MAX_SAMPLES: usize = 120;
4608 if self.frame_times.len() > MAX_SAMPLES {
4609 let remove_count = self.frame_times.len() - MAX_SAMPLES;
4610 self.frame_times.drain(0..remove_count);
4611 }
4612 }
4613 self.last_frame_time = Some(current_time);
4614 }
4615
4616 pub fn current_fps(&self) -> f32 {
4618 if self.frame_times.is_empty() {
4619 0.0
4620 } else {
4621 1.0 / (self.frame_times.iter().sum::<f32>() / self.frame_times.len() as f32)
4622 }
4623 }
4624
4625 pub fn reset_split_time(
4627 &mut self,
4628 name: &str,
4629 safe_mode: Option<bool>,
4630 ) -> Result<(), RustConstructorError> {
4631 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4632 && !self.check_resource_exists(name, "SplitTime")
4633 {
4634 self.problem_report_custom(
4635 RustConstructorError::SplitTimeNotFound {
4636 split_time_name: name.to_string(),
4637 },
4638 SeverityLevel::SevereWarning,
4639 self.problem_list.clone(),
4640 );
4641 return Err(RustConstructorError::SplitTimeNotFound {
4642 split_time_name: name.to_string(),
4643 });
4644 };
4645 let new_time = [self.timer.now_time, self.timer.total_time];
4646 let split_time = self
4647 .get_resource_mut::<SplitTime>(name, "SplitTime")
4648 .unwrap()
4649 .unwrap();
4650 split_time.time = new_time;
4651 Ok(())
4652 }
4653
4654 pub fn split_time(
4656 &mut self,
4657 name: &str,
4658 safe_mode: Option<bool>,
4659 ) -> Result<[f32; 2], RustConstructorError> {
4660 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4661 && !self.check_resource_exists(name, "SplitTime")
4662 {
4663 self.problem_report_custom(
4664 RustConstructorError::SplitTimeNotFound {
4665 split_time_name: name.to_string(),
4666 },
4667 SeverityLevel::SevereWarning,
4668 self.problem_list.clone(),
4669 );
4670 return Err(RustConstructorError::SplitTimeNotFound {
4671 split_time_name: name.to_string(),
4672 });
4673 };
4674 let split_time = self
4675 .get_resource_mut::<SplitTime>(name, "SplitTime")
4676 .unwrap()
4677 .unwrap();
4678 split_time.modify_active(true);
4679 Ok(split_time.time)
4680 }
4681
4682 pub fn update_timer(&mut self) {
4684 let elapsed = self.timer.timer.elapsed();
4685 let seconds = elapsed.as_secs();
4686 let milliseconds = elapsed.subsec_millis();
4687 self.timer.total_time = seconds as f32 + milliseconds as f32 / 1000.0;
4688 self.timer.now_time = self.timer.total_time - self.timer.start_time
4689 }
4690
4691 pub fn custom_rect(
4693 &mut self,
4694 name: &str,
4695 ui: &mut Ui,
4696 ctx: &Context,
4697 safe_mode: Option<bool>,
4698 ) -> Result<(), RustConstructorError> {
4699 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4700 && !self.check_resource_exists(name, "CustomRect")
4701 {
4702 self.problem_report_custom(
4703 RustConstructorError::RectNotFound {
4704 rect_name: name.to_string(),
4705 },
4706 SeverityLevel::SevereWarning,
4707 self.problem_list.clone(),
4708 );
4709 return Err(RustConstructorError::RectNotFound {
4710 rect_name: name.to_string(),
4711 });
4712 };
4713 let mut custom_rect = self
4714 .get_resource_mut::<CustomRect>(name, "CustomRect")
4715 .unwrap()
4716 .unwrap()
4717 .clone();
4718 custom_rect.modify_active(true);
4719 [custom_rect.position, custom_rect.size] =
4720 self.position_size_processor(PositionConfig::from_custom_rect(&custom_rect), ctx);
4721 if custom_rect.clip_rect.is_some() {
4722 let [min, size] =
4723 self.position_size_processor(custom_rect.clip_rect.clone().unwrap(), ctx);
4724 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
4725 };
4726 ui.painter().rect(
4727 Rect::from_min_max(
4728 Pos2::new(custom_rect.position[0], custom_rect.position[1]),
4729 Pos2::new(
4730 custom_rect.position[0] + custom_rect.size[0],
4731 custom_rect.position[1] + custom_rect.size[1],
4732 ),
4733 ),
4734 custom_rect.rounding,
4735 Color32::from_rgba_unmultiplied(
4736 custom_rect.color[0],
4737 custom_rect.color[1],
4738 custom_rect.color[2],
4739 custom_rect.color[3],
4740 ),
4741 Stroke {
4742 width: custom_rect.border_width,
4743 color: Color32::from_rgba_unmultiplied(
4744 custom_rect.border_color[0],
4745 custom_rect.border_color[1],
4746 custom_rect.border_color[2],
4747 custom_rect.border_color[3],
4748 ),
4749 },
4750 StrokeKind::Inside,
4751 );
4752 if custom_rect.clip_rect.is_some() {
4753 ui.set_clip_rect(Rect::from_min_size(
4754 [0_f32, 0_f32].into(),
4755 [ctx.available_rect().width(), ctx.available_rect().height()].into(),
4756 ));
4757 };
4758 self.replace_resource(name, "CustomRect", custom_rect)
4759 .unwrap();
4760 Ok(())
4761 }
4762
4763 pub fn text(
4765 &mut self,
4766 name: &str,
4767 ui: &mut Ui,
4768 ctx: &Context,
4769 safe_mode: Option<bool>,
4770 ) -> Result<(), RustConstructorError> {
4771 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4772 && !self.check_resource_exists(name, "Text")
4773 {
4774 self.problem_report_custom(
4775 RustConstructorError::TextNotFound {
4776 text_name: name.to_string(),
4777 },
4778 SeverityLevel::SevereWarning,
4779 self.problem_list.clone(),
4780 );
4781 return Err(RustConstructorError::TextNotFound {
4782 text_name: name.to_string(),
4783 });
4784 };
4785 let mut text = self
4786 .get_resource::<Text>(name, "Text")
4787 .unwrap()
4788 .unwrap()
4789 .clone();
4790 text.modify_active(true);
4791 [text.position, text.size] =
4792 self.position_size_processor(PositionConfig::from_text(&text), ctx);
4793 let display_content = if text.truncate {
4794 let original_galley = ui.fonts_mut(|f| {
4795 f.layout(
4796 text.content.to_string(),
4797 FontId::proportional(text.font_size),
4798 Color32::default(),
4799 text.size[0],
4800 )
4801 });
4802
4803 let mut truncated = text.content.to_string();
4804 let mut ellipsis = "";
4805 if original_galley.size().y > text.size[1] {
4806 ellipsis = "...";
4808
4809 while !truncated.is_empty() {
4810 let test_text = format!("{}{}", truncated, ellipsis);
4811 let test_galley = ui.fonts_mut(|f| {
4812 f.layout(
4813 test_text.clone(),
4814 FontId::proportional(text.font_size),
4815 Color32::default(),
4816 text.size[0],
4817 )
4818 });
4819
4820 if test_galley.size().y <= text.size[1] {
4821 break;
4822 }
4823
4824 truncated.pop();
4826 }
4827 };
4828 format!("{}{}", truncated, ellipsis)
4829 } else {
4830 text.content.to_string()
4831 };
4832 let galley: Arc<Galley> = ui.fonts_mut(|f| {
4834 f.layout(
4835 display_content.to_string(),
4836 if !text.font.is_empty() {
4837 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
4838 && !self.check_resource_exists(&text.font.clone(), "Font")
4839 {
4840 self.problem_report_custom(
4841 RustConstructorError::FontNotFound {
4842 font_name: text.font.clone(),
4843 },
4844 SeverityLevel::MildWarning,
4845 self.problem_list.clone(),
4846 );
4847 FontId::new(text.font_size, FontFamily::Name(text.font.clone().into()))
4848 } else {
4849 FontId::proportional(text.font_size)
4850 }
4851 } else {
4852 FontId::proportional(text.font_size)
4853 },
4854 Color32::from_rgba_unmultiplied(
4855 text.color[0],
4856 text.color[1],
4857 text.color[2],
4858 text.color[3],
4859 ),
4860 text.size[0],
4861 )
4862 });
4863 text.actual_size = [galley.size().x, galley.size().y];
4864 let rect = Rect::from_min_size(text.position.into(), text.actual_size.into());
4866 ui.painter().rect_filled(
4868 rect,
4869 text.background_rounding,
4870 Color32::from_rgba_unmultiplied(
4871 text.background_color[0],
4872 text.background_color[1],
4873 text.background_color[2],
4874 text.background_color[3],
4875 ),
4876 );
4877
4878 if text.clip_rect.is_some() {
4879 let [min, size] = self.position_size_processor(text.clip_rect.clone().unwrap(), ctx);
4880 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
4881 };
4882
4883 ui.painter().galley(
4885 text.position.into(),
4886 galley.clone(),
4887 Color32::from_rgba_unmultiplied(
4888 text.color[0],
4889 text.color[1],
4890 text.color[2],
4891 text.color[3], ),
4893 );
4894
4895 if text.last_frame_content != display_content {
4897 text.hyperlink_index.clear();
4898
4899 let byte_to_char_map: std::collections::HashMap<usize, usize> = display_content
4901 .char_indices()
4902 .enumerate()
4903 .map(|(char_idx, (byte_idx, _))| (byte_idx, char_idx))
4904 .collect();
4905
4906 for (hyperlink_text, method) in &text.hyperlink_text {
4907 let matches: Vec<(usize, &str)> =
4908 display_content.match_indices(hyperlink_text).collect();
4909 let text_char_count = hyperlink_text.chars().count();
4910
4911 if let HyperlinkSelectMethod::All(url) = method {
4912 for (byte_index, _) in matches {
4913 if let Some(&start_char_index) = byte_to_char_map.get(&byte_index) {
4914 text.hyperlink_index.push((
4915 start_char_index,
4916 start_char_index + text_char_count,
4917 url.clone(),
4918 ));
4919 };
4920 }
4921 } else if let HyperlinkSelectMethod::Segment(list) = method {
4922 for (index, url) in list {
4923 if *index >= matches.len() {
4924 continue;
4925 };
4926 let (byte_index, _) = matches[*index];
4927 if let Some(&start_char_index) = byte_to_char_map.get(&byte_index) {
4928 text.hyperlink_index.push((
4929 start_char_index,
4930 start_char_index + text_char_count,
4931 url.clone(),
4932 ));
4933 };
4934 }
4935 };
4936 }
4937 };
4938
4939 for (start, end, _) in &text.hyperlink_index {
4941 let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
4943 let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
4944
4945 let start_pos = start_cursor.left_top();
4946 let end_pos = end_cursor.right_top();
4947 if start_cursor.min.y == end_cursor.min.y {
4950 let underline_y = text.position[1]
4952 + start_pos.y
4953 + galley.rows.first().map_or(14.0, |row| row.height())
4954 - 2.0;
4955
4956 let color = Color32::from_rgba_unmultiplied(
4958 text.color[0],
4959 text.color[1],
4960 text.color[2],
4961 text.color[3],
4962 );
4963
4964 ui.painter().line_segment(
4965 [
4966 Pos2::new(text.position[0] + start_pos.x, underline_y),
4967 Pos2::new(text.position[0] + end_pos.x, underline_y),
4968 ],
4969 Stroke::new(text.font_size / 10_f32, color),
4970 );
4971 } else {
4972 let row_height = galley.rows.first().map_or(14.0, |row| row.height()); let start_row = (start_pos.y / row_height).round() as usize;
4977 let end_row = (end_pos.y / row_height).round() as usize;
4978
4979 for row in start_row..=end_row {
4980 let row_y = text.position[1] + row as f32 * row_height + row_height - 2.0; if let Some(current_row) = galley.rows.get(row) {
4984 let row_rect = current_row.rect();
4985
4986 let color = Color32::from_rgba_unmultiplied(
4987 text.color[0],
4988 text.color[1],
4989 text.color[2],
4990 text.color[3],
4991 );
4992
4993 if row == start_row {
4994 ui.painter().line_segment(
4996 [
4997 Pos2::new(text.position[0] + start_pos.x, row_y),
4998 Pos2::new(text.position[0] + row_rect.max.x, row_y),
4999 ],
5000 Stroke::new(text.font_size / 10_f32, color),
5001 );
5002 } else if row == end_row {
5003 ui.painter().line_segment(
5005 [
5006 Pos2::new(text.position[0] + row_rect.min.x, row_y),
5007 Pos2::new(text.position[0] + end_pos.x, row_y),
5008 ],
5009 Stroke::new(text.font_size / 10_f32, color),
5010 );
5011 } else {
5012 ui.painter().line_segment(
5014 [
5015 Pos2::new(text.position[0] + row_rect.min.x, row_y),
5016 Pos2::new(text.position[0] + row_rect.max.x, row_y),
5017 ],
5018 Stroke::new(text.font_size / 10_f32, color),
5019 );
5020 };
5021 };
5022 }
5023 };
5024 }
5025
5026 if text.selectable {
5027 if !self.check_resource_exists(&text.name, "MouseDetector") {
5028 self.add_resource(
5029 MouseDetector::default()
5030 .name(&text.name)
5031 .from_position_config(PositionConfig::from_text(&text))
5032 .offset(-20_f32, -5_f32)
5033 .origin_size(text.actual_size[0] + 40_f32, text.actual_size[1] + 10_f32),
5034 safe_mode,
5035 )
5036 .unwrap();
5037 } else {
5038 self.replace_resource(
5039 &text.name,
5040 "MouseDetector",
5041 MouseDetector::default()
5042 .name(&text.name)
5043 .from_position_config(PositionConfig::from_text(&text))
5044 .offset(-20_f32, -5_f32)
5045 .origin_size(text.actual_size[0] + 40_f32, text.actual_size[1] + 10_f32),
5046 )
5047 .unwrap();
5048 };
5049
5050 let cursor_at_pointer = |pointer_pos: Vec2| -> usize {
5052 let relative_pos = pointer_pos - text.position.into();
5053 let cursor = galley.cursor_from_pos(relative_pos);
5054 cursor.index
5055 };
5056
5057 self.mouse_detector(&text.name, ui, ctx, MouseDetectorLevel::Default, safe_mode)
5058 .unwrap();
5059 let fullscreen_detect_result = ui.input(|i| i.pointer.clone());
5060 let detect_result = self
5061 .check_mouse_detect_result(&text.name, safe_mode)
5062 .unwrap();
5063 if !detect_result.clicked
5064 && (fullscreen_detect_result.any_click() || fullscreen_detect_result.any_pressed())
5065 {
5066 text.selection = None;
5067 };
5068
5069 if (detect_result.clicked || detect_result.drag_started.unwrap())
5070 && let Some(pointer_pos) = ui.input(|i| i.pointer.interact_pos())
5071 {
5072 let cursor = cursor_at_pointer(pointer_pos.to_vec2());
5073 text.selection = Some((cursor, cursor));
5074 };
5075
5076 if detect_result.dragged.unwrap()
5077 && text.selection.is_some()
5078 && let Some(pointer_pos) = ui.input(|i| i.pointer.interact_pos())
5079 {
5080 let cursor = cursor_at_pointer(pointer_pos.to_vec2());
5081 if let Some((start, _)) = text.selection {
5082 text.selection = Some((start, cursor));
5083 };
5084 };
5085
5086 if text.selection.is_some()
5087 && ui.input(|input| input.key_released(Key::A) && input.modifiers.command)
5088 {
5089 text.selection = Some((0, display_content.chars().count()));
5090 };
5091
5092 let copy_triggered = ui.input(|input| {
5094 let c_released = input.key_released(Key::C);
5095 let cmd_pressed = input.modifiers.command;
5096 c_released && cmd_pressed
5097 });
5098 if copy_triggered && let Some((start, end)) = text.selection {
5099 let (start, end) = (start.min(end), start.max(end));
5100 let chars: Vec<char> = display_content.chars().collect();
5101 if start <= chars.len() && end <= chars.len() && start < end {
5102 let selected_text: String = chars[start..end].iter().collect();
5103 ui.ctx().copy_text(selected_text);
5104 };
5105 };
5106
5107 if let Some((start, end)) = text.selection {
5109 let (start, end) = (start.min(end), start.max(end));
5110 if start != end {
5111 let start_cursor = galley.pos_from_cursor(CCursor::new(start));
5113 let end_cursor = galley.pos_from_cursor(CCursor::new(end));
5114
5115 let start_pos = start_cursor.left_top();
5116 let end_pos = end_cursor.right_top();
5117 if start_pos.y == end_pos.y {
5119 let rows = &galley.rows;
5121 let row_height = if !rows.is_empty() {
5122 if let Some(row) = rows.first() {
5124 row.height()
5125 } else {
5126 text.actual_size[1] / display_content.lines().count() as f32
5127 }
5128 } else {
5129 text.actual_size[1] / display_content.lines().count() as f32
5130 };
5131
5132 let selection_rect = Rect::from_min_max(
5133 Pos2::new(
5134 text.position[0] + start_pos.x,
5135 text.position[1] + start_pos.y,
5136 ),
5137 Pos2::new(
5138 text.position[0] + end_pos.x,
5139 text.position[1] + start_pos.y + row_height,
5140 ),
5141 );
5142 ui.painter().rect_filled(
5143 selection_rect,
5144 0.0,
5145 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5146 );
5147 } else {
5148 let rows = &galley.rows;
5150 let row_height = if !rows.is_empty() {
5151 rows[0].height()
5152 } else {
5153 text.actual_size[1] / display_content.lines().count() as f32
5154 };
5155
5156 let selection_top = text.position[1] + start_pos.y.min(end_pos.y);
5158 let selection_bottom = text.position[1] + start_pos.y.max(end_pos.y);
5159
5160 let start_row_index = (start_pos.y / row_height).floor() as usize;
5162 let end_row_index = (end_pos.y / row_height).floor() as usize;
5163 let (first_row_index, last_row_index) = if start_row_index <= end_row_index
5164 {
5165 (start_row_index, end_row_index)
5166 } else {
5167 (end_row_index, start_row_index)
5168 };
5169
5170 for (i, row) in rows.iter().enumerate() {
5171 let row_y = text.position[1] + row_height * i as f32;
5172 let row_bottom = row_y + row_height;
5173 if row_bottom > selection_top && row_y <= selection_bottom {
5175 let left = if i == first_row_index {
5176 text.position[0] + start_pos.x
5178 } else {
5179 text.position[0] + row.rect().min.x
5181 };
5182
5183 let right = if i == last_row_index {
5184 text.position[0] + end_pos.x
5186 } else {
5187 text.position[0] + row.rect().max.x
5189 };
5190
5191 let selection_rect = Rect::from_min_max(
5192 Pos2::new(left, row_y),
5193 Pos2::new(right, row_bottom),
5194 );
5195
5196 if selection_rect.width() > 0.0 && selection_rect.height() > 0.0 {
5198 ui.painter().rect_filled(
5199 selection_rect,
5200 0.0,
5201 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5202 );
5203 };
5204 };
5205 }
5206 };
5207 };
5208 };
5209 };
5210
5211 for (start, end, url) in &text.hyperlink_index {
5213 let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
5215 let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
5216
5217 let start_pos = start_cursor.left_top();
5218 let end_pos = end_cursor.right_top();
5219
5220 let row_height = galley.rows.first().map_or(14.0, |row| row.height());
5221
5222 let link_responses = if start_cursor.min.y == end_cursor.min.y {
5224 let link_rect = Rect::from_min_max(
5226 Pos2::new(
5227 text.position[0] + start_pos.x,
5228 text.position[1] + start_pos.y,
5229 ),
5230 Pos2::new(
5231 text.position[0] + end_pos.x,
5232 text.position[1] + start_pos.y + row_height,
5233 ),
5234 );
5235 vec![ui.interact(
5236 link_rect,
5237 egui::Id::new(format!("link_{}_{}_{}", text.name, start, end)),
5238 egui::Sense::click(),
5239 )]
5240 } else {
5241 let start_row = (start_pos.y / row_height).round() as usize;
5243 let end_row = (end_pos.y / row_height).round() as usize;
5244 let mut responses = Vec::new();
5245
5246 for row in start_row..=end_row {
5247 if let Some(current_row) = galley.rows.get(row) {
5248 let row_rect = current_row.rect();
5249 let row_y = text.position[1] + row as f32 * row_height;
5250
5251 let link_rect = if row == start_row {
5252 Rect::from_min_max(
5254 Pos2::new(text.position[0] + start_pos.x, row_y),
5255 Pos2::new(text.position[0] + row_rect.max.x, row_y + row_height),
5256 )
5257 } else if row == end_row {
5258 Rect::from_min_max(
5260 Pos2::new(text.position[0] + row_rect.min.x, row_y),
5261 Pos2::new(text.position[0] + end_pos.x, row_y + row_height),
5262 )
5263 } else {
5264 Rect::from_min_max(
5266 Pos2::new(text.position[0] + row_rect.min.x, row_y),
5267 Pos2::new(text.position[0] + row_rect.max.x, row_y + row_height),
5268 )
5269 };
5270
5271 responses.push(ui.interact(
5272 link_rect,
5273 Id::new(format!("link_{}_{}_{}_row_{}", text.name, start, end, row)),
5274 Sense::click(),
5275 ));
5276 };
5277 }
5278 responses
5279 };
5280
5281 let mut is_pressing_link = false;
5283 for link_response in &link_responses {
5284 if link_response.is_pointer_button_down_on() && !link_response.drag_started() {
5285 text.selection = None;
5286 if let Some(pointer_pos) = ui.input(|i| i.pointer.interact_pos()) {
5287 let relative_pos =
5288 pointer_pos - <[f32; 2] as Into<Pos2>>::into(text.position);
5289 let cursor = galley.cursor_from_pos(relative_pos);
5290 if cursor.index >= *start && cursor.index <= *end {
5291 is_pressing_link = true;
5292 break;
5293 };
5294 };
5295 };
5296 }
5297
5298 let mut clicked_on_link = false;
5300 for link_response in &link_responses {
5301 if link_response.clicked()
5302 && let Some(pointer_pos) = ui.input(|i| i.pointer.interact_pos())
5303 {
5304 let relative_pos = pointer_pos - <[f32; 2] as Into<Pos2>>::into(text.position);
5305 let cursor = galley.cursor_from_pos(relative_pos);
5306 if cursor.index >= *start && cursor.index <= *end {
5307 clicked_on_link = true;
5308 break;
5309 };
5310 };
5311 }
5312
5313 if clicked_on_link {
5314 if !url.is_empty() {
5316 ui.ctx().open_url(OpenUrl::new_tab(url));
5317 };
5318 };
5319
5320 if is_pressing_link {
5322 if start_cursor.min.y == end_cursor.min.y {
5323 let selection_rect = Rect::from_min_max(
5325 Pos2::new(
5326 text.position[0] + start_pos.x,
5327 text.position[1] + start_pos.y,
5328 ),
5329 Pos2::new(
5330 text.position[0] + end_pos.x,
5331 text.position[1]
5332 + start_pos.y
5333 + galley.rows.first().map_or(14.0, |row| row.height()),
5334 ),
5335 );
5336 ui.painter().rect_filled(
5337 selection_rect,
5338 0.0,
5339 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5340 );
5341 } else {
5342 let row_height = galley.rows.first().map_or(14.0, |row| row.height());
5344 let start_row = (start_pos.y / row_height).round() as usize;
5345 let end_row = (end_pos.y / row_height).round() as usize;
5346
5347 for row in start_row..=end_row {
5348 if let Some(current_row) = galley.rows.get(row) {
5349 let row_rect = current_row.rect();
5350
5351 if row == start_row {
5352 let selection_rect = Rect::from_min_max(
5354 Pos2::new(
5355 text.position[0] + start_pos.x,
5356 text.position[1] + row as f32 * row_height,
5357 ),
5358 Pos2::new(
5359 text.position[0] + row_rect.max.x,
5360 text.position[1] + row as f32 * row_height + row_height,
5361 ),
5362 );
5363 ui.painter().rect_filled(
5364 selection_rect,
5365 0.0,
5366 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5367 );
5368 } else if row == end_row {
5369 let selection_rect = Rect::from_min_max(
5371 Pos2::new(
5372 text.position[0] + row_rect.min.x,
5373 text.position[1] + row as f32 * row_height,
5374 ),
5375 Pos2::new(
5376 text.position[0] + end_pos.x,
5377 text.position[1] + row as f32 * row_height + row_height,
5378 ),
5379 );
5380 ui.painter().rect_filled(
5381 selection_rect,
5382 0.0,
5383 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5384 );
5385 } else {
5386 let selection_rect = Rect::from_min_max(
5388 Pos2::new(
5389 text.position[0] + row_rect.min.x,
5390 text.position[1] + row as f32 * row_height,
5391 ),
5392 Pos2::new(
5393 text.position[0] + row_rect.max.x,
5394 text.position[1] + row as f32 * row_height + row_height,
5395 ),
5396 );
5397 ui.painter().rect_filled(
5398 selection_rect,
5399 0.0,
5400 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
5401 );
5402 };
5403 };
5404 }
5405 };
5406 };
5407 }
5408 text.last_frame_content = display_content.clone();
5409 if text.clip_rect.is_some() {
5410 ui.set_clip_rect(Rect::from_min_size(
5411 [0_f32, 0_f32].into(),
5412 [ctx.available_rect().width(), ctx.available_rect().height()].into(),
5413 ));
5414 };
5415 self.replace_resource(name, "Text", text).unwrap();
5416 Ok(())
5417 }
5418
5419 pub fn modify_var<T: Debug + 'static>(
5421 &mut self,
5422 name: &str,
5423 value: Option<T>,
5424 safe_mode: Option<bool>,
5425 ) -> Result<(), RustConstructorError> {
5426 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5427 && !self.check_resource_exists(name, "Variable")
5428 {
5429 self.problem_report_custom(
5430 RustConstructorError::VariableNotFound {
5431 variable_name: name.to_string(),
5432 },
5433 SeverityLevel::SevereWarning,
5434 self.problem_list.clone(),
5435 );
5436 return Err(RustConstructorError::VariableNotFound {
5437 variable_name: name.to_string(),
5438 });
5439 };
5440 let v = self
5441 .get_resource_mut::<Variable<T>>(name, "Variable")
5442 .unwrap()
5443 .unwrap();
5444 v.value = value;
5445 Ok(())
5446 }
5447
5448 pub fn var<T: Debug + 'static>(
5450 &mut self,
5451 name: &str,
5452 safe_mode: Option<bool>,
5453 ) -> Result<Option<&T>, RustConstructorError> {
5454 if safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode {
5455 if !self.check_resource_exists(name, "Variable") {
5456 self.problem_report_custom(
5457 RustConstructorError::VariableNotFound {
5458 variable_name: name.to_string(),
5459 },
5460 SeverityLevel::SevereWarning,
5461 self.problem_list.clone(),
5462 );
5463 return Err(RustConstructorError::VariableNotFound {
5464 variable_name: name.to_string(),
5465 });
5466 };
5467 if self
5468 .get_resource::<Variable<T>>(name, "Variable")
5469 .unwrap()
5470 .is_none()
5471 {
5472 self.problem_report_custom(
5473 RustConstructorError::VariableTypeMismatch {
5474 variable_name: name.to_string(),
5475 },
5476 SeverityLevel::SevereWarning,
5477 self.problem_list.clone(),
5478 );
5479 return Err(RustConstructorError::VariableTypeMismatch {
5480 variable_name: name.to_string(),
5481 });
5482 };
5483 };
5484 let v = self
5485 .get_resource_mut::<Variable<T>>(name, "Variable")
5486 .unwrap()
5487 .unwrap();
5488 v.modify_active(true);
5489 Ok(v.value.as_ref())
5490 }
5491
5492 pub fn image_texture(
5494 &mut self,
5495 name: &str,
5496 safe_mode: Option<bool>,
5497 ) -> Result<Option<DebugTextureHandle>, RustConstructorError> {
5498 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5499 && !self.check_resource_exists(name, "ImageTexture")
5500 {
5501 self.problem_report_custom(
5502 RustConstructorError::ImageNotFound {
5503 image_name: name.to_string(),
5504 },
5505 SeverityLevel::SevereWarning,
5506 self.problem_list.clone(),
5507 );
5508 return Err(RustConstructorError::ImageNotFound {
5509 image_name: name.to_string(),
5510 });
5511 };
5512 let image_texture = self
5513 .get_resource_mut::<ImageTexture>(name, "ImageTexture")
5514 .unwrap()
5515 .unwrap();
5516 image_texture.modify_active(true);
5517 Ok(image_texture.texture.clone())
5518 }
5519
5520 pub fn reset_image_texture(
5522 &mut self,
5523 name: &str,
5524 path: &str,
5525 flip: [bool; 2],
5526 ctx: &Context,
5527 safe_mode: Option<bool>,
5528 ) -> Result<(), RustConstructorError> {
5529 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5530 && !self.check_resource_exists(name, "ImageTexture")
5531 {
5532 self.problem_report_custom(
5533 RustConstructorError::ImageTextureNotFound {
5534 image_texture_name: name.to_string(),
5535 },
5536 SeverityLevel::SevereWarning,
5537 self.problem_list.clone(),
5538 );
5539 return Err(RustConstructorError::ImageTextureNotFound {
5540 image_texture_name: name.to_string(),
5541 });
5542 };
5543 let image_texture = self
5544 .get_resource_mut::<ImageTexture>(name, "ImageTexture")
5545 .unwrap()
5546 .unwrap();
5547 if let Ok(mut file) = File::open(path) {
5548 let mut buffer = Vec::new();
5549 file.read_to_end(&mut buffer).unwrap();
5550 let img_bytes = buffer;
5551 let img = image::load_from_memory(&img_bytes).unwrap();
5552 let color_data = match flip {
5553 [true, true] => img.fliph().flipv().into_rgba8(),
5554 [true, false] => img.fliph().into_rgba8(),
5555 [false, true] => img.flipv().into_rgba8(),
5556 _ => img.into_rgba8(),
5557 };
5558 let (w, h) = (color_data.width(), color_data.height());
5559 let raw_data: Vec<u8> = color_data.into_raw();
5560
5561 let color_image =
5562 ColorImage::from_rgba_unmultiplied([w as usize, h as usize], &raw_data);
5563 let texture = ctx.load_texture(
5564 image_texture.name.clone(),
5565 color_image,
5566 TextureOptions::LINEAR,
5567 );
5568 image_texture.texture = Some(DebugTextureHandle::new(texture));
5569 image_texture.cite_path = path.to_string();
5570 } else {
5571 self.problem_report_custom(
5572 RustConstructorError::ImageGetFailed {
5573 image_path: path.to_string(),
5574 },
5575 SeverityLevel::SevereWarning,
5576 self.problem_list.clone(),
5577 );
5578 };
5579 Ok(())
5580 }
5581
5582 pub fn image(
5584 &mut self,
5585 name: &str,
5586 ui: &mut Ui,
5587 ctx: &Context,
5588 safe_mode: Option<bool>,
5589 ) -> Result<(), RustConstructorError> {
5590 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5591 && !self.check_resource_exists(name, "Image")
5592 {
5593 self.problem_report_custom(
5594 RustConstructorError::ImageNotFound {
5595 image_name: name.to_string(),
5596 },
5597 SeverityLevel::SevereWarning,
5598 self.problem_list.clone(),
5599 );
5600 return Err(RustConstructorError::ImageNotFound {
5601 image_name: name.to_string(),
5602 });
5603 };
5604 let mut image = self
5605 .get_resource_mut::<Image>(name, "Image")
5606 .unwrap()
5607 .unwrap()
5608 .clone();
5609 if image.cite_texture != image.last_frame_cite_texture {
5610 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5611 && !self.check_resource_exists(&image.cite_texture, "ImageTexture")
5612 {
5613 self.problem_report_custom(
5614 RustConstructorError::ImageTextureNotFound {
5615 image_texture_name: image.cite_texture.clone(),
5616 },
5617 SeverityLevel::MildWarning,
5618 self.problem_list.clone(),
5619 );
5620 } else {
5621 let it = self
5622 .get_resource::<ImageTexture>(&image.cite_texture, "ImageTexture")
5623 .unwrap()
5624 .unwrap();
5625 image.texture = it.texture.clone();
5626 };
5627 };
5628 image.modify_active(true);
5629 [image.position, image.size] =
5630 self.position_size_processor(PositionConfig::from_image(&image), ctx);
5631 if image.clip_rect.is_some() {
5632 let [min, size] = self.position_size_processor(image.clip_rect.clone().unwrap(), ctx);
5633 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
5634 };
5635 if let Some(texture) = &image.texture {
5636 let rect = Rect::from_min_size(
5637 Pos2::new(image.position[0], image.position[1]),
5638 Vec2::new(image.size[0], image.size[1]),
5639 );
5640
5641 egui::Image::new(ImageSource::Texture((&texture.0).into()))
5643 .tint(Color32::from_rgba_unmultiplied(
5644 image.overlay_color[0],
5645 image.overlay_color[1],
5646 image.overlay_color[2],
5647 (image.alpha as f32 * image.overlay_color[3] as f32 / 255.0) as u8,
5649 ))
5650 .bg_fill(Color32::from_rgba_unmultiplied(
5651 image.background_color[0],
5652 image.background_color[1],
5653 image.background_color[2],
5654 image.background_color[3],
5655 ))
5656 .rotate(
5657 image.rotate_angle,
5658 [
5659 image.rotate_center[0] / image.size[0],
5660 image.rotate_center[1] / image.size[1],
5661 ]
5662 .into(),
5663 )
5664 .paint_at(ui, rect)
5665 };
5666 image.last_frame_cite_texture = image.cite_texture.clone();
5667 if image.clip_rect.is_some() {
5668 ui.set_clip_rect(Rect::from_min_size(
5669 [0_f32, 0_f32].into(),
5670 [ctx.available_rect().width(), ctx.available_rect().height()].into(),
5671 ));
5672 };
5673 self.replace_resource(name, "Image", image).unwrap();
5674 Ok(())
5675 }
5676
5677 pub fn message_box(&mut self, ctx: &Context, ui: &mut Ui, safe_mode: Option<bool>) {
5679 let mut offset = 0_f32;
5680 let mut delete_count = 0;
5681 let mut index_list = Vec::new();
5682 for i in 0..self.rust_constructor_resource.len() {
5683 if self.rust_constructor_resource[i]
5684 .as_any()
5685 .downcast_ref::<MessageBox>()
5686 .is_some()
5687 {
5688 index_list.push(i);
5689 };
5690 }
5691 for u in 0..index_list.len() {
5692 let mut deleted = false;
5693 let i = u - delete_count;
5694 let mut mb = self.rust_constructor_resource[index_list[i]]
5695 .as_any()
5696 .downcast_ref::<MessageBox>()
5697 .unwrap()
5698 .clone();
5699 if safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode {
5700 if !self.check_resource_exists(&mb.image_name, "Image") {
5701 self.problem_report_custom(
5702 RustConstructorError::ImageNotFound {
5703 image_name: mb.image_name,
5704 },
5705 SeverityLevel::SevereWarning,
5706 self.problem_list.clone(),
5707 );
5708 continue;
5709 };
5710 if !self.check_resource_exists(&format!("MessageBox{}", mb.name), "CustomRect") {
5711 self.problem_report_custom(
5712 RustConstructorError::RectNotFound {
5713 rect_name: format!("MessageBox{}", mb.name),
5714 },
5715 SeverityLevel::SevereWarning,
5716 self.problem_list.clone(),
5717 );
5718 continue;
5719 };
5720 if !self.check_resource_exists(&mb.title_name, "Text") {
5721 self.problem_report_custom(
5722 RustConstructorError::TextNotFound {
5723 text_name: mb.title_name,
5724 },
5725 SeverityLevel::SevereWarning,
5726 self.problem_list.clone(),
5727 );
5728 continue;
5729 };
5730 if !self.check_resource_exists(&mb.content_name, "Text") {
5731 self.problem_report_custom(
5732 RustConstructorError::TextNotFound {
5733 text_name: mb.content_name,
5734 },
5735 SeverityLevel::SevereWarning,
5736 self.problem_list.clone(),
5737 );
5738 continue;
5739 };
5740 if !self.check_resource_exists(&format!("MessageBox{}Close", mb.name), "Switch") {
5741 self.problem_report_custom(
5742 RustConstructorError::SwitchNotFound {
5743 switch_name: format!("MessageBox{}Close", mb.name),
5744 },
5745 SeverityLevel::SevereWarning,
5746 self.problem_list.clone(),
5747 );
5748 continue;
5749 };
5750 if !self
5751 .check_resource_exists(&format!("MessageBox{}Animation", mb.name), "SplitTime")
5752 {
5753 self.problem_report_custom(
5754 RustConstructorError::SplitTimeNotFound {
5755 split_time_name: format!("MessageBox{}Animation", mb.name),
5756 },
5757 SeverityLevel::SevereWarning,
5758 self.problem_list.clone(),
5759 );
5760 continue;
5761 };
5762 if !mb.keep_existing
5763 && !self.check_resource_exists(&format!("MessageBox{}", mb.name), "SplitTime")
5764 {
5765 self.problem_report_custom(
5766 RustConstructorError::SplitTimeNotFound {
5767 split_time_name: format!("MessageBox{}", mb.name),
5768 },
5769 SeverityLevel::SevereWarning,
5770 self.problem_list.clone(),
5771 );
5772 continue;
5773 };
5774 };
5775 let mut im1 = self
5776 .get_resource::<Image>(&mb.image_name, "Image")
5777 .unwrap()
5778 .unwrap()
5779 .clone();
5780 let mut cr = self
5781 .get_resource::<CustomRect>(&format!("MessageBox{}", mb.name), "CustomRect")
5782 .unwrap()
5783 .unwrap()
5784 .clone();
5785 let mut t1 = self
5786 .get_resource::<Text>(&mb.title_name, "Text")
5787 .unwrap()
5788 .unwrap()
5789 .clone();
5790 let mut t2 = self
5791 .get_resource::<Text>(&mb.content_name, "Text")
5792 .unwrap()
5793 .unwrap()
5794 .clone();
5795 let mut s = self
5796 .get_resource::<Switch>(&format!("MessageBox{}Close", mb.name), "Switch")
5797 .unwrap()
5798 .unwrap()
5799 .clone();
5800 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
5801 && !self.check_resource_exists(&s.fill_resource_name, &s.fill_resource_type)
5802 {
5803 self.problem_report_custom(
5804 RustConstructorError::ResourceNotFound {
5805 resource_name: s.fill_resource_name,
5806 resource_type: s.fill_resource_type,
5807 },
5808 SeverityLevel::SevereWarning,
5809 self.problem_list.clone(),
5810 );
5811 continue;
5812 };
5813 let fr: Box<dyn BasicFrontResource> = match s.fill_resource_type.as_str() {
5814 "Image" => Box::new(
5815 self.get_resource::<Image>(&s.fill_resource_name, "Image")
5816 .unwrap()
5817 .unwrap()
5818 .clone(),
5819 ),
5820 "CustomRect" => Box::new(
5821 self.get_resource::<CustomRect>(&s.fill_resource_name, "CustomRect")
5822 .unwrap()
5823 .unwrap()
5824 .clone(),
5825 ),
5826 _ => {
5827 self.problem_report_custom(
5828 RustConstructorError::SwitchFillResourceMismatch {
5829 switch_name: s.name,
5830 fill_resource_name: s.fill_resource_name,
5831 fill_resource_type: s.fill_resource_type,
5832 },
5833 SeverityLevel::SevereWarning,
5834 self.problem_list.clone(),
5835 );
5836 continue;
5837 }
5838 };
5839 mb.modify_active(true);
5840 if mb.size[1] < t1.actual_size[1] + t2.actual_size[1] + 10_f32 {
5841 mb.size[1] = t1.actual_size[1] + t2.actual_size[1] + 10_f32;
5842 cr.origin_size[1] = mb.size[1];
5843 im1.origin_size = [mb.size[1] - 15_f32, mb.size[1] - 15_f32];
5844 t1.origin_size[0] = mb.size[0] - mb.size[1] + 5_f32;
5845 t2.origin_size[0] = mb.size[0] - mb.size[1] + 5_f32;
5846 };
5847 if self.timer.total_time
5848 - self
5849 .split_time(&format!("MessageBox{}Animation", mb.name), safe_mode)
5850 .unwrap()[1]
5851 >= self.tick_interval
5852 {
5853 self.reset_split_time(&format!("MessageBox{}Animation", mb.name), safe_mode)
5854 .unwrap();
5855 if offset != mb.memory_offset {
5856 if mb.memory_offset < offset {
5857 if mb.memory_offset + mb.restore_speed >= offset {
5858 mb.memory_offset = offset;
5859 } else {
5860 mb.memory_offset += mb.restore_speed;
5861 };
5862 } else if mb.memory_offset - mb.restore_speed <= offset {
5863 mb.memory_offset = offset;
5864 } else {
5865 mb.memory_offset -= mb.restore_speed;
5866 };
5867 };
5868 if cr.origin_position[0] != -mb.size[0] - 5_f32 {
5869 if mb.exist {
5870 if cr.origin_position[0] - mb.speed <= -mb.size[0] - 5_f32 {
5871 cr.origin_position[0] = -mb.size[0] - 5_f32;
5872 if self.check_resource_exists(
5873 &format!("MessageBox{}", mb.name),
5874 "SplitTime",
5875 ) {
5876 self.reset_split_time(&format!("MessageBox{}", mb.name), safe_mode)
5877 .unwrap();
5878 };
5879 } else {
5880 cr.origin_position[0] -= mb.speed;
5881 };
5882 } else if cr.origin_position[0] + mb.speed >= 15_f32 {
5883 cr.origin_position[0] = 15_f32;
5884 delete_count += 1;
5885 deleted = true;
5886 } else {
5887 cr.origin_position[0] += mb.speed;
5888 };
5889 };
5890 };
5891 cr.origin_position[1] = mb.memory_offset + 20_f32;
5892 im1.origin_position = [
5893 cr.origin_position[0] + 5_f32,
5894 cr.origin_position[1] + mb.size[1] / 2_f32,
5895 ];
5896 t1.origin_position = [
5897 im1.origin_position[0] + im1.origin_size[0] + 5_f32,
5898 cr.origin_position[1] + 5_f32,
5899 ];
5900 t2.origin_position = [
5901 im1.origin_position[0] + im1.origin_size[0] + 5_f32,
5902 t1.origin_position[1] + t1.actual_size[1] + 5_f32,
5903 ];
5904 for sd in &mut s.appearance {
5905 sd.image_config.origin_position = cr.position;
5906 sd.custom_rect_config.origin_position = cr.position;
5907 }
5908 if !mb.keep_existing
5909 && self.timer.total_time
5910 - self
5911 .split_time(&format!("MessageBox{}", mb.name), safe_mode)
5912 .unwrap()[1]
5913 >= mb.existing_time
5914 && cr.origin_position[0] == -mb.size[0] - 5_f32
5915 {
5916 mb.exist = false;
5917 if cr.origin_position[0] + mb.speed >= 15_f32 {
5918 cr.origin_position[0] = 15_f32;
5919 } else {
5920 cr.origin_position[0] += mb.speed;
5921 };
5922 };
5923 if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos()) {
5924 let rect = Rect::from_min_size(
5925 Pos2 {
5926 x: fr.display_position()[0],
5927 y: fr.display_position()[1],
5928 },
5929 Vec2 {
5930 x: cr.origin_size[0] + 15_f32,
5931 y: cr.size[1] + 15_f32,
5932 },
5933 );
5934 if rect.contains(mouse_pos) {
5935 s.appearance[0].image_config.overlay_color[3] = 255;
5936 s.appearance[0].custom_rect_config.color[3] = 255;
5937 s.appearance[0].custom_rect_config.border_color[3] = 255;
5938 } else {
5939 s.appearance[0].image_config.overlay_color[3] = 0;
5940 s.appearance[0].custom_rect_config.color[3] = 0;
5941 s.appearance[0].custom_rect_config.border_color[3] = 0;
5942 };
5943 };
5944 self.rust_constructor_resource[index_list[i]] = Box::new(mb.clone());
5945 self.replace_resource(&mb.image_name, "Image", im1.clone())
5946 .unwrap();
5947 self.replace_resource(&format!("MessageBox{}", mb.name), "CustomRect", cr.clone())
5948 .unwrap();
5949 self.replace_resource(&mb.title_name, "Text", t1.clone())
5950 .unwrap();
5951 self.replace_resource(&mb.content_name, "Text", t2.clone())
5952 .unwrap();
5953 self.replace_resource(&format!("MessageBox{}Close", mb.name), "Switch", s.clone())
5954 .unwrap();
5955 match s.fill_resource_type.as_str() {
5956 "Image" => {
5957 self.replace_resource(
5958 &s.fill_resource_name,
5959 &s.fill_resource_type,
5960 fr.as_any().downcast_ref::<Image>().unwrap().clone(),
5961 )
5962 .unwrap();
5963 }
5964 "CustomRect" => {
5965 self.replace_resource(
5966 &s.fill_resource_name,
5967 &s.fill_resource_type,
5968 fr.as_any().downcast_ref::<CustomRect>().unwrap().clone(),
5969 )
5970 .unwrap();
5971 }
5972 _ => {
5973 self.problem_report_custom(
5974 RustConstructorError::SwitchFillResourceMismatch {
5975 switch_name: s.name,
5976 fill_resource_name: s.fill_resource_name,
5977 fill_resource_type: s.fill_resource_type,
5978 },
5979 SeverityLevel::SevereWarning,
5980 self.problem_list.clone(),
5981 );
5982 continue;
5983 }
5984 };
5985 self.custom_rect(&format!("MessageBox{}", mb.name), ui, ctx, safe_mode)
5986 .unwrap();
5987 self.image(&mb.image_name.clone(), ui, ctx, safe_mode)
5988 .unwrap();
5989 self.text(&t1.name.clone(), ui, ctx, safe_mode).unwrap();
5990 self.text(&t2.name.clone(), ui, ctx, safe_mode).unwrap();
5991 self.switch(
5992 &format!("MessageBox{}Close", mb.name),
5993 ui,
5994 ctx,
5995 s.state == 0 && mb.exist,
5996 safe_mode,
5997 )
5998 .unwrap();
5999 let switch_data = self
6000 .check_switch_data(&format!("MessageBox{}Close", mb.name), safe_mode)
6001 .unwrap();
6002 if switch_data.last_time_clicked_index == 0
6003 && switch_data.state == 1
6004 && switch_data.switched
6005 {
6006 mb.exist = false;
6007 if cr.origin_position[0] + mb.speed >= 15_f32 {
6008 cr.origin_position[0] = 15_f32;
6009 } else {
6010 cr.origin_position[0] += mb.speed;
6011 };
6012 self.rust_constructor_resource[index_list[i]] = Box::new(mb.clone());
6013 self.replace_resource(&format!("MessageBox{}", mb.name), "CustomRect", cr.clone())
6014 .unwrap();
6015 };
6016 if deleted {
6017 self.rust_constructor_resource.remove(
6018 self.rust_constructor_resource
6019 .iter()
6020 .position(|x| x.expose_type() == "Image" && x.name() == mb.image_name)
6021 .unwrap(),
6022 );
6023 self.rust_constructor_resource.remove(
6024 self.rust_constructor_resource
6025 .iter()
6026 .position(|x| {
6027 x.expose_type() == "CustomRect"
6028 && x.name() == format!("MessageBox{}", mb.name)
6029 })
6030 .unwrap(),
6031 );
6032 self.rust_constructor_resource.remove(
6033 self.rust_constructor_resource
6034 .iter()
6035 .position(|x| x.expose_type() == "Text" && x.name() == mb.title_name)
6036 .unwrap(),
6037 );
6038 self.rust_constructor_resource.remove(
6039 self.rust_constructor_resource
6040 .iter()
6041 .position(|x| x.expose_type() == "Text" && x.name() == mb.content_name)
6042 .unwrap(),
6043 );
6044 self.rust_constructor_resource.remove(
6045 self.rust_constructor_resource
6046 .iter()
6047 .position(|x| {
6048 x.expose_type() == "Switch"
6049 && x.name() == format!("MessageBox{}Close", mb.name)
6050 })
6051 .unwrap(),
6052 );
6053 self.rust_constructor_resource.remove(
6054 self.rust_constructor_resource
6055 .iter()
6056 .position(|x| {
6057 x.expose_type() == s.fill_resource_type
6058 && x.name() == s.fill_resource_name
6059 })
6060 .unwrap(),
6061 );
6062 self.rust_constructor_resource.remove(
6063 self.rust_constructor_resource
6064 .iter()
6065 .position(|x| {
6066 x.expose_type() == "SplitTime"
6067 && x.name() == format!("MessageBox{}Animation", mb.name)
6068 })
6069 .unwrap(),
6070 );
6071 if !mb.keep_existing {
6072 self.rust_constructor_resource.remove(
6073 self.rust_constructor_resource
6074 .iter()
6075 .position(|x| {
6076 x.expose_type() == "SplitTime"
6077 && x.name() == format!("MessageBox{}", mb.name)
6078 })
6079 .unwrap(),
6080 );
6081 };
6082 self.rust_constructor_resource.remove(
6083 self.rust_constructor_resource
6084 .iter()
6085 .position(|x| x.expose_type() == "MessageBox" && x.name() == mb.name)
6086 .unwrap(),
6087 );
6088 self.rust_constructor_resource.remove(
6089 self.rust_constructor_resource
6090 .iter()
6091 .position(|x| x.expose_type() == "MouseDetector" && x.name() == t1.name)
6092 .unwrap(),
6093 );
6094 self.rust_constructor_resource.remove(
6095 self.rust_constructor_resource
6096 .iter()
6097 .position(|x| x.expose_type() == "MouseDetector" && x.name() == t2.name)
6098 .unwrap(),
6099 );
6100 } else {
6101 offset += mb.size[1] + 15_f32;
6102 };
6103 }
6104 }
6105
6106 pub fn switch(
6108 &mut self,
6109 name: &str,
6110 ui: &mut Ui,
6111 ctx: &Context,
6112 enable: bool,
6113 safe_mode: Option<bool>,
6114 ) -> Result<(), RustConstructorError> {
6115 let mut appearance_count = 0;
6116 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6117 && !self.check_resource_exists(name, "Switch")
6118 {
6119 self.problem_report_custom(
6120 RustConstructorError::SwitchNotFound {
6121 switch_name: name.to_string(),
6122 },
6123 SeverityLevel::SevereWarning,
6124 self.problem_list.clone(),
6125 );
6126 return Err(RustConstructorError::SwitchNotFound {
6127 switch_name: name.to_string(),
6128 });
6129 };
6130 let mut s = self
6131 .get_resource::<Switch>(name, "Switch")
6132 .unwrap()
6133 .unwrap()
6134 .clone();
6135 s.switched = false;
6136 if safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode {
6137 if !self.check_resource_exists(&s.fill_resource_name.clone(), &s.fill_resource_type) {
6138 self.problem_report_custom(
6139 RustConstructorError::ResourceNotFound {
6140 resource_name: s.fill_resource_name.clone(),
6141 resource_type: s.fill_resource_type.clone(),
6142 },
6143 SeverityLevel::SevereWarning,
6144 self.problem_list.clone(),
6145 );
6146 return Err(RustConstructorError::ResourceNotFound {
6147 resource_name: s.fill_resource_name,
6148 resource_type: s.fill_resource_type,
6149 });
6150 };
6151 if !s.hint_text_name.is_empty() {
6152 if !self.check_resource_exists(&format!("{}StartHoverTime", s.name), "SplitTime") {
6153 self.problem_report_custom(
6154 RustConstructorError::SplitTimeNotFound {
6155 split_time_name: format!("{}StartHoverTime", s.name),
6156 },
6157 SeverityLevel::MildWarning,
6158 self.problem_list.clone(),
6159 );
6160 self.add_resource(
6161 SplitTime::default().name(&format!("{}StartHoverTime", s.name)),
6162 safe_mode,
6163 )
6164 .unwrap();
6165 };
6166 if !self.check_resource_exists(&format!("{}HintFadeAnimation", s.name), "SplitTime")
6167 {
6168 self.problem_report_custom(
6169 RustConstructorError::SplitTimeNotFound {
6170 split_time_name: format!("{}HintFadeAnimation", s.name),
6171 },
6172 SeverityLevel::MildWarning,
6173 self.problem_list.clone(),
6174 );
6175 self.add_resource(
6176 SplitTime::default().name(&format!("{}HintFadeAnimation", s.name)),
6177 safe_mode,
6178 )
6179 .unwrap();
6180 };
6181 if !self.check_resource_exists(&s.hint_text_name, "Text") {
6182 self.problem_report_custom(
6183 RustConstructorError::TextNotFound {
6184 text_name: s.hint_text_name.clone(),
6185 },
6186 SeverityLevel::MildWarning,
6187 self.problem_list.clone(),
6188 );
6189 self.add_resource(
6190 Text::default()
6191 .name(&s.hint_text_name)
6192 .content("")
6193 .origin_position(0_f32, 0_f32)
6194 .font_size(25_f32)
6195 .origin_size(300_f32, 0_f32)
6196 .background_rounding(10_f32)
6197 .color(255, 255, 255, 0)
6198 .background_color(0, 0, 0, 255)
6199 .center_display(HorizontalAlign::Left, VerticalAlign::Top)
6200 .selectable(false),
6201 safe_mode,
6202 )
6203 .unwrap();
6204 };
6205 };
6206 };
6207 let fr: Box<dyn BasicFrontResource> = match &*s.fill_resource_type {
6208 "Image" => Box::new(
6209 self.get_resource::<Image>(&s.fill_resource_name.clone(), &s.fill_resource_type)
6210 .unwrap()
6211 .unwrap()
6212 .clone(),
6213 ),
6214 "CustomRect" => Box::new(
6215 self.get_resource::<CustomRect>(
6216 &s.fill_resource_name.clone(),
6217 &s.fill_resource_type,
6218 )
6219 .unwrap()
6220 .unwrap()
6221 .clone(),
6222 ),
6223 _ => {
6224 self.problem_report_custom(
6225 RustConstructorError::SwitchFillResourceMismatch {
6226 switch_name: name.to_string(),
6227 fill_resource_name: s.fill_resource_name.clone(),
6228 fill_resource_type: s.fill_resource_type.clone(),
6229 },
6230 SeverityLevel::SevereWarning,
6231 self.problem_list.clone(),
6232 );
6233 return Err(RustConstructorError::SwitchFillResourceMismatch {
6234 switch_name: name.to_string(),
6235 fill_resource_name: s.fill_resource_name,
6236 fill_resource_type: s.fill_resource_type,
6237 });
6238 }
6239 };
6240 s.modify_active(true);
6241 let rect = Rect::from_min_size(
6242 Pos2::new(fr.display_position()[0], fr.display_position()[1]),
6243 Vec2::new(fr.display_size()[0], fr.display_size()[1]),
6244 );
6245 let mut hovered = false;
6246 if enable {
6247 if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos()) {
6248 if rect.contains(mouse_pos) {
6250 if !s.hint_text_name.is_empty() {
6251 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6252 && !self.check_resource_exists(&s.hint_text_name, "Text")
6253 {
6254 self.problem_report_custom(
6255 RustConstructorError::TextNotFound {
6256 text_name: s.hint_text_name.clone(),
6257 },
6258 SeverityLevel::SevereWarning,
6259 self.problem_list.clone(),
6260 );
6261 return Err(RustConstructorError::TextNotFound {
6262 text_name: s.hint_text_name.clone(),
6263 });
6264 };
6265 let mut t = self
6266 .get_resource::<Text>(&s.hint_text_name, "Text")
6267 .unwrap()
6268 .unwrap()
6269 .clone();
6270 if !s.last_time_hovered {
6271 self.reset_split_time(&format!("{}StartHoverTime", s.name), safe_mode)
6272 .unwrap();
6273 } else if self.timer.total_time
6274 - self
6275 .split_time(&format!("{}StartHoverTime", s.name), safe_mode)
6276 .unwrap()[1]
6277 >= 2_f32
6278 || t.color[3] != 0
6279 {
6280 t.color[3] = 255;
6281 t.origin_position = [mouse_pos.x, mouse_pos.y];
6282 };
6283 t.center_display.0 =
6284 if mouse_pos.x + t.actual_size[0] <= ctx.available_rect().width() {
6285 HorizontalAlign::Left
6286 } else {
6287 HorizontalAlign::Right
6288 };
6289 t.center_display.1 =
6290 if mouse_pos.y + t.actual_size[1] <= ctx.available_rect().height() {
6291 VerticalAlign::Top
6292 } else {
6293 VerticalAlign::Bottom
6294 };
6295 self.replace_resource(&s.hint_text_name, "Text", t.clone())
6296 .unwrap();
6297 };
6298 hovered = true;
6299 let mut clicked = vec![];
6300 for u in 0..s.click_method.len() as u32 {
6301 clicked.push(ui.input(|i| {
6302 i.pointer
6303 .button_down(s.click_method[u as usize].click_method)
6304 }));
6305 if clicked[u as usize] {
6306 s.last_time_clicked_index = u as usize;
6307 break;
6308 };
6309 }
6310 if clicked.iter().any(|x| *x) {
6311 s.last_time_clicked = true;
6312 if s.enable_hover_click_fill_resource[1] {
6313 if s.enable_hover_click_fill_resource[0] {
6314 appearance_count = 2;
6315 } else {
6316 appearance_count = 1;
6317 };
6318 } else if !s.enable_hover_click_fill_resource[0] {
6319 appearance_count = 0;
6320 };
6321 } else {
6322 if s.last_time_clicked {
6323 s.switched = true;
6324 if s.click_method[s.last_time_clicked_index].action {
6325 if s.state
6326 < (s.appearance.len() / s.animation_count as usize - 1) as u32
6327 {
6328 s.state += 1;
6329 } else {
6330 s.state = 0;
6331 };
6332 };
6333 s.last_time_clicked = false;
6334 };
6335 if s.enable_hover_click_fill_resource[0] {
6336 appearance_count = 1;
6337 } else {
6338 appearance_count = 0;
6339 };
6340 };
6341 } else {
6342 s.last_time_clicked = false;
6343 appearance_count = 0;
6344 };
6345 } else {
6346 s.last_time_clicked = false;
6347 appearance_count = 0;
6348 };
6349 } else {
6350 s.last_time_clicked = false;
6351 appearance_count = 0;
6352 };
6353 if !hovered && !s.hint_text_name.is_empty() {
6354 if s.last_time_hovered {
6355 self.reset_split_time(&format!("{}HintFadeAnimation", s.name), safe_mode)
6356 .unwrap();
6357 };
6358 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6359 && !self.check_resource_exists(&s.hint_text_name, "Text")
6360 {
6361 self.problem_report_custom(
6362 RustConstructorError::TextNotFound {
6363 text_name: s.hint_text_name.clone(),
6364 },
6365 SeverityLevel::SevereWarning,
6366 self.problem_list.clone(),
6367 );
6368 return Err(RustConstructorError::TextNotFound {
6369 text_name: s.hint_text_name.clone(),
6370 });
6371 };
6372 let mut t = self
6373 .get_resource::<Text>(&s.hint_text_name, "Text")
6374 .unwrap()
6375 .unwrap()
6376 .clone();
6377 if self.timer.total_time
6378 - self
6379 .split_time(&format!("{}HintFadeAnimation", s.name), safe_mode)
6380 .unwrap()[1]
6381 >= self.tick_interval
6382 {
6383 self.reset_split_time(&format!("{}HintFadeAnimation", s.name), safe_mode)
6384 .unwrap();
6385 t.color[3] = t.color[3].saturating_sub(10);
6386 };
6387 self.replace_resource(&s.hint_text_name, "Text", t.clone())
6388 .unwrap();
6389 };
6390 let fr: Box<dyn BasicFrontResource> = match &*s.fill_resource_type {
6391 "Image" => {
6392 let mut im = Box::new(
6393 fr.as_any()
6394 .downcast_ref::<Image>()
6395 .unwrap()
6396 .clone()
6397 .from_config(
6398 &s.appearance
6399 [(s.state * s.animation_count + appearance_count) as usize]
6400 .image_config
6401 .clone(),
6402 ),
6403 );
6404 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6405 && !self.check_resource_exists(
6406 &s.appearance[(s.state * s.animation_count + appearance_count) as usize]
6407 .texture
6408 .clone(),
6409 "ImageTexture",
6410 )
6411 {
6412 self.problem_report_custom(
6413 RustConstructorError::ImageTextureNotFound {
6414 image_texture_name: s.appearance
6415 [(s.state * s.animation_count + appearance_count) as usize]
6416 .texture
6417 .clone(),
6418 },
6419 SeverityLevel::SevereWarning,
6420 self.problem_list.clone(),
6421 );
6422 return Err(RustConstructorError::ImageTextureNotFound {
6423 image_texture_name: s.appearance
6424 [(s.state * s.animation_count + appearance_count) as usize]
6425 .texture
6426 .clone(),
6427 });
6428 };
6429 im.cite_texture = s.appearance
6430 [(s.state * s.animation_count + appearance_count) as usize]
6431 .texture
6432 .clone();
6433 im
6434 }
6435 "CustomRect" => Box::new(
6436 fr.as_any()
6437 .downcast_ref::<CustomRect>()
6438 .unwrap()
6439 .clone()
6440 .name(&s.fill_resource_name)
6441 .from_config(
6442 &s.appearance[(s.state * s.animation_count + appearance_count) as usize]
6443 .custom_rect_config
6444 .clone(),
6445 ),
6446 ),
6447 _ => {
6448 self.problem_report_custom(
6449 RustConstructorError::SwitchFillResourceMismatch {
6450 switch_name: name.to_string(),
6451 fill_resource_name: s.fill_resource_name.clone(),
6452 fill_resource_type: s.fill_resource_type.clone(),
6453 },
6454 SeverityLevel::SevereWarning,
6455 self.problem_list.clone(),
6456 );
6457 return Err(RustConstructorError::SwitchFillResourceMismatch {
6458 switch_name: name.to_string(),
6459 fill_resource_name: s.fill_resource_name,
6460 fill_resource_type: s.fill_resource_type,
6461 });
6462 }
6463 };
6464 if !s.hint_text_name.is_empty() {
6465 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6466 && !self.check_resource_exists(&s.hint_text_name, "Text")
6467 {
6468 self.problem_report_custom(
6469 RustConstructorError::TextNotFound {
6470 text_name: s.hint_text_name.clone(),
6471 },
6472 SeverityLevel::SevereWarning,
6473 self.problem_list.clone(),
6474 );
6475 return Err(RustConstructorError::TextNotFound {
6476 text_name: s.hint_text_name,
6477 });
6478 };
6479 let mut t = self
6480 .get_resource::<Text>(&s.hint_text_name, "Text")
6481 .unwrap()
6482 .unwrap()
6483 .clone();
6484 t.background_color[3] = t.color[3];
6485 t.content = s.appearance[(s.state * s.animation_count + appearance_count) as usize]
6486 .hint_text
6487 .clone();
6488 self.replace_resource(&s.hint_text_name, "Text", t.clone())
6489 .unwrap();
6490 };
6491 s.last_time_hovered = hovered;
6492 self.replace_resource(name, "Switch", s.clone()).unwrap();
6493 match s.fill_resource_type.as_str() {
6494 "Image" => {
6495 let im = fr.as_any().downcast_ref::<Image>().unwrap().clone();
6496 self.replace_resource(&s.fill_resource_name, &s.fill_resource_type, im)
6497 .unwrap();
6498 self.image(&s.fill_resource_name.clone(), ui, ctx, safe_mode)
6499 .unwrap();
6500 }
6501 "CustomRect" => {
6502 let cr = fr.as_any().downcast_ref::<CustomRect>().unwrap().clone();
6503 self.replace_resource(&s.fill_resource_name, &s.fill_resource_type, cr)
6504 .unwrap();
6505 self.custom_rect(&s.fill_resource_name.clone(), ui, ctx, safe_mode)
6506 .unwrap();
6507 }
6508 _ => {}
6509 };
6510 s.text_origin_position = s.appearance
6511 [(s.state * s.animation_count + appearance_count) as usize]
6512 .text_config
6513 .origin_position;
6514 if !s.text_name.is_empty() {
6515 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6516 && !self.check_resource_exists(&s.text_name, "Text")
6517 {
6518 self.problem_report_custom(
6519 RustConstructorError::TextNotFound {
6520 text_name: s.text_name.clone(),
6521 },
6522 SeverityLevel::SevereWarning,
6523 self.problem_list.clone(),
6524 );
6525 return Err(RustConstructorError::TextNotFound {
6526 text_name: s.text_name,
6527 });
6528 };
6529 let mut t = self
6530 .get_resource::<Text>(&s.text_name, "Text")
6531 .unwrap()
6532 .unwrap()
6533 .clone();
6534 t.origin_position = [
6535 fr.display_position()[0] + s.text_origin_position[0],
6536 fr.display_position()[1] + s.text_origin_position[1],
6537 ];
6538 t = t.from_config(
6539 &s.appearance[(s.state * s.animation_count + appearance_count) as usize]
6540 .text_config
6541 .clone(),
6542 );
6543 self.replace_resource(&s.text_name, "Text", t.clone())
6544 .unwrap();
6545 self.text(&s.text_name, ui, ctx, safe_mode).unwrap();
6546 };
6547 if !s.hint_text_name.is_empty() {
6548 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6549 && !self.check_resource_exists(&s.hint_text_name, "Text")
6550 {
6551 self.problem_report_custom(
6552 RustConstructorError::TextNotFound {
6553 text_name: s.hint_text_name.clone(),
6554 },
6555 SeverityLevel::SevereWarning,
6556 self.problem_list.clone(),
6557 );
6558 return Err(RustConstructorError::TextNotFound {
6559 text_name: s.hint_text_name,
6560 });
6561 };
6562 self.text(&s.hint_text_name, ui, ctx, safe_mode).unwrap();
6563 };
6564 Ok(())
6565 }
6566
6567 pub fn check_switch_data(
6569 &self,
6570 name: &str,
6571 safe_mode: Option<bool>,
6572 ) -> Result<SwitchData, RustConstructorError> {
6573 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6574 && !self.check_resource_exists(name, "Switch")
6575 {
6576 self.problem_report_custom(
6577 RustConstructorError::SwitchNotFound {
6578 switch_name: name.to_string(),
6579 },
6580 SeverityLevel::SevereWarning,
6581 self.problem_list.clone(),
6582 );
6583 return Err(RustConstructorError::SwitchNotFound {
6584 switch_name: name.to_string(),
6585 });
6586 };
6587 let s = self
6588 .get_resource::<Switch>(name, "Switch")
6589 .unwrap()
6590 .unwrap();
6591 Ok(SwitchData {
6592 switched: s.switched,
6593 last_time_clicked_index: s.last_time_clicked_index,
6594 state: s.state,
6595 })
6596 }
6597
6598 pub fn mouse_detector(
6599 &mut self,
6600 name: &str,
6601 ui: &Ui,
6602 ctx: &Context,
6603 mouse_detector_level: MouseDetectorLevel,
6604 safe_mode: Option<bool>,
6605 ) -> Result<(), RustConstructorError> {
6606 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6607 && !self.check_resource_exists(name, "MouseDetector")
6608 {
6609 self.problem_report_custom(
6610 RustConstructorError::MouseDetectorNotFound {
6611 mouse_detector_name: name.to_string(),
6612 },
6613 SeverityLevel::SevereWarning,
6614 self.problem_list.clone(),
6615 );
6616 return Err(RustConstructorError::MouseDetectorNotFound {
6617 mouse_detector_name: name.to_string(),
6618 });
6619 };
6620 let mut mouse_detector = self
6621 .get_resource_mut::<MouseDetector>(name, "MouseDetector")
6622 .unwrap()
6623 .unwrap()
6624 .clone();
6625 mouse_detector.modify_active(true);
6626 [mouse_detector.position, mouse_detector.size] =
6627 self.position_size_processor(PositionConfig::from_mouse_detector(&mouse_detector), ctx);
6628 let rect = Rect::from_min_size(mouse_detector.position.into(), mouse_detector.size.into());
6629 let response = ui.interact(rect, Id::new(name), Sense::click_and_drag());
6630 mouse_detector.detect_result = match mouse_detector_level {
6631 MouseDetectorLevel::Lite => MouseDetectResult {
6632 clicked: response.clicked(),
6633 contains_pointer: response.contains_pointer(),
6634 secondary_clicked: None,
6635 middle_clicked: None,
6636 clicked_by_extra_button: None,
6637 long_touched: None,
6638 double_clicked: None,
6639 triple_clicked: None,
6640 double_clicked_by: None,
6641 triple_clicked_by: None,
6642 clicked_elsewhere: None,
6643 hovered: None,
6644 drag_started: None,
6645 drag_started_by: None,
6646 dragged: None,
6647 dragged_by: None,
6648 drag_stopped: None,
6649 deag_stopped_by: None,
6650 drag_delta: None,
6651 total_drag_delta: None,
6652 drag_motion: None,
6653 interact_pointer_pos: None,
6654 hover_pos: None,
6655 is_pointer_button_down_on: None,
6656 raw_scroll_delta: None,
6657 smooth_scroll_delta: None,
6658 },
6659 MouseDetectorLevel::Default => {
6660 let interact_hover_pos = response.interact_pointer_pos();
6661 let hover_pos = response.hover_pos();
6662 MouseDetectResult {
6663 clicked: response.clicked(),
6664 contains_pointer: response.contains_pointer(),
6665 secondary_clicked: Some(response.secondary_clicked()),
6666 middle_clicked: Some(response.middle_clicked()),
6667 clicked_by_extra_button: None,
6668 long_touched: None,
6669 double_clicked: Some(response.double_clicked()),
6670 triple_clicked: Some(response.triple_clicked()),
6671 double_clicked_by: None,
6672 triple_clicked_by: None,
6673 clicked_elsewhere: Some(response.clicked_elsewhere()),
6674 hovered: Some(response.hovered()),
6675 drag_started: Some(response.drag_started()),
6676 drag_started_by: None,
6677 dragged: Some(response.dragged()),
6678 dragged_by: None,
6679 drag_stopped: Some(response.drag_stopped()),
6680 deag_stopped_by: None,
6681 drag_delta: None,
6682 total_drag_delta: None,
6683 drag_motion: None,
6684 interact_pointer_pos: if let Some(interact_hover_pos) = interact_hover_pos {
6685 Some(Some([interact_hover_pos.x, interact_hover_pos.y]))
6686 } else {
6687 Some(None)
6688 },
6689 hover_pos: if let Some(hover_pos) = hover_pos {
6690 Some(Some([hover_pos.x, hover_pos.y]))
6691 } else {
6692 Some(None)
6693 },
6694 is_pointer_button_down_on: Some(response.is_pointer_button_down_on()),
6695 raw_scroll_delta: Some(ui.input(|i| i.raw_scroll_delta).into()),
6696 smooth_scroll_delta: Some(ui.input(|i| i.smooth_scroll_delta).into()),
6697 }
6698 }
6699 MouseDetectorLevel::Pro => {
6700 let interact_hover_pos = response.interact_pointer_pos();
6701 let hover_pos = response.hover_pos();
6702 let total_drag_delta = response.total_drag_delta();
6703 MouseDetectResult {
6704 clicked: response.clicked(),
6705 contains_pointer: response.contains_pointer(),
6706 secondary_clicked: Some(response.secondary_clicked()),
6707 middle_clicked: Some(response.middle_clicked()),
6708 clicked_by_extra_button: Some([
6709 response.clicked_by(PointerButton::Extra1),
6710 response.clicked_by(PointerButton::Extra2),
6711 ]),
6712 long_touched: Some(response.long_touched()),
6713 double_clicked: Some(response.double_clicked()),
6714 triple_clicked: Some(response.triple_clicked()),
6715 double_clicked_by: Some([
6716 response.double_clicked_by(PointerButton::Primary),
6717 response.double_clicked_by(PointerButton::Secondary),
6718 response.double_clicked_by(PointerButton::Middle),
6719 response.double_clicked_by(PointerButton::Extra1),
6720 response.double_clicked_by(PointerButton::Extra2),
6721 ]),
6722 triple_clicked_by: Some([
6723 response.triple_clicked_by(PointerButton::Primary),
6724 response.triple_clicked_by(PointerButton::Secondary),
6725 response.triple_clicked_by(PointerButton::Middle),
6726 response.triple_clicked_by(PointerButton::Extra1),
6727 response.triple_clicked_by(PointerButton::Extra2),
6728 ]),
6729 clicked_elsewhere: Some(response.clicked_elsewhere()),
6730 hovered: Some(response.hovered()),
6731 drag_started: Some(response.drag_started()),
6732 drag_started_by: Some([
6733 response.drag_started_by(PointerButton::Primary),
6734 response.drag_started_by(PointerButton::Secondary),
6735 response.drag_started_by(PointerButton::Middle),
6736 response.drag_started_by(PointerButton::Extra1),
6737 response.drag_started_by(PointerButton::Extra2),
6738 ]),
6739 dragged: Some(response.dragged()),
6740 dragged_by: Some([
6741 response.dragged_by(PointerButton::Primary),
6742 response.dragged_by(PointerButton::Secondary),
6743 response.dragged_by(PointerButton::Middle),
6744 response.dragged_by(PointerButton::Extra1),
6745 response.dragged_by(PointerButton::Extra2),
6746 ]),
6747 drag_stopped: Some(response.drag_stopped()),
6748 deag_stopped_by: Some([
6749 response.drag_stopped_by(PointerButton::Primary),
6750 response.drag_stopped_by(PointerButton::Secondary),
6751 response.drag_stopped_by(PointerButton::Middle),
6752 response.drag_stopped_by(PointerButton::Extra1),
6753 response.drag_stopped_by(PointerButton::Extra2),
6754 ]),
6755 drag_delta: Some([response.drag_delta().x, response.drag_delta().y]),
6756 total_drag_delta: if let Some(total_drag_delta) = total_drag_delta {
6757 Some(Some([total_drag_delta.x, total_drag_delta.y]))
6758 } else {
6759 Some(None)
6760 },
6761 drag_motion: Some([response.drag_motion().x, response.drag_motion().y]),
6762 interact_pointer_pos: if let Some(interact_hover_pos) = interact_hover_pos {
6763 Some(Some([interact_hover_pos.x, interact_hover_pos.y]))
6764 } else {
6765 Some(None)
6766 },
6767 hover_pos: if let Some(hover_pos) = hover_pos {
6768 Some(Some([hover_pos.x, hover_pos.y]))
6769 } else {
6770 Some(None)
6771 },
6772 is_pointer_button_down_on: Some(response.is_pointer_button_down_on()),
6773 raw_scroll_delta: Some(ui.input(|i| i.raw_scroll_delta).into()),
6774 smooth_scroll_delta: Some(ui.input(|i| i.smooth_scroll_delta).into()),
6775 }
6776 }
6777 };
6778 self.replace_resource(name, "MouseDetector", mouse_detector)
6779 .unwrap();
6780 Ok(())
6781 }
6782
6783 pub fn check_mouse_detect_result(
6784 &self,
6785 name: &str,
6786 safe_mode: Option<bool>,
6787 ) -> Result<MouseDetectResult, RustConstructorError> {
6788 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6789 && !self.check_resource_exists(name, "MouseDetector")
6790 {
6791 self.problem_report_custom(
6792 RustConstructorError::MouseDetectorNotFound {
6793 mouse_detector_name: name.to_string(),
6794 },
6795 SeverityLevel::SevereWarning,
6796 self.problem_list.clone(),
6797 );
6798 return Err(RustConstructorError::MouseDetectorNotFound {
6799 mouse_detector_name: name.to_string(),
6800 });
6801 };
6802 let md = self
6803 .get_resource::<MouseDetector>(name, "MouseDetector")
6804 .unwrap()
6805 .unwrap();
6806 Ok(md.detect_result.clone())
6807 }
6808
6809 pub fn resource_panel(
6810 &mut self,
6811 name: &str,
6812 ui: &mut Ui,
6813 ctx: &Context,
6814 safe_mode: Option<bool>,
6815 ) -> Result<(), RustConstructorError> {
6816 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6817 && !self.check_resource_exists(name, "ResourcePanel")
6818 {
6819 self.problem_report_custom(
6820 RustConstructorError::ResourcePanelNotFound {
6821 resource_panel_name: name.to_string(),
6822 },
6823 SeverityLevel::SevereWarning,
6824 self.problem_list.clone(),
6825 );
6826 return Err(RustConstructorError::ResourcePanelNotFound {
6827 resource_panel_name: name.to_string(),
6828 });
6829 };
6830 let mut resource_panel = self
6831 .get_resource_mut::<ResourcePanel>(name, "ResourcePanel")
6832 .unwrap()
6833 .unwrap()
6834 .clone();
6835 if (safe_mode.is_some() && safe_mode.unwrap() || self.safe_mode)
6836 && resource_panel.display_rect.is_some()
6837 && !self
6838 .check_resource_exists(&format!("{}DisplayRect", resource_panel.name), "CustomRect")
6839 {
6840 self.problem_report_custom(
6841 RustConstructorError::RectNotFound {
6842 rect_name: format!("{}DisplayRect", resource_panel.name),
6843 },
6844 SeverityLevel::MildWarning,
6845 self.problem_list.clone(),
6846 );
6847 self.add_resource(
6848 CustomRect::default().name(&format!("{}DisplayRect", resource_panel.name)),
6849 safe_mode,
6850 )
6851 .unwrap();
6852 };
6853 resource_panel.modify_active(true);
6854 let rect = Rect::from_min_size(resource_panel.position.into(), resource_panel.size.into());
6855 if resource_panel.resizable.contains(&true) {
6856 resource_panel.x_location_grid = [0, 0];
6857 resource_panel.y_location_grid = [0, 0];
6858 resource_panel.x_size_grid = [0, 0];
6859 resource_panel.y_size_grid = [0, 0];
6860 };
6861 if resource_panel.min_size[0] < 10_f32 {
6862 resource_panel.min_size[0] = 10_f32;
6863 };
6864 if resource_panel.min_size[1] < 10_f32 {
6865 resource_panel.min_size[1] = 10_f32;
6866 };
6867 if resource_panel.origin_size[0] < resource_panel.min_size[0] {
6868 resource_panel.origin_size[0] = resource_panel.min_size[0];
6869 };
6870 if resource_panel.origin_size[1] < resource_panel.min_size[1] {
6871 resource_panel.origin_size[1] = resource_panel.min_size[1];
6872 };
6873 [resource_panel.position, resource_panel.size] =
6874 self.position_size_processor(PositionConfig::from_resource_panel(&resource_panel), ctx);
6875 if let Some(custom_rect_config) = &mut resource_panel.display_rect.clone() {
6876 *custom_rect_config = custom_rect_config
6877 .clone()
6878 .from_position_config(&PositionConfig::from_resource_panel(&resource_panel));
6879 };
6880 if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos()) {
6881 let top_rect = Rect::from_min_size(
6882 [
6883 resource_panel.position[0] - 3_f32,
6884 resource_panel.position[1] - 3_f32,
6885 ]
6886 .into(),
6887 [resource_panel.size[0] + 6_f32, 6_f32].into(),
6888 );
6889 let bottom_rect = Rect::from_min_size(
6890 [
6891 resource_panel.position[0] - 3_f32,
6892 resource_panel.position[1] + resource_panel.size[1] - 3_f32,
6893 ]
6894 .into(),
6895 [resource_panel.size[0] + 6_f32, 6_f32].into(),
6896 );
6897 let left_rect = Rect::from_min_size(
6898 [
6899 resource_panel.position[0] - 3_f32,
6900 resource_panel.position[1] - 3_f32,
6901 ]
6902 .into(),
6903 [6_f32, resource_panel.size[1] + 6_f32].into(),
6904 );
6905 let right_rect = Rect::from_min_size(
6906 [
6907 resource_panel.position[0] + resource_panel.size[0] - 3_f32,
6908 resource_panel.position[1] - 3_f32,
6909 ]
6910 .into(),
6911 [6_f32, resource_panel.size[1] + 6_f32].into(),
6912 );
6913 match [
6914 top_rect.contains(mouse_pos),
6915 bottom_rect.contains(mouse_pos),
6916 left_rect.contains(mouse_pos),
6917 right_rect.contains(mouse_pos),
6918 ] {
6919 [true, false, false, false] => {
6920 if resource_panel.resizable[0] {
6921 if resource_panel.last_frame_mouse_status.is_none()
6922 && ui.input(|i| i.pointer.primary_pressed())
6923 {
6924 resource_panel.last_frame_mouse_status = Some((
6925 mouse_pos.into(),
6926 ClickAim::TopResize,
6927 [
6928 mouse_pos.x - resource_panel.position[0],
6929 mouse_pos.y - resource_panel.position[1],
6930 ],
6931 ))
6932 };
6933 if resource_panel.size[1] > resource_panel.min_size[1]
6934 && (resource_panel.max_size.is_none()
6935 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
6936 {
6937 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
6938 } else if resource_panel.max_size.is_some()
6939 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
6940 {
6941 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
6942 } else {
6943 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
6944 };
6945 };
6946 }
6947 [false, true, false, false] => {
6948 if resource_panel.resizable[1] {
6949 if resource_panel.last_frame_mouse_status.is_none()
6950 && ui.input(|i| i.pointer.primary_pressed())
6951 {
6952 resource_panel.last_frame_mouse_status = Some((
6953 mouse_pos.into(),
6954 ClickAim::BottomResize,
6955 [
6956 mouse_pos.x - resource_panel.position[0],
6957 mouse_pos.y - resource_panel.position[1],
6958 ],
6959 ))
6960 };
6961 if resource_panel.size[1] > resource_panel.min_size[1]
6962 && (resource_panel.max_size.is_none()
6963 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
6964 {
6965 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
6966 } else if resource_panel.max_size.is_some()
6967 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
6968 {
6969 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
6970 } else {
6971 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
6972 };
6973 };
6974 }
6975 [false, false, true, false] => {
6976 if resource_panel.resizable[2] {
6977 if resource_panel.last_frame_mouse_status.is_none()
6978 && ui.input(|i| i.pointer.primary_pressed())
6979 {
6980 resource_panel.last_frame_mouse_status = Some((
6981 mouse_pos.into(),
6982 ClickAim::LeftResize,
6983 [
6984 mouse_pos.x - resource_panel.position[0],
6985 mouse_pos.y - resource_panel.position[1],
6986 ],
6987 ))
6988 };
6989 if resource_panel.size[0] > resource_panel.min_size[0]
6990 && (resource_panel.max_size.is_none()
6991 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
6992 {
6993 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
6994 } else if resource_panel.max_size.is_some()
6995 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
6996 {
6997 ctx.set_cursor_icon(CursorIcon::ResizeEast);
6998 } else {
6999 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7000 };
7001 };
7002 }
7003 [false, false, false, true] => {
7004 if resource_panel.resizable[3] {
7005 if resource_panel.last_frame_mouse_status.is_none()
7006 && ui.input(|i| i.pointer.primary_pressed())
7007 {
7008 resource_panel.last_frame_mouse_status = Some((
7009 mouse_pos.into(),
7010 ClickAim::RightResize,
7011 [
7012 mouse_pos.x - resource_panel.position[0],
7013 mouse_pos.y - resource_panel.position[1],
7014 ],
7015 ))
7016 };
7017 if resource_panel.size[0] > resource_panel.min_size[0]
7018 && (resource_panel.max_size.is_none()
7019 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7020 {
7021 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7022 } else if resource_panel.max_size.is_some()
7023 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7024 {
7025 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7026 } else {
7027 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7028 };
7029 };
7030 }
7031 [true, false, true, false] => {
7032 match [resource_panel.resizable[0], resource_panel.resizable[2]] {
7033 [true, true] => {
7034 if resource_panel.last_frame_mouse_status.is_none()
7035 && ui.input(|i| i.pointer.primary_pressed())
7036 {
7037 resource_panel.last_frame_mouse_status = Some((
7038 mouse_pos.into(),
7039 ClickAim::LeftTopResize,
7040 [
7041 mouse_pos.x - resource_panel.position[0],
7042 mouse_pos.y - resource_panel.position[1],
7043 ],
7044 ))
7045 };
7046 if resource_panel.size[0] > resource_panel.min_size[0]
7047 && (resource_panel.max_size.is_none()
7048 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7049 || resource_panel.size[1] > resource_panel.min_size[1]
7050 && (resource_panel.max_size.is_none()
7051 || resource_panel.size[1]
7052 < resource_panel.max_size.unwrap()[1])
7053 {
7054 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
7055 } else if resource_panel.max_size.is_some()
7056 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7057 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7058 {
7059 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast);
7060 } else {
7061 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest)
7062 };
7063 }
7064 [false, true] => {
7065 if resource_panel.last_frame_mouse_status.is_none()
7066 && ui.input(|i| i.pointer.primary_pressed())
7067 {
7068 resource_panel.last_frame_mouse_status = Some((
7069 mouse_pos.into(),
7070 ClickAim::LeftResize,
7071 [
7072 mouse_pos.x - resource_panel.position[0],
7073 mouse_pos.y - resource_panel.position[1],
7074 ],
7075 ))
7076 };
7077 if resource_panel.size[0] > resource_panel.min_size[0]
7078 && (resource_panel.max_size.is_none()
7079 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7080 {
7081 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7082 } else if resource_panel.max_size.is_some()
7083 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7084 {
7085 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7086 } else {
7087 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7088 };
7089 }
7090 [true, false] => {
7091 if resource_panel.last_frame_mouse_status.is_none()
7092 && ui.input(|i| i.pointer.primary_pressed())
7093 {
7094 resource_panel.last_frame_mouse_status = Some((
7095 mouse_pos.into(),
7096 ClickAim::TopResize,
7097 [
7098 mouse_pos.x - resource_panel.position[0],
7099 mouse_pos.y - resource_panel.position[1],
7100 ],
7101 ))
7102 };
7103 if resource_panel.size[1] > resource_panel.min_size[1]
7104 && (resource_panel.max_size.is_none()
7105 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7106 {
7107 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7108 } else if resource_panel.max_size.is_some()
7109 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7110 {
7111 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7112 } else {
7113 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7114 };
7115 }
7116 [false, false] => {}
7117 }
7118 }
7119 [false, true, false, true] => {
7120 match [resource_panel.resizable[1], resource_panel.resizable[3]] {
7121 [true, true] => {
7122 if resource_panel.last_frame_mouse_status.is_none()
7123 && ui.input(|i| i.pointer.primary_pressed())
7124 {
7125 resource_panel.last_frame_mouse_status = Some((
7126 mouse_pos.into(),
7127 ClickAim::RightBottomResize,
7128 [
7129 mouse_pos.x - resource_panel.position[0],
7130 mouse_pos.y - resource_panel.position[1],
7131 ],
7132 ))
7133 };
7134 if resource_panel.size[0] > resource_panel.min_size[0]
7135 && (resource_panel.max_size.is_none()
7136 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7137 || resource_panel.size[1] > resource_panel.min_size[1]
7138 && (resource_panel.max_size.is_none()
7139 || resource_panel.size[1]
7140 < resource_panel.max_size.unwrap()[1])
7141 {
7142 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
7143 } else if resource_panel.max_size.is_some()
7144 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7145 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7146 {
7147 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest);
7148 } else {
7149 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast)
7150 };
7151 }
7152 [false, true] => {
7153 if resource_panel.last_frame_mouse_status.is_none()
7154 && ui.input(|i| i.pointer.primary_pressed())
7155 {
7156 resource_panel.last_frame_mouse_status = Some((
7157 mouse_pos.into(),
7158 ClickAim::RightResize,
7159 [
7160 mouse_pos.x - resource_panel.position[0],
7161 mouse_pos.y - resource_panel.position[1],
7162 ],
7163 ))
7164 };
7165 if resource_panel.size[0] > resource_panel.min_size[0]
7166 && (resource_panel.max_size.is_none()
7167 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7168 {
7169 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7170 } else if resource_panel.max_size.is_some()
7171 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7172 {
7173 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7174 } else {
7175 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7176 };
7177 }
7178 [true, false] => {
7179 if resource_panel.last_frame_mouse_status.is_none()
7180 && ui.input(|i| i.pointer.primary_pressed())
7181 {
7182 resource_panel.last_frame_mouse_status = Some((
7183 mouse_pos.into(),
7184 ClickAim::BottomResize,
7185 [
7186 mouse_pos.x - resource_panel.position[0],
7187 mouse_pos.y - resource_panel.position[1],
7188 ],
7189 ))
7190 };
7191 if resource_panel.size[1] > resource_panel.min_size[1]
7192 && (resource_panel.max_size.is_none()
7193 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7194 {
7195 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7196 } else if resource_panel.max_size.is_some()
7197 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7198 {
7199 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7200 } else {
7201 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7202 };
7203 }
7204 [false, false] => {}
7205 }
7206 }
7207 [true, false, false, true] => {
7208 match [resource_panel.resizable[0], resource_panel.resizable[3]] {
7209 [true, true] => {
7210 if resource_panel.last_frame_mouse_status.is_none()
7211 && ui.input(|i| i.pointer.primary_pressed())
7212 {
7213 resource_panel.last_frame_mouse_status = Some((
7214 mouse_pos.into(),
7215 ClickAim::RightTopResize,
7216 [
7217 mouse_pos.x - resource_panel.position[0],
7218 mouse_pos.y - resource_panel.position[1],
7219 ],
7220 ))
7221 };
7222 if resource_panel.size[0] > resource_panel.min_size[0]
7223 && (resource_panel.max_size.is_none()
7224 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7225 || resource_panel.size[1] > resource_panel.min_size[1]
7226 && (resource_panel.max_size.is_none()
7227 || resource_panel.size[1]
7228 < resource_panel.max_size.unwrap()[1])
7229 {
7230 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
7231 } else if resource_panel.max_size.is_some()
7232 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7233 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7234 {
7235 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest);
7236 } else {
7237 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast)
7238 };
7239 }
7240 [false, true] => {
7241 if resource_panel.last_frame_mouse_status.is_none()
7242 && ui.input(|i| i.pointer.primary_pressed())
7243 {
7244 resource_panel.last_frame_mouse_status = Some((
7245 mouse_pos.into(),
7246 ClickAim::RightResize,
7247 [
7248 mouse_pos.x - resource_panel.position[0],
7249 mouse_pos.y - resource_panel.position[1],
7250 ],
7251 ))
7252 };
7253 if resource_panel.size[0] > resource_panel.min_size[0]
7254 && (resource_panel.max_size.is_none()
7255 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7256 {
7257 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7258 } else if resource_panel.max_size.is_some()
7259 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7260 {
7261 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7262 } else {
7263 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7264 };
7265 }
7266 [true, false] => {
7267 if resource_panel.last_frame_mouse_status.is_none()
7268 && ui.input(|i| i.pointer.primary_pressed())
7269 {
7270 resource_panel.last_frame_mouse_status = Some((
7271 mouse_pos.into(),
7272 ClickAim::TopResize,
7273 [
7274 mouse_pos.x - resource_panel.position[0],
7275 mouse_pos.y - resource_panel.position[1],
7276 ],
7277 ))
7278 };
7279 if resource_panel.size[1] > resource_panel.min_size[1]
7280 && (resource_panel.max_size.is_none()
7281 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7282 {
7283 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7284 } else if resource_panel.max_size.is_some()
7285 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7286 {
7287 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7288 } else {
7289 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7290 };
7291 }
7292 [false, false] => {}
7293 }
7294 }
7295 [false, true, true, false] => {
7296 match [resource_panel.resizable[1], resource_panel.resizable[2]] {
7297 [true, true] => {
7298 if resource_panel.last_frame_mouse_status.is_none()
7299 && ui.input(|i| i.pointer.primary_pressed())
7300 {
7301 resource_panel.last_frame_mouse_status = Some((
7302 mouse_pos.into(),
7303 ClickAim::LeftBottomResize,
7304 [
7305 mouse_pos.x - resource_panel.position[0],
7306 mouse_pos.y - resource_panel.position[1],
7307 ],
7308 ))
7309 };
7310 if resource_panel.size[0] > resource_panel.min_size[0]
7311 && (resource_panel.max_size.is_none()
7312 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7313 || resource_panel.size[1] > resource_panel.min_size[1]
7314 && (resource_panel.max_size.is_none()
7315 || resource_panel.size[1]
7316 < resource_panel.max_size.unwrap()[1])
7317 {
7318 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
7319 } else if resource_panel.max_size.is_some()
7320 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7321 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7322 {
7323 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast);
7324 } else {
7325 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest)
7326 };
7327 }
7328 [false, true] => {
7329 if resource_panel.last_frame_mouse_status.is_none()
7330 && ui.input(|i| i.pointer.primary_pressed())
7331 {
7332 resource_panel.last_frame_mouse_status = Some((
7333 mouse_pos.into(),
7334 ClickAim::LeftResize,
7335 [
7336 mouse_pos.x - resource_panel.position[0],
7337 mouse_pos.y - resource_panel.position[1],
7338 ],
7339 ))
7340 };
7341 if resource_panel.size[0] > resource_panel.min_size[0]
7342 && (resource_panel.max_size.is_none()
7343 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7344 {
7345 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7346 } else if resource_panel.max_size.is_some()
7347 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7348 {
7349 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7350 } else {
7351 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7352 };
7353 }
7354 [true, false] => {
7355 if resource_panel.last_frame_mouse_status.is_none()
7356 && ui.input(|i| i.pointer.primary_pressed())
7357 {
7358 resource_panel.last_frame_mouse_status = Some((
7359 mouse_pos.into(),
7360 ClickAim::BottomResize,
7361 [
7362 mouse_pos.x - resource_panel.position[0],
7363 mouse_pos.y - resource_panel.position[1],
7364 ],
7365 ))
7366 };
7367 if resource_panel.size[1] > resource_panel.min_size[1]
7368 && (resource_panel.max_size.is_none()
7369 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7370 {
7371 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7372 } else if resource_panel.max_size.is_some()
7373 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7374 {
7375 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7376 } else {
7377 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7378 };
7379 }
7380 [false, false] => {}
7381 }
7382 }
7383 _ => {}
7384 };
7385 resource_panel.last_frame_mouse_status =
7386 if resource_panel.last_frame_mouse_status.is_none()
7387 && rect.contains(mouse_pos)
7388 && ui.input(|i| i.pointer.primary_pressed())
7389 {
7390 Some((
7391 [mouse_pos.x, mouse_pos.y],
7392 ClickAim::Move,
7393 [
7394 mouse_pos.x - resource_panel.position[0],
7395 mouse_pos.y - resource_panel.position[1],
7396 ],
7397 ))
7398 } else if resource_panel.last_frame_mouse_status.is_some()
7399 && !ui.input(|i| i.pointer.primary_released())
7400 {
7401 Some((
7402 [mouse_pos.x, mouse_pos.y],
7403 resource_panel.last_frame_mouse_status.unwrap().1,
7404 resource_panel.last_frame_mouse_status.unwrap().2,
7405 ))
7406 } else {
7407 None
7408 };
7409 let [x_scroll_delta, y_scroll_delta] = if resource_panel.use_smooth_scroll_delta {
7410 ui.input(|i| i.smooth_scroll_delta).into()
7411 } else {
7412 ui.input(|i| i.raw_scroll_delta).into()
7413 };
7414 if let Some(_) = resource_panel.scroll_length_method[0]
7415 && x_scroll_delta != 0_f32
7416 {
7417 resource_panel.scroll_progress[0] = if resource_panel.scroll_progress[0]
7418 + x_scroll_delta * resource_panel.scroll_sensitivity
7419 > resource_panel.scroll_length[0]
7420 {
7421 resource_panel.scroll_length[0]
7422 } else if resource_panel.scroll_progress[0]
7423 + x_scroll_delta * resource_panel.scroll_sensitivity
7424 > 0_f32
7425 {
7426 resource_panel.scroll_progress[0]
7427 + x_scroll_delta * resource_panel.scroll_sensitivity
7428 } else {
7429 0_f32
7430 };
7431 };
7432 if let Some(_) = resource_panel.scroll_length_method[1]
7433 && y_scroll_delta != 0_f32
7434 {
7435 resource_panel.scroll_progress[1] = if resource_panel.scroll_progress[1]
7436 + y_scroll_delta * resource_panel.scroll_sensitivity
7437 > resource_panel.scroll_length[1]
7438 {
7439 resource_panel.scroll_length[1]
7440 } else if resource_panel.scroll_progress[1]
7441 + y_scroll_delta * resource_panel.scroll_sensitivity
7442 > 0_f32
7443 {
7444 resource_panel.scroll_progress[1]
7445 + y_scroll_delta * resource_panel.scroll_sensitivity
7446 } else {
7447 0_f32
7448 };
7449 };
7450 };
7451 if let Some((mouse_pos, click_aim, offset)) = resource_panel.last_frame_mouse_status {
7452 match click_aim {
7453 ClickAim::LeftTopResize => {
7454 if resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7455 > resource_panel.min_size[0]
7456 && (resource_panel.max_size.is_none()
7457 || resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7458 < resource_panel.max_size.unwrap()[0])
7459 {
7460 resource_panel.origin_size[0] += resource_panel.position[0] - mouse_pos[0];
7461 resource_panel.origin_position[0] = mouse_pos[0];
7462 } else if resource_panel.max_size.is_some()
7463 && resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7464 >= resource_panel.max_size.unwrap()[0]
7465 {
7466 resource_panel.origin_position[0] -=
7467 resource_panel.max_size.unwrap()[0] - resource_panel.origin_size[0];
7468 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7469 } else {
7470 resource_panel.origin_position[0] +=
7471 resource_panel.origin_size[0] - resource_panel.min_size[0];
7472 resource_panel.origin_size[0] = resource_panel.min_size[0];
7473 };
7474 if resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7475 > resource_panel.min_size[1]
7476 && (resource_panel.max_size.is_none()
7477 || resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7478 < resource_panel.max_size.unwrap()[1])
7479 {
7480 resource_panel.origin_size[1] += resource_panel.position[1] - mouse_pos[1];
7481 resource_panel.origin_position[1] = mouse_pos[1];
7482 } else if resource_panel.max_size.is_some()
7483 && resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7484 >= resource_panel.max_size.unwrap()[1]
7485 {
7486 resource_panel.origin_position[1] -=
7487 resource_panel.max_size.unwrap()[1] - resource_panel.origin_size[1];
7488 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7489 } else {
7490 resource_panel.origin_position[1] +=
7491 resource_panel.origin_size[1] - resource_panel.min_size[1];
7492 resource_panel.origin_size[1] = resource_panel.min_size[1];
7493 };
7494 if resource_panel.size[0] > resource_panel.min_size[0]
7495 && (resource_panel.max_size.is_none()
7496 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7497 || resource_panel.size[1] > resource_panel.min_size[1]
7498 && (resource_panel.max_size.is_none()
7499 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7500 {
7501 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
7502 } else if resource_panel.max_size.is_some()
7503 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7504 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7505 {
7506 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast);
7507 } else {
7508 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest)
7509 };
7510 }
7511 ClickAim::RightBottomResize => {
7512 if mouse_pos[0] - resource_panel.position[0] > resource_panel.min_size[0]
7513 && (resource_panel.max_size.is_none()
7514 || mouse_pos[0] - resource_panel.position[0]
7515 < resource_panel.max_size.unwrap()[0])
7516 {
7517 resource_panel.origin_size[0] = mouse_pos[0] - resource_panel.position[0];
7518 } else if resource_panel.max_size.is_some()
7519 && mouse_pos[0] - resource_panel.position[0]
7520 >= resource_panel.max_size.unwrap()[0]
7521 {
7522 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7523 } else {
7524 resource_panel.origin_size[0] = resource_panel.min_size[0];
7525 };
7526 if mouse_pos[1] - resource_panel.position[1] > resource_panel.min_size[1]
7527 && (resource_panel.max_size.is_none()
7528 || mouse_pos[1] - resource_panel.position[1]
7529 < resource_panel.max_size.unwrap()[1])
7530 {
7531 resource_panel.origin_size[1] = mouse_pos[1] - resource_panel.position[1];
7532 } else if resource_panel.max_size.is_some()
7533 && mouse_pos[1] - resource_panel.position[1]
7534 >= resource_panel.max_size.unwrap()[1]
7535 {
7536 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7537 } else {
7538 resource_panel.origin_size[1] = resource_panel.min_size[1];
7539 };
7540 if resource_panel.size[0] > resource_panel.min_size[0]
7541 && (resource_panel.max_size.is_none()
7542 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7543 || resource_panel.size[1] > resource_panel.min_size[1]
7544 && (resource_panel.max_size.is_none()
7545 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7546 {
7547 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
7548 } else if resource_panel.max_size.is_some()
7549 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7550 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7551 {
7552 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest);
7553 } else {
7554 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast)
7555 };
7556 }
7557 ClickAim::RightTopResize => {
7558 if mouse_pos[0] - resource_panel.position[0] > resource_panel.min_size[0]
7559 && (resource_panel.max_size.is_none()
7560 || mouse_pos[0] - resource_panel.position[0]
7561 < resource_panel.max_size.unwrap()[0])
7562 {
7563 resource_panel.origin_size[0] = mouse_pos[0] - resource_panel.position[0];
7564 } else if resource_panel.max_size.is_some()
7565 && mouse_pos[0] - resource_panel.position[0]
7566 >= resource_panel.max_size.unwrap()[0]
7567 {
7568 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7569 } else {
7570 resource_panel.origin_size[0] = resource_panel.min_size[0];
7571 };
7572 if resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7573 > resource_panel.min_size[1]
7574 && (resource_panel.max_size.is_none()
7575 || resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7576 < resource_panel.max_size.unwrap()[1])
7577 {
7578 resource_panel.origin_size[1] += resource_panel.position[1] - mouse_pos[1];
7579 resource_panel.origin_position[1] = mouse_pos[1];
7580 } else if resource_panel.max_size.is_some()
7581 && resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7582 >= resource_panel.max_size.unwrap()[1]
7583 {
7584 resource_panel.origin_position[1] -=
7585 resource_panel.max_size.unwrap()[1] - resource_panel.origin_size[1];
7586 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7587 } else {
7588 resource_panel.origin_position[1] +=
7589 resource_panel.origin_size[1] - resource_panel.min_size[1];
7590 resource_panel.origin_size[1] = resource_panel.min_size[1];
7591 };
7592 if resource_panel.size[0] > resource_panel.min_size[0]
7593 && (resource_panel.max_size.is_none()
7594 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7595 || resource_panel.size[1] > resource_panel.min_size[1]
7596 && (resource_panel.max_size.is_none()
7597 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7598 {
7599 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
7600 } else if resource_panel.max_size.is_some()
7601 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7602 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7603 {
7604 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest);
7605 } else {
7606 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast)
7607 };
7608 }
7609 ClickAim::LeftBottomResize => {
7610 if resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7611 > resource_panel.min_size[0]
7612 && (resource_panel.max_size.is_none()
7613 || resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7614 < resource_panel.max_size.unwrap()[0])
7615 {
7616 resource_panel.origin_size[0] += resource_panel.position[0] - mouse_pos[0];
7617 resource_panel.origin_position[0] = mouse_pos[0];
7618 } else if resource_panel.max_size.is_some()
7619 && resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7620 >= resource_panel.max_size.unwrap()[0]
7621 {
7622 resource_panel.origin_position[0] -=
7623 resource_panel.max_size.unwrap()[0] - resource_panel.origin_size[0];
7624 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7625 } else {
7626 resource_panel.origin_position[0] +=
7627 resource_panel.origin_size[0] - resource_panel.min_size[0];
7628 resource_panel.origin_size[0] = resource_panel.min_size[0];
7629 };
7630 if mouse_pos[1] - resource_panel.position[1] > resource_panel.min_size[1]
7631 && (resource_panel.max_size.is_none()
7632 || mouse_pos[1] - resource_panel.position[1]
7633 < resource_panel.max_size.unwrap()[1])
7634 {
7635 resource_panel.origin_size[1] = mouse_pos[1] - resource_panel.position[1];
7636 } else if resource_panel.max_size.is_some()
7637 && mouse_pos[1] - resource_panel.position[1]
7638 >= resource_panel.max_size.unwrap()[1]
7639 {
7640 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7641 } else {
7642 resource_panel.origin_size[1] = resource_panel.min_size[1];
7643 };
7644 if resource_panel.size[0] > resource_panel.min_size[0]
7645 && (resource_panel.max_size.is_none()
7646 || resource_panel.size[0] < resource_panel.max_size.unwrap()[0])
7647 || resource_panel.size[1] > resource_panel.min_size[1]
7648 && (resource_panel.max_size.is_none()
7649 || resource_panel.size[1] < resource_panel.max_size.unwrap()[1])
7650 {
7651 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
7652 } else if resource_panel.max_size.is_some()
7653 && resource_panel.size[0] >= resource_panel.max_size.unwrap()[0]
7654 && resource_panel.size[1] >= resource_panel.max_size.unwrap()[1]
7655 {
7656 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast);
7657 } else {
7658 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest)
7659 };
7660 }
7661 ClickAim::TopResize => {
7662 if resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7663 > resource_panel.min_size[1]
7664 && (resource_panel.max_size.is_none()
7665 || resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7666 < resource_panel.max_size.unwrap()[1])
7667 {
7668 resource_panel.origin_size[1] += resource_panel.position[1] - mouse_pos[1];
7669 resource_panel.origin_position[1] = mouse_pos[1];
7670 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7671 } else if resource_panel.max_size.is_some()
7672 && resource_panel.position[1] - mouse_pos[1] + resource_panel.size[1]
7673 >= resource_panel.max_size.unwrap()[1]
7674 {
7675 resource_panel.origin_position[1] -=
7676 resource_panel.max_size.unwrap()[1] - resource_panel.origin_size[1];
7677 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7678 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7679 } else {
7680 resource_panel.origin_position[1] +=
7681 resource_panel.origin_size[1] - resource_panel.min_size[1];
7682 resource_panel.origin_size[1] = resource_panel.min_size[1];
7683 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7684 };
7685 }
7686 ClickAim::BottomResize => {
7687 if mouse_pos[1] - resource_panel.position[1] > resource_panel.min_size[1]
7688 && (resource_panel.max_size.is_none()
7689 || mouse_pos[1] - resource_panel.position[1]
7690 < resource_panel.max_size.unwrap()[1])
7691 {
7692 resource_panel.origin_size[1] = mouse_pos[1] - resource_panel.position[1];
7693 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
7694 } else if resource_panel.max_size.is_some()
7695 && mouse_pos[1] - resource_panel.position[1]
7696 >= resource_panel.max_size.unwrap()[1]
7697 {
7698 resource_panel.origin_size[1] = resource_panel.max_size.unwrap()[1];
7699 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
7700 } else {
7701 resource_panel.origin_size[1] = resource_panel.min_size[1];
7702 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
7703 };
7704 }
7705 ClickAim::LeftResize => {
7706 if resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7707 > resource_panel.min_size[0]
7708 && (resource_panel.max_size.is_none()
7709 || resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7710 < resource_panel.max_size.unwrap()[0])
7711 {
7712 resource_panel.origin_size[0] += resource_panel.position[0] - mouse_pos[0];
7713 resource_panel.origin_position[0] = mouse_pos[0];
7714 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7715 } else if resource_panel.max_size.is_some()
7716 && resource_panel.position[0] - mouse_pos[0] + resource_panel.size[0]
7717 >= resource_panel.max_size.unwrap()[0]
7718 {
7719 resource_panel.origin_position[0] -=
7720 resource_panel.max_size.unwrap()[0] - resource_panel.origin_size[0];
7721 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7722 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7723 } else {
7724 resource_panel.origin_position[0] +=
7725 resource_panel.origin_size[0] - resource_panel.min_size[0];
7726 resource_panel.origin_size[0] = resource_panel.min_size[0];
7727 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7728 };
7729 }
7730 ClickAim::RightResize => {
7731 if mouse_pos[0] - resource_panel.position[0] > resource_panel.min_size[0]
7732 && (resource_panel.max_size.is_none()
7733 || mouse_pos[0] - resource_panel.position[0]
7734 < resource_panel.max_size.unwrap()[0])
7735 {
7736 resource_panel.origin_size[0] = mouse_pos[0] - resource_panel.position[0];
7737 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
7738 } else if resource_panel.max_size.is_some()
7739 && mouse_pos[0] - resource_panel.position[0]
7740 >= resource_panel.max_size.unwrap()[0]
7741 {
7742 resource_panel.origin_size[0] = resource_panel.max_size.unwrap()[0];
7743 ctx.set_cursor_icon(CursorIcon::ResizeWest);
7744 } else {
7745 resource_panel.origin_size[0] = resource_panel.min_size[0];
7746 ctx.set_cursor_icon(CursorIcon::ResizeEast);
7747 };
7748 }
7749 ClickAim::Move => {
7750 if resource_panel.movable[0] {
7751 resource_panel.origin_position[0] = mouse_pos[0] - offset[0];
7752 };
7753 if resource_panel.movable[1] {
7754 resource_panel.origin_position[1] = mouse_pos[1] - offset[1];
7755 };
7756 }
7757 };
7758 };
7759 if let Some(config) = &mut resource_panel.display_rect.clone() {
7760 *config = config
7761 .clone()
7762 .from_position_config(&PositionConfig::from_resource_panel(&resource_panel));
7763 let custom_rect = self
7764 .get_resource_mut::<CustomRect>(
7765 &format!("{}DisplayRect", resource_panel.name),
7766 "CustomRect",
7767 )
7768 .unwrap()
7769 .unwrap();
7770 *custom_rect = CustomRect::default()
7771 .name(&format!("{}DisplayRect", resource_panel.name))
7772 .from_config(config)
7773 .from_position_config(&PositionConfig::from_resource_panel(&resource_panel));
7774 self.custom_rect(
7775 &format!("{}DisplayRect", resource_panel.name),
7776 ui,
7777 ctx,
7778 safe_mode,
7779 )
7780 .unwrap();
7781 };
7782 let mut resource_point_list: Vec<([f32; 2], [f32; 2], [bool; 2])> = Vec::new();
7783 for rcr in &mut self.rust_constructor_resource {
7784 if self
7785 .basic_front_resource_list
7786 .contains(&rcr.expose_type().to_string())
7787 {
7788 let mut basic_front_resource: Box<dyn BasicFrontResource> = match rcr.expose_type()
7789 {
7790 "Image" => {
7791 let mut image =
7792 Box::new(rcr.as_any().downcast_ref::<Image>().unwrap().clone());
7793 image.x_location_grid = [0, 0];
7794 image.y_location_grid = [0, 0];
7795 image.x_size_grid = [0, 0];
7796 image.y_size_grid = [0, 0];
7797 image
7798 }
7799 "Text" => {
7800 let mut text =
7801 Box::new(rcr.as_any().downcast_ref::<Text>().unwrap().clone());
7802 text.x_location_grid = [0, 0];
7803 text.y_location_grid = [0, 0];
7804 text.x_size_grid = [0, 0];
7805 text.y_size_grid = [0, 0];
7806 text
7807 }
7808 "CustomRect" => {
7809 let mut custom_rect =
7810 Box::new(rcr.as_any().downcast_ref::<CustomRect>().unwrap().clone());
7811 custom_rect.x_location_grid = [0, 0];
7812 custom_rect.y_location_grid = [0, 0];
7813 custom_rect.x_size_grid = [0, 0];
7814 custom_rect.y_size_grid = [0, 0];
7815 custom_rect
7816 }
7817 _ => {
7818 unreachable!()
7819 }
7820 };
7821 if basic_front_resource.display_panel_name() == resource_panel.name {
7822 basic_front_resource.modify_clip_rect(&Some(
7823 PositionConfig::from_resource_panel(&resource_panel),
7824 ));
7825 basic_front_resource.modify_offset(
7826 if basic_front_resource.display_allow_scrolling()[0] {
7827 basic_front_resource.display_offset()[0]
7828 + (resource_panel.scroll_progress[0]
7829 - resource_panel.last_frame_scroll_progress[0])
7830 } else {
7831 basic_front_resource.display_offset()[0]
7832 },
7833 if basic_front_resource.display_allow_scrolling()[1] {
7834 basic_front_resource.display_offset()[1]
7835 + (resource_panel.scroll_progress[1]
7836 - resource_panel.last_frame_scroll_progress[1])
7837 } else {
7838 basic_front_resource.display_offset()[1]
7839 },
7840 );
7841 if let Some(layout) = &mut basic_front_resource.display_panel_layout().clone() {
7842 if basic_front_resource
7843 .display_allow_scrolling()
7844 .contains(&false)
7845 {
7846 layout.1 = match layout.1 {
7847 PanelLayout::Horizontal(top, bottom, left, right, _) => {
7848 PanelLayout::None(top, bottom, left, right, false)
7849 }
7850 PanelLayout::Vertical(top, bottom, left, right, _) => {
7851 PanelLayout::None(top, bottom, left, right, false)
7852 }
7853 PanelLayout::None(_, _, _, _, _) => layout.1,
7854 };
7855 };
7856 match layout.1 {
7857 PanelLayout::Vertical(top, bottom, left, right, move_to_bottom) => {
7858 let mut modify_y = 0_f32;
7859 let [default_x_position, default_y_position] = match layout.0 {
7860 PanelLocation::Absolute(x, y) => [
7861 resource_panel.position[0] + x,
7862 resource_panel.position[1] + y,
7863 ],
7864 PanelLocation::Relative([x, y]) => [
7865 resource_panel.position[0]
7866 + (resource_panel.size[0] / x[1] as f32 * x[0] as f32),
7867 resource_panel.position[1]
7868 + (resource_panel.size[1] / y[1] as f32 * y[0] as f32),
7869 ],
7870 };
7871 let default_x_position =
7872 match basic_front_resource.display_center_display().0 {
7873 HorizontalAlign::Left => default_x_position,
7874 HorizontalAlign::Center => {
7875 default_x_position
7876 - basic_front_resource.display_size()[0] / 2.0
7877 }
7878 HorizontalAlign::Right => {
7879 default_x_position
7880 - basic_front_resource.display_size()[0]
7881 }
7882 };
7883 let default_y_position =
7884 match basic_front_resource.display_center_display().1 {
7885 VerticalAlign::Top => default_y_position,
7886 VerticalAlign::Center => {
7887 default_y_position
7888 - basic_front_resource.display_size()[1] / 2.0
7889 }
7890 VerticalAlign::Bottom => {
7891 default_y_position
7892 - basic_front_resource.display_size()[1]
7893 }
7894 };
7895 for point in &resource_point_list {
7896 if default_x_position - left < point.1[0]
7897 && default_y_position - top < point.1[1]
7898 && default_x_position
7899 + basic_front_resource.display_size()[0]
7900 + right
7901 > point.0[0]
7902 && default_y_position
7903 + basic_front_resource.display_size()[1]
7904 + bottom
7905 > point.0[1]
7906 {
7907 if move_to_bottom
7908 && point.1[1] - default_y_position + top > modify_y
7909 {
7910 modify_y = point.1[1] - default_y_position + top;
7911 } else if !move_to_bottom
7912 && point.0[1]
7913 - default_y_position
7914 - basic_front_resource.display_size()[1]
7915 - bottom
7916 < modify_y
7917 {
7918 modify_y = point.0[1]
7919 - default_y_position
7920 - basic_front_resource.display_size()[1];
7921 };
7922 };
7923 }
7924 let real_x_position =
7925 match basic_front_resource.display_center_display().0 {
7926 HorizontalAlign::Left => default_x_position,
7927 HorizontalAlign::Center => {
7928 default_x_position
7929 + basic_front_resource.display_size()[0] / 2.0
7930 }
7931 HorizontalAlign::Right => {
7932 default_x_position
7933 + basic_front_resource.display_size()[0]
7934 }
7935 };
7936 let real_y_position =
7937 match basic_front_resource.display_center_display().1 {
7938 VerticalAlign::Top => default_y_position + modify_y,
7939 VerticalAlign::Center => {
7940 default_y_position
7941 + modify_y
7942 + basic_front_resource.display_size()[1] / 2.0
7943 }
7944 VerticalAlign::Bottom => {
7945 default_y_position
7946 + modify_y
7947 + basic_front_resource.display_size()[1]
7948 }
7949 };
7950 basic_front_resource
7951 .modify_position(real_x_position, real_y_position);
7952 resource_point_list.push((
7953 [real_x_position - left, real_y_position - top],
7954 [
7955 real_x_position
7956 + basic_front_resource.display_size()[0]
7957 + right,
7958 real_y_position
7959 + basic_front_resource.display_size()[1]
7960 + bottom,
7961 ],
7962 basic_front_resource.display_allow_scrolling(),
7963 ));
7964 }
7965 PanelLayout::Horizontal(top, bottom, left, right, move_to_right) => {
7966 let mut modify_x = 0_f32;
7967 let [default_x_position, default_y_position] = match layout.0 {
7968 PanelLocation::Absolute(x, y) => [
7969 resource_panel.position[0] + x,
7970 resource_panel.position[1] + y,
7971 ],
7972 PanelLocation::Relative([x, y]) => [
7973 resource_panel.position[0]
7974 + (resource_panel.size[0] / x[1] as f32 * x[0] as f32),
7975 resource_panel.position[1]
7976 + (resource_panel.size[1] / y[1] as f32 * y[0] as f32),
7977 ],
7978 };
7979 let default_x_position =
7980 match basic_front_resource.display_center_display().0 {
7981 HorizontalAlign::Left => default_x_position,
7982 HorizontalAlign::Center => {
7983 default_x_position
7984 - basic_front_resource.display_size()[0] / 2.0
7985 }
7986 HorizontalAlign::Right => {
7987 default_x_position
7988 - basic_front_resource.display_size()[0]
7989 }
7990 };
7991 let default_y_position =
7992 match basic_front_resource.display_center_display().1 {
7993 VerticalAlign::Top => default_y_position,
7994 VerticalAlign::Center => {
7995 default_y_position
7996 - basic_front_resource.display_size()[1] / 2.0
7997 }
7998 VerticalAlign::Bottom => {
7999 default_y_position
8000 - basic_front_resource.display_size()[1]
8001 }
8002 };
8003 for point in &resource_point_list {
8004 if default_x_position - left < point.1[0]
8005 && default_y_position - top < point.1[1]
8006 && default_x_position
8007 + basic_front_resource.display_size()[0]
8008 + right
8009 > point.0[0]
8010 && default_y_position
8011 + basic_front_resource.display_size()[1]
8012 + bottom
8013 > point.0[1]
8014 {
8015 if move_to_right
8016 && point.1[0] - default_x_position + left > modify_x
8017 {
8018 modify_x = point.1[0] - default_x_position + left;
8019 } else if !move_to_right
8020 && point.0[0]
8021 - default_x_position
8022 - basic_front_resource.display_size()[0]
8023 - right
8024 < modify_x
8025 {
8026 modify_x = point.0[0]
8027 - default_x_position
8028 - basic_front_resource.display_size()[0]
8029 - right;
8030 };
8031 };
8032 }
8033 let real_x_position =
8034 match basic_front_resource.display_center_display().0 {
8035 HorizontalAlign::Left => default_x_position + modify_x,
8036 HorizontalAlign::Center => {
8037 default_x_position
8038 + modify_x
8039 + basic_front_resource.display_size()[0] / 2.0
8040 }
8041 HorizontalAlign::Right => {
8042 default_x_position
8043 + modify_x
8044 + basic_front_resource.display_size()[0]
8045 }
8046 };
8047 let real_y_position =
8048 match basic_front_resource.display_center_display().1 {
8049 VerticalAlign::Top => default_y_position,
8050 VerticalAlign::Center => {
8051 default_y_position
8052 + basic_front_resource.display_size()[1] / 2.0
8053 }
8054 VerticalAlign::Bottom => {
8055 default_y_position
8056 + basic_front_resource.display_size()[1]
8057 }
8058 };
8059 basic_front_resource
8060 .modify_position(real_x_position, real_y_position);
8061 resource_point_list.push((
8062 [real_x_position - left, real_y_position - top],
8063 [
8064 real_x_position
8065 + basic_front_resource.display_size()[0]
8066 + right,
8067 real_y_position
8068 + basic_front_resource.display_size()[1]
8069 + bottom,
8070 ],
8071 basic_front_resource.display_allow_scrolling(),
8072 ));
8073 }
8074 PanelLayout::None(top, bottom, left, right, influence_layout) => {
8075 let [default_x_position, default_y_position] = match layout.0 {
8076 PanelLocation::Absolute(x, y) => [
8077 resource_panel.position[0] + x,
8078 resource_panel.position[1] + y,
8079 ],
8080 PanelLocation::Relative([x, y]) => [
8081 resource_panel.position[0]
8082 + (resource_panel.size[0] / x[1] as f32 * x[0] as f32),
8083 resource_panel.position[1]
8084 + (resource_panel.size[1] / y[1] as f32 * y[0] as f32),
8085 ],
8086 };
8087 basic_front_resource
8088 .modify_position(default_x_position, default_y_position);
8089 if influence_layout {
8090 resource_point_list.push((
8091 [default_x_position - left, default_y_position - top],
8092 [
8093 default_x_position
8094 + basic_front_resource.display_size()[0]
8095 + right,
8096 default_y_position
8097 + basic_front_resource.display_size()[1]
8098 + bottom,
8099 ],
8100 basic_front_resource.display_allow_scrolling(),
8101 ));
8102 };
8103 }
8104 };
8105 };
8106 *rcr = basic_front_resource;
8107 };
8108 };
8109 }
8110 let mut resource_length = [[None, None], [None, None]];
8111 for point in resource_point_list {
8112 resource_length = [
8113 [
8114 if resource_length[0][0].is_none()
8115 || resource_length[0][0].is_some()
8116 && point.0[0] < resource_length[0][0].unwrap()
8117 && point.2[0]
8118 {
8119 Some(point.0[0])
8120 } else {
8121 resource_length[0][0]
8122 },
8123 if resource_length[0][1].is_none()
8124 || resource_length[0][1].is_some()
8125 && point.0[1] < resource_length[0][1].unwrap()
8126 && point.2[1]
8127 {
8128 Some(point.0[1])
8129 } else {
8130 resource_length[0][1]
8131 },
8132 ],
8133 [
8134 if resource_length[1][0].is_none()
8135 || resource_length[1][0].is_some()
8136 && point.1[0] < resource_length[1][0].unwrap()
8137 && point.2[0]
8138 {
8139 Some(point.1[0])
8140 } else {
8141 resource_length[1][0]
8142 },
8143 if resource_length[1][1].is_none()
8144 || resource_length[1][1].is_some()
8145 && point.1[1] < resource_length[1][1].unwrap()
8146 && point.2[1]
8147 {
8148 Some(point.1[1])
8149 } else {
8150 resource_length[1][1]
8151 },
8152 ],
8153 ]
8154 }
8155 if let Some(horizontal_scroll_length_method) = resource_panel.scroll_length_method[0] {
8156 resource_panel.scroll_length[0] = match horizontal_scroll_length_method {
8157 ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
8158 ScrollLengthMethod::AutoFit => {
8159 if let [Some(min), Some(max)] = [resource_length[0][0], resource_length[1][0]] {
8160 let width = max - min;
8161 if width - resource_panel.size[0] > 0_f32 {
8162 width - resource_panel.size[0]
8163 } else {
8164 0_f32
8165 }
8166 } else {
8167 0_f32
8168 }
8169 }
8170 };
8171 resource_panel.scroll_progress[0] =
8172 if resource_panel.scroll_progress[0] > resource_panel.scroll_length[0] {
8173 resource_panel.scroll_length[0]
8174 } else {
8175 resource_panel.scroll_progress[0]
8176 };
8177 };
8178 if let Some(vertical_scroll_length_method) = resource_panel.scroll_length_method[1] {
8179 resource_panel.scroll_length[1] = match vertical_scroll_length_method {
8180 ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
8181 ScrollLengthMethod::AutoFit => {
8182 if let [Some(min), Some(max)] = [resource_length[0][1], resource_length[1][1]] {
8183 let height = max - min;
8184 if height - resource_panel.size[1] > 0_f32 {
8185 height - resource_panel.size[1]
8186 } else {
8187 0_f32
8188 }
8189 } else {
8190 0_f32
8191 }
8192 }
8193 };
8194 resource_panel.scroll_progress[1] =
8195 if resource_panel.scroll_progress[1] > resource_panel.scroll_length[1] {
8196 resource_panel.scroll_length[1]
8197 } else {
8198 resource_panel.scroll_progress[1]
8199 };
8200 };
8201 resource_panel.last_frame_scroll_progress = resource_panel.scroll_progress;
8202 self.replace_resource(
8203 &resource_panel.name,
8204 "ResourcePanel",
8205 resource_panel.clone(),
8206 )
8207 .unwrap();
8208 Ok(())
8209 }
8210}