1use eframe::{
23 Result,
24 emath::Rect,
25 epaint::{Stroke, textures::TextureOptions},
26};
27use egui::{
28 Color32, ColorImage, Context, CornerRadius, CursorIcon, FontData, FontDefinitions, FontFamily,
29 FontId, Galley, Id, ImageSource, Key, OpenUrl, PointerButton, Pos2, Sense, StrokeKind,
30 TextureHandle, Ui, Vec2, text::CCursor,
31};
32use std::{
33 any::{Any, type_name_of_val},
34 char,
35 cmp::Ordering,
36 error::Error,
37 fmt::{Debug, Display, Formatter},
38 fs::{File, read},
39 io::Read,
40 sync::Arc,
41 time::Instant,
42 vec::Vec,
43};
44
45pub trait RustConstructorResource: Debug {
47 fn as_any(&self) -> &dyn Any;
49
50 fn as_any_mut(&mut self) -> &mut dyn Any;
52
53 fn display_display_info(&self) -> Option<DisplayInfo>;
55
56 fn modify_display_info(&mut self, display_info: DisplayInfo);
58
59 fn display_tags(&self) -> Vec<[String; 2]>;
61
62 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool);
64}
65
66pub trait BasicFrontResource: RustConstructorResource {
68 fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig;
70
71 fn display_position_size_config(&self) -> PositionSizeConfig;
73
74 fn display_clip_rect(&self) -> Option<PositionSizeConfig>;
76
77 fn display_position(&self) -> [f32; 2];
79
80 fn display_size(&self) -> [f32; 2];
82
83 fn modify_basic_front_resource_config(
85 &mut self,
86 basic_front_resource_config: BasicFrontResourceConfig,
87 );
88
89 fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig);
91
92 fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>);
94}
95
96#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
98pub struct RustConstructorId {
99 pub name: String,
101 pub discern_type: String,
103}
104
105#[derive(Debug)]
107pub struct RustConstructorResourceBox {
108 pub id: RustConstructorId,
110 pub content: Box<dyn RustConstructorResource>,
112}
113
114impl RustConstructorResourceBox {
115 pub fn new(name: &str, discern_type: &str, content: Box<dyn RustConstructorResource>) -> Self {
116 Self {
117 id: RustConstructorId {
118 name: name.to_string(),
119 discern_type: discern_type.to_string(),
120 },
121 content,
122 }
123 }
124}
125
126#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
128pub struct BasicFrontResourceConfig {
129 pub position_size_config: PositionSizeConfig,
131 pub clip_rect: Option<PositionSizeConfig>,
133}
134
135impl BasicFrontResourceConfig {
136 #[inline]
137 pub fn position_size_config(mut self, position_size_config: PositionSizeConfig) -> Self {
138 self.position_size_config = position_size_config;
139 self
140 }
141
142 #[inline]
143 pub fn clip_rect(mut self, clip_rect: Option<PositionSizeConfig>) -> Self {
144 self.clip_rect = clip_rect;
145 self
146 }
147}
148
149#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
151pub struct PositionSizeConfig {
152 pub origin_position: [f32; 2],
154 pub origin_size: [f32; 2],
156 pub x_location_grid: [f32; 2],
158 pub y_location_grid: [f32; 2],
160 pub x_size_grid: [f32; 2],
162 pub y_size_grid: [f32; 2],
164 pub display_method: (HorizontalAlign, VerticalAlign),
166 pub offset: [f32; 2],
168}
169
170impl Default for PositionSizeConfig {
171 fn default() -> Self {
172 PositionSizeConfig {
173 origin_position: [0_f32, 0_f32],
174 origin_size: [0_f32, 0_f32],
175 x_location_grid: [0_f32, 0_f32],
176 y_location_grid: [0_f32, 0_f32],
177 x_size_grid: [0_f32, 0_f32],
178 y_size_grid: [0_f32, 0_f32],
179 display_method: (HorizontalAlign::default(), VerticalAlign::default()),
180 offset: [0_f32, 0_f32],
181 }
182 }
183}
184
185impl PositionSizeConfig {
186 #[inline]
187 pub fn origin_position(mut self, x: f32, y: f32) -> Self {
188 self.origin_position = [x, y];
189 self
190 }
191
192 #[inline]
193 pub fn origin_size(mut self, width: f32, height: f32) -> Self {
194 self.origin_size = [width, height];
195 self
196 }
197
198 #[inline]
199 pub fn x_size_grid(mut self, fetch: f32, total: f32) -> Self {
200 self.x_size_grid = [fetch, total];
201 self
202 }
203
204 #[inline]
205 pub fn y_size_grid(mut self, fetch: f32, total: f32) -> Self {
206 self.y_size_grid = [fetch, total];
207 self
208 }
209
210 #[inline]
211 pub fn x_location_grid(mut self, fetch: f32, total: f32) -> Self {
212 self.x_location_grid = [fetch, total];
213 self
214 }
215
216 #[inline]
217 pub fn y_location_grid(mut self, fetch: f32, total: f32) -> Self {
218 self.y_location_grid = [fetch, total];
219 self
220 }
221
222 #[inline]
223 pub fn display_method(
224 mut self,
225 horizontal_align: HorizontalAlign,
226 vertical_align: VerticalAlign,
227 ) -> Self {
228 self.display_method = (horizontal_align, vertical_align);
229 self
230 }
231
232 #[inline]
233 pub fn offset(mut self, x: f32, y: f32) -> Self {
234 self.offset = [x, y];
235 self
236 }
237}
238
239#[derive(Debug, Clone, PartialEq, PartialOrd)]
241pub struct EventState {
242 pub current_page: String,
244 pub current_total_runtime: f32,
246 pub current_page_runtime: f32,
248}
249
250#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
252pub struct PageData {
253 pub forced_update: bool,
255 pub change_page_updated: bool,
257 pub enter_page_updated: bool,
259 pub tags: Vec<[String; 2]>,
261}
262
263impl RustConstructorResource for PageData {
264 fn as_any(&self) -> &dyn Any {
265 self
266 }
267
268 fn as_any_mut(&mut self) -> &mut dyn Any {
269 self
270 }
271
272 fn display_display_info(&self) -> Option<DisplayInfo> {
273 None
274 }
275
276 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
277
278 fn display_tags(&self) -> Vec<[String; 2]> {
279 self.tags.clone()
280 }
281
282 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
283 if replace {
284 self.tags = tags.to_owned();
285 } else {
286 for tag in tags {
287 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
288 self.tags.remove(index);
289 };
290 }
291 self.tags.extend(tags.iter().cloned());
292 };
293 }
294}
295
296impl Default for PageData {
297 fn default() -> Self {
298 PageData {
299 forced_update: true,
300 change_page_updated: false,
301 enter_page_updated: false,
302 tags: Vec::new(),
303 }
304 }
305}
306
307impl PageData {
308 #[inline]
309 pub fn forced_update(mut self, forced_update: bool) -> Self {
310 self.forced_update = forced_update;
311 self
312 }
313
314 #[inline]
315 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
316 if replace {
317 self.tags = tags.to_owned();
318 } else {
319 for tag in tags {
320 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
321 self.tags.remove(index);
322 };
323 }
324 self.tags.extend(tags.iter().cloned());
325 };
326 self
327 }
328}
329
330#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
332pub struct Timer {
333 pub start_time: f32,
335 pub total_time: f32,
337 pub timer: Instant,
339 pub now_time: f32,
341}
342
343impl Default for Timer {
344 fn default() -> Self {
345 Timer {
346 start_time: 0_f32,
347 total_time: 0_f32,
348 timer: Instant::now(),
349 now_time: 0_f32,
350 }
351 }
352}
353
354#[derive(Clone, PartialEq, Eq, Hash)]
356pub struct DebugTextureHandle(TextureHandle);
357
358impl Debug for DebugTextureHandle {
359 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
360 f.debug_struct("DebugTextureHandle").finish()
362 }
363}
364
365impl DebugTextureHandle {
366 pub fn new(texture_handle: &TextureHandle) -> Self {
367 Self(texture_handle.clone())
368 }
369}
370
371#[derive(Clone, Debug, Default, PartialEq)]
373pub struct ImageTexture {
374 pub texture: Option<DebugTextureHandle>,
376 pub cite_path: String,
378 pub flip: [bool; 2],
380 pub context: Context,
382 pub tags: Vec<[String; 2]>,
384}
385
386impl RustConstructorResource for ImageTexture {
387 fn as_any(&self) -> &dyn Any {
388 self
389 }
390
391 fn as_any_mut(&mut self) -> &mut dyn Any {
392 self
393 }
394
395 fn display_display_info(&self) -> Option<DisplayInfo> {
396 None
397 }
398
399 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
400
401 fn display_tags(&self) -> Vec<[String; 2]> {
402 self.tags.clone()
403 }
404
405 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
406 if replace {
407 self.tags = tags.to_owned();
408 } else {
409 for tag in tags {
410 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
411 self.tags.remove(index);
412 };
413 }
414 self.tags.extend(tags.iter().cloned());
415 };
416 }
417}
418
419impl ImageTexture {
420 #[inline]
421 pub fn cite_path(mut self, cite_path: &str) -> Self {
422 self.cite_path = cite_path.to_string();
423 self
424 }
425
426 #[inline]
427 pub fn flip(mut self, horizontal_flip: bool, vertical_flip: bool) -> Self {
428 self.flip = [horizontal_flip, vertical_flip];
429 self
430 }
431
432 #[inline]
433 pub fn ctx(mut self, context: &Context) -> Self {
434 self.context = context.clone();
435 self
436 }
437
438 #[inline]
439 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
440 if replace {
441 self.tags = tags.to_owned();
442 } else {
443 for tag in tags {
444 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
445 self.tags.remove(index);
446 };
447 }
448 self.tags.extend(tags.iter().cloned());
449 };
450 self
451 }
452}
453
454#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
456pub enum BorderKind {
457 #[default]
459 Inside,
460 Middle,
462 Outside,
464}
465
466#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
468pub struct CustomRectConfig {
469 pub position_size_config: Option<PositionSizeConfig>,
471 pub clip_rect: Option<Option<PositionSizeConfig>>,
473 pub hidden: Option<bool>,
475 pub ignore_render_layer: Option<bool>,
477 pub rounding: Option<f32>,
479 pub color: Option<[u8; 3]>,
481 pub alpha: Option<u8>,
483 pub border_width: Option<f32>,
485 pub border_color: Option<[u8; 3]>,
487 pub border_alpha: Option<u8>,
489 pub border_kind: Option<BorderKind>,
491 pub tags: Option<Vec<[String; 2]>>,
493}
494
495impl CustomRectConfig {
496 pub fn from_custom_rect(custom_rect: &CustomRect) -> Self {
497 Self {
498 position_size_config: Some(
499 custom_rect.basic_front_resource_config.position_size_config,
500 ),
501 clip_rect: Some(custom_rect.basic_front_resource_config.clip_rect),
502 hidden: Some(custom_rect.display_info.hidden),
503 ignore_render_layer: Some(custom_rect.display_info.ignore_render_layer),
504 rounding: Some(custom_rect.rounding),
505 color: Some(custom_rect.color),
506 alpha: Some(custom_rect.alpha),
507 border_width: Some(custom_rect.border_width),
508 border_color: Some(custom_rect.border_color),
509 border_alpha: Some(custom_rect.border_alpha),
510 border_kind: Some(custom_rect.border_kind),
511 tags: Some(custom_rect.tags.clone()),
512 }
513 }
514
515 #[inline]
516 pub fn position_size_config(
517 mut self,
518 position_size_config: Option<PositionSizeConfig>,
519 ) -> Self {
520 self.position_size_config = position_size_config;
521 self
522 }
523
524 #[inline]
525 pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
526 self.clip_rect = clip_rect;
527 self
528 }
529
530 #[inline]
531 pub fn hidden(mut self, hidden: Option<bool>) -> Self {
532 self.hidden = hidden;
533 self
534 }
535
536 #[inline]
537 pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
538 self.ignore_render_layer = ignore_render_layer;
539 self
540 }
541
542 #[inline]
543 pub fn rounding(mut self, rounding: Option<f32>) -> Self {
544 self.rounding = rounding;
545 self
546 }
547
548 #[inline]
549 pub fn color(mut self, color: Option<[u8; 3]>) -> Self {
550 self.color = color;
551 self
552 }
553
554 #[inline]
555 pub fn alpha(mut self, alpha: Option<u8>) -> Self {
556 self.alpha = alpha;
557 self
558 }
559
560 #[inline]
561 pub fn border_width(mut self, border_width: Option<f32>) -> Self {
562 self.border_width = border_width;
563 self
564 }
565
566 #[inline]
567 pub fn border_color(mut self, border_color: Option<[u8; 3]>) -> Self {
568 self.border_color = border_color;
569 self
570 }
571
572 #[inline]
573 pub fn border_alpha(mut self, border_alpha: Option<u8>) -> Self {
574 self.border_alpha = border_alpha;
575 self
576 }
577
578 #[inline]
579 pub fn border_kind(mut self, border_kind: Option<BorderKind>) -> Self {
580 self.border_kind = border_kind;
581 self
582 }
583
584 #[inline]
585 pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
586 self.tags = tags;
587 self
588 }
589}
590
591#[derive(Debug, Clone, PartialEq, PartialOrd)]
593pub struct CustomRect {
594 pub basic_front_resource_config: BasicFrontResourceConfig,
596 pub position: [f32; 2],
598 pub size: [f32; 2],
600 pub display_info: DisplayInfo,
602 pub rounding: f32,
604 pub color: [u8; 3],
606 pub alpha: u8,
608 pub border_width: f32,
610 pub border_color: [u8; 3],
612 pub border_alpha: u8,
614 pub border_kind: BorderKind,
616 pub tags: Vec<[String; 2]>,
618}
619
620impl RustConstructorResource for CustomRect {
621 fn as_any(&self) -> &dyn Any {
622 self
623 }
624
625 fn as_any_mut(&mut self) -> &mut dyn Any {
626 self
627 }
628
629 fn display_display_info(&self) -> Option<DisplayInfo> {
630 Some(self.display_info)
631 }
632
633 fn modify_display_info(&mut self, display_info: DisplayInfo) {
634 self.display_info = display_info;
635 }
636
637 fn display_tags(&self) -> Vec<[String; 2]> {
638 self.tags.clone()
639 }
640
641 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
642 if replace {
643 self.tags = tags.to_owned();
644 } else {
645 for tag in tags {
646 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
647 self.tags.remove(index);
648 };
649 }
650 self.tags.extend(tags.iter().cloned());
651 };
652 }
653}
654
655impl BasicFrontResource for CustomRect {
656 fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
657 self.basic_front_resource_config.clone()
658 }
659
660 fn display_position_size_config(&self) -> PositionSizeConfig {
661 self.basic_front_resource_config.position_size_config
662 }
663
664 fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
665 self.basic_front_resource_config.clip_rect
666 }
667
668 fn display_position(&self) -> [f32; 2] {
669 self.position
670 }
671
672 fn display_size(&self) -> [f32; 2] {
673 self.size
674 }
675
676 fn modify_basic_front_resource_config(
677 &mut self,
678 basic_front_resource_config: BasicFrontResourceConfig,
679 ) {
680 self.basic_front_resource_config = basic_front_resource_config;
681 }
682
683 fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
684 self.basic_front_resource_config.position_size_config = position_size_config;
685 }
686
687 fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
688 self.basic_front_resource_config.clip_rect = clip_rect;
689 }
690}
691
692impl Default for CustomRect {
693 fn default() -> Self {
694 Self {
695 basic_front_resource_config: BasicFrontResourceConfig::default(),
696 position: [0_f32, 0_f32],
697 size: [0_f32, 0_f32],
698 display_info: DisplayInfo::default(),
699 rounding: 2_f32,
700 color: [255, 255, 255],
701 alpha: 255,
702 border_width: 2_f32,
703 border_color: [0, 0, 0],
704 border_alpha: 255,
705 border_kind: BorderKind::default(),
706 tags: Vec::new(),
707 }
708 }
709}
710
711impl CustomRect {
712 pub fn from_config(mut self, config: &CustomRectConfig) -> Self {
713 if let Some(position_size_config) = config.position_size_config {
714 self.basic_front_resource_config.position_size_config = position_size_config;
715 };
716 if let Some(clip_rect) = config.clip_rect {
717 self.basic_front_resource_config.clip_rect = clip_rect;
718 };
719 if let Some(hidden) = config.hidden {
720 self.display_info.hidden = hidden;
721 };
722 if let Some(ignore_render_layer) = config.ignore_render_layer {
723 self.display_info.ignore_render_layer = ignore_render_layer;
724 };
725 if let Some(rounding) = config.rounding {
726 self.rounding = rounding;
727 };
728 if let Some(color) = config.color {
729 self.color = color;
730 };
731 if let Some(alpha) = config.alpha {
732 self.alpha = alpha;
733 };
734 if let Some(border_width) = config.border_width {
735 self.border_width = border_width;
736 };
737 if let Some(border_color) = config.border_color {
738 self.border_color = border_color;
739 };
740 if let Some(border_alpha) = config.border_alpha {
741 self.border_alpha = border_alpha;
742 };
743 if let Some(border_kind) = config.border_kind {
744 self.border_kind = border_kind;
745 };
746 if let Some(tags) = config.tags.clone() {
747 self.tags = tags;
748 };
749 self
750 }
751
752 #[inline]
753 pub fn basic_front_resource_config(
754 mut self,
755 basic_front_resource_config: &BasicFrontResourceConfig,
756 ) -> Self {
757 self.basic_front_resource_config = basic_front_resource_config.clone();
758 self
759 }
760
761 #[inline]
762 pub fn hidden(mut self, hidden: bool) -> Self {
763 self.display_info.hidden = hidden;
764 self
765 }
766
767 #[inline]
768 pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
769 self.display_info.ignore_render_layer = ignore_render_layer;
770 self
771 }
772
773 #[inline]
774 pub fn rounding(mut self, rounding: f32) -> Self {
775 self.rounding = rounding;
776 self
777 }
778
779 #[inline]
780 pub fn color(mut self, r: u8, g: u8, b: u8) -> Self {
781 self.color = [r, g, b];
782 self
783 }
784
785 #[inline]
786 pub fn alpha(mut self, alpha: u8) -> Self {
787 self.alpha = alpha;
788 self
789 }
790
791 #[inline]
792 pub fn border_width(mut self, border_width: f32) -> Self {
793 self.border_width = border_width;
794 self
795 }
796
797 #[inline]
798 pub fn border_color(mut self, r: u8, g: u8, b: u8) -> Self {
799 self.border_color = [r, g, b];
800 self
801 }
802
803 #[inline]
804 pub fn border_alpha(mut self, border_alpha: u8) -> Self {
805 self.border_alpha = border_alpha;
806 self
807 }
808
809 #[inline]
810 pub fn border_kind(mut self, border_kind: BorderKind) -> Self {
811 self.border_kind = border_kind;
812 self
813 }
814
815 #[inline]
816 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
817 if replace {
818 self.tags = tags.to_owned();
819 } else {
820 for tag in tags {
821 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
822 self.tags.remove(index);
823 };
824 }
825 self.tags.extend(tags.iter().cloned());
826 };
827 self
828 }
829}
830
831#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
833pub struct ImageConfig {
834 pub position_size_config: Option<PositionSizeConfig>,
836 pub clip_rect: Option<Option<PositionSizeConfig>>,
838 pub hidden: Option<bool>,
840 pub ignore_render_layer: Option<bool>,
842 pub alpha: Option<u8>,
844 pub overlay_color: Option<[u8; 3]>,
846 pub overlay_alpha: Option<u8>,
848 pub background_color: Option<[u8; 3]>,
850 pub background_alpha: Option<u8>,
852 pub rotate_angle: Option<f32>,
854 pub rotate_center: Option<[f32; 2]>,
856 pub cite_texture: Option<String>,
858 pub tags: Option<Vec<[String; 2]>>,
860}
861
862impl ImageConfig {
863 pub fn from_image(image: &Image) -> Self {
864 Self {
865 position_size_config: Some(image.basic_front_resource_config.position_size_config),
866 clip_rect: Some(image.basic_front_resource_config.clip_rect),
867 hidden: Some(image.display_info.hidden),
868 ignore_render_layer: Some(image.display_info.ignore_render_layer),
869 alpha: Some(image.alpha),
870 overlay_color: Some(image.overlay_color),
871 overlay_alpha: Some(image.overlay_alpha),
872 background_color: Some(image.background_color),
873 background_alpha: Some(image.background_alpha),
874 rotate_angle: Some(image.rotate_angle),
875 rotate_center: Some(image.rotate_center),
876 cite_texture: Some(image.cite_texture.clone()),
877 tags: Some(image.tags.clone()),
878 }
879 }
880
881 #[inline]
882 pub fn position_size_config(
883 mut self,
884 position_size_config: Option<PositionSizeConfig>,
885 ) -> Self {
886 self.position_size_config = position_size_config;
887 self
888 }
889
890 #[inline]
891 pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
892 self.clip_rect = clip_rect;
893 self
894 }
895
896 #[inline]
897 pub fn hidden(mut self, hidden: Option<bool>) -> Self {
898 self.hidden = hidden;
899 self
900 }
901
902 #[inline]
903 pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
904 self.ignore_render_layer = ignore_render_layer;
905 self
906 }
907
908 #[inline]
909 pub fn alpha(mut self, alpha: Option<u8>) -> Self {
910 self.alpha = alpha;
911 self
912 }
913
914 #[inline]
915 pub fn overlay_color(mut self, overlay_color: Option<[u8; 3]>) -> Self {
916 self.overlay_color = overlay_color;
917 self
918 }
919
920 #[inline]
921 pub fn overlay_alpha(mut self, overlay_alpha: Option<u8>) -> Self {
922 self.overlay_alpha = overlay_alpha;
923 self
924 }
925
926 #[inline]
927 pub fn background_color(mut self, background_color: Option<[u8; 3]>) -> Self {
928 self.background_color = background_color;
929 self
930 }
931
932 #[inline]
933 pub fn background_alpha(mut self, background_alpha: Option<u8>) -> Self {
934 self.background_alpha = background_alpha;
935 self
936 }
937
938 #[inline]
939 pub fn rotate_angle(mut self, rotate_angle: Option<f32>) -> Self {
940 self.rotate_angle = rotate_angle;
941 self
942 }
943
944 #[inline]
945 pub fn rotate_center(mut self, rotate_center: Option<[f32; 2]>) -> Self {
946 self.rotate_center = rotate_center;
947 self
948 }
949
950 #[inline]
951 pub fn cite_texture(mut self, cite_texture: Option<String>) -> Self {
952 self.cite_texture = cite_texture;
953 self
954 }
955
956 #[inline]
957 pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
958 self.tags = tags;
959 self
960 }
961}
962
963#[derive(Debug, Clone, PartialEq)]
965pub struct Image {
966 pub basic_front_resource_config: BasicFrontResourceConfig,
968 pub position: [f32; 2],
970 pub size: [f32; 2],
972 pub display_info: DisplayInfo,
974 pub texture: Option<DebugTextureHandle>,
976 pub alpha: u8,
978 pub overlay_color: [u8; 3],
980 pub overlay_alpha: u8,
982 pub background_color: [u8; 3],
984 pub background_alpha: u8,
986 pub rotate_angle: f32,
988 pub rotate_center: [f32; 2],
990 pub cite_texture: String,
992 pub last_frame_cite_texture: String,
994 pub tags: Vec<[String; 2]>,
996}
997
998impl RustConstructorResource for Image {
999 fn as_any(&self) -> &dyn Any {
1000 self
1001 }
1002
1003 fn as_any_mut(&mut self) -> &mut dyn Any {
1004 self
1005 }
1006
1007 fn display_display_info(&self) -> Option<DisplayInfo> {
1008 Some(self.display_info)
1009 }
1010
1011 fn modify_display_info(&mut self, display_info: DisplayInfo) {
1012 self.display_info = display_info;
1013 }
1014
1015 fn display_tags(&self) -> Vec<[String; 2]> {
1016 self.tags.clone()
1017 }
1018
1019 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1020 if replace {
1021 self.tags = tags.to_owned();
1022 } else {
1023 for tag in tags {
1024 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1025 self.tags.remove(index);
1026 };
1027 }
1028 self.tags.extend(tags.iter().cloned());
1029 };
1030 }
1031}
1032
1033impl BasicFrontResource for Image {
1034 fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
1035 self.basic_front_resource_config.clone()
1036 }
1037
1038 fn display_position_size_config(&self) -> PositionSizeConfig {
1039 self.basic_front_resource_config.position_size_config
1040 }
1041
1042 fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
1043 self.basic_front_resource_config.clip_rect
1044 }
1045
1046 fn display_position(&self) -> [f32; 2] {
1047 self.position
1048 }
1049
1050 fn display_size(&self) -> [f32; 2] {
1051 self.size
1052 }
1053
1054 fn modify_basic_front_resource_config(
1055 &mut self,
1056 basic_front_resource_config: BasicFrontResourceConfig,
1057 ) {
1058 self.basic_front_resource_config = basic_front_resource_config;
1059 }
1060
1061 fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
1062 self.basic_front_resource_config.position_size_config = position_size_config;
1063 }
1064
1065 fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
1066 self.basic_front_resource_config.clip_rect = clip_rect;
1067 }
1068}
1069
1070impl Default for Image {
1071 fn default() -> Self {
1072 Self {
1073 basic_front_resource_config: BasicFrontResourceConfig::default(),
1074 position: [0_f32, 0_f32],
1075 size: [0_f32, 0_f32],
1076 display_info: DisplayInfo::default(),
1077 texture: None,
1078 alpha: 255,
1079 overlay_color: [255, 255, 255],
1080 overlay_alpha: 255,
1081 background_color: [0, 0, 0],
1082 background_alpha: 0,
1083 rotate_angle: 0_f32,
1084 rotate_center: [0_f32, 0_f32],
1085 cite_texture: String::from("rust_constructor::ImageTexture"),
1086 last_frame_cite_texture: String::from("rust_constructor::ImageTexture"),
1087 tags: Vec::new(),
1088 }
1089 }
1090}
1091
1092impl Image {
1093 pub fn from_config(mut self, config: &ImageConfig) -> Self {
1094 if let Some(position_size_config) = config.position_size_config {
1095 self.basic_front_resource_config.position_size_config = position_size_config;
1096 };
1097 if let Some(clip_rect) = config.clip_rect {
1098 self.basic_front_resource_config.clip_rect = clip_rect;
1099 };
1100 if let Some(hidden) = config.hidden {
1101 self.display_info.hidden = hidden;
1102 };
1103 if let Some(ignore_render_layer) = config.ignore_render_layer {
1104 self.display_info.ignore_render_layer = ignore_render_layer;
1105 };
1106 if let Some(alpha) = config.alpha {
1107 self.alpha = alpha;
1108 };
1109 if let Some(overlay_color) = config.overlay_color {
1110 self.overlay_color = overlay_color;
1111 };
1112 if let Some(overlay_alpha) = config.overlay_alpha {
1113 self.overlay_alpha = overlay_alpha;
1114 };
1115 if let Some(background_color) = config.background_color {
1116 self.background_color = background_color;
1117 };
1118 if let Some(background_alpha) = config.background_alpha {
1119 self.background_alpha = background_alpha;
1120 };
1121 if let Some(rotate_angle) = config.rotate_angle {
1122 self.rotate_angle = rotate_angle;
1123 };
1124 if let Some(rotate_center) = config.rotate_center {
1125 self.rotate_center = rotate_center;
1126 };
1127 if let Some(cite_texture) = config.cite_texture.clone() {
1128 self.cite_texture = cite_texture;
1129 };
1130 if let Some(tags) = config.tags.clone() {
1131 self.tags = tags;
1132 };
1133 self
1134 }
1135
1136 #[inline]
1137 pub fn basic_front_resource_config(
1138 mut self,
1139 basic_front_resource_config: &BasicFrontResourceConfig,
1140 ) -> Self {
1141 self.basic_front_resource_config = basic_front_resource_config.clone();
1142 self
1143 }
1144
1145 #[inline]
1146 pub fn hidden(mut self, hidden: bool) -> Self {
1147 self.display_info.hidden = hidden;
1148 self
1149 }
1150
1151 #[inline]
1152 pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
1153 self.display_info.ignore_render_layer = ignore_render_layer;
1154 self
1155 }
1156
1157 #[inline]
1158 pub fn alpha(mut self, alpha: u8) -> Self {
1159 self.alpha = alpha;
1160 self
1161 }
1162
1163 #[inline]
1164 pub fn overlay_color(mut self, r: u8, g: u8, b: u8) -> Self {
1165 self.overlay_color = [r, g, b];
1166 self
1167 }
1168
1169 #[inline]
1170 pub fn overlay_alpha(mut self, overlay_alpha: u8) -> Self {
1171 self.overlay_alpha = overlay_alpha;
1172 self
1173 }
1174
1175 #[inline]
1176 pub fn background_color(mut self, r: u8, g: u8, b: u8) -> Self {
1177 self.background_color = [r, g, b];
1178 self
1179 }
1180
1181 #[inline]
1182 pub fn background_alpha(mut self, background_alpha: u8) -> Self {
1183 self.background_alpha = background_alpha;
1184 self
1185 }
1186
1187 #[inline]
1188 pub fn rotate_angle(mut self, rotate_angle: f32) -> Self {
1189 self.rotate_angle = rotate_angle;
1190 self
1191 }
1192
1193 #[inline]
1194 pub fn rotate_center(mut self, x: f32, y: f32) -> Self {
1195 self.rotate_center = [x, y];
1196 self
1197 }
1198
1199 #[inline]
1200 pub fn cite_texture(mut self, cite_texture: &str) -> Self {
1201 self.cite_texture = cite_texture.to_string();
1202 self
1203 }
1204
1205 #[inline]
1206 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1207 if replace {
1208 self.tags = tags.to_owned();
1209 } else {
1210 for tag in tags {
1211 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1212 self.tags.remove(index);
1213 };
1214 }
1215 self.tags.extend(tags.iter().cloned());
1216 };
1217 self
1218 }
1219}
1220
1221#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
1223pub enum HyperlinkSelectMethod {
1224 All(String),
1226 Segment(Vec<(usize, String)>),
1228}
1229
1230#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
1232pub struct TextConfig {
1233 pub position_size_config: Option<PositionSizeConfig>,
1235 pub clip_rect: Option<Option<PositionSizeConfig>>,
1237 pub hidden: Option<bool>,
1239 pub ignore_render_layer: Option<bool>,
1241 pub content: Option<String>,
1243 pub font_size: Option<f32>,
1245 pub color: Option<[u8; 3]>,
1247 pub alpha: Option<u8>,
1249 pub background_color: Option<[u8; 3]>,
1251 pub background_alpha: Option<u8>,
1253 pub background_rounding: Option<f32>,
1255 pub font: Option<String>,
1257 pub selectable: Option<bool>,
1259 pub hyperlink_text: Option<Vec<(String, HyperlinkSelectMethod)>>,
1261 pub auto_fit: Option<[bool; 2]>,
1263 pub tags: Option<Vec<[String; 2]>>,
1265}
1266
1267impl TextConfig {
1268 pub fn from_text(text: &Text) -> Self {
1269 Self {
1270 position_size_config: Some(text.basic_front_resource_config.position_size_config),
1271 clip_rect: Some(text.basic_front_resource_config.clip_rect),
1272 hidden: Some(text.display_info.hidden),
1273 ignore_render_layer: Some(text.display_info.ignore_render_layer),
1274 content: Some(text.content.clone()),
1275 font_size: Some(text.font_size),
1276 color: Some(text.color),
1277 alpha: Some(text.alpha),
1278 background_color: Some(text.background_color),
1279 background_alpha: Some(text.background_alpha),
1280 background_rounding: Some(text.background_rounding),
1281 font: Some(text.font.clone()),
1282 selectable: Some(text.selectable),
1283 hyperlink_text: Some(text.hyperlink_text.clone()),
1284 auto_fit: Some(text.auto_fit),
1285 tags: Some(text.tags.clone()),
1286 }
1287 }
1288
1289 #[inline]
1290 pub fn position_size_config(
1291 mut self,
1292 position_size_config: Option<PositionSizeConfig>,
1293 ) -> Self {
1294 self.position_size_config = position_size_config;
1295 self
1296 }
1297
1298 #[inline]
1299 pub fn clip_rect(mut self, clip_rect: Option<Option<PositionSizeConfig>>) -> Self {
1300 self.clip_rect = clip_rect;
1301 self
1302 }
1303
1304 #[inline]
1305 pub fn hidden(mut self, hidden: Option<bool>) -> Self {
1306 self.hidden = hidden;
1307 self
1308 }
1309
1310 #[inline]
1311 pub fn ignore_render_layer(mut self, ignore_render_layer: Option<bool>) -> Self {
1312 self.ignore_render_layer = ignore_render_layer;
1313 self
1314 }
1315
1316 #[inline]
1317 pub fn content(mut self, content: Option<String>) -> Self {
1318 self.content = content;
1319 self
1320 }
1321
1322 #[inline]
1323 pub fn font_size(mut self, font_size: Option<f32>) -> Self {
1324 self.font_size = font_size;
1325 self
1326 }
1327
1328 #[inline]
1329 pub fn color(mut self, color: Option<[u8; 3]>) -> Self {
1330 self.color = color;
1331 self
1332 }
1333
1334 #[inline]
1335 pub fn alpha(mut self, alpha: Option<u8>) -> Self {
1336 self.alpha = alpha;
1337 self
1338 }
1339
1340 #[inline]
1341 pub fn background_color(mut self, background_color: Option<[u8; 3]>) -> Self {
1342 self.background_color = background_color;
1343 self
1344 }
1345
1346 #[inline]
1347 pub fn background_alpha(mut self, background_alpha: Option<u8>) -> Self {
1348 self.background_alpha = background_alpha;
1349 self
1350 }
1351
1352 #[inline]
1353 pub fn background_rounding(mut self, background_rounding: Option<f32>) -> Self {
1354 self.background_rounding = background_rounding;
1355 self
1356 }
1357
1358 #[inline]
1359 pub fn font(mut self, font: Option<String>) -> Self {
1360 self.font = font;
1361 self
1362 }
1363
1364 #[inline]
1365 pub fn selectable(mut self, selectable: Option<bool>) -> Self {
1366 self.selectable = selectable;
1367 self
1368 }
1369
1370 #[inline]
1371 pub fn hyperlink_text(
1372 mut self,
1373 hyperlink_text: Option<Vec<(String, HyperlinkSelectMethod)>>,
1374 ) -> Self {
1375 self.hyperlink_text = hyperlink_text;
1376 self
1377 }
1378
1379 #[inline]
1380 pub fn auto_fit(mut self, auto_fit: Option<[bool; 2]>) -> Self {
1381 self.auto_fit = auto_fit;
1382 self
1383 }
1384
1385 #[inline]
1386 pub fn tags(mut self, tags: Option<Vec<[String; 2]>>) -> Self {
1387 self.tags = tags;
1388 self
1389 }
1390}
1391
1392#[derive(Debug, Clone, PartialEq, PartialOrd)]
1394pub struct Text {
1395 pub basic_front_resource_config: BasicFrontResourceConfig,
1397 pub position: [f32; 2],
1399 pub size: [f32; 2],
1401 pub display_info: DisplayInfo,
1403 pub content: String,
1405 pub font_size: f32,
1407 pub color: [u8; 3],
1409 pub alpha: u8,
1411 pub background_color: [u8; 3],
1413 pub background_alpha: u8,
1415 pub background_rounding: f32,
1417 pub font: String,
1419 pub selectable: bool,
1421 pub hyperlink_text: Vec<(String, HyperlinkSelectMethod)>,
1423 pub hyperlink_index: Vec<(usize, usize, String)>,
1425 pub auto_fit: [bool; 2],
1427 pub last_frame_content: String,
1429 pub selection: Option<(usize, usize)>,
1431 pub truncate_size: [f32; 2],
1433 pub actual_size: [f32; 2],
1435 pub tags: Vec<[String; 2]>,
1437}
1438
1439impl RustConstructorResource for Text {
1440 fn as_any(&self) -> &dyn Any {
1441 self
1442 }
1443
1444 fn as_any_mut(&mut self) -> &mut dyn Any {
1445 self
1446 }
1447
1448 fn display_display_info(&self) -> Option<DisplayInfo> {
1449 Some(self.display_info)
1450 }
1451
1452 fn modify_display_info(&mut self, display_info: DisplayInfo) {
1453 self.display_info = display_info;
1454 }
1455
1456 fn display_tags(&self) -> Vec<[String; 2]> {
1457 self.tags.clone()
1458 }
1459
1460 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1461 if replace {
1462 self.tags = tags.to_owned();
1463 } else {
1464 for tag in tags {
1465 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1466 self.tags.remove(index);
1467 };
1468 }
1469 self.tags.extend(tags.iter().cloned());
1470 };
1471 }
1472}
1473
1474impl BasicFrontResource for Text {
1475 fn display_basic_front_resource_config(&self) -> BasicFrontResourceConfig {
1476 self.basic_front_resource_config.clone()
1477 }
1478
1479 fn display_position_size_config(&self) -> PositionSizeConfig {
1480 self.basic_front_resource_config.position_size_config
1481 }
1482
1483 fn display_clip_rect(&self) -> Option<PositionSizeConfig> {
1484 self.basic_front_resource_config.clip_rect
1485 }
1486
1487 fn display_position(&self) -> [f32; 2] {
1488 self.position
1489 }
1490
1491 fn display_size(&self) -> [f32; 2] {
1492 self.size
1493 }
1494
1495 fn modify_basic_front_resource_config(
1496 &mut self,
1497 basic_front_resource_config: BasicFrontResourceConfig,
1498 ) {
1499 self.basic_front_resource_config = basic_front_resource_config;
1500 }
1501
1502 fn modify_position_size_config(&mut self, position_size_config: PositionSizeConfig) {
1503 self.basic_front_resource_config.position_size_config = position_size_config;
1504 }
1505
1506 fn modify_clip_rect(&mut self, clip_rect: Option<PositionSizeConfig>) {
1507 self.basic_front_resource_config.clip_rect = clip_rect;
1508 }
1509}
1510
1511impl Default for Text {
1512 fn default() -> Self {
1513 Self {
1514 basic_front_resource_config: BasicFrontResourceConfig::default(),
1515 position: [0_f32, 0_f32],
1516 size: [0_f32, 0_f32],
1517 display_info: DisplayInfo::default(),
1518 content: String::from("Hello world"),
1519 font_size: 16_f32,
1520 color: [255, 255, 255],
1521 alpha: 255,
1522 background_color: [0, 0, 0],
1523 background_alpha: 0,
1524 background_rounding: 2_f32,
1525 font: String::new(),
1526 selectable: true,
1527 auto_fit: [true, true],
1528 hyperlink_text: Vec::new(),
1529 hyperlink_index: Vec::new(),
1530 last_frame_content: String::from(""),
1531 selection: None,
1532 truncate_size: [0_f32, 0_f32],
1533 actual_size: [0_f32, 0_f32],
1534 tags: Vec::new(),
1535 }
1536 }
1537}
1538
1539impl Text {
1540 pub fn from_config(mut self, config: &TextConfig) -> Self {
1541 if let Some(position_size_config) = config.position_size_config {
1542 self.basic_front_resource_config.position_size_config = position_size_config;
1543 };
1544 if let Some(clip_rect) = config.clip_rect {
1545 self.basic_front_resource_config.clip_rect = clip_rect;
1546 };
1547 if let Some(hidden) = config.hidden {
1548 self.display_info.hidden = hidden;
1549 };
1550 if let Some(ignore_render_layer) = config.ignore_render_layer {
1551 self.display_info.ignore_render_layer = ignore_render_layer;
1552 };
1553 if let Some(content) = config.content.clone() {
1554 self.content = content;
1555 };
1556 if let Some(font_size) = config.font_size {
1557 self.font_size = font_size;
1558 };
1559 if let Some(color) = config.color {
1560 self.color = color;
1561 };
1562 if let Some(alpha) = config.alpha {
1563 self.alpha = alpha;
1564 };
1565 if let Some(background_color) = config.background_color {
1566 self.background_color = background_color;
1567 };
1568 if let Some(background_alpha) = config.background_alpha {
1569 self.background_alpha = background_alpha;
1570 };
1571 if let Some(background_rounding) = config.background_rounding {
1572 self.background_rounding = background_rounding;
1573 };
1574 if let Some(font) = config.font.clone() {
1575 self.font = font;
1576 };
1577 if let Some(selectable) = config.selectable {
1578 self.selectable = selectable;
1579 };
1580 if let Some(hyperlink_text) = config.hyperlink_text.clone() {
1581 self.hyperlink_text = hyperlink_text;
1582 };
1583 if let Some(auto_fit) = config.auto_fit {
1584 self.auto_fit = auto_fit;
1585 };
1586 if let Some(tags) = config.tags.clone() {
1587 self.tags = tags;
1588 };
1589 self
1590 }
1591
1592 #[inline]
1593 pub fn basic_front_resource_config(
1594 mut self,
1595 basic_front_resource_config: &BasicFrontResourceConfig,
1596 ) -> Self {
1597 self.basic_front_resource_config = basic_front_resource_config.clone();
1598 self
1599 }
1600
1601 #[inline]
1602 pub fn hidden(mut self, hidden: bool) -> Self {
1603 self.display_info.hidden = hidden;
1604 self
1605 }
1606
1607 #[inline]
1608 pub fn ignore_render_layer(mut self, ignore_render_layer: bool) -> Self {
1609 self.display_info.ignore_render_layer = ignore_render_layer;
1610 self
1611 }
1612
1613 #[inline]
1614 pub fn content(mut self, content: &str) -> Self {
1615 self.content = content.to_string();
1616 self
1617 }
1618
1619 #[inline]
1620 pub fn font_size(mut self, font_size: f32) -> Self {
1621 self.font_size = font_size;
1622 self
1623 }
1624
1625 #[inline]
1626 pub fn color(mut self, r: u8, g: u8, b: u8) -> Self {
1627 self.color = [r, g, b];
1628 self
1629 }
1630
1631 #[inline]
1632 pub fn alpha(mut self, alpha: u8) -> Self {
1633 self.alpha = alpha;
1634 self
1635 }
1636
1637 #[inline]
1638 pub fn background_color(mut self, r: u8, g: u8, b: u8) -> Self {
1639 self.background_color = [r, g, b];
1640 self
1641 }
1642
1643 #[inline]
1644 pub fn background_alpha(mut self, alpha: u8) -> Self {
1645 self.background_alpha = alpha;
1646 self
1647 }
1648
1649 #[inline]
1650 pub fn background_rounding(mut self, background_rounding: f32) -> Self {
1651 self.background_rounding = background_rounding;
1652 self
1653 }
1654
1655 #[inline]
1656 pub fn font(mut self, font: &str) -> Self {
1657 self.font = font.to_string();
1658 self
1659 }
1660
1661 #[inline]
1662 pub fn selectable(mut self, selectable: bool) -> Self {
1663 self.selectable = selectable;
1664 self
1665 }
1666
1667 #[inline]
1668 pub fn push_hyperlink_text(
1669 mut self,
1670 target_text: &str,
1671 select_method: HyperlinkSelectMethod,
1672 ) -> Self {
1673 self.hyperlink_text
1674 .push((target_text.to_string(), select_method));
1675 self
1676 }
1677
1678 #[inline]
1679 pub fn hyperlink_text(mut self, hyperlink_text: Vec<(String, HyperlinkSelectMethod)>) -> Self {
1680 self.hyperlink_text = hyperlink_text;
1681 self
1682 }
1683
1684 #[inline]
1685 pub fn auto_fit(mut self, x: bool, y: bool) -> Self {
1686 self.auto_fit = [x, y];
1687 self
1688 }
1689
1690 #[inline]
1691 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1692 if replace {
1693 self.tags = tags.to_owned();
1694 } else {
1695 for tag in tags {
1696 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1697 self.tags.remove(index);
1698 };
1699 }
1700 self.tags.extend(tags.iter().cloned());
1701 };
1702 self
1703 }
1704}
1705
1706#[derive(Debug, Clone, PartialEq, PartialOrd)]
1708pub struct Variable<T> {
1709 pub value: Option<T>,
1711 pub tags: Vec<[String; 2]>,
1713}
1714
1715impl<T: Debug + 'static> RustConstructorResource for Variable<T> {
1716 fn as_any(&self) -> &dyn Any {
1717 self
1718 }
1719
1720 fn as_any_mut(&mut self) -> &mut dyn Any {
1721 self
1722 }
1723
1724 fn display_display_info(&self) -> Option<DisplayInfo> {
1725 None
1726 }
1727
1728 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
1729
1730 fn display_tags(&self) -> Vec<[String; 2]> {
1731 self.tags.clone()
1732 }
1733
1734 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1735 if replace {
1736 self.tags = tags.to_owned();
1737 } else {
1738 for tag in tags {
1739 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1740 self.tags.remove(index);
1741 };
1742 }
1743 self.tags.extend(tags.iter().cloned());
1744 };
1745 }
1746}
1747
1748impl<T> Default for Variable<T> {
1749 fn default() -> Self {
1750 Variable {
1751 value: None,
1752 tags: Vec::new(),
1753 }
1754 }
1755}
1756
1757impl<T> Variable<T> {
1758 #[inline]
1759 pub fn value(mut self, value: Option<T>) -> Self {
1760 self.value = value;
1761 self
1762 }
1763
1764 #[inline]
1765 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1766 if replace {
1767 self.tags = tags.to_owned();
1768 } else {
1769 for tag in tags {
1770 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1771 self.tags.remove(index);
1772 };
1773 }
1774 self.tags.extend(tags.iter().cloned());
1775 };
1776 self
1777 }
1778}
1779
1780#[derive(Clone, Debug, Default, PartialEq)]
1782pub struct Font {
1783 pub font_definitions: FontDefinitions,
1785 pub path: String,
1787 pub tags: Vec<[String; 2]>,
1789}
1790
1791impl RustConstructorResource for Font {
1792 fn as_any(&self) -> &dyn Any {
1793 self
1794 }
1795
1796 fn as_any_mut(&mut self) -> &mut dyn Any {
1797 self
1798 }
1799
1800 fn display_display_info(&self) -> Option<DisplayInfo> {
1801 None
1802 }
1803
1804 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
1805
1806 fn display_tags(&self) -> Vec<[String; 2]> {
1807 self.tags.clone()
1808 }
1809
1810 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1811 if replace {
1812 self.tags = tags.to_owned();
1813 } else {
1814 for tag in tags {
1815 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1816 self.tags.remove(index);
1817 };
1818 }
1819 self.tags.extend(tags.iter().cloned());
1820 };
1821 }
1822}
1823
1824impl Font {
1825 #[inline]
1826 pub fn path(mut self, path: &str) -> Self {
1827 self.path = path.to_string();
1828 self
1829 }
1830
1831 #[inline]
1832 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1833 if replace {
1834 self.tags = tags.to_owned();
1835 } else {
1836 for tag in tags {
1837 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1838 self.tags.remove(index);
1839 };
1840 }
1841 self.tags.extend(tags.iter().cloned());
1842 };
1843 self
1844 }
1845}
1846
1847#[derive(Debug, Clone, PartialEq, PartialOrd)]
1849pub struct SplitTime {
1850 pub time: [f32; 2],
1852 pub tags: Vec<[String; 2]>,
1854}
1855
1856impl RustConstructorResource for SplitTime {
1857 fn as_any(&self) -> &dyn Any {
1858 self
1859 }
1860
1861 fn as_any_mut(&mut self) -> &mut dyn Any {
1862 self
1863 }
1864
1865 fn display_display_info(&self) -> Option<DisplayInfo> {
1866 None
1867 }
1868
1869 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
1870
1871 fn display_tags(&self) -> Vec<[String; 2]> {
1872 self.tags.clone()
1873 }
1874
1875 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1876 if replace {
1877 self.tags = tags.to_owned();
1878 } else {
1879 for tag in tags {
1880 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1881 self.tags.remove(index);
1882 };
1883 }
1884 self.tags.extend(tags.iter().cloned());
1885 };
1886 }
1887}
1888
1889impl Default for SplitTime {
1890 fn default() -> Self {
1891 Self {
1892 time: [0_f32, 0_f32],
1893 tags: Vec::new(),
1894 }
1895 }
1896}
1897
1898impl SplitTime {
1899 #[inline]
1900 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1901 if replace {
1902 self.tags = tags.to_owned();
1903 } else {
1904 for tag in tags {
1905 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1906 self.tags.remove(index);
1907 };
1908 }
1909 self.tags.extend(tags.iter().cloned());
1910 };
1911 self
1912 }
1913}
1914
1915#[derive(Clone, Debug, PartialEq, PartialOrd)]
1917pub enum BackgroundType {
1918 Image(ImageConfig),
1920 CustomRect(CustomRectConfig),
1922}
1923
1924impl Default for BackgroundType {
1925 fn default() -> Self {
1926 BackgroundType::CustomRect(CustomRectConfig::default())
1927 }
1928}
1929
1930#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
1932pub struct Background {
1933 pub background_type: BackgroundType,
1935 pub auto_update: bool,
1937 pub use_background_tags: bool,
1939 pub tags: Vec<[String; 2]>,
1941}
1942
1943impl RustConstructorResource for Background {
1944 fn as_any(&self) -> &dyn Any {
1945 self
1946 }
1947
1948 fn as_any_mut(&mut self) -> &mut dyn Any {
1949 self
1950 }
1951
1952 fn display_display_info(&self) -> Option<DisplayInfo> {
1953 None
1954 }
1955
1956 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
1957
1958 fn display_tags(&self) -> Vec<[String; 2]> {
1959 self.tags.clone()
1960 }
1961
1962 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
1963 if replace {
1964 self.tags = tags.to_owned();
1965 } else {
1966 for tag in tags {
1967 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
1968 self.tags.remove(index);
1969 };
1970 }
1971 self.tags.extend(tags.iter().cloned());
1972 };
1973 }
1974}
1975
1976impl Background {
1977 #[inline]
1978 pub fn background_type(mut self, background_type: &BackgroundType) -> Self {
1979 self.background_type = background_type.clone();
1980 self
1981 }
1982
1983 #[inline]
1984 pub fn auto_update(mut self, auto_update: bool) -> Self {
1985 self.auto_update = auto_update;
1986 self
1987 }
1988
1989 #[inline]
1990 pub fn use_background_tags(mut self, use_background_tags: bool) -> Self {
1991 self.use_background_tags = use_background_tags;
1992 self
1993 }
1994
1995 #[inline]
1996 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
1997 if replace {
1998 self.tags = tags.to_owned();
1999 } else {
2000 for tag in tags {
2001 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
2002 self.tags.remove(index);
2003 };
2004 }
2005 self.tags.extend(tags.iter().cloned());
2006 };
2007 self
2008 }
2009}
2010
2011#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
2013pub enum ScrollLengthMethod {
2014 Fixed(f32),
2016 AutoFit(f32),
2018}
2019
2020#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2022pub enum ClickAim {
2023 Move,
2025 TopResize,
2027 BottomResize,
2029 LeftResize,
2031 RightResize,
2033 LeftTopResize,
2035 RightTopResize,
2037 LeftBottomResize,
2039 RightBottomResize,
2041}
2042
2043#[derive(Debug, Clone, PartialEq, PartialOrd)]
2044pub enum ScrollBarDisplayMethod {
2046 Always(BackgroundType, [f32; 2], f32),
2048 OnlyScroll(BackgroundType, [f32; 2], f32),
2050 Hidden,
2052}
2053
2054#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
2056pub enum PanelMargin {
2057 Vertical([f32; 4], bool),
2059 Horizontal([f32; 4], bool),
2061 None([f32; 4], bool),
2063}
2064
2065#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
2067pub struct PanelLayout {
2068 pub panel_margin: PanelMargin,
2069 pub panel_location: PanelLocation,
2070}
2071
2072#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
2074pub enum PanelLocation {
2075 Absolute([f32; 2]),
2077 Relative([[u32; 2]; 2]),
2079}
2080
2081#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
2083pub struct PanelStorage {
2084 pub id: RustConstructorId,
2086 pub ignore_render_layer: bool,
2088 pub hidden: bool,
2090 pub origin_size: [f32; 2],
2092}
2093
2094#[derive(Debug, Clone, PartialEq, PartialOrd)]
2096pub struct ResourcePanel {
2097 pub resizable: [bool; 4],
2099 pub background: BackgroundType,
2101 pub min_size: [f32; 2],
2103 pub max_size: Option<[f32; 2]>,
2105 pub movable: [bool; 2],
2107 pub scroll_length_method: [Option<ScrollLengthMethod>; 2],
2109 pub scroll_sensitivity: f32,
2111 pub use_smooth_scroll_delta: bool,
2113 pub scroll_bar_display_method: ScrollBarDisplayMethod,
2115 pub layout: PanelLayout,
2117 pub hidden: bool,
2119 pub reverse_scroll_direction: [bool; 2],
2121 pub auto_shrink: [bool; 2],
2123 pub scroll_length: [f32; 2],
2125 pub scroll_progress: [f32; 2],
2127 pub last_frame_mouse_status: Option<([f32; 2], ClickAim, [f32; 2])>,
2129 pub scrolled: [bool; 2],
2131 pub scroll_bar_alpha: [u8; 2],
2133 pub resource_storage: Vec<PanelStorage>,
2135 pub tags: Vec<[String; 2]>,
2137}
2138
2139impl RustConstructorResource for ResourcePanel {
2140 fn as_any(&self) -> &dyn Any {
2141 self
2142 }
2143
2144 fn as_any_mut(&mut self) -> &mut dyn Any {
2145 self
2146 }
2147
2148 fn display_display_info(&self) -> Option<DisplayInfo> {
2149 None
2150 }
2151
2152 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
2153
2154 fn display_tags(&self) -> Vec<[String; 2]> {
2155 self.tags.clone()
2156 }
2157
2158 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
2159 if replace {
2160 self.tags = tags.to_owned();
2161 } else {
2162 for tag in tags {
2163 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
2164 self.tags.remove(index);
2165 };
2166 }
2167 self.tags.extend(tags.iter().cloned());
2168 };
2169 }
2170}
2171
2172impl Default for ResourcePanel {
2173 fn default() -> Self {
2174 Self {
2175 resizable: [true, true, true, true],
2176 background: BackgroundType::default(),
2177 min_size: [10_f32, 10_f32],
2178 max_size: None,
2179 movable: [true, true],
2180 scroll_length_method: [None, None],
2181 scroll_sensitivity: 0_f32,
2182 use_smooth_scroll_delta: true,
2183 scroll_bar_display_method: ScrollBarDisplayMethod::OnlyScroll(
2184 BackgroundType::default(),
2185 [4_f32, 2_f32],
2186 4_f32,
2187 ),
2188 layout: (PanelLayout {
2189 panel_margin: PanelMargin::Vertical([0_f32, 0_f32, 0_f32, 0_f32], false),
2190 panel_location: PanelLocation::Absolute([0_f32, 0_f32]),
2191 }),
2192 hidden: false,
2193 reverse_scroll_direction: [false, false],
2194 auto_shrink: [true, false],
2195 scroll_length: [0_f32, 0_f32],
2196 scroll_progress: [0_f32, 0_f32],
2197 last_frame_mouse_status: None,
2198 scrolled: [false, false],
2199 scroll_bar_alpha: [0, 0],
2200 resource_storage: Vec::new(),
2201 tags: Vec::new(),
2202 }
2203 }
2204}
2205
2206impl ResourcePanel {
2207 #[inline]
2208 pub fn resizable(mut self, top: bool, bottom: bool, left: bool, right: bool) -> Self {
2209 self.resizable = [top, bottom, left, right];
2210 self
2211 }
2212
2213 #[inline]
2214 pub fn background(mut self, background: &BackgroundType) -> Self {
2215 self.background = background.clone();
2216 self
2217 }
2218
2219 #[inline]
2220 pub fn min_size(mut self, width: f32, height: f32) -> Self {
2221 self.min_size = [width, height];
2222 self
2223 }
2224
2225 #[inline]
2226 pub fn max_size(mut self, max_size: Option<[f32; 2]>) -> Self {
2227 self.max_size = max_size;
2228 self
2229 }
2230
2231 #[inline]
2232 pub fn movable(mut self, horizontal: bool, vertical: bool) -> Self {
2233 self.movable = [horizontal, vertical];
2234 self
2235 }
2236
2237 #[inline]
2238 pub fn scroll_length_method(
2239 mut self,
2240 horizontal: Option<ScrollLengthMethod>,
2241 vertical: Option<ScrollLengthMethod>,
2242 ) -> Self {
2243 self.scroll_length_method = [horizontal, vertical];
2244 self
2245 }
2246
2247 #[inline]
2248 pub fn scroll_sensitivity(mut self, scroll_sensitivity: f32) -> Self {
2249 self.scroll_sensitivity = scroll_sensitivity;
2250 self
2251 }
2252
2253 #[inline]
2254 pub fn use_smooth_scroll_delta(mut self, use_smooth_scroll_delta: bool) -> Self {
2255 self.use_smooth_scroll_delta = use_smooth_scroll_delta;
2256 self
2257 }
2258
2259 #[inline]
2260 pub fn scroll_bar_display_method(
2261 mut self,
2262 scroll_bar_display_method: ScrollBarDisplayMethod,
2263 ) -> Self {
2264 self.scroll_bar_display_method = scroll_bar_display_method;
2265 self
2266 }
2267
2268 #[inline]
2269 pub fn layout(mut self, layout: PanelLayout) -> Self {
2270 self.layout = layout;
2271 self
2272 }
2273
2274 #[inline]
2275 pub fn hidden(mut self, hidden: bool) -> Self {
2276 self.hidden = hidden;
2277 self
2278 }
2279
2280 #[inline]
2281 pub fn reverse_scroll_direction(mut self, horizontal: bool, vertical: bool) -> Self {
2282 self.reverse_scroll_direction = [horizontal, vertical];
2283 self
2284 }
2285
2286 #[inline]
2287 pub fn auto_shrink(mut self, horizontal: bool, vertical: bool) -> Self {
2288 self.auto_shrink = [horizontal, vertical];
2289 self
2290 }
2291
2292 #[inline]
2293 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
2294 if replace {
2295 self.tags = tags.to_owned();
2296 } else {
2297 for tag in tags {
2298 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
2299 self.tags.remove(index);
2300 };
2301 }
2302 self.tags.extend(tags.iter().cloned());
2303 };
2304 self
2305 }
2306}
2307
2308#[derive(Clone, Debug, Default, PartialEq, PartialOrd)]
2310pub struct SwitchAppearanceConfig {
2311 pub background_config: BackgroundType,
2313 pub text_config: TextConfig,
2315 pub hint_text_config: TextConfig,
2317}
2318
2319#[derive(Debug, Clone, Copy, PartialEq, Eq)]
2321pub struct SwitchClickConfig {
2322 pub click_method: PointerButton,
2324 pub action: bool,
2326}
2327
2328#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2330pub struct SwitchData {
2331 pub switched: bool,
2333 pub last_frame_clicked: Option<usize>,
2335 pub state: u32,
2337}
2338
2339#[derive(Debug, Clone, PartialEq)]
2341pub struct Switch {
2342 pub appearance: Vec<SwitchAppearanceConfig>,
2344 pub background_type: BackgroundType,
2346 pub text_config: TextConfig,
2348 pub hint_text_config: TextConfig,
2350 pub enable_animation: [bool; 2],
2352 pub state_amount: u32,
2354 pub click_method: Vec<SwitchClickConfig>,
2356 pub enable: bool,
2358 pub state: u32,
2360 pub last_frame_hovered: bool,
2362 pub last_frame_clicked: Option<usize>,
2364 pub switched: bool,
2366 pub use_switch_tags: bool,
2368 pub tags: Vec<[String; 2]>,
2370}
2371
2372impl RustConstructorResource for Switch {
2373 fn as_any(&self) -> &dyn Any {
2374 self
2375 }
2376
2377 fn as_any_mut(&mut self) -> &mut dyn Any {
2378 self
2379 }
2380
2381 fn display_display_info(&self) -> Option<DisplayInfo> {
2382 None
2383 }
2384
2385 fn modify_display_info(&mut self, _display_info: DisplayInfo) {}
2386
2387 fn display_tags(&self) -> Vec<[String; 2]> {
2388 self.tags.clone()
2389 }
2390
2391 fn modify_tags(&mut self, tags: &[[String; 2]], replace: bool) {
2392 if replace {
2393 self.tags = tags.to_owned();
2394 } else {
2395 for tag in tags {
2396 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
2397 self.tags.remove(index);
2398 };
2399 }
2400 self.tags.extend(tags.iter().cloned());
2401 };
2402 }
2403}
2404
2405impl Default for Switch {
2406 fn default() -> Self {
2407 Self {
2408 appearance: vec![],
2409 background_type: BackgroundType::default(),
2410 text_config: TextConfig::default(),
2411 hint_text_config: TextConfig::default(),
2412 enable_animation: [false, false],
2413 state_amount: 0,
2414 click_method: vec![],
2415 enable: true,
2416 state: 0,
2417 last_frame_hovered: false,
2418 last_frame_clicked: None,
2419 switched: false,
2420 use_switch_tags: false,
2421 tags: Vec::new(),
2422 }
2423 }
2424}
2425
2426impl Switch {
2427 #[inline]
2428 pub fn appearance(mut self, appearance: &[SwitchAppearanceConfig]) -> Self {
2429 self.appearance = appearance.to_owned();
2430 self
2431 }
2432
2433 #[inline]
2434 pub fn background_type(mut self, background_type: &BackgroundType) -> Self {
2435 self.background_type = background_type.clone();
2436 self
2437 }
2438
2439 #[inline]
2440 pub fn text_config(mut self, text_config: &TextConfig) -> Self {
2441 self.text_config = text_config.clone();
2442 self
2443 }
2444
2445 #[inline]
2446 pub fn hint_text_config(mut self, hint_text_config: &TextConfig) -> Self {
2447 self.hint_text_config = hint_text_config.clone();
2448 self
2449 }
2450
2451 #[inline]
2452 pub fn enable_animation(mut self, enable_hover: bool, enable_click: bool) -> Self {
2453 self.enable_animation = [enable_hover, enable_click];
2454 self
2455 }
2456
2457 #[inline]
2458 pub fn state_amount(mut self, state_amount: u32) -> Self {
2459 self.state_amount = state_amount;
2460 self
2461 }
2462
2463 #[inline]
2464 pub fn click_method(mut self, click_method: Vec<SwitchClickConfig>) -> Self {
2465 self.click_method = click_method;
2466 self
2467 }
2468
2469 #[inline]
2470 pub fn enable(mut self, enable: bool) -> Self {
2471 self.enable = enable;
2472 self
2473 }
2474
2475 #[inline]
2476 pub fn use_switch_tags(mut self, use_switch_tags: bool) -> Self {
2477 self.use_switch_tags = use_switch_tags;
2478 self
2479 }
2480
2481 #[inline]
2482 pub fn tags(mut self, tags: &[[String; 2]], replace: bool) -> Self {
2483 if replace {
2484 self.tags = tags.to_owned();
2485 } else {
2486 for tag in tags {
2487 if let Some(index) = self.tags.iter().position(|x| x[0] == tag[0]) {
2488 self.tags.remove(index);
2489 };
2490 }
2491 self.tags.extend(tags.iter().cloned());
2492 };
2493 self
2494 }
2495}
2496
2497#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2499pub struct RustConstructorError {
2500 pub error_id: String,
2502 pub description: String,
2504}
2505
2506impl Display for RustConstructorError {
2507 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
2508 Debug::fmt(self, f)
2509 }
2510}
2511
2512impl Error for RustConstructorError {}
2513
2514#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2516pub enum HorizontalAlign {
2517 #[default]
2519 Left,
2520 Center,
2522 Right,
2524}
2525
2526#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2528pub enum VerticalAlign {
2529 #[default]
2531 Top,
2532 Center,
2534 Bottom,
2536}
2537
2538#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
2540pub enum RenderConfig {
2541 Line(f32, [u8; 4]),
2542 Rect([u8; 4], [u8; 4], [u8; 4], f32, BorderKind),
2543}
2544
2545#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2547pub struct DisplayInfo {
2548 pub enable: bool,
2550 pub hidden: bool,
2552 pub ignore_render_layer: bool,
2554}
2555
2556#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
2558pub enum RequestMethod {
2559 Id(RustConstructorId),
2561 Citer(RustConstructorId),
2563}
2564
2565#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2567pub enum RequestType {
2568 Top,
2570 Up(u32),
2572}
2573
2574#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
2576pub enum ActiveListInfoMethod {
2577 Detailed(bool),
2579 #[default]
2581 Simple,
2582}
2583
2584#[derive(Debug)]
2586pub struct App {
2587 pub rust_constructor_resource: Vec<RustConstructorResourceBox>,
2589 pub tick_interval: f32,
2591 pub current_page: String,
2593 pub timer: Timer,
2595 pub frame_times: Vec<f32>,
2597 pub last_frame_time: Option<f32>,
2599 pub basic_front_resource_list: Vec<String>,
2601 pub render_layer: Vec<(RustConstructorId, [[f32; 2]; 2], bool)>,
2603 pub active_list: Vec<RustConstructorId>,
2605 pub render_list: Vec<RustConstructorId>,
2607}
2608
2609impl Default for App {
2610 fn default() -> Self {
2611 App {
2612 rust_constructor_resource: Vec::new(),
2613 tick_interval: 0.05,
2614 current_page: String::new(),
2615 timer: Timer::default(),
2616 frame_times: Vec::new(),
2617 last_frame_time: None,
2618 basic_front_resource_list: vec![
2619 String::from("rust_constructor::Image"),
2620 String::from("rust_constructor::Text"),
2621 String::from("rust_constructor::CustomRect"),
2622 ],
2623 render_layer: Vec::new(),
2624 active_list: Vec::new(),
2625 render_list: Vec::new(),
2626 }
2627 }
2628}
2629
2630impl App {
2631 #[inline]
2632 pub fn tick_interval(mut self, tick_interval: f32) -> Self {
2633 self.tick_interval = tick_interval;
2634 self
2635 }
2636
2637 #[inline]
2638 pub fn current_page(mut self, current_page: &str) -> Self {
2639 self.current_page = current_page.to_string();
2640 self
2641 }
2642
2643 pub fn get_tag(&self, tag_name: &str, target: &[[String; 2]]) -> Option<(usize, String)> {
2645 target
2646 .iter()
2647 .position(|x| x[0] == tag_name)
2648 .map(|index| (index, target[index][1].clone()))
2649 }
2650
2651 pub fn draw_resources(&mut self, ui: &mut Ui, ctx: &Context) {
2653 for i in 0..self.render_list.len() {
2654 #[allow(warnings)]
2655 self.draw_resource_by_index(ui, ctx, i);
2656 }
2657 }
2658
2659 pub fn draw_resource_by_index(
2661 &mut self,
2662 ui: &mut Ui,
2663 ctx: &Context,
2664 index: usize,
2665 ) -> Result<(), RustConstructorError> {
2666 if let Some(render_resource) = self.render_list.clone().get(index) {
2667 match &*render_resource.discern_type {
2668 "rust_constructor::Image" => {
2669 let image = self
2670 .get_resource::<Image>(&render_resource.name, "rust_constructor::Image")?;
2671 if image.display_info.enable {
2672 let mut image = image.clone();
2673 if image.cite_texture != image.last_frame_cite_texture {
2674 let image_texture = self.get_resource::<ImageTexture>(
2675 &image.cite_texture,
2676 "rust_constructor::ImageTexture",
2677 )?;
2678 image.texture = image_texture.texture.clone();
2679 };
2680 [image.position, image.size] = self.position_size_processor(
2681 image.basic_front_resource_config.position_size_config,
2682 ctx,
2683 );
2684 if !image.display_info.hidden {
2685 if let Some(clip_rect) = image.basic_front_resource_config.clip_rect {
2686 let [min, size] = self.position_size_processor(clip_rect, ctx);
2687 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
2688 };
2689 if let Some(texture) = &image.texture {
2690 let rect = Rect::from_min_size(
2691 Pos2::new(image.position[0], image.position[1]),
2692 Vec2::new(image.size[0], image.size[1]),
2693 );
2694
2695 egui::Image::new(ImageSource::Texture((&texture.0).into()))
2697 .tint(Color32::from_rgba_unmultiplied(
2698 image.overlay_color[0],
2699 image.overlay_color[1],
2700 image.overlay_color[2],
2701 (image.alpha as f32 * image.overlay_alpha as f32 / 255_f32)
2703 as u8,
2704 ))
2705 .bg_fill(Color32::from_rgba_unmultiplied(
2706 image.background_color[0],
2707 image.background_color[1],
2708 image.background_color[2],
2709 (image.alpha as f32 * image.background_alpha as f32
2710 / 255_f32)
2711 as u8,
2712 ))
2713 .rotate(
2714 image.rotate_angle,
2715 [
2716 image.rotate_center[0] / image.size[0],
2717 image.rotate_center[1] / image.size[1],
2718 ]
2719 .into(),
2720 )
2721 .paint_at(ui, rect)
2722 };
2723 if image.basic_front_resource_config.clip_rect.is_some() {
2724 ui.set_clip_rect(Rect::from_min_size(
2725 [0_f32, 0_f32].into(),
2726 [ctx.available_rect().width(), ctx.available_rect().height()]
2727 .into(),
2728 ));
2729 };
2730 };
2731 image.last_frame_cite_texture = image.cite_texture.clone();
2732 self.replace_resource(&render_resource.name, image)?;
2733 };
2734 }
2735 "rust_constructor::Text" => {
2736 let text =
2737 self.get_resource::<Text>(&render_resource.name, "rust_constructor::Text")?;
2738 if text.display_info.enable {
2739 let mut text = text.clone();
2740 [_, text.truncate_size] = self.position_size_processor(
2741 text.basic_front_resource_config.position_size_config,
2742 ctx,
2743 );
2744 let display_content = if text.content.is_empty()
2745 || text
2746 .basic_front_resource_config
2747 .position_size_config
2748 .origin_size
2749 .contains(&0_f32)
2750 {
2751 "".to_string()
2752 } else {
2753 let original_galley = ui.fonts_mut(|f| {
2754 f.layout(
2755 text.content.to_string(),
2756 FontId::proportional(text.font_size),
2757 Color32::default(),
2758 text.truncate_size[0],
2759 )
2760 });
2761
2762 let mut truncated = text.content.to_string();
2763 let mut ellipsis = "";
2764 if original_galley.size().y > text.truncate_size[1] {
2765 ellipsis = "...";
2767
2768 while !truncated.is_empty() {
2769 let test_text = format!("{}{}", truncated, ellipsis);
2770 let test_galley = ui.fonts_mut(|f| {
2771 f.layout(
2772 test_text,
2773 FontId::proportional(text.font_size),
2774 Color32::default(),
2775 text.truncate_size[0],
2776 )
2777 });
2778
2779 if test_galley.size().y <= text.truncate_size[1] {
2780 break;
2781 }
2782
2783 truncated.pop();
2785 }
2786 };
2787 format!("{}{}", truncated, ellipsis)
2788 };
2789 let galley: Arc<Galley> = ui.fonts_mut(|f| {
2791 f.layout(
2792 display_content.to_string(),
2793 if !text.font.is_empty() {
2794 if self
2795 .check_resource_exists(&text.font, "rust_constructor::Font")
2796 .is_none()
2797 {
2798 FontId::proportional(text.font_size)
2799 } else {
2800 FontId::new(
2801 text.font_size,
2802 FontFamily::Name(text.font.clone().into()),
2803 )
2804 }
2805 } else {
2806 FontId::proportional(text.font_size)
2807 },
2808 Color32::from_rgba_unmultiplied(
2809 text.color[0],
2810 text.color[1],
2811 text.color[2],
2812 text.alpha,
2813 ),
2814 text.truncate_size[0],
2815 )
2816 });
2817 text.size = [
2818 if text.auto_fit[0] {
2819 galley.size().x
2820 } else {
2821 text.truncate_size[0]
2822 },
2823 if text.auto_fit[1] {
2824 galley.size().y
2825 } else {
2826 text.truncate_size[1]
2827 },
2828 ];
2829 text.actual_size = [galley.size().x, galley.size().y];
2830 [text.position, _] = self.position_size_processor(
2831 text.basic_front_resource_config
2832 .position_size_config
2833 .x_size_grid(0_f32, 0_f32)
2834 .y_size_grid(0_f32, 0_f32)
2835 .origin_size(text.size[0], text.size[1]),
2836 ctx,
2837 );
2838 if text.last_frame_content != display_content {
2840 text.hyperlink_index.clear();
2841
2842 let byte_to_char_map: std::collections::HashMap<usize, usize> =
2844 display_content
2845 .char_indices()
2846 .enumerate()
2847 .map(|(char_idx, (byte_idx, _))| (byte_idx, char_idx))
2848 .collect();
2849
2850 for (hyperlink_text, method) in &text.hyperlink_text {
2851 let matches: Vec<(usize, &str)> =
2852 display_content.match_indices(hyperlink_text).collect();
2853 let text_char_count = hyperlink_text.chars().count();
2854
2855 if let HyperlinkSelectMethod::All(url) = method {
2856 for (byte_index, _) in matches {
2857 if let Some(&start_char_index) =
2858 byte_to_char_map.get(&byte_index)
2859 {
2860 text.hyperlink_index.push((
2861 start_char_index,
2862 start_char_index + text_char_count,
2863 url.clone(),
2864 ));
2865 };
2866 }
2867 } else if let HyperlinkSelectMethod::Segment(list) = method {
2868 for (index, url) in list {
2869 if *index >= matches.len() {
2870 continue;
2871 };
2872 let (byte_index, _) = matches[*index];
2873 if let Some(&start_char_index) =
2874 byte_to_char_map.get(&byte_index)
2875 {
2876 text.hyperlink_index.push((
2877 start_char_index,
2878 start_char_index + text_char_count,
2879 url.clone(),
2880 ));
2881 };
2882 }
2883 };
2884 }
2885 };
2886 if !text.display_info.hidden {
2887 let rect =
2889 Rect::from_min_size(text.position.into(), text.actual_size.into());
2890 ui.painter().rect_filled(
2892 rect,
2893 text.background_rounding,
2894 Color32::from_rgba_unmultiplied(
2895 text.background_color[0],
2896 text.background_color[1],
2897 text.background_color[2],
2898 text.background_alpha,
2899 ),
2900 );
2901
2902 if let Some(clip_rect) = text.basic_front_resource_config.clip_rect {
2903 let [min, size] = self.position_size_processor(clip_rect, ctx);
2904 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
2905 };
2906
2907 ui.painter().galley(
2909 text.position.into(),
2910 galley.clone(),
2911 Color32::from_rgba_unmultiplied(
2912 text.color[0],
2913 text.color[1],
2914 text.color[2],
2915 text.alpha,
2916 ),
2917 );
2918
2919 for (start, end, _) in &text.hyperlink_index {
2921 let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
2923 let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
2924
2925 let start_pos = start_cursor.left_top();
2926 let end_pos = end_cursor.right_top();
2927 if start_cursor.min.y == end_cursor.min.y {
2930 let underline_y = text.position[1]
2932 + start_pos.y
2933 + galley.rows.first().map_or(14.0, |row| row.height())
2934 - 2.0;
2935
2936 let color = Color32::from_rgba_unmultiplied(
2938 text.color[0],
2939 text.color[1],
2940 text.color[2],
2941 text.alpha,
2942 );
2943
2944 ui.painter().line_segment(
2945 [
2946 Pos2::new(text.position[0] + start_pos.x, underline_y),
2947 Pos2::new(text.position[0] + end_pos.x, underline_y),
2948 ],
2949 Stroke::new(text.font_size / 10_f32, color),
2950 );
2951 } else {
2952 let row_height =
2954 galley.rows.first().map_or(14.0, |row| row.height()); let start_row = (start_pos.y / row_height).round() as usize;
2958 let end_row = (end_pos.y / row_height).round() as usize;
2959
2960 for row in start_row..=end_row {
2961 let row_y =
2962 text.position[1] + row as f32 * row_height + row_height
2963 - 2.0; if let Some(current_row) = galley.rows.get(row) {
2967 let row_rect = current_row.rect();
2968
2969 let color = Color32::from_rgba_unmultiplied(
2970 text.color[0],
2971 text.color[1],
2972 text.color[2],
2973 text.alpha,
2974 );
2975
2976 if row == start_row {
2977 ui.painter().line_segment(
2979 [
2980 Pos2::new(
2981 text.position[0] + start_pos.x,
2982 row_y,
2983 ),
2984 Pos2::new(
2985 text.position[0] + row_rect.max.x,
2986 row_y,
2987 ),
2988 ],
2989 Stroke::new(text.font_size / 10_f32, color),
2990 );
2991 } else if row == end_row {
2992 ui.painter().line_segment(
2994 [
2995 Pos2::new(
2996 text.position[0] + row_rect.min.x,
2997 row_y,
2998 ),
2999 Pos2::new(
3000 text.position[0] + end_pos.x,
3001 row_y,
3002 ),
3003 ],
3004 Stroke::new(text.font_size / 10_f32, color),
3005 );
3006 } else {
3007 ui.painter().line_segment(
3009 [
3010 Pos2::new(
3011 text.position[0] + row_rect.min.x,
3012 row_y,
3013 ),
3014 Pos2::new(
3015 text.position[0] + row_rect.max.x,
3016 row_y,
3017 ),
3018 ],
3019 Stroke::new(text.font_size / 10_f32, color),
3020 );
3021 };
3022 };
3023 }
3024 };
3025 }
3026
3027 if text.selectable {
3028 let cursor_at_pointer = |pointer_pos: Vec2| -> usize {
3030 let relative_pos = pointer_pos - text.position.into();
3031 let cursor = galley.cursor_from_pos(relative_pos);
3032 cursor.index
3033 };
3034
3035 let fullscreen_detect_result = ui.input(|i| i.pointer.clone());
3036 let rect = Rect::from_min_size(
3037 text.position.into(),
3038 text.actual_size.into(),
3039 );
3040 let detect_result = ui.interact(
3041 rect,
3042 Id::new(&render_resource.name),
3043 Sense::click_and_drag(),
3044 );
3045
3046 if !detect_result.clicked()
3047 && (fullscreen_detect_result.any_click()
3048 || fullscreen_detect_result.any_pressed())
3049 {
3050 text.selection = None;
3051 };
3052
3053 if let Some(index) = self.get_render_layer_resource(
3054 &render_resource.name,
3055 "rust_constructor::Text",
3056 ) && let Some(mouse_pos) =
3057 fullscreen_detect_result.interact_pos()
3058 && self.resource_get_focus(index, mouse_pos.into())
3059 && (detect_result.clicked() || detect_result.drag_started())
3060 {
3061 let cursor = cursor_at_pointer(mouse_pos.to_vec2());
3062 text.selection = Some((cursor, cursor));
3063 };
3064
3065 if detect_result.dragged()
3066 && text.selection.is_some()
3067 && let Some(pointer_pos) =
3068 ui.input(|i| i.pointer.interact_pos())
3069 {
3070 let cursor = cursor_at_pointer(pointer_pos.to_vec2());
3071 if let Some((start, _)) = text.selection {
3072 text.selection = Some((start, cursor));
3073 };
3074 };
3075
3076 if text.selection.is_some()
3077 && ui.input(|input| {
3078 input.key_released(Key::A) && input.modifiers.command
3079 })
3080 {
3081 text.selection = Some((0, display_content.chars().count()));
3082 };
3083
3084 let copy_triggered = ui.input(|input| {
3086 let c_released = input.key_released(Key::C);
3087 let cmd_pressed = input.modifiers.command;
3088 c_released && cmd_pressed
3089 });
3090 if copy_triggered && let Some((start, end)) = text.selection {
3091 let (start, end) = (start.min(end), start.max(end));
3092 let chars: Vec<char> = display_content.chars().collect();
3093 if start <= chars.len() && end <= chars.len() && start < end {
3094 let selected_text: String =
3095 chars[start..end].iter().collect();
3096 ui.ctx().copy_text(selected_text);
3097 };
3098 };
3099
3100 if let Some((start, end)) = text.selection {
3102 let (start, end) = (start.min(end), start.max(end));
3103 if start != end {
3104 let start_cursor =
3106 galley.pos_from_cursor(CCursor::new(start));
3107 let end_cursor = galley.pos_from_cursor(CCursor::new(end));
3108
3109 let start_pos = start_cursor.left_top();
3110 let end_pos = end_cursor.right_top();
3111 if start_pos.y == end_pos.y {
3113 let rows = &galley.rows;
3115 let row_height = if !rows.is_empty() {
3116 if let Some(row) = rows.first() {
3118 row.height()
3119 } else {
3120 text.actual_size[1]
3121 / display_content.lines().count() as f32
3122 }
3123 } else {
3124 text.actual_size[1]
3125 / display_content.lines().count() as f32
3126 };
3127
3128 let selection_rect = Rect::from_min_max(
3129 Pos2::new(
3130 text.position[0] + start_pos.x,
3131 text.position[1] + start_pos.y,
3132 ),
3133 Pos2::new(
3134 text.position[0] + end_pos.x,
3135 text.position[1] + start_pos.y + row_height,
3136 ),
3137 );
3138 ui.painter().rect_filled(
3139 selection_rect,
3140 0.0,
3141 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
3142 );
3143 } else {
3144 let rows = &galley.rows;
3146 let row_height = if !rows.is_empty() {
3147 rows[0].height()
3148 } else {
3149 text.actual_size[1]
3150 / display_content.lines().count() as f32
3151 };
3152
3153 let selection_top =
3155 text.position[1] + start_pos.y.min(end_pos.y);
3156 let selection_bottom =
3157 text.position[1] + start_pos.y.max(end_pos.y);
3158
3159 let start_row_index =
3161 (start_pos.y / row_height).floor() as usize;
3162 let end_row_index =
3163 (end_pos.y / row_height).floor() as usize;
3164 let (first_row_index, last_row_index) =
3165 if start_row_index <= end_row_index {
3166 (start_row_index, end_row_index)
3167 } else {
3168 (end_row_index, start_row_index)
3169 };
3170
3171 for (i, row) in rows.iter().enumerate() {
3172 let row_y =
3173 text.position[1] + row_height * i as f32;
3174 let row_bottom = row_y + row_height;
3175 if row_bottom > selection_top
3177 && row_y <= selection_bottom
3178 {
3179 let left = if i == first_row_index {
3180 text.position[0] + start_pos.x
3182 } else {
3183 text.position[0] + row.rect().min.x
3185 };
3186
3187 let right = if i == last_row_index {
3188 text.position[0] + end_pos.x
3190 } else {
3191 text.position[0] + row.rect().max.x
3193 };
3194
3195 let selection_rect = Rect::from_min_max(
3196 Pos2::new(left, row_y),
3197 Pos2::new(right, row_bottom),
3198 );
3199
3200 if selection_rect.width() > 0.0
3202 && selection_rect.height() > 0.0
3203 {
3204 ui.painter().rect_filled(
3205 selection_rect,
3206 0.0,
3207 Color32::from_rgba_unmultiplied(
3208 0, 120, 255, 100,
3209 ),
3210 );
3211 };
3212 };
3213 }
3214 };
3215 };
3216 };
3217 };
3218
3219 for (start, end, url) in &text.hyperlink_index {
3221 let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
3223 let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
3224
3225 let start_pos = start_cursor.left_top();
3226 let end_pos = end_cursor.right_top();
3227
3228 let row_height =
3229 galley.rows.first().map_or(14.0, |row| row.height());
3230
3231 let link_responses = if start_cursor.min.y == end_cursor.min.y {
3233 let link_rect = Rect::from_min_max(
3235 Pos2::new(
3236 text.position[0] + start_pos.x,
3237 text.position[1] + start_pos.y,
3238 ),
3239 Pos2::new(
3240 text.position[0] + end_pos.x,
3241 text.position[1] + start_pos.y + row_height,
3242 ),
3243 );
3244 vec![ui.interact(
3245 link_rect,
3246 egui::Id::new(format!(
3247 "link_{}_{}_{}",
3248 render_resource.name, start, end
3249 )),
3250 egui::Sense::click(),
3251 )]
3252 } else {
3253 let start_row = (start_pos.y / row_height).round() as usize;
3255 let end_row = (end_pos.y / row_height).round() as usize;
3256 let mut responses = Vec::new();
3257
3258 for row in start_row..=end_row {
3259 if let Some(current_row) = galley.rows.get(row) {
3260 let row_rect = current_row.rect();
3261 let row_y = text.position[1] + row as f32 * row_height;
3262
3263 let link_rect = if row == start_row {
3264 Rect::from_min_max(
3266 Pos2::new(
3267 text.position[0] + start_pos.x,
3268 row_y,
3269 ),
3270 Pos2::new(
3271 text.position[0] + row_rect.max.x,
3272 row_y + row_height,
3273 ),
3274 )
3275 } else if row == end_row {
3276 Rect::from_min_max(
3278 Pos2::new(
3279 text.position[0] + row_rect.min.x,
3280 row_y,
3281 ),
3282 Pos2::new(
3283 text.position[0] + end_pos.x,
3284 row_y + row_height,
3285 ),
3286 )
3287 } else {
3288 Rect::from_min_max(
3290 Pos2::new(
3291 text.position[0] + row_rect.min.x,
3292 row_y,
3293 ),
3294 Pos2::new(
3295 text.position[0] + row_rect.max.x,
3296 row_y + row_height,
3297 ),
3298 )
3299 };
3300
3301 responses.push(ui.interact(
3302 link_rect,
3303 Id::new(format!(
3304 "link_{}_{}_{}_row_{}",
3305 render_resource.name, start, end, row
3306 )),
3307 Sense::click(),
3308 ));
3309 };
3310 }
3311 responses
3312 };
3313
3314 let mut is_pressing_link = false;
3316 for link_response in &link_responses {
3317 if let Some(index) = self.get_render_layer_resource(
3318 &render_resource.name,
3319 "rust_constructor::Text",
3320 ) && let Some(mouse_pos) =
3321 ui.input(|i| i.pointer.interact_pos())
3322 && self.resource_get_focus(index, mouse_pos.into())
3323 {
3324 if link_response.is_pointer_button_down_on()
3325 && !link_response.drag_started()
3326 {
3327 text.selection = None;
3328 if let Some(pointer_pos) =
3329 ui.input(|i| i.pointer.interact_pos())
3330 {
3331 let relative_pos = pointer_pos
3332 - <[f32; 2] as Into<Pos2>>::into(text.position);
3333 let cursor = galley.cursor_from_pos(relative_pos);
3334 if cursor.index >= *start && cursor.index <= *end {
3335 is_pressing_link = true;
3336 break;
3337 };
3338 };
3339 };
3340 let mut clicked_on_link = false;
3342 for link_response in &link_responses {
3343 if link_response.clicked()
3344 && let Some(pointer_pos) =
3345 ui.input(|i| i.pointer.interact_pos())
3346 {
3347 let relative_pos = pointer_pos
3348 - <[f32; 2] as Into<Pos2>>::into(text.position);
3349 let cursor = galley.cursor_from_pos(relative_pos);
3350 if cursor.index >= *start && cursor.index <= *end {
3351 clicked_on_link = true;
3352 break;
3353 };
3354 };
3355 }
3356
3357 if clicked_on_link {
3358 if !url.is_empty() {
3360 ui.ctx().open_url(OpenUrl::new_tab(url));
3361 };
3362 };
3363 };
3364 }
3365
3366 if is_pressing_link {
3368 if start_cursor.min.y == end_cursor.min.y {
3369 let selection_rect = Rect::from_min_max(
3371 Pos2::new(
3372 text.position[0] + start_pos.x,
3373 text.position[1] + start_pos.y,
3374 ),
3375 Pos2::new(
3376 text.position[0] + end_pos.x,
3377 text.position[1]
3378 + start_pos.y
3379 + galley
3380 .rows
3381 .first()
3382 .map_or(14.0, |row| row.height()),
3383 ),
3384 );
3385 ui.painter().rect_filled(
3386 selection_rect,
3387 0.0,
3388 Color32::from_rgba_unmultiplied(0, 120, 255, 100),
3389 );
3390 } else {
3391 let row_height =
3393 galley.rows.first().map_or(14.0, |row| row.height());
3394 let start_row = (start_pos.y / row_height).round() as usize;
3395 let end_row = (end_pos.y / row_height).round() as usize;
3396
3397 for row in start_row..=end_row {
3398 if let Some(current_row) = galley.rows.get(row) {
3399 let row_rect = current_row.rect();
3400
3401 if row == start_row {
3402 let selection_rect = Rect::from_min_max(
3404 Pos2::new(
3405 text.position[0] + start_pos.x,
3406 text.position[1]
3407 + row as f32 * row_height,
3408 ),
3409 Pos2::new(
3410 text.position[0] + row_rect.max.x,
3411 text.position[1]
3412 + row as f32 * row_height
3413 + row_height,
3414 ),
3415 );
3416 ui.painter().rect_filled(
3417 selection_rect,
3418 0.0,
3419 Color32::from_rgba_unmultiplied(
3420 0, 120, 255, 100,
3421 ),
3422 );
3423 } else if row == end_row {
3424 let selection_rect = Rect::from_min_max(
3426 Pos2::new(
3427 text.position[0] + row_rect.min.x,
3428 text.position[1]
3429 + row as f32 * row_height,
3430 ),
3431 Pos2::new(
3432 text.position[0] + end_pos.x,
3433 text.position[1]
3434 + row as f32 * row_height
3435 + row_height,
3436 ),
3437 );
3438 ui.painter().rect_filled(
3439 selection_rect,
3440 0.0,
3441 Color32::from_rgba_unmultiplied(
3442 0, 120, 255, 100,
3443 ),
3444 );
3445 } else {
3446 let selection_rect = Rect::from_min_max(
3448 Pos2::new(
3449 text.position[0] + row_rect.min.x,
3450 text.position[1]
3451 + row as f32 * row_height,
3452 ),
3453 Pos2::new(
3454 text.position[0] + row_rect.max.x,
3455 text.position[1]
3456 + row as f32 * row_height
3457 + row_height,
3458 ),
3459 );
3460 ui.painter().rect_filled(
3461 selection_rect,
3462 0.0,
3463 Color32::from_rgba_unmultiplied(
3464 0, 120, 255, 100,
3465 ),
3466 );
3467 };
3468 };
3469 }
3470 };
3471 };
3472 }
3473 if text.basic_front_resource_config.clip_rect.is_some() {
3474 ui.set_clip_rect(Rect::from_min_size(
3475 [0_f32, 0_f32].into(),
3476 [ctx.available_rect().width(), ctx.available_rect().height()]
3477 .into(),
3478 ));
3479 };
3480 } else {
3481 text.selection = None;
3482 };
3483 text.last_frame_content = display_content;
3484 self.replace_resource(&render_resource.name, text)?;
3485 };
3486 }
3487 "rust_constructor::CustomRect" => {
3488 let custom_rect = self.get_resource::<CustomRect>(
3489 &render_resource.name,
3490 "rust_constructor::CustomRect",
3491 )?;
3492 if custom_rect.display_info.enable {
3493 let mut custom_rect = custom_rect.clone();
3494 [custom_rect.position, custom_rect.size] = self.position_size_processor(
3495 custom_rect.basic_front_resource_config.position_size_config,
3496 ctx,
3497 );
3498 if !custom_rect.display_info.hidden {
3499 if let Some(clip_rect) =
3500 custom_rect.basic_front_resource_config.clip_rect
3501 {
3502 let [min, size] = self.position_size_processor(clip_rect, ctx);
3503 ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
3504 };
3505 ui.painter().rect(
3506 Rect::from_min_max(
3507 Pos2::new(custom_rect.position[0], custom_rect.position[1]),
3508 Pos2::new(
3509 custom_rect.position[0] + custom_rect.size[0],
3510 custom_rect.position[1] + custom_rect.size[1],
3511 ),
3512 ),
3513 custom_rect.rounding,
3514 Color32::from_rgba_unmultiplied(
3515 custom_rect.color[0],
3516 custom_rect.color[1],
3517 custom_rect.color[2],
3518 custom_rect.alpha,
3519 ),
3520 Stroke {
3521 width: custom_rect.border_width,
3522 color: Color32::from_rgba_unmultiplied(
3523 custom_rect.border_color[0],
3524 custom_rect.border_color[1],
3525 custom_rect.border_color[2],
3526 custom_rect.alpha,
3527 ),
3528 },
3529 match custom_rect.border_kind {
3530 BorderKind::Inside => StrokeKind::Inside,
3531 BorderKind::Middle => StrokeKind::Middle,
3532 BorderKind::Outside => StrokeKind::Outside,
3533 },
3534 );
3535 if custom_rect.basic_front_resource_config.clip_rect.is_some() {
3536 ui.set_clip_rect(Rect::from_min_size(
3537 [0_f32, 0_f32].into(),
3538 [ctx.available_rect().width(), ctx.available_rect().height()]
3539 .into(),
3540 ));
3541 };
3542 };
3543 self.replace_resource(&render_resource.name, custom_rect)?;
3544 };
3545 }
3546 _ => {
3547 unreachable!()
3548 }
3549 }
3550 Ok(())
3551 } else {
3552 Err(RustConstructorError {
3553 error_id: "IndexOutOfRange".to_string(),
3554 description: format!(
3555 "The maximum index of the target list is {}, but the index is {index}.",
3556 self.render_list.len() - 1
3557 ),
3558 })
3559 }
3560 }
3561
3562 pub fn active_list_info(&self, method: ActiveListInfoMethod) -> String {
3564 let mut text = String::from("Resource Active Info:\n");
3565 for info in &self.active_list {
3566 if let ActiveListInfoMethod::Detailed(format) = method {
3567 if let Some(index) = self.check_resource_exists(&info.name, &info.discern_type) {
3568 text += &if format {
3569 format!(
3570 "\nName: {}\nType: {}\nDetail: {:#?}\n",
3571 info.name, info.discern_type, self.rust_constructor_resource[index],
3572 )
3573 } else {
3574 format!(
3575 "\nName: {}\nType: {}\nDetail: {:?}\n",
3576 info.name, info.discern_type, self.rust_constructor_resource[index],
3577 )
3578 };
3579 };
3580 } else {
3581 text += &format!("\nName: {}\nType: {}\n", info.name, info.discern_type);
3582 };
3583 }
3584 text
3585 }
3586
3587 pub fn render_layer_info(&self) -> String {
3589 let mut text = String::from("Render Layer Info:\n");
3590 for (
3591 RustConstructorId { name, discern_type },
3592 [min_position, max_position],
3593 ignore_render_layer,
3594 ) in &self.render_layer
3595 {
3596 text += &format!(
3597 "\nName: {:?}\nType: {:?}\nMin Position: {:?}\nMax Position: {:?}\nIgnore Render Layer: {}\n",
3598 name, discern_type, min_position, max_position, ignore_render_layer
3599 );
3600 }
3601 text
3602 }
3603
3604 pub fn render_list_info(&self) -> String {
3606 let mut text = String::from("Render List Info:\n");
3607 for RustConstructorId { name, discern_type } in &self.render_list {
3608 text += &format!("\nName: {:?}\nType: {:?}\n", name, discern_type);
3609 }
3610 text
3611 }
3612
3613 pub fn update_render_list(&mut self) {
3615 if self.render_list.is_empty() {
3616 for info in &self.active_list {
3617 if self.basic_front_resource_list.contains(&info.discern_type) {
3618 self.render_list.push(RustConstructorId {
3619 name: info.name.clone(),
3620 discern_type: info.discern_type.clone(),
3621 });
3622 };
3623 }
3624 } else {
3625 let mut count = 0;
3626 for render_resource in &self.render_list.clone() {
3627 if !self.active_list.contains(render_resource) {
3628 self.render_list.remove(count);
3629 } else {
3630 count += 1;
3631 };
3632 }
3633 let mut insert_index = 0;
3634 for info in &self.active_list {
3635 if self.basic_front_resource_list.contains(&info.discern_type) {
3636 if !self.render_list.contains(info) {
3637 self.render_list.insert(
3638 insert_index,
3639 RustConstructorId {
3640 name: info.name.clone(),
3641 discern_type: info.discern_type.clone(),
3642 },
3643 );
3644 insert_index += 1;
3645 } else if self.render_list[insert_index].cmp(info) == Ordering::Equal {
3646 insert_index += 1;
3647 };
3648 };
3649 }
3650 };
3651 }
3652
3653 pub fn try_request_jump_render_list(
3655 &mut self,
3656 requester: RequestMethod,
3657 request_type: RequestType,
3658 ) {
3659 #[allow(warnings)]
3660 self.request_jump_render_list(requester, request_type);
3661 }
3662
3663 pub fn request_jump_render_list(
3665 &mut self,
3666 requester: RequestMethod,
3667 request_type: RequestType,
3668 ) -> Result<(), RustConstructorError> {
3669 match requester {
3670 RequestMethod::Id(RustConstructorId { name, discern_type }) => {
3671 if let Some(index) = self
3672 .render_list
3673 .iter()
3674 .position(|x| x.name == name && x.discern_type == discern_type)
3675 {
3676 self.jump_render_list_processor(index, request_type)?;
3677 Ok(())
3678 } else {
3679 Err(RustConstructorError {
3680 error_id: "RenderResourceNotFound".to_string(),
3681 description: format!(
3682 "Render resource \"{name}({discern_type})\" not found.",
3683 ),
3684 })
3685 }
3686 }
3687 RequestMethod::Citer(RustConstructorId { name, discern_type }) => {
3688 for (i, render_resource) in self.render_list.iter().enumerate() {
3689 let [resource_name, resource_type] = [
3690 render_resource.name.clone(),
3691 render_resource.discern_type.clone(),
3692 ];
3693 let tags = self
3694 .get_box_resource(&resource_name, &resource_type)?
3695 .display_tags();
3696 if let [Some(tag_name), Some(tag_type)] = [
3697 self.get_tag("citer_name", &tags),
3698 self.get_tag("citer_type", &tags),
3699 ] && tag_name.1 == name
3700 && tag_type.1 == discern_type
3701 {
3702 self.jump_render_list_processor(i, request_type)?;
3703 return Ok(());
3704 };
3705 }
3706 Err(RustConstructorError {
3707 error_id: "RenderResourceNotFound".to_string(),
3708 description: format!("Render resource \"{name}({discern_type})\" not found.",),
3709 })
3710 }
3711 }
3712 }
3713
3714 pub fn jump_render_list_processor(
3716 &mut self,
3717 requester_index: usize,
3718 request_type: RequestType,
3719 ) -> Result<(), RustConstructorError> {
3720 if requester_index < self.render_list.len() {
3721 let requester = self.render_list.remove(requester_index);
3722 let new_index = match request_type {
3723 RequestType::Top => self.render_list.len(),
3724 RequestType::Up(up) => {
3725 if requester_index + up as usize <= self.render_list.len() {
3726 requester_index + up as usize
3727 } else {
3728 self.render_list.len()
3729 }
3730 }
3731 };
3732 self.render_list.insert(new_index, requester);
3733 Ok(())
3734 } else {
3735 Err(RustConstructorError {
3736 error_id: "IndexOutOfRange".to_string(),
3737 description: format!(
3738 "The maximum index of the target list is {}, but the index is {requester_index}.",
3739 self.render_list.len() - 1
3740 ),
3741 })
3742 }
3743 }
3744
3745 pub fn update_render_layer(&mut self) {
3747 self.render_layer.clear();
3748 for info in &self.render_list {
3749 if let Some(index) = self.check_resource_exists(&info.name, &info.discern_type) {
3750 let basic_front_resource: Box<dyn BasicFrontResource> = match &*info.discern_type {
3751 "rust_constructor::Image" => Box::new(
3752 self.rust_constructor_resource[index]
3753 .content
3754 .as_any()
3755 .downcast_ref::<Image>()
3756 .unwrap()
3757 .clone(),
3758 ),
3759 "rust_constructor::Text" => Box::new(
3760 self.rust_constructor_resource[index]
3761 .content
3762 .as_any()
3763 .downcast_ref::<Text>()
3764 .unwrap()
3765 .clone(),
3766 ),
3767 "rust_constructor::CustomRect" => Box::new(
3768 self.rust_constructor_resource[index]
3769 .content
3770 .as_any()
3771 .downcast_ref::<CustomRect>()
3772 .unwrap()
3773 .clone(),
3774 ),
3775 _ => {
3776 unreachable!()
3777 }
3778 };
3779 if let Some(display_info) = basic_front_resource.display_display_info() {
3780 self.render_layer.push((
3781 info.clone(),
3782 [
3783 basic_front_resource.display_position(),
3784 [
3785 basic_front_resource.display_position()[0]
3786 + basic_front_resource.display_size()[0],
3787 basic_front_resource.display_position()[1]
3788 + basic_front_resource.display_size()[1],
3789 ],
3790 ],
3791 display_info.ignore_render_layer,
3792 ));
3793 };
3794 };
3795 }
3796 }
3797
3798 pub fn display_render_layer(
3800 &self,
3801 ui: &mut Ui,
3802 render_config: &RenderConfig,
3803 ignore_render_config: &RenderConfig,
3804 ) {
3805 for (_, point, ignore_render_layer) in &self.render_layer {
3806 match if *ignore_render_layer {
3807 ignore_render_config
3808 } else {
3809 render_config
3810 } {
3811 RenderConfig::Rect(
3812 corner_radius,
3813 fill_color,
3814 border_color,
3815 border_width,
3816 border_kind,
3817 ) => {
3818 let rect = Rect::from_min_max(point[0].into(), point[1].into());
3819 ui.painter().rect(
3820 rect,
3821 CornerRadius {
3822 nw: corner_radius[0],
3823 ne: corner_radius[1],
3824 sw: corner_radius[2],
3825 se: corner_radius[3],
3826 },
3827 Color32::from_rgba_unmultiplied(
3828 fill_color[0],
3829 fill_color[1],
3830 fill_color[2],
3831 fill_color[3],
3832 ),
3833 Stroke::new(
3834 *border_width,
3835 Color32::from_rgba_unmultiplied(
3836 border_color[0],
3837 border_color[1],
3838 border_color[2],
3839 border_color[3],
3840 ),
3841 ),
3842 match *border_kind {
3843 BorderKind::Inside => StrokeKind::Inside,
3844 BorderKind::Middle => StrokeKind::Middle,
3845 BorderKind::Outside => StrokeKind::Outside,
3846 },
3847 );
3848 }
3849 RenderConfig::Line(width, color) => {
3850 ui.painter().line_segment(
3851 [point[0].into(), point[1].into()],
3852 Stroke::new(
3853 *width,
3854 Color32::from_rgba_unmultiplied(color[0], color[1], color[2], color[3]),
3855 ),
3856 );
3857 }
3858 };
3859 }
3860 }
3861
3862 pub fn get_render_layer_resource(&self, name: &str, discern_type: &str) -> Option<usize> {
3864 self.render_layer
3865 .iter()
3866 .position(|x| x.0.name == name && x.0.discern_type == discern_type)
3867 }
3868
3869 pub fn resource_get_focus(&self, index: usize, mouse_pos: [f32; 2]) -> bool {
3871 for i in index + 1..self.render_layer.len() {
3872 let point = self.render_layer[i].1;
3873 if mouse_pos[0] > point[0][0]
3874 && mouse_pos[1] > point[0][1]
3875 && mouse_pos[0] < point[1][0]
3876 && mouse_pos[1] < point[1][1]
3877 && !self.render_layer[i].2
3878 {
3879 return false;
3880 };
3881 }
3882 true
3883 }
3884
3885 pub fn add_active_resource(
3887 &mut self,
3888 name: &str,
3889 discern_type: &str,
3890 ) -> Result<(), RustConstructorError> {
3891 if self.check_resource_exists(name, discern_type).is_some() {
3892 self.active_list.push(RustConstructorId {
3893 name: name.to_string(),
3894 discern_type: discern_type.to_string(),
3895 });
3896 Ok(())
3897 } else {
3898 Err(RustConstructorError {
3899 error_id: "ResourceNotFound".to_string(),
3900 description: format!("Resource \"{name}({discern_type})\" not found."),
3901 })
3902 }
3903 }
3904
3905 pub fn add_resource<T: RustConstructorResource + 'static>(
3907 &mut self,
3908 name: &str,
3909 mut resource: T,
3910 ) -> Result<(), RustConstructorError> {
3911 let discern_type = if let Some(list) = type_name_of_val(&resource).split_once("<") {
3912 list.0
3913 } else {
3914 type_name_of_val(&resource)
3915 };
3916 if self.check_resource_exists(name, discern_type).is_some() {
3917 return Err(RustConstructorError {
3918 error_id: "ResourceNameRepetition".to_string(),
3919 description: format!("Resource \"{name}({discern_type})\" has already existed."),
3920 });
3921 };
3922 if name.is_empty() {
3923 return Err(RustConstructorError {
3924 error_id: "ResourceUntitled".to_string(),
3925 description: "All resources must have a valid name.".to_string(),
3926 });
3927 };
3928 match discern_type {
3929 "rust_constructor::SplitTime" => {
3930 if let Some(split_time) = resource.as_any_mut().downcast_mut::<SplitTime>() {
3931 split_time.time = [self.timer.now_time, self.timer.total_time];
3932 };
3933 }
3934 "rust_constructor::ImageTexture" => {
3935 if let Some(image_texture) = resource.as_any_mut().downcast_mut::<ImageTexture>() {
3936 if let Ok(mut file) = File::open(&image_texture.cite_path) {
3937 let mut buffer = Vec::new();
3938 file.read_to_end(&mut buffer).unwrap();
3939 let img_bytes = buffer;
3940 let img = image::load_from_memory(&img_bytes).unwrap();
3941 let color_data = match image_texture.flip {
3942 [true, true] => img.fliph().flipv().into_rgba8(),
3943 [true, false] => img.fliph().into_rgba8(),
3944 [false, true] => img.flipv().into_rgba8(),
3945 _ => img.into_rgba8(),
3946 };
3947 let (w, h) = (color_data.width(), color_data.height());
3948 let raw_data: Vec<u8> = color_data.into_raw();
3949
3950 let color_image =
3951 ColorImage::from_rgba_unmultiplied([w as usize, h as usize], &raw_data);
3952 let loaded_image_texture = image_texture.context.load_texture(
3953 name,
3954 color_image,
3955 TextureOptions::LINEAR,
3956 );
3957 image_texture.texture =
3958 Some(DebugTextureHandle::new(&loaded_image_texture));
3959 image_texture.cite_path = image_texture.cite_path.to_string();
3960 } else {
3961 return Err(RustConstructorError {
3962 error_id: "ImageLoadFailed".to_string(),
3963 description: format!(
3964 "Failed to load an image from the path \"{}\".",
3965 image_texture.cite_path
3966 ),
3967 });
3968 };
3969 };
3970 }
3971 "rust_constructor::Image" => {
3972 if let Some(image) = resource.as_any_mut().downcast_mut::<Image>() {
3973 let image_texture = self.get_resource::<ImageTexture>(
3974 &image.cite_texture,
3975 "rust_constructor::ImageTexture",
3976 )?;
3977 image.texture = image_texture.texture.clone();
3978 image.last_frame_cite_texture = image.cite_texture.clone();
3979 };
3980 }
3981 "rust_constructor::Font" => {
3982 if let Some(font) = resource.as_any_mut().downcast_mut::<Font>() {
3983 let mut fonts = FontDefinitions::default();
3984 if let Ok(font_read_data) = read(&font.path) {
3985 let font_data: Arc<Vec<u8>> = Arc::new(font_read_data);
3986 fonts.font_data.insert(
3987 name.to_owned(),
3988 Arc::new(FontData::from_owned(
3989 Arc::try_unwrap(font_data).ok().unwrap(),
3990 )),
3991 );
3992
3993 fonts
3995 .families
3996 .entry(FontFamily::Proportional)
3997 .or_default()
3998 .insert(0, name.to_owned());
3999
4000 fonts
4001 .families
4002 .entry(FontFamily::Monospace)
4003 .or_default()
4004 .insert(0, name.to_owned());
4005
4006 font.font_definitions = fonts;
4007 } else {
4008 return Err(RustConstructorError {
4009 error_id: "FontLoadFailed".to_string(),
4010 description: format!(
4011 "Failed to load a font from the path \"{}\".",
4012 font.path
4013 ),
4014 });
4015 }
4016 };
4017 }
4018 "rust_constructor::Background" => {
4019 if let Some(background) = resource.as_any_mut().downcast_mut::<Background>() {
4020 match &background.background_type {
4021 BackgroundType::CustomRect(config) => {
4022 let mut custom_rect = CustomRect::default().from_config(config);
4023 if background.use_background_tags {
4024 custom_rect.modify_tags(&background.tags, false);
4025 };
4026 self.add_resource(name, custom_rect)
4027 }
4028 BackgroundType::Image(config) => {
4029 let mut image = Image::default().from_config(config);
4030 if background.use_background_tags {
4031 image.modify_tags(&background.tags, false);
4032 };
4033 self.add_resource(name, image)
4034 }
4035 }?;
4036 };
4037 }
4038 "rust_constructor::Switch" => {
4039 if let Some(switch) = resource.as_any_mut().downcast_mut::<Switch>() {
4040 let count = 1 + switch.enable_animation.iter().filter(|x| **x).count();
4041 if switch.appearance.len() != count * switch.state_amount as usize {
4042 return Err(RustConstructorError {
4043 error_id: "SwitchAppearanceConfigMismatch".to_string(),
4044 description: format!(
4045 "Expected {} elements, found {}.",
4046 count * switch.state_amount as usize,
4047 switch.appearance.len()
4048 ),
4049 });
4050 };
4051 self.add_resource(
4052 &format!("{name}Background"),
4053 Background::default()
4054 .background_type(&switch.background_type)
4055 .auto_update(true)
4056 .use_background_tags(true)
4057 .tags(
4058 if switch.use_switch_tags {
4059 &switch.tags
4060 } else {
4061 &[]
4062 },
4063 false,
4064 )
4065 .tags(
4066 &[
4067 ["citer_name".to_string(), name.to_string()],
4068 ["citer_type".to_string(), discern_type.to_string()],
4069 ],
4070 false,
4071 ),
4072 )?;
4073 self.add_resource(
4074 &format!("{name}Text"),
4075 Text::default()
4076 .from_config(&switch.text_config)
4077 .tags(
4078 if switch.use_switch_tags {
4079 &switch.tags
4080 } else {
4081 &[]
4082 },
4083 false,
4084 )
4085 .tags(
4086 &[
4087 ["citer_name".to_string(), name.to_string()],
4088 ["citer_type".to_string(), discern_type.to_string()],
4089 ],
4090 false,
4091 ),
4092 )?;
4093 self.add_resource(
4094 &format!("{name}HintText"),
4095 Text::default()
4096 .from_config(&switch.hint_text_config)
4097 .ignore_render_layer(true)
4098 .hidden(true)
4099 .alpha(0)
4100 .tags(
4101 &[
4102 ["citer_name".to_string(), name.to_string()],
4103 ["citer_type".to_string(), discern_type.to_string()],
4104 ["disable_x_scrolling".to_string(), "".to_string()],
4105 ["disable_y_scrolling".to_string(), "".to_string()],
4106 ],
4107 false,
4108 ),
4109 )?;
4110 self.add_resource(
4111 &format!("{name}StartHoverTime"),
4112 SplitTime::default().tags(
4113 &[
4114 ["citer_name".to_string(), name.to_string()],
4115 ["citer_type".to_string(), discern_type.to_string()],
4116 ],
4117 false,
4118 ),
4119 )?;
4120 self.add_resource(
4121 &format!("{name}HintFadeAnimation"),
4122 SplitTime::default().tags(
4123 &[
4124 ["citer_name".to_string(), name.to_string()],
4125 ["citer_type".to_string(), discern_type.to_string()],
4126 ],
4127 false,
4128 ),
4129 )?;
4130 };
4131 }
4132 "rust_constructor::ResourcePanel" => {
4133 if let Some(resource_panel) = resource.as_any_mut().downcast_mut::<ResourcePanel>()
4134 {
4135 self.add_resource(
4136 &format!("{name}Background"),
4137 Background::default()
4138 .background_type(&resource_panel.background)
4139 .auto_update(true)
4140 .use_background_tags(true)
4141 .tags(
4142 &[
4143 ["citer_name".to_string(), name.to_string()],
4144 ["citer_type".to_string(), discern_type.to_string()],
4145 ],
4146 false,
4147 ),
4148 )?;
4149 if let ScrollBarDisplayMethod::Always(_, _, _) =
4150 &resource_panel.scroll_bar_display_method
4151 {
4152 self.add_resource(
4153 &format!("{name}XScroll"),
4154 Background::default()
4155 .auto_update(true)
4156 .use_background_tags(true)
4157 .tags(
4158 &[
4159 ["citer_name".to_string(), name.to_string()],
4160 ["citer_type".to_string(), discern_type.to_string()],
4161 ],
4162 false,
4163 ),
4164 )?;
4165 self.add_resource(
4166 &format!("{name}YScroll"),
4167 Background::default()
4168 .auto_update(true)
4169 .use_background_tags(true)
4170 .tags(
4171 &[
4172 ["citer_name".to_string(), name.to_string()],
4173 ["citer_type".to_string(), discern_type.to_string()],
4174 ],
4175 false,
4176 ),
4177 )?;
4178 };
4179 if let ScrollBarDisplayMethod::OnlyScroll(_, _, _) =
4180 &resource_panel.scroll_bar_display_method
4181 {
4182 self.add_resource(
4183 &format!("{name}XScroll"),
4184 Background::default()
4185 .auto_update(true)
4186 .use_background_tags(true)
4187 .tags(
4188 &[
4189 ["citer_name".to_string(), name.to_string()],
4190 ["citer_type".to_string(), discern_type.to_string()],
4191 ],
4192 false,
4193 ),
4194 )?;
4195 self.add_resource(
4196 &format!("{name}YScroll"),
4197 Background::default()
4198 .auto_update(true)
4199 .use_background_tags(true)
4200 .tags(
4201 &[
4202 ["citer_name".to_string(), name.to_string()],
4203 ["citer_type".to_string(), discern_type.to_string()],
4204 ],
4205 false,
4206 ),
4207 )?;
4208 self.add_resource(
4209 &format!("{name}ScrollBarXAlpha"),
4210 SplitTime::default().tags(
4211 &[
4212 ["citer_name".to_string(), name.to_string()],
4213 ["citer_type".to_string(), discern_type.to_string()],
4214 ],
4215 false,
4216 ),
4217 )?;
4218 self.add_resource(
4219 &format!("{name}ScrollBarXAlphaStart"),
4220 SplitTime::default().tags(
4221 &[
4222 ["citer_name".to_string(), name.to_string()],
4223 ["citer_type".to_string(), discern_type.to_string()],
4224 ],
4225 false,
4226 ),
4227 )?;
4228 self.add_resource(
4229 &format!("{name}ScrollBarYAlpha"),
4230 SplitTime::default().tags(
4231 &[
4232 ["citer_name".to_string(), name.to_string()],
4233 ["citer_type".to_string(), discern_type.to_string()],
4234 ],
4235 false,
4236 ),
4237 )?;
4238 self.add_resource(
4239 &format!("{name}ScrollBarYAlphaStart"),
4240 SplitTime::default().tags(
4241 &[
4242 ["citer_name".to_string(), name.to_string()],
4243 ["citer_type".to_string(), discern_type.to_string()],
4244 ],
4245 false,
4246 ),
4247 )?;
4248 };
4249 };
4250 }
4251 _ => {}
4252 };
4253 self.rust_constructor_resource
4254 .push(RustConstructorResourceBox::new(
4255 name,
4256 discern_type,
4257 Box::new(resource),
4258 ));
4259 Ok(())
4260 }
4261
4262 pub fn drop_resource(
4264 &mut self,
4265 name: &str,
4266 discern_type: &str,
4267 ) -> Result<(), RustConstructorError> {
4268 if let Some(index) = self.check_resource_exists(name, discern_type) {
4269 self.rust_constructor_resource.remove(index);
4270 if let Some(index) = self
4271 .active_list
4272 .iter()
4273 .position(|x| x.name == name && x.discern_type == discern_type)
4274 {
4275 self.active_list.remove(index);
4276 };
4277 if let Some(index) = self
4278 .render_layer
4279 .iter()
4280 .position(|x| x.0.name == name && x.0.discern_type == discern_type)
4281 {
4282 self.render_layer.remove(index);
4283 };
4284 Ok(())
4285 } else {
4286 Err(RustConstructorError {
4287 error_id: "ResourceNotFound".to_string(),
4288 description: format!("Resource \"{name}({discern_type})\" not found."),
4289 })
4290 }
4291 }
4292
4293 pub fn replace_resource<T>(
4295 &mut self,
4296 name: &str,
4297 resource: T,
4298 ) -> Result<(), RustConstructorError>
4299 where
4300 T: RustConstructorResource + 'static,
4301 {
4302 let discern_type = if let Some(list) = type_name_of_val(&resource).split_once("<") {
4303 list.0
4304 } else {
4305 type_name_of_val(&resource)
4306 };
4307 if let Some(index) = self.check_resource_exists(name, discern_type) {
4308 self.rust_constructor_resource[index] =
4309 RustConstructorResourceBox::new(name, discern_type, Box::new(resource));
4310 Ok(())
4311 } else {
4312 Err(RustConstructorError {
4313 error_id: "ResourceNotFound".to_string(),
4314 description: format!("Resource \"{name}({discern_type})\" not found."),
4315 })
4316 }
4317 }
4318
4319 pub fn get_box_resource(
4321 &self,
4322 name: &str,
4323 discern_type: &str,
4324 ) -> Result<&dyn RustConstructorResource, RustConstructorError> {
4325 if let Some(index) = self.check_resource_exists(name, discern_type) {
4326 Ok(&*self.rust_constructor_resource[index].content)
4327 } else {
4328 Err(RustConstructorError {
4329 error_id: "ResourceNotFound".to_string(),
4330 description: format!("Resource \"{name}({discern_type})\" not found."),
4331 })
4332 }
4333 }
4334
4335 pub fn get_box_resource_mut(
4337 &mut self,
4338 name: &str,
4339 discern_type: &str,
4340 ) -> Result<&mut dyn RustConstructorResource, RustConstructorError> {
4341 if let Some(index) = self.check_resource_exists(name, discern_type) {
4342 Ok(&mut *self.rust_constructor_resource[index].content)
4343 } else {
4344 Err(RustConstructorError {
4345 error_id: "ResourceNotFound".to_string(),
4346 description: format!("Resource \"{name}({discern_type})\" not found."),
4347 })
4348 }
4349 }
4350
4351 pub fn get_resource<T>(
4353 &self,
4354 name: &str,
4355 discern_type: &str,
4356 ) -> Result<&T, RustConstructorError>
4357 where
4358 T: RustConstructorResource + 'static,
4359 {
4360 if let Some(resource) = self
4361 .get_box_resource(name, discern_type)?
4362 .as_any()
4363 .downcast_ref::<T>()
4364 {
4365 Ok(resource)
4366 } else {
4367 Err(RustConstructorError {
4368 error_id: "ResourceGenericMismatch".to_string(),
4369 description: format!(
4370 "The generic type of the resource \"{name}({discern_type})\" is mismatched."
4371 ),
4372 })
4373 }
4374 }
4375
4376 pub fn get_resource_mut<T>(
4378 &mut self,
4379 name: &str,
4380 discern_type: &str,
4381 ) -> Result<&mut T, RustConstructorError>
4382 where
4383 T: RustConstructorResource + 'static,
4384 {
4385 if let Some(resource) = self
4386 .get_box_resource_mut(name, discern_type)?
4387 .as_any_mut()
4388 .downcast_mut::<T>()
4389 {
4390 Ok(resource)
4391 } else {
4392 Err(RustConstructorError {
4393 error_id: "ResourceGenericMismatch".to_string(),
4394 description: format!(
4395 "The generic type of the resource \"{name}({discern_type})\" is mismatched."
4396 ),
4397 })
4398 }
4399 }
4400
4401 pub fn check_resource_exists(&self, name: &str, discern_type: &str) -> Option<usize> {
4403 self.rust_constructor_resource
4404 .iter()
4405 .position(|x| x.id.name == name && x.id.discern_type == discern_type)
4406 }
4407
4408 pub fn quick_place<T: RustConstructorResource + 'static>(
4410 &mut self,
4411 name: &str,
4412 resource: T,
4413 ui: &mut Ui,
4414 ctx: &Context,
4415 ) -> Result<(), RustConstructorError> {
4416 let discern_type = if let Some(list) = type_name_of_val(&resource).split_once("<") {
4417 list.0
4418 } else {
4419 type_name_of_val(&resource)
4420 };
4421 if self.check_resource_exists(name, discern_type).is_none() {
4422 self.add_resource(name, resource)
4423 } else {
4424 self.use_resource(name, discern_type, ui, ctx)
4425 }
4426 }
4427
4428 pub fn use_resource(
4430 &mut self,
4431 name: &str,
4432 discern_type: &str,
4433 ui: &mut Ui,
4434 ctx: &Context,
4435 ) -> Result<(), RustConstructorError> {
4436 if self.check_resource_exists(name, discern_type).is_some() {
4437 match discern_type {
4438 "rust_constructor::CustomRect"
4439 | "rust_constructor::Text"
4440 | "rust_constructor::Image" => {
4441 self.add_active_resource(name, discern_type)?;
4442 }
4443 "rust_constructor::PageData" => {
4444 self.update_frame_stats();
4446 self.update_render_list();
4448 for i in 0..self.render_list.len() {
4450 self.draw_resource_by_index(ui, ctx, i)?;
4451 }
4452 self.update_render_layer();
4454 self.active_list.clear();
4456 for rcr in &mut self.rust_constructor_resource {
4458 if let Some(display_info) = &mut rcr.content.display_display_info() {
4459 rcr.content.modify_display_info(DisplayInfo {
4460 enable: true,
4461 hidden: display_info.hidden,
4462 ignore_render_layer: display_info.ignore_render_layer,
4463 });
4464 };
4465 }
4466 self.update_timer();
4468 let current_page = &self.current_page.clone();
4469 let page_data =
4470 self.get_resource::<PageData>(current_page, "rust_constructor::PageData")?;
4471 if page_data.forced_update {
4472 ctx.request_repaint();
4473 };
4474 }
4475 "rust_constructor::Background" => {
4476 let background = self.get_resource::<Background>(name, discern_type)?.clone();
4477 if background.auto_update {
4478 match &background.background_type {
4479 BackgroundType::CustomRect(config) => {
4480 let mut custom_rect = self
4481 .get_resource::<CustomRect>(
4482 name,
4483 "rust_constructor::CustomRect",
4484 )?
4485 .clone()
4486 .from_config(config);
4487 if background.use_background_tags {
4488 custom_rect.modify_tags(&background.tags, false);
4489 };
4490 self.replace_resource(name, custom_rect)?;
4491 }
4492 BackgroundType::Image(config) => {
4493 let mut image = self
4494 .get_resource::<Image>(name, "rust_constructor::Image")?
4495 .clone()
4496 .from_config(config);
4497 if background.use_background_tags {
4498 image.modify_tags(&background.tags, false);
4499 };
4500 self.replace_resource(name, image)?;
4501 }
4502 };
4503 };
4504 match background.background_type {
4505 BackgroundType::CustomRect(_) => {
4506 self.use_resource(name, "rust_constructor::CustomRect", ui, ctx)
4507 }
4508 BackgroundType::Image(_) => {
4509 self.use_resource(name, "rust_constructor::Image", ui, ctx)
4510 }
4511 }?;
4512 }
4513 "rust_constructor::Switch" => {
4514 let mut switch = self
4515 .get_resource::<Switch>(name, "rust_constructor::Switch")?
4516 .clone();
4517 let mut background = self
4518 .get_resource::<Background>(
4519 &format!("{name}Background"),
4520 "rust_constructor::Background",
4521 )?
4522 .clone();
4523 let background_resource_type = match switch.background_type {
4524 BackgroundType::CustomRect(_) => "rust_constructor::CustomRect",
4525 BackgroundType::Image(_) => "rust_constructor::Image",
4526 };
4527 let background_resource: Box<dyn BasicFrontResource> =
4528 match background_resource_type {
4529 "rust_constructor::CustomRect" => Box::new(
4530 self.get_resource::<CustomRect>(
4531 &format!("{name}Background"),
4532 background_resource_type,
4533 )?
4534 .clone(),
4535 ),
4536 "rust_constructor::Image" => Box::new(
4537 self.get_resource::<Image>(
4538 &format!("{name}Background"),
4539 background_resource_type,
4540 )?
4541 .clone(),
4542 ),
4543 _ => {
4544 unreachable!()
4545 }
4546 };
4547 let mut text = self
4548 .get_resource::<Text>(&format!("{name}Text"), "rust_constructor::Text")?
4549 .clone();
4550 let mut hint_text = self
4551 .get_resource::<Text>(&format!("{name}HintText"), "rust_constructor::Text")?
4552 .clone();
4553 let rect = Rect::from_min_size(
4554 background_resource.display_position().into(),
4555 background_resource.display_size().into(),
4556 );
4557 switch.switched = false;
4558 let animation_count =
4559 1 + switch.enable_animation.iter().filter(|x| **x).count();
4560 let mut clicked = None;
4561 let mut hovered = false;
4562 let mut appearance_count = 0;
4563 if let Some(index) = self.get_render_layer_resource(
4565 &format!("{name}Background"),
4566 background_resource_type,
4567 ) && switch.enable
4568 && let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos())
4569 && self.resource_get_focus(index, mouse_pos.into())
4570 && let Some(display_info) = background_resource.display_display_info()
4571 && !display_info.hidden
4572 {
4573 if rect.contains(mouse_pos) {
4575 if !switch.last_frame_hovered {
4576 self.reset_split_time(&format!("{name}StartHoverTime"))?;
4577 } else if self.timer.total_time
4578 - self.get_split_time(&format!("{name}StartHoverTime"))?[1]
4579 >= 2_f32
4580 || hint_text.alpha != 0
4581 {
4582 hint_text.alpha = 255;
4583 hint_text
4584 .basic_front_resource_config
4585 .position_size_config
4586 .origin_position = [mouse_pos.x, mouse_pos.y];
4587 };
4588 hint_text
4589 .basic_front_resource_config
4590 .position_size_config
4591 .display_method
4592 .0 = if mouse_pos.x + hint_text.actual_size[0]
4593 <= ctx.available_rect().width()
4594 {
4595 HorizontalAlign::Left
4596 } else {
4597 HorizontalAlign::Right
4598 };
4599 hint_text
4600 .basic_front_resource_config
4601 .position_size_config
4602 .display_method
4603 .1 = if mouse_pos.y + hint_text.actual_size[1]
4604 <= ctx.available_rect().height()
4605 {
4606 VerticalAlign::Top
4607 } else {
4608 VerticalAlign::Bottom
4609 };
4610 hovered = true;
4611 for (count, click_method) in switch.click_method.iter().enumerate() {
4612 if ui.input(|i| {
4613 switch.last_frame_clicked.is_none()
4614 && i.pointer.button_pressed(click_method.click_method)
4615 || switch.last_frame_clicked.is_some()
4616 && i.pointer.button_down(click_method.click_method)
4617 }) {
4618 clicked = Some(count);
4619 break;
4620 };
4621 }
4622 if let Some(clicked_index) = switch.last_frame_clicked
4623 && clicked.is_none()
4624 {
4625 switch.switched = true;
4626 if switch.click_method[clicked_index].action {
4627 if switch.state
4628 < (switch.appearance.len() / animation_count - 1) as u32
4629 {
4630 switch.state += 1;
4631 } else {
4632 switch.state = 0;
4633 };
4634 };
4635 };
4636 appearance_count = if clicked.is_some() {
4637 match switch.enable_animation {
4638 [true, true] => 2,
4639 [true, false] | [false, true] => 1,
4640 [false, false] => 0,
4641 }
4642 } else if switch.enable_animation[0] {
4643 1
4644 } else {
4645 0
4646 };
4647 };
4648 };
4649
4650 if !hovered {
4652 if switch.last_frame_hovered {
4653 self.reset_split_time(&format!("{name}HintFadeAnimation"))?;
4654 };
4655 if self.timer.total_time
4656 - self.get_split_time(&format!("{name}HintFadeAnimation"))?[1]
4657 >= self.tick_interval
4658 {
4659 self.reset_split_time(&format!("{name}HintFadeAnimation"))?;
4660 hint_text.alpha = hint_text.alpha.saturating_sub(10);
4661 };
4662 };
4663
4664 hint_text.display_info.hidden = hint_text.alpha == 0;
4665
4666 background.background_type = switch.appearance
4668 [(switch.state * animation_count as u32 + appearance_count) as usize]
4669 .background_config
4670 .clone();
4671
4672 background.modify_tags(
4673 if switch.use_switch_tags {
4674 &switch.tags
4675 } else {
4676 &[]
4677 },
4678 false,
4679 );
4680
4681 let alpha = hint_text.alpha;
4683 hint_text = hint_text
4684 .from_config(
4685 &switch.appearance[(switch.state * animation_count as u32
4686 + appearance_count)
4687 as usize]
4688 .hint_text_config,
4689 )
4690 .ignore_render_layer(true);
4691 hint_text.background_alpha = alpha;
4692 hint_text.alpha = alpha;
4693 hint_text.display_info.hidden = if let Some(display_info) =
4694 background_resource.display_display_info()
4695 && display_info.hidden
4696 {
4697 true
4698 } else {
4699 hint_text.display_info.hidden
4700 };
4701
4702 text = text
4704 .tags(
4705 if switch.use_switch_tags {
4706 &switch.tags
4707 } else {
4708 &[]
4709 },
4710 false,
4711 )
4712 .from_config(
4713 &switch.appearance[(switch.state * animation_count as u32
4714 + appearance_count)
4715 as usize]
4716 .text_config,
4717 );
4718
4719 switch.last_frame_hovered = hovered;
4720 switch.last_frame_clicked = clicked;
4721
4722 self.replace_resource(&format!("{name}Text"), text)?;
4723 self.replace_resource(&format!("{name}HintText"), hint_text)?;
4724 self.replace_resource(name, switch)?;
4725 self.replace_resource(&format!("{name}Background"), background)?;
4726
4727 self.use_resource(
4728 &format!("{name}Background"),
4729 "rust_constructor::Background",
4730 ui,
4731 ctx,
4732 )?;
4733 self.use_resource(&format!("{name}Text"), "rust_constructor::Text", ui, ctx)?;
4734 if alpha != 0 {
4735 self.use_resource(
4736 &format!("{name}HintText"),
4737 "rust_constructor::Text",
4738 ui,
4739 ctx,
4740 )?;
4741 };
4742 }
4743 "rust_constructor::ResourcePanel" => {
4744 let mut resource_panel = self
4745 .get_resource::<ResourcePanel>(name, "rust_constructor::ResourcePanel")?
4746 .clone();
4747 let background = self
4748 .get_resource::<Background>(
4749 &format!("{name}Background"),
4750 "rust_constructor::Background",
4751 )?
4752 .clone();
4753 let background_resource: Box<dyn BasicFrontResource> =
4754 match background.background_type.clone() {
4755 BackgroundType::CustomRect(_) => Box::new(
4756 self.get_resource::<CustomRect>(
4757 &format!("{name}Background"),
4758 "rust_constructor::CustomRect",
4759 )?
4760 .clone(),
4761 ),
4762 BackgroundType::Image(_) => Box::new(
4763 self.get_resource::<Image>(
4764 &format!("{name}Background"),
4765 "rust_constructor::Image",
4766 )?
4767 .clone(),
4768 ),
4769 };
4770 let (mut position_size_config, mut position, mut size) = (
4771 background_resource
4772 .display_basic_front_resource_config()
4773 .position_size_config,
4774 background_resource.display_position(),
4775 background_resource.display_size(),
4776 );
4777 let rect = Rect::from_min_size(position.into(), size.into());
4778 resource_panel.scrolled = [false, false];
4779 if resource_panel.resizable.contains(&true)
4780 || resource_panel.movable.contains(&true)
4781 {
4782 position_size_config.x_location_grid = [0_f32, 0_f32];
4783 position_size_config.y_location_grid = [0_f32, 0_f32];
4784 position_size_config.x_size_grid = [0_f32, 0_f32];
4785 position_size_config.y_size_grid = [0_f32, 0_f32];
4786 };
4787 if resource_panel.min_size[0] < 10_f32 {
4788 resource_panel.min_size[0] = 10_f32;
4789 };
4790 if resource_panel.min_size[1] < 10_f32 {
4791 resource_panel.min_size[1] = 10_f32;
4792 };
4793 if position_size_config.origin_size[0] < resource_panel.min_size[0] {
4794 position_size_config.origin_size[0] = resource_panel.min_size[0];
4795 };
4796 if position_size_config.origin_size[1] < resource_panel.min_size[1] {
4797 position_size_config.origin_size[1] = resource_panel.min_size[1];
4798 };
4799 [position, size] = self.position_size_processor(position_size_config, ctx);
4800 let scroll_delta: [f32; 2] = if resource_panel.use_smooth_scroll_delta {
4801 ui.input(|i| i.smooth_scroll_delta).into()
4802 } else {
4803 ui.input(|i| i.raw_scroll_delta).into()
4804 };
4805 let [x_scroll_delta, y_scroll_delta] =
4806 if scroll_delta[0].abs() >= scroll_delta[1].abs() {
4807 [
4808 if resource_panel.reverse_scroll_direction[0] {
4809 -scroll_delta[0]
4810 } else {
4811 scroll_delta[0]
4812 },
4813 0_f32,
4814 ]
4815 } else {
4816 [
4817 0_f32,
4818 if resource_panel.reverse_scroll_direction[1] {
4819 -scroll_delta[1]
4820 } else {
4821 scroll_delta[1]
4822 },
4823 ]
4824 };
4825 if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos())
4826 && !resource_panel.hidden
4827 {
4828 if let Some(index) = self.get_render_layer_resource(
4829 &format!("{name}Background"),
4830 match background.background_type {
4831 BackgroundType::CustomRect(_) => "rust_constructor::CustomRect",
4832 BackgroundType::Image(_) => "rust_constructor::Image",
4833 },
4834 ) && self.resource_get_focus(index, mouse_pos.into())
4835 {
4836 if ui.input(|i| i.pointer.primary_pressed())
4837 && Rect::from_min_size(position.into(), size.into())
4838 .contains(mouse_pos)
4839 {
4840 self.request_jump_render_list(
4841 RequestMethod::Id(RustConstructorId {
4842 name: format!("{name}Background"),
4843 discern_type: match background.background_type {
4844 BackgroundType::CustomRect(_) => {
4845 "rust_constructor::CustomRect"
4846 }
4847 BackgroundType::Image(_) => "rust_constructor::Image",
4848 }
4849 .to_string(),
4850 }),
4851 RequestType::Top,
4852 )
4853 .unwrap();
4854 let mut update_list = Vec::new();
4855 for rcr in &self.rust_constructor_resource {
4856 if self
4857 .basic_front_resource_list
4858 .contains(&rcr.id.discern_type)
4859 && let Some(panel_name) =
4860 self.get_tag("panel_name", &rcr.content.display_tags())
4861 && panel_name.1 == name
4862 {
4863 update_list.push(rcr.id.clone());
4864 };
4865 }
4866 for id in update_list {
4867 self.try_request_jump_render_list(
4868 RequestMethod::Id(id),
4869 RequestType::Top,
4870 );
4871 }
4872 if let ScrollBarDisplayMethod::Always(ref background_type, _, _) =
4873 resource_panel.scroll_bar_display_method
4874 {
4875 self.try_request_jump_render_list(
4876 RequestMethod::Id(RustConstructorId {
4877 name: format!("{name}XScroll"),
4878 discern_type: match background_type {
4879 BackgroundType::CustomRect(_) => {
4880 "rust_constructor::CustomRect"
4881 }
4882 BackgroundType::Image(_) => {
4883 "rust_constructor::Image"
4884 }
4885 }
4886 .to_string(),
4887 }),
4888 RequestType::Top,
4889 );
4890 self.try_request_jump_render_list(
4891 RequestMethod::Id(RustConstructorId {
4892 name: format!("{name}YScroll"),
4893 discern_type: match background_type {
4894 BackgroundType::CustomRect(_) => {
4895 "rust_constructor::CustomRect"
4896 }
4897 BackgroundType::Image(_) => {
4898 "rust_constructor::Image"
4899 }
4900 }
4901 .to_string(),
4902 }),
4903 RequestType::Top,
4904 );
4905 };
4906 if let ScrollBarDisplayMethod::OnlyScroll(
4907 ref background_type,
4908 _,
4909 _,
4910 ) = resource_panel.scroll_bar_display_method
4911 {
4912 self.try_request_jump_render_list(
4913 RequestMethod::Id(RustConstructorId {
4914 name: format!("{name}XScroll"),
4915 discern_type: match background_type {
4916 BackgroundType::CustomRect(_) => {
4917 "rust_constructor::CustomRect"
4918 }
4919 BackgroundType::Image(_) => {
4920 "rust_constructor::Image"
4921 }
4922 }
4923 .to_string(),
4924 }),
4925 RequestType::Top,
4926 );
4927 self.try_request_jump_render_list(
4928 RequestMethod::Id(RustConstructorId {
4929 name: format!("{name}YScroll"),
4930 discern_type: match background_type {
4931 BackgroundType::CustomRect(_) => {
4932 "rust_constructor::CustomRect"
4933 }
4934 BackgroundType::Image(_) => {
4935 "rust_constructor::Image"
4936 }
4937 }
4938 .to_string(),
4939 }),
4940 RequestType::Top,
4941 );
4942 };
4943 };
4944 let top_rect = Rect::from_min_size(
4945 [position[0], position[1]].into(),
4946 [size[0], 3_f32].into(),
4947 );
4948 let bottom_rect = Rect::from_min_size(
4949 [position[0], position[1] + size[1] - 3_f32].into(),
4950 [size[0], 3_f32].into(),
4951 );
4952 let left_rect = Rect::from_min_size(
4953 [position[0], position[1]].into(),
4954 [3_f32, size[1]].into(),
4955 );
4956 let right_rect = Rect::from_min_size(
4957 [position[0] + size[0] - 3_f32, position[1]].into(),
4958 [3_f32, size[1]].into(),
4959 );
4960 match [
4961 top_rect.contains(mouse_pos),
4962 bottom_rect.contains(mouse_pos),
4963 left_rect.contains(mouse_pos),
4964 right_rect.contains(mouse_pos),
4965 ] {
4966 [true, false, false, false] => {
4967 if resource_panel.resizable[0] {
4968 if resource_panel.last_frame_mouse_status.is_none()
4969 && ui.input(|i| i.pointer.primary_pressed())
4970 {
4971 resource_panel.last_frame_mouse_status = Some((
4972 mouse_pos.into(),
4973 ClickAim::TopResize,
4974 [
4975 mouse_pos.x - position[0],
4976 mouse_pos.y - position[1],
4977 ],
4978 ))
4979 };
4980 if size[1] > resource_panel.min_size[1]
4981 && (resource_panel.max_size.is_none()
4982 || size[1] < resource_panel.max_size.unwrap()[1])
4983 {
4984 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
4985 } else if resource_panel.max_size.is_some()
4986 && size[1] >= resource_panel.max_size.unwrap()[1]
4987 {
4988 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
4989 } else {
4990 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
4991 };
4992 };
4993 }
4994 [false, true, false, false] => {
4995 if resource_panel.resizable[1] {
4996 if resource_panel.last_frame_mouse_status.is_none()
4997 && ui.input(|i| i.pointer.primary_pressed())
4998 {
4999 resource_panel.last_frame_mouse_status = Some((
5000 mouse_pos.into(),
5001 ClickAim::BottomResize,
5002 [
5003 mouse_pos.x - position[0],
5004 mouse_pos.y - position[1],
5005 ],
5006 ))
5007 };
5008 if size[1] > resource_panel.min_size[1]
5009 && (resource_panel.max_size.is_none()
5010 || size[1] < resource_panel.max_size.unwrap()[1])
5011 {
5012 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5013 } else if resource_panel.max_size.is_some()
5014 && size[1] >= resource_panel.max_size.unwrap()[1]
5015 {
5016 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5017 } else {
5018 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5019 };
5020 };
5021 }
5022 [false, false, true, false] => {
5023 if resource_panel.resizable[2] {
5024 if resource_panel.last_frame_mouse_status.is_none()
5025 && ui.input(|i| i.pointer.primary_pressed())
5026 {
5027 resource_panel.last_frame_mouse_status = Some((
5028 mouse_pos.into(),
5029 ClickAim::LeftResize,
5030 [
5031 mouse_pos.x - position[0],
5032 mouse_pos.y - position[1],
5033 ],
5034 ))
5035 };
5036 if size[0] > resource_panel.min_size[0]
5037 && (resource_panel.max_size.is_none()
5038 || size[0] < resource_panel.max_size.unwrap()[0])
5039 {
5040 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5041 } else if resource_panel.max_size.is_some()
5042 && size[0] >= resource_panel.max_size.unwrap()[0]
5043 {
5044 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5045 } else {
5046 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5047 };
5048 };
5049 }
5050 [false, false, false, true] => {
5051 if resource_panel.resizable[3] {
5052 if resource_panel.last_frame_mouse_status.is_none()
5053 && ui.input(|i| i.pointer.primary_pressed())
5054 {
5055 resource_panel.last_frame_mouse_status = Some((
5056 mouse_pos.into(),
5057 ClickAim::RightResize,
5058 [
5059 mouse_pos.x - position[0],
5060 mouse_pos.y - position[1],
5061 ],
5062 ))
5063 };
5064 if size[0] > resource_panel.min_size[0]
5065 && (resource_panel.max_size.is_none()
5066 || size[0] < resource_panel.max_size.unwrap()[0])
5067 {
5068 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5069 } else if resource_panel.max_size.is_some()
5070 && size[0] >= resource_panel.max_size.unwrap()[0]
5071 {
5072 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5073 } else {
5074 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5075 };
5076 };
5077 }
5078 [true, false, true, false] => {
5079 match [resource_panel.resizable[0], resource_panel.resizable[2]]
5080 {
5081 [true, true] => {
5082 if resource_panel.last_frame_mouse_status.is_none()
5083 && ui.input(|i| i.pointer.primary_pressed())
5084 {
5085 resource_panel.last_frame_mouse_status = Some((
5086 mouse_pos.into(),
5087 ClickAim::LeftTopResize,
5088 [
5089 mouse_pos.x - position[0],
5090 mouse_pos.y - position[1],
5091 ],
5092 ))
5093 };
5094 if size[0] > resource_panel.min_size[0]
5095 && (resource_panel.max_size.is_none()
5096 || size[0]
5097 < resource_panel.max_size.unwrap()[0])
5098 || size[1] > resource_panel.min_size[1]
5099 && (resource_panel.max_size.is_none()
5100 || size[1]
5101 < resource_panel.max_size.unwrap()[1])
5102 {
5103 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
5104 } else if resource_panel.max_size.is_some()
5105 && size[0] >= resource_panel.max_size.unwrap()[0]
5106 && size[1] >= resource_panel.max_size.unwrap()[1]
5107 {
5108 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast);
5109 } else {
5110 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest)
5111 };
5112 }
5113 [false, true] => {
5114 if resource_panel.last_frame_mouse_status.is_none()
5115 && ui.input(|i| i.pointer.primary_pressed())
5116 {
5117 resource_panel.last_frame_mouse_status = Some((
5118 mouse_pos.into(),
5119 ClickAim::LeftResize,
5120 [
5121 mouse_pos.x - position[0],
5122 mouse_pos.y - position[1],
5123 ],
5124 ))
5125 };
5126 if size[0] > resource_panel.min_size[0]
5127 && (resource_panel.max_size.is_none()
5128 || size[0]
5129 < resource_panel.max_size.unwrap()[0])
5130 {
5131 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5132 } else if resource_panel.max_size.is_some()
5133 && size[0] >= resource_panel.max_size.unwrap()[0]
5134 {
5135 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5136 } else {
5137 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5138 };
5139 }
5140 [true, false] => {
5141 if resource_panel.last_frame_mouse_status.is_none()
5142 && ui.input(|i| i.pointer.primary_pressed())
5143 {
5144 resource_panel.last_frame_mouse_status = Some((
5145 mouse_pos.into(),
5146 ClickAim::TopResize,
5147 [
5148 mouse_pos.x - position[0],
5149 mouse_pos.y - position[1],
5150 ],
5151 ))
5152 };
5153 if size[1] > resource_panel.min_size[1]
5154 && (resource_panel.max_size.is_none()
5155 || size[1]
5156 < resource_panel.max_size.unwrap()[1])
5157 {
5158 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5159 } else if resource_panel.max_size.is_some()
5160 && size[1] >= resource_panel.max_size.unwrap()[1]
5161 {
5162 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5163 } else {
5164 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5165 };
5166 }
5167 [false, false] => {}
5168 }
5169 }
5170 [false, true, false, true] => {
5171 match [resource_panel.resizable[1], resource_panel.resizable[3]]
5172 {
5173 [true, true] => {
5174 if resource_panel.last_frame_mouse_status.is_none()
5175 && ui.input(|i| i.pointer.primary_pressed())
5176 {
5177 resource_panel.last_frame_mouse_status = Some((
5178 mouse_pos.into(),
5179 ClickAim::RightBottomResize,
5180 [
5181 mouse_pos.x - position[0],
5182 mouse_pos.y - position[1],
5183 ],
5184 ))
5185 };
5186 if size[0] > resource_panel.min_size[0]
5187 && (resource_panel.max_size.is_none()
5188 || size[0]
5189 < resource_panel.max_size.unwrap()[0])
5190 || size[1] > resource_panel.min_size[1]
5191 && (resource_panel.max_size.is_none()
5192 || size[1]
5193 < resource_panel.max_size.unwrap()[1])
5194 {
5195 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
5196 } else if resource_panel.max_size.is_some()
5197 && size[0] >= resource_panel.max_size.unwrap()[0]
5198 && size[1] >= resource_panel.max_size.unwrap()[1]
5199 {
5200 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest);
5201 } else {
5202 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast)
5203 };
5204 }
5205 [false, true] => {
5206 if resource_panel.last_frame_mouse_status.is_none()
5207 && ui.input(|i| i.pointer.primary_pressed())
5208 {
5209 resource_panel.last_frame_mouse_status = Some((
5210 mouse_pos.into(),
5211 ClickAim::RightResize,
5212 [
5213 mouse_pos.x - position[0],
5214 mouse_pos.y - position[1],
5215 ],
5216 ))
5217 };
5218 if size[0] > resource_panel.min_size[0]
5219 && (resource_panel.max_size.is_none()
5220 || size[0]
5221 < resource_panel.max_size.unwrap()[0])
5222 {
5223 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5224 } else if resource_panel.max_size.is_some()
5225 && size[0] >= resource_panel.max_size.unwrap()[0]
5226 {
5227 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5228 } else {
5229 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5230 };
5231 }
5232 [true, false] => {
5233 if resource_panel.last_frame_mouse_status.is_none()
5234 && ui.input(|i| i.pointer.primary_pressed())
5235 {
5236 resource_panel.last_frame_mouse_status = Some((
5237 mouse_pos.into(),
5238 ClickAim::BottomResize,
5239 [
5240 mouse_pos.x - position[0],
5241 mouse_pos.y - position[1],
5242 ],
5243 ))
5244 };
5245 if size[1] > resource_panel.min_size[1]
5246 && (resource_panel.max_size.is_none()
5247 || size[1]
5248 < resource_panel.max_size.unwrap()[1])
5249 {
5250 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5251 } else if resource_panel.max_size.is_some()
5252 && size[1] >= resource_panel.max_size.unwrap()[1]
5253 {
5254 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5255 } else {
5256 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5257 };
5258 }
5259 [false, false] => {}
5260 }
5261 }
5262 [true, false, false, true] => {
5263 match [resource_panel.resizable[0], resource_panel.resizable[3]]
5264 {
5265 [true, true] => {
5266 if resource_panel.last_frame_mouse_status.is_none()
5267 && ui.input(|i| i.pointer.primary_pressed())
5268 {
5269 resource_panel.last_frame_mouse_status = Some((
5270 mouse_pos.into(),
5271 ClickAim::RightTopResize,
5272 [
5273 mouse_pos.x - position[0],
5274 mouse_pos.y - position[1],
5275 ],
5276 ))
5277 };
5278 if size[0] > resource_panel.min_size[0]
5279 && (resource_panel.max_size.is_none()
5280 || size[0]
5281 < resource_panel.max_size.unwrap()[0])
5282 || size[1] > resource_panel.min_size[1]
5283 && (resource_panel.max_size.is_none()
5284 || size[1]
5285 < resource_panel.max_size.unwrap()[1])
5286 {
5287 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
5288 } else if resource_panel.max_size.is_some()
5289 && size[0] >= resource_panel.max_size.unwrap()[0]
5290 && size[1] >= resource_panel.max_size.unwrap()[1]
5291 {
5292 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest);
5293 } else {
5294 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast)
5295 };
5296 }
5297 [false, true] => {
5298 if resource_panel.last_frame_mouse_status.is_none()
5299 && ui.input(|i| i.pointer.primary_pressed())
5300 {
5301 resource_panel.last_frame_mouse_status = Some((
5302 mouse_pos.into(),
5303 ClickAim::RightResize,
5304 [
5305 mouse_pos.x - position[0],
5306 mouse_pos.y - position[1],
5307 ],
5308 ))
5309 };
5310 if size[0] > resource_panel.min_size[0]
5311 && (resource_panel.max_size.is_none()
5312 || size[0]
5313 < resource_panel.max_size.unwrap()[0])
5314 {
5315 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5316 } else if resource_panel.max_size.is_some()
5317 && size[0] >= resource_panel.max_size.unwrap()[0]
5318 {
5319 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5320 } else {
5321 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5322 };
5323 }
5324 [true, false] => {
5325 if resource_panel.last_frame_mouse_status.is_none()
5326 && ui.input(|i| i.pointer.primary_pressed())
5327 {
5328 resource_panel.last_frame_mouse_status = Some((
5329 mouse_pos.into(),
5330 ClickAim::TopResize,
5331 [
5332 mouse_pos.x - position[0],
5333 mouse_pos.y - position[1],
5334 ],
5335 ))
5336 };
5337 if size[1] > resource_panel.min_size[1]
5338 && (resource_panel.max_size.is_none()
5339 || size[1]
5340 < resource_panel.max_size.unwrap()[1])
5341 {
5342 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5343 } else if resource_panel.max_size.is_some()
5344 && size[1] >= resource_panel.max_size.unwrap()[1]
5345 {
5346 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5347 } else {
5348 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5349 };
5350 }
5351 [false, false] => {}
5352 }
5353 }
5354 [false, true, true, false] => {
5355 match [resource_panel.resizable[1], resource_panel.resizable[2]]
5356 {
5357 [true, true] => {
5358 if resource_panel.last_frame_mouse_status.is_none()
5359 && ui.input(|i| i.pointer.primary_pressed())
5360 {
5361 resource_panel.last_frame_mouse_status = Some((
5362 mouse_pos.into(),
5363 ClickAim::LeftBottomResize,
5364 [
5365 mouse_pos.x - position[0],
5366 mouse_pos.y - position[1],
5367 ],
5368 ))
5369 };
5370 if size[0] > resource_panel.min_size[0]
5371 && (resource_panel.max_size.is_none()
5372 || size[0]
5373 < resource_panel.max_size.unwrap()[0])
5374 || size[1] > resource_panel.min_size[1]
5375 && (resource_panel.max_size.is_none()
5376 || size[1]
5377 < resource_panel.max_size.unwrap()[1])
5378 {
5379 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
5380 } else if resource_panel.max_size.is_some()
5381 && size[0] >= resource_panel.max_size.unwrap()[0]
5382 && size[1] >= resource_panel.max_size.unwrap()[1]
5383 {
5384 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast);
5385 } else {
5386 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest)
5387 };
5388 }
5389 [false, true] => {
5390 if resource_panel.last_frame_mouse_status.is_none()
5391 && ui.input(|i| i.pointer.primary_pressed())
5392 {
5393 resource_panel.last_frame_mouse_status = Some((
5394 mouse_pos.into(),
5395 ClickAim::LeftResize,
5396 [
5397 mouse_pos.x - position[0],
5398 mouse_pos.y - position[1],
5399 ],
5400 ))
5401 };
5402 if size[0] > resource_panel.min_size[0]
5403 && (resource_panel.max_size.is_none()
5404 || size[0]
5405 < resource_panel.max_size.unwrap()[0])
5406 {
5407 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5408 } else if resource_panel.max_size.is_some()
5409 && size[0] >= resource_panel.max_size.unwrap()[0]
5410 {
5411 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5412 } else {
5413 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5414 };
5415 }
5416 [true, false] => {
5417 if resource_panel.last_frame_mouse_status.is_none()
5418 && ui.input(|i| i.pointer.primary_pressed())
5419 {
5420 resource_panel.last_frame_mouse_status = Some((
5421 mouse_pos.into(),
5422 ClickAim::BottomResize,
5423 [
5424 mouse_pos.x - position[0],
5425 mouse_pos.y - position[1],
5426 ],
5427 ))
5428 };
5429 if size[1] > resource_panel.min_size[1]
5430 && (resource_panel.max_size.is_none()
5431 || size[1]
5432 < resource_panel.max_size.unwrap()[1])
5433 {
5434 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5435 } else if resource_panel.max_size.is_some()
5436 && size[1] >= resource_panel.max_size.unwrap()[1]
5437 {
5438 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5439 } else {
5440 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5441 };
5442 }
5443 [false, false] => {}
5444 }
5445 }
5446 _ => {}
5447 };
5448 resource_panel.last_frame_mouse_status =
5449 if resource_panel.last_frame_mouse_status.is_none()
5450 && rect.contains(mouse_pos)
5451 && ui.input(|i| i.pointer.primary_pressed())
5452 {
5453 Some((
5454 [mouse_pos.x, mouse_pos.y],
5455 ClickAim::Move,
5456 [mouse_pos.x - position[0], mouse_pos.y - position[1]],
5457 ))
5458 } else if resource_panel.last_frame_mouse_status.is_some()
5459 && !ui.input(|i| i.pointer.primary_released())
5460 {
5461 Some((
5462 [mouse_pos.x, mouse_pos.y],
5463 resource_panel.last_frame_mouse_status.unwrap().1,
5464 resource_panel.last_frame_mouse_status.unwrap().2,
5465 ))
5466 } else {
5467 None
5468 };
5469 if resource_panel.scroll_length_method[0].is_some()
5470 && x_scroll_delta != 0_f32
5471 && rect.contains(mouse_pos)
5472 {
5473 resource_panel.scrolled[0] = true;
5474 resource_panel.scroll_progress[0] = if resource_panel
5475 .scroll_progress[0]
5476 + -x_scroll_delta * resource_panel.scroll_sensitivity
5477 > resource_panel.scroll_length[0]
5478 {
5479 resource_panel.scroll_length[0]
5480 } else if resource_panel.scroll_progress[0]
5481 + -x_scroll_delta * resource_panel.scroll_sensitivity
5482 > 0_f32
5483 {
5484 resource_panel.scroll_progress[0]
5485 + -x_scroll_delta * resource_panel.scroll_sensitivity
5486 } else {
5487 0_f32
5488 };
5489 };
5490 if resource_panel.scroll_length_method[1].is_some()
5491 && y_scroll_delta != 0_f32
5492 && rect.contains(mouse_pos)
5493 {
5494 resource_panel.scrolled[1] = true;
5495 resource_panel.scroll_progress[1] = if resource_panel
5496 .scroll_progress[1]
5497 + -y_scroll_delta * resource_panel.scroll_sensitivity
5498 > resource_panel.scroll_length[1]
5499 {
5500 resource_panel.scroll_length[1]
5501 } else if resource_panel.scroll_progress[1]
5502 + -y_scroll_delta * resource_panel.scroll_sensitivity
5503 > 0_f32
5504 {
5505 resource_panel.scroll_progress[1]
5506 + -y_scroll_delta * resource_panel.scroll_sensitivity
5507 } else {
5508 0_f32
5509 };
5510 };
5511 } else if ui.input(|i| i.pointer.primary_released()) {
5512 resource_panel.last_frame_mouse_status = None;
5513 };
5514 };
5515 if let Some((mouse_pos, click_aim, offset)) =
5516 resource_panel.last_frame_mouse_status
5517 {
5518 match click_aim {
5519 ClickAim::LeftTopResize => {
5520 if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
5521 && (resource_panel.max_size.is_none()
5522 || position[0] - mouse_pos[0] + size[0]
5523 < resource_panel.max_size.unwrap()[0])
5524 {
5525 position_size_config.origin_size[0] +=
5526 position[0] - mouse_pos[0];
5527 position_size_config.origin_position[0] = mouse_pos[0];
5528 } else if resource_panel.max_size.is_some()
5529 && position[0] - mouse_pos[0] + size[0]
5530 >= resource_panel.max_size.unwrap()[0]
5531 {
5532 position_size_config.origin_position[0] -=
5533 resource_panel.max_size.unwrap()[0]
5534 - position_size_config.origin_size[0];
5535 position_size_config.origin_size[0] =
5536 resource_panel.max_size.unwrap()[0];
5537 } else {
5538 position_size_config.origin_position[0] += position_size_config
5539 .origin_size[0]
5540 - resource_panel.min_size[0];
5541 position_size_config.origin_size[0] =
5542 resource_panel.min_size[0];
5543 };
5544 if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
5545 && (resource_panel.max_size.is_none()
5546 || position[1] - mouse_pos[1] + size[1]
5547 < resource_panel.max_size.unwrap()[1])
5548 {
5549 position_size_config.origin_size[1] +=
5550 position[1] - mouse_pos[1];
5551 position_size_config.origin_position[1] = mouse_pos[1];
5552 } else if resource_panel.max_size.is_some()
5553 && position[1] - mouse_pos[1] + size[1]
5554 >= resource_panel.max_size.unwrap()[1]
5555 {
5556 position_size_config.origin_position[1] -=
5557 resource_panel.max_size.unwrap()[1]
5558 - position_size_config.origin_size[1];
5559 position_size_config.origin_size[1] =
5560 resource_panel.max_size.unwrap()[1];
5561 } else {
5562 position_size_config.origin_position[1] += position_size_config
5563 .origin_size[1]
5564 - resource_panel.min_size[1];
5565 position_size_config.origin_size[1] =
5566 resource_panel.min_size[1];
5567 };
5568 if size[0] > resource_panel.min_size[0]
5569 && (resource_panel.max_size.is_none()
5570 || size[0] < resource_panel.max_size.unwrap()[0])
5571 || size[1] > resource_panel.min_size[1]
5572 && (resource_panel.max_size.is_none()
5573 || size[1] < resource_panel.max_size.unwrap()[1])
5574 {
5575 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
5576 } else if resource_panel.max_size.is_some()
5577 && size[0] >= resource_panel.max_size.unwrap()[0]
5578 && size[1] >= resource_panel.max_size.unwrap()[1]
5579 {
5580 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast);
5581 } else {
5582 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest)
5583 };
5584 }
5585 ClickAim::RightBottomResize => {
5586 if mouse_pos[0] - position[0] > resource_panel.min_size[0]
5587 && (resource_panel.max_size.is_none()
5588 || mouse_pos[0] - position[0]
5589 < resource_panel.max_size.unwrap()[0])
5590 {
5591 position_size_config.origin_size[0] =
5592 mouse_pos[0] - position[0];
5593 } else if resource_panel.max_size.is_some()
5594 && mouse_pos[0] - position[0]
5595 >= resource_panel.max_size.unwrap()[0]
5596 {
5597 position_size_config.origin_size[0] =
5598 resource_panel.max_size.unwrap()[0];
5599 } else {
5600 position_size_config.origin_size[0] =
5601 resource_panel.min_size[0];
5602 };
5603 if mouse_pos[1] - position[1] > resource_panel.min_size[1]
5604 && (resource_panel.max_size.is_none()
5605 || mouse_pos[1] - position[1]
5606 < resource_panel.max_size.unwrap()[1])
5607 {
5608 position_size_config.origin_size[1] =
5609 mouse_pos[1] - position[1];
5610 } else if resource_panel.max_size.is_some()
5611 && mouse_pos[1] - position[1]
5612 >= resource_panel.max_size.unwrap()[1]
5613 {
5614 position_size_config.origin_size[1] =
5615 resource_panel.max_size.unwrap()[1];
5616 } else {
5617 position_size_config.origin_size[1] =
5618 resource_panel.min_size[1];
5619 };
5620 if size[0] > resource_panel.min_size[0]
5621 && (resource_panel.max_size.is_none()
5622 || size[0] < resource_panel.max_size.unwrap()[0])
5623 || size[1] > resource_panel.min_size[1]
5624 && (resource_panel.max_size.is_none()
5625 || size[1] < resource_panel.max_size.unwrap()[1])
5626 {
5627 ctx.set_cursor_icon(CursorIcon::ResizeNwSe);
5628 } else if resource_panel.max_size.is_some()
5629 && size[0] >= resource_panel.max_size.unwrap()[0]
5630 && size[1] >= resource_panel.max_size.unwrap()[1]
5631 {
5632 ctx.set_cursor_icon(CursorIcon::ResizeNorthWest);
5633 } else {
5634 ctx.set_cursor_icon(CursorIcon::ResizeSouthEast)
5635 };
5636 }
5637 ClickAim::RightTopResize => {
5638 if mouse_pos[0] - position[0] > resource_panel.min_size[0]
5639 && (resource_panel.max_size.is_none()
5640 || mouse_pos[0] - position[0]
5641 < resource_panel.max_size.unwrap()[0])
5642 {
5643 position_size_config.origin_size[0] =
5644 mouse_pos[0] - position[0];
5645 } else if resource_panel.max_size.is_some()
5646 && mouse_pos[0] - position[0]
5647 >= resource_panel.max_size.unwrap()[0]
5648 {
5649 position_size_config.origin_size[0] =
5650 resource_panel.max_size.unwrap()[0];
5651 } else {
5652 position_size_config.origin_size[0] =
5653 resource_panel.min_size[0];
5654 };
5655 if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
5656 && (resource_panel.max_size.is_none()
5657 || position[1] - mouse_pos[1] + size[1]
5658 < resource_panel.max_size.unwrap()[1])
5659 {
5660 position_size_config.origin_size[1] +=
5661 position[1] - mouse_pos[1];
5662 position_size_config.origin_position[1] = mouse_pos[1];
5663 } else if resource_panel.max_size.is_some()
5664 && position[1] - mouse_pos[1] + size[1]
5665 >= resource_panel.max_size.unwrap()[1]
5666 {
5667 position_size_config.origin_position[1] -=
5668 resource_panel.max_size.unwrap()[1]
5669 - position_size_config.origin_size[1];
5670 position_size_config.origin_size[1] =
5671 resource_panel.max_size.unwrap()[1];
5672 } else {
5673 position_size_config.origin_position[1] += position_size_config
5674 .origin_size[1]
5675 - resource_panel.min_size[1];
5676 position_size_config.origin_size[1] =
5677 resource_panel.min_size[1];
5678 };
5679 if size[0] > resource_panel.min_size[0]
5680 && (resource_panel.max_size.is_none()
5681 || size[0] < resource_panel.max_size.unwrap()[0])
5682 || size[1] > resource_panel.min_size[1]
5683 && (resource_panel.max_size.is_none()
5684 || size[1] < resource_panel.max_size.unwrap()[1])
5685 {
5686 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
5687 } else if resource_panel.max_size.is_some()
5688 && size[0] >= resource_panel.max_size.unwrap()[0]
5689 && size[1] >= resource_panel.max_size.unwrap()[1]
5690 {
5691 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest);
5692 } else {
5693 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast)
5694 };
5695 }
5696 ClickAim::LeftBottomResize => {
5697 if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
5698 && (resource_panel.max_size.is_none()
5699 || position[0] - mouse_pos[0] + size[0]
5700 < resource_panel.max_size.unwrap()[0])
5701 {
5702 position_size_config.origin_size[0] +=
5703 position[0] - mouse_pos[0];
5704 position_size_config.origin_position[0] = mouse_pos[0];
5705 } else if resource_panel.max_size.is_some()
5706 && position[0] - mouse_pos[0] + size[0]
5707 >= resource_panel.max_size.unwrap()[0]
5708 {
5709 position_size_config.origin_position[0] -=
5710 resource_panel.max_size.unwrap()[0]
5711 - position_size_config.origin_size[0];
5712 position_size_config.origin_size[0] =
5713 resource_panel.max_size.unwrap()[0];
5714 } else {
5715 position_size_config.origin_position[0] += position_size_config
5716 .origin_size[0]
5717 - resource_panel.min_size[0];
5718 position_size_config.origin_size[0] =
5719 resource_panel.min_size[0];
5720 };
5721 if mouse_pos[1] - position[1] > resource_panel.min_size[1]
5722 && (resource_panel.max_size.is_none()
5723 || mouse_pos[1] - position[1]
5724 < resource_panel.max_size.unwrap()[1])
5725 {
5726 position_size_config.origin_size[1] =
5727 mouse_pos[1] - position[1];
5728 } else if resource_panel.max_size.is_some()
5729 && mouse_pos[1] - position[1]
5730 >= resource_panel.max_size.unwrap()[1]
5731 {
5732 position_size_config.origin_size[1] =
5733 resource_panel.max_size.unwrap()[1];
5734 } else {
5735 position_size_config.origin_size[1] =
5736 resource_panel.min_size[1];
5737 };
5738 if size[0] > resource_panel.min_size[0]
5739 && (resource_panel.max_size.is_none()
5740 || size[0] < resource_panel.max_size.unwrap()[0])
5741 || size[1] > resource_panel.min_size[1]
5742 && (resource_panel.max_size.is_none()
5743 || size[1] < resource_panel.max_size.unwrap()[1])
5744 {
5745 ctx.set_cursor_icon(CursorIcon::ResizeNeSw);
5746 } else if resource_panel.max_size.is_some()
5747 && size[0] >= resource_panel.max_size.unwrap()[0]
5748 && size[1] >= resource_panel.max_size.unwrap()[1]
5749 {
5750 ctx.set_cursor_icon(CursorIcon::ResizeNorthEast);
5751 } else {
5752 ctx.set_cursor_icon(CursorIcon::ResizeSouthWest)
5753 };
5754 }
5755 ClickAim::TopResize => {
5756 if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
5757 && (resource_panel.max_size.is_none()
5758 || position[1] - mouse_pos[1] + size[1]
5759 < resource_panel.max_size.unwrap()[1])
5760 {
5761 position_size_config.origin_size[1] +=
5762 position[1] - mouse_pos[1];
5763 position_size_config.origin_position[1] = mouse_pos[1];
5764 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5765 } else if resource_panel.max_size.is_some()
5766 && position[1] - mouse_pos[1] + size[1]
5767 >= resource_panel.max_size.unwrap()[1]
5768 {
5769 position_size_config.origin_position[1] -=
5770 resource_panel.max_size.unwrap()[1]
5771 - position_size_config.origin_size[1];
5772 position_size_config.origin_size[1] =
5773 resource_panel.max_size.unwrap()[1];
5774 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5775 } else {
5776 position_size_config.origin_position[1] += position_size_config
5777 .origin_size[1]
5778 - resource_panel.min_size[1];
5779 position_size_config.origin_size[1] =
5780 resource_panel.min_size[1];
5781 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5782 };
5783 }
5784 ClickAim::BottomResize => {
5785 if mouse_pos[1] - position[1] > resource_panel.min_size[1]
5786 && (resource_panel.max_size.is_none()
5787 || mouse_pos[1] - position[1]
5788 < resource_panel.max_size.unwrap()[1])
5789 {
5790 position_size_config.origin_size[1] =
5791 mouse_pos[1] - position[1];
5792 ctx.set_cursor_icon(CursorIcon::ResizeVertical);
5793 } else if resource_panel.max_size.is_some()
5794 && mouse_pos[1] - position[1]
5795 >= resource_panel.max_size.unwrap()[1]
5796 {
5797 position_size_config.origin_size[1] =
5798 resource_panel.max_size.unwrap()[1];
5799 ctx.set_cursor_icon(CursorIcon::ResizeNorth);
5800 } else {
5801 position_size_config.origin_size[1] =
5802 resource_panel.min_size[1];
5803 ctx.set_cursor_icon(CursorIcon::ResizeSouth);
5804 };
5805 }
5806 ClickAim::LeftResize => {
5807 if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
5808 && (resource_panel.max_size.is_none()
5809 || position[0] - mouse_pos[0] + size[0]
5810 < resource_panel.max_size.unwrap()[0])
5811 {
5812 position_size_config.origin_size[0] +=
5813 position[0] - mouse_pos[0];
5814 position_size_config.origin_position[0] = mouse_pos[0];
5815 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5816 } else if resource_panel.max_size.is_some()
5817 && position[0] - mouse_pos[0] + size[0]
5818 >= resource_panel.max_size.unwrap()[0]
5819 {
5820 position_size_config.origin_position[0] -=
5821 resource_panel.max_size.unwrap()[0]
5822 - position_size_config.origin_size[0];
5823 position_size_config.origin_size[0] =
5824 resource_panel.max_size.unwrap()[0];
5825 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5826 } else {
5827 position_size_config.origin_position[0] += position_size_config
5828 .origin_size[0]
5829 - resource_panel.min_size[0];
5830 position_size_config.origin_size[0] =
5831 resource_panel.min_size[0];
5832 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5833 };
5834 }
5835 ClickAim::RightResize => {
5836 if mouse_pos[0] - position[0] > resource_panel.min_size[0]
5837 && (resource_panel.max_size.is_none()
5838 || mouse_pos[0] - position[0]
5839 < resource_panel.max_size.unwrap()[0])
5840 {
5841 position_size_config.origin_size[0] =
5842 mouse_pos[0] - position[0];
5843 ctx.set_cursor_icon(CursorIcon::ResizeHorizontal);
5844 } else if resource_panel.max_size.is_some()
5845 && mouse_pos[0] - position[0]
5846 >= resource_panel.max_size.unwrap()[0]
5847 {
5848 position_size_config.origin_size[0] =
5849 resource_panel.max_size.unwrap()[0];
5850 ctx.set_cursor_icon(CursorIcon::ResizeWest);
5851 } else {
5852 position_size_config.origin_size[0] =
5853 resource_panel.min_size[0];
5854 ctx.set_cursor_icon(CursorIcon::ResizeEast);
5855 };
5856 }
5857 ClickAim::Move => {
5858 if resource_panel.movable[0] {
5859 position_size_config.origin_position[0] =
5860 mouse_pos[0] - offset[0];
5861 };
5862 if resource_panel.movable[1] {
5863 position_size_config.origin_position[1] =
5864 mouse_pos[1] - offset[1];
5865 };
5866 }
5867 };
5868 };
5869 [position, size] = self.position_size_processor(position_size_config, ctx);
5870 let background_type = match background.background_type.clone() {
5871 BackgroundType::CustomRect(config) => BackgroundType::CustomRect(
5872 config
5873 .position_size_config(Some(position_size_config))
5874 .hidden(Some(resource_panel.hidden)),
5875 ),
5876 BackgroundType::Image(config) => BackgroundType::Image(
5877 config
5878 .position_size_config(Some(position_size_config))
5879 .hidden(Some(resource_panel.hidden)),
5880 ),
5881 };
5882 self.replace_resource(
5883 &format!("{name}Background"),
5884 background.clone().background_type(&background_type).clone(),
5885 )?;
5886 self.use_resource(
5887 &format!("{name}Background"),
5888 "rust_constructor::Background",
5889 ui,
5890 ctx,
5891 )?;
5892 let mut resource_point_list: Vec<([f32; 2], [f32; 2], [bool; 2])> = Vec::new();
5893 let mut use_resource_list = Vec::new();
5894 let mut replace_resource_list = Vec::new();
5895 for rcr in &self.rust_constructor_resource {
5896 if self
5897 .basic_front_resource_list
5898 .contains(&rcr.id.discern_type)
5899 && let Some(panel_name) =
5900 self.get_tag("panel_name", &rcr.content.display_tags())
5901 && panel_name.1 == name
5902 {
5903 if let [Some(citer_name), Some(citer_type)] = [
5904 self.get_tag("citer_name", &rcr.content.display_tags()),
5905 self.get_tag("citer_type", &rcr.content.display_tags()),
5906 ] {
5907 if !use_resource_list
5908 .iter()
5909 .any(|x| x == &[citer_name.1.clone(), citer_type.1.clone()])
5910 {
5911 use_resource_list.push([citer_name.1, citer_type.1]);
5912 };
5913 } else if !use_resource_list
5914 .iter()
5915 .any(|x| x == &[rcr.id.name.clone(), rcr.id.discern_type.clone()])
5916 {
5917 use_resource_list
5918 .push([rcr.id.name.clone(), rcr.id.discern_type.clone()]);
5919 };
5920 let mut basic_front_resource: Box<dyn BasicFrontResource> = match &*rcr
5921 .id
5922 .discern_type
5923 {
5924 "rust_constructor::Image" => Box::new(
5925 rcr.content
5926 .as_any()
5927 .downcast_ref::<Image>()
5928 .unwrap()
5929 .clone(),
5930 ),
5931 "rust_constructor::Text" => Box::new(
5932 rcr.content.as_any().downcast_ref::<Text>().unwrap().clone(),
5933 ),
5934 "rust_constructor::CustomRect" => Box::new(
5935 rcr.content
5936 .as_any()
5937 .downcast_ref::<CustomRect>()
5938 .unwrap()
5939 .clone(),
5940 ),
5941 _ => {
5942 unreachable!()
5943 }
5944 };
5945 if !resource_panel
5946 .resource_storage
5947 .iter()
5948 .any(|x| x.id == rcr.id)
5949 {
5950 resource_panel.resource_storage.push(PanelStorage {
5951 id: rcr.id.clone(),
5952 ignore_render_layer: if let Some(display_info) =
5953 basic_front_resource.display_display_info()
5954 {
5955 display_info.ignore_render_layer
5956 } else {
5957 false
5958 },
5959 hidden: if let Some(display_info) =
5960 basic_front_resource.display_display_info()
5961 {
5962 display_info.hidden
5963 } else {
5964 false
5965 },
5966 origin_size: basic_front_resource
5967 .display_position_size_config()
5968 .origin_size,
5969 });
5970 };
5971 let enable_scrolling = [
5972 self.get_tag("disable_x_scrolling", &rcr.content.display_tags())
5973 .is_none(),
5974 self.get_tag("disable_y_scrolling", &rcr.content.display_tags())
5975 .is_none(),
5976 ];
5977 let offset = basic_front_resource.display_position_size_config().offset;
5978 basic_front_resource.modify_position_size_config(
5979 basic_front_resource
5980 .display_position_size_config()
5981 .x_location_grid(0_f32, 0_f32)
5982 .y_location_grid(0_f32, 0_f32)
5983 .x_size_grid(0_f32, 0_f32)
5984 .y_size_grid(0_f32, 0_f32)
5985 .offset(
5986 if enable_scrolling[0] {
5987 -resource_panel.scroll_progress[0]
5988 } else {
5989 offset[0]
5990 },
5991 if enable_scrolling[1] {
5992 -resource_panel.scroll_progress[1]
5993 } else {
5994 offset[1]
5995 },
5996 ),
5997 );
5998 match resource_panel.layout.panel_margin {
5999 PanelMargin::Vertical(
6000 [top, bottom, left, right],
6001 move_to_bottom,
6002 ) => {
6003 let mut modify_y = 0_f32;
6004 let [default_x_position, default_y_position] =
6005 match resource_panel.layout.panel_location {
6006 PanelLocation::Absolute([x, y]) => {
6007 [position[0] + x, position[1] + y]
6008 }
6009 PanelLocation::Relative([x, y]) => [
6010 position[0] + (size[0] / x[1] as f32 * x[0] as f32),
6011 position[1] + (size[1] / y[1] as f32 * y[0] as f32),
6012 ],
6013 };
6014 let default_x_position = match basic_front_resource
6015 .display_position_size_config()
6016 .display_method
6017 .0
6018 {
6019 HorizontalAlign::Left => default_x_position,
6020 HorizontalAlign::Center => {
6021 default_x_position
6022 - basic_front_resource.display_size()[0] / 2.0
6023 }
6024 HorizontalAlign::Right => {
6025 default_x_position
6026 - basic_front_resource.display_size()[0]
6027 }
6028 };
6029 let default_y_position = match basic_front_resource
6030 .display_position_size_config()
6031 .display_method
6032 .1
6033 {
6034 VerticalAlign::Top => default_y_position,
6035 VerticalAlign::Center => {
6036 default_y_position
6037 - basic_front_resource.display_size()[1] / 2.0
6038 }
6039 VerticalAlign::Bottom => {
6040 default_y_position
6041 - basic_front_resource.display_size()[1]
6042 }
6043 };
6044 for point in &resource_point_list {
6045 if default_x_position - left < point.1[0]
6046 && default_y_position - top + modify_y < point.1[1]
6047 && default_x_position
6048 + basic_front_resource.display_size()[0]
6049 + right
6050 > point.0[0]
6051 && default_y_position
6052 + basic_front_resource.display_size()[1]
6053 + bottom
6054 + modify_y
6055 > point.0[1]
6056 {
6057 if move_to_bottom
6058 && point.1[1] - default_y_position + top > modify_y
6059 {
6060 modify_y = point.1[1] - default_y_position + top;
6061 } else if !move_to_bottom
6062 && point.0[1]
6063 - default_y_position
6064 - basic_front_resource.display_size()[1]
6065 - bottom
6066 < modify_y
6067 {
6068 modify_y = point.0[1]
6069 - default_y_position
6070 - basic_front_resource.display_size()[1]
6071 - bottom;
6072 };
6073 };
6074 }
6075 let real_x_position = match basic_front_resource
6076 .display_position_size_config()
6077 .display_method
6078 .0
6079 {
6080 HorizontalAlign::Left => default_x_position,
6081 HorizontalAlign::Center => {
6082 default_x_position
6083 + basic_front_resource.display_size()[0] / 2.0
6084 }
6085 HorizontalAlign::Right => {
6086 default_x_position
6087 + basic_front_resource.display_size()[0]
6088 }
6089 };
6090 let real_y_position = match basic_front_resource
6091 .display_position_size_config()
6092 .display_method
6093 .1
6094 {
6095 VerticalAlign::Top => default_y_position + modify_y,
6096 VerticalAlign::Center => {
6097 default_y_position
6098 + modify_y
6099 + basic_front_resource.display_size()[1] / 2.0
6100 }
6101 VerticalAlign::Bottom => {
6102 default_y_position
6103 + modify_y
6104 + basic_front_resource.display_size()[1]
6105 }
6106 };
6107 let default_storage = if let Some(resource_storage) =
6108 resource_panel
6109 .resource_storage
6110 .iter()
6111 .find(|x| x.id == rcr.id)
6112 {
6113 (true, resource_storage.origin_size)
6114 } else {
6115 (false, [0_f32, 0_f32])
6116 };
6117 basic_front_resource.modify_position_size_config(
6118 basic_front_resource
6119 .display_position_size_config()
6120 .origin_size(
6121 if basic_front_resource.display_position()[0]
6122 < position[0] + size[0]
6123 {
6124 if resource_panel.auto_shrink[0]
6125 && basic_front_resource
6126 .display_position_size_config()
6127 .origin_size[0]
6128 > position_size_config.origin_size[0]
6129 - (basic_front_resource
6130 .display_position()[0]
6131 - position[0])
6132 - right
6133 {
6134 position_size_config.origin_size[0]
6135 - (basic_front_resource
6136 .display_position()[0]
6137 - position[0])
6138 - right
6139 } else if default_storage.0 {
6140 if default_storage.1[0]
6141 > position_size_config.origin_size[0]
6142 - (basic_front_resource
6143 .display_position()[0]
6144 - position[0])
6145 - right
6146 {
6147 position_size_config.origin_size[0]
6148 - (basic_front_resource
6149 .display_position()[0]
6150 - position[0])
6151 - right
6152 } else {
6153 default_storage.1[0]
6154 }
6155 } else {
6156 basic_front_resource
6157 .display_position_size_config()
6158 .origin_size[0]
6159 }
6160 } else {
6161 0_f32
6162 },
6163 if basic_front_resource.display_position()[1]
6164 < position[1] + size[1]
6165 {
6166 if resource_panel.auto_shrink[1]
6167 && basic_front_resource
6168 .display_position_size_config()
6169 .origin_size[1]
6170 > position_size_config.origin_size[1]
6171 - (basic_front_resource
6172 .display_position()[1]
6173 - position[1])
6174 - bottom
6175 {
6176 position_size_config.origin_size[1]
6177 - (basic_front_resource
6178 .display_position()[1]
6179 - position[1])
6180 - bottom
6181 } else if default_storage.0 {
6182 if default_storage.1[1]
6183 > position_size_config.origin_size[1]
6184 - (basic_front_resource
6185 .display_position()[1]
6186 - position[1])
6187 - bottom
6188 {
6189 position_size_config.origin_size[1]
6190 - (basic_front_resource
6191 .display_position()[1]
6192 - position[1])
6193 - bottom
6194 } else {
6195 default_storage.1[1]
6196 }
6197 } else {
6198 basic_front_resource
6199 .display_position_size_config()
6200 .origin_size[1]
6201 }
6202 } else {
6203 0_f32
6204 },
6205 )
6206 .origin_position(real_x_position, real_y_position),
6207 );
6208 replace_resource_list.push((
6209 basic_front_resource.display_position_size_config(),
6210 [rcr.id.name.clone(), rcr.id.discern_type.clone()],
6211 ));
6212 resource_point_list.push((
6213 [real_x_position - left, real_y_position - top],
6214 [
6215 real_x_position
6216 + basic_front_resource.display_size()[0]
6217 + right,
6218 real_y_position
6219 + basic_front_resource.display_size()[1]
6220 + bottom,
6221 ],
6222 enable_scrolling,
6223 ));
6224 }
6225 PanelMargin::Horizontal(
6226 [top, bottom, left, right],
6227 move_to_right,
6228 ) => {
6229 let mut modify_x = 0_f32;
6230 let [default_x_position, default_y_position] =
6231 match resource_panel.layout.panel_location {
6232 PanelLocation::Absolute([x, y]) => {
6233 [position[0] + x, position[1] + y]
6234 }
6235 PanelLocation::Relative([x, y]) => [
6236 position[0] + (size[0] / x[1] as f32 * x[0] as f32),
6237 position[1] + (size[1] / y[1] as f32 * y[0] as f32),
6238 ],
6239 };
6240 let default_x_position = match basic_front_resource
6241 .display_position_size_config()
6242 .display_method
6243 .0
6244 {
6245 HorizontalAlign::Left => default_x_position,
6246 HorizontalAlign::Center => {
6247 default_x_position
6248 - basic_front_resource.display_size()[0] / 2.0
6249 }
6250 HorizontalAlign::Right => {
6251 default_x_position
6252 - basic_front_resource.display_size()[0]
6253 }
6254 };
6255 let default_y_position = match basic_front_resource
6256 .display_position_size_config()
6257 .display_method
6258 .1
6259 {
6260 VerticalAlign::Top => default_y_position,
6261 VerticalAlign::Center => {
6262 default_y_position
6263 - basic_front_resource.display_size()[1] / 2.0
6264 }
6265 VerticalAlign::Bottom => {
6266 default_y_position
6267 - basic_front_resource.display_size()[1]
6268 }
6269 };
6270 for point in &resource_point_list {
6271 if default_x_position - left + modify_x < point.1[0]
6272 && default_y_position - top < point.1[1]
6273 && default_x_position
6274 + basic_front_resource.display_size()[0]
6275 + right
6276 + modify_x
6277 > point.0[0]
6278 && default_y_position
6279 + basic_front_resource.display_size()[1]
6280 + bottom
6281 > point.0[1]
6282 {
6283 if move_to_right
6284 && point.1[0] - default_x_position + left > modify_x
6285 {
6286 modify_x = point.1[0] - default_x_position + left;
6287 } else if !move_to_right
6288 && point.0[0]
6289 - default_x_position
6290 - basic_front_resource.display_size()[0]
6291 - right
6292 < modify_x
6293 {
6294 modify_x = point.0[0]
6295 - default_x_position
6296 - basic_front_resource.display_size()[0]
6297 - right;
6298 };
6299 };
6300 }
6301 let real_x_position = match basic_front_resource
6302 .display_position_size_config()
6303 .display_method
6304 .0
6305 {
6306 HorizontalAlign::Left => default_x_position + modify_x,
6307 HorizontalAlign::Center => {
6308 default_x_position
6309 + modify_x
6310 + basic_front_resource.display_size()[0] / 2.0
6311 }
6312 HorizontalAlign::Right => {
6313 default_x_position
6314 + modify_x
6315 + basic_front_resource.display_size()[0]
6316 }
6317 };
6318 let real_y_position = match basic_front_resource
6319 .display_position_size_config()
6320 .display_method
6321 .1
6322 {
6323 VerticalAlign::Top => default_y_position,
6324 VerticalAlign::Center => {
6325 default_y_position
6326 + basic_front_resource.display_size()[1] / 2.0
6327 }
6328 VerticalAlign::Bottom => {
6329 default_y_position
6330 + basic_front_resource.display_size()[1]
6331 }
6332 };
6333 let default_storage = if let Some(resource_storage) =
6334 resource_panel
6335 .resource_storage
6336 .iter()
6337 .find(|x| x.id == rcr.id)
6338 {
6339 (true, resource_storage.origin_size)
6340 } else {
6341 (false, [0_f32, 0_f32])
6342 };
6343 basic_front_resource.modify_position_size_config(
6344 basic_front_resource
6345 .display_position_size_config()
6346 .origin_size(
6347 if basic_front_resource.display_position()[0]
6348 < position[0] + size[0]
6349 {
6350 if resource_panel.auto_shrink[0]
6351 && basic_front_resource
6352 .display_position_size_config()
6353 .origin_size[0]
6354 > position_size_config.origin_size[0]
6355 - (basic_front_resource
6356 .display_position()[0]
6357 - position[0])
6358 - right
6359 {
6360 position_size_config.origin_size[0]
6361 - (basic_front_resource
6362 .display_position()[0]
6363 - position[0])
6364 - right
6365 } else if default_storage.0 {
6366 if default_storage.1[0]
6367 > position_size_config.origin_size[0]
6368 - (basic_front_resource
6369 .display_position()[0]
6370 - position[0])
6371 - right
6372 {
6373 position_size_config.origin_size[0]
6374 - (basic_front_resource
6375 .display_position()[0]
6376 - position[0])
6377 - right
6378 } else {
6379 default_storage.1[0]
6380 }
6381 } else {
6382 basic_front_resource
6383 .display_position_size_config()
6384 .origin_size[0]
6385 }
6386 } else {
6387 0_f32
6388 },
6389 if basic_front_resource.display_position()[1]
6390 < position[1] + size[1]
6391 {
6392 if resource_panel.auto_shrink[1]
6393 && basic_front_resource
6394 .display_position_size_config()
6395 .origin_size[1]
6396 > position_size_config.origin_size[1]
6397 - (basic_front_resource
6398 .display_position()[1]
6399 - position[1])
6400 - bottom
6401 {
6402 position_size_config.origin_size[1]
6403 - (basic_front_resource
6404 .display_position()[1]
6405 - position[1])
6406 - bottom
6407 } else if default_storage.0 {
6408 if default_storage.1[1]
6409 > position_size_config.origin_size[1]
6410 - (basic_front_resource
6411 .display_position()[1]
6412 - position[1])
6413 - bottom
6414 {
6415 position_size_config.origin_size[1]
6416 - (basic_front_resource
6417 .display_position()[1]
6418 - position[1])
6419 - bottom
6420 } else {
6421 default_storage.1[1]
6422 }
6423 } else {
6424 basic_front_resource
6425 .display_position_size_config()
6426 .origin_size[1]
6427 }
6428 } else {
6429 0_f32
6430 },
6431 )
6432 .origin_position(real_x_position, real_y_position),
6433 );
6434 replace_resource_list.push((
6435 basic_front_resource.display_position_size_config(),
6436 [rcr.id.name.clone(), rcr.id.discern_type.clone()],
6437 ));
6438 resource_point_list.push((
6439 [real_x_position - left, real_y_position - top],
6440 [
6441 real_x_position
6442 + basic_front_resource.display_size()[0]
6443 + right,
6444 real_y_position
6445 + basic_front_resource.display_size()[1]
6446 + bottom,
6447 ],
6448 enable_scrolling,
6449 ));
6450 }
6451 PanelMargin::None([top, bottom, left, right], influence_layout) => {
6452 let [default_x_position, default_y_position] =
6453 match resource_panel.layout.panel_location {
6454 PanelLocation::Absolute([x, y]) => {
6455 [position[0] + x, position[1] + y]
6456 }
6457 PanelLocation::Relative([x, y]) => [
6458 position[0] + (size[0] / x[1] as f32 * x[0] as f32),
6459 position[1] + (size[1] / y[1] as f32 * y[0] as f32),
6460 ],
6461 };
6462 let default_storage = if let Some(resource_storage) =
6463 resource_panel
6464 .resource_storage
6465 .iter()
6466 .find(|x| x.id == rcr.id)
6467 {
6468 (true, resource_storage.origin_size)
6469 } else {
6470 (false, [0_f32, 0_f32])
6471 };
6472 basic_front_resource.modify_position_size_config(
6473 basic_front_resource
6474 .display_position_size_config()
6475 .origin_size(
6476 if basic_front_resource.display_position()[0]
6477 < position[0] + size[0]
6478 {
6479 if resource_panel.auto_shrink[0]
6480 && basic_front_resource
6481 .display_position_size_config()
6482 .origin_size[0]
6483 > position_size_config.origin_size[0]
6484 - (basic_front_resource
6485 .display_position()[0]
6486 - position[0])
6487 - right
6488 {
6489 position_size_config.origin_size[0]
6490 - (basic_front_resource
6491 .display_position()[0]
6492 - position[0])
6493 - right
6494 } else if default_storage.0 {
6495 if default_storage.1[0]
6496 > position_size_config.origin_size[0]
6497 - (basic_front_resource
6498 .display_position()[0]
6499 - position[0])
6500 - right
6501 {
6502 position_size_config.origin_size[0]
6503 - (basic_front_resource
6504 .display_position()[0]
6505 - position[0])
6506 - right
6507 } else {
6508 default_storage.1[0]
6509 }
6510 } else {
6511 basic_front_resource
6512 .display_position_size_config()
6513 .origin_size[0]
6514 }
6515 } else {
6516 0_f32
6517 },
6518 if basic_front_resource.display_position()[1]
6519 < position[1] + size[1]
6520 {
6521 if resource_panel.auto_shrink[1]
6522 && basic_front_resource
6523 .display_position_size_config()
6524 .origin_size[1]
6525 > position_size_config.origin_size[1]
6526 - (basic_front_resource
6527 .display_position()[1]
6528 - position[1])
6529 - bottom
6530 {
6531 position_size_config.origin_size[1]
6532 - (basic_front_resource
6533 .display_position()[1]
6534 - position[1])
6535 - bottom
6536 } else if default_storage.0 {
6537 if default_storage.1[1]
6538 > position_size_config.origin_size[1]
6539 - (basic_front_resource
6540 .display_position()[1]
6541 - position[1])
6542 - bottom
6543 {
6544 position_size_config.origin_size[1]
6545 - (basic_front_resource
6546 .display_position()[1]
6547 - position[1])
6548 - bottom
6549 } else {
6550 default_storage.1[1]
6551 }
6552 } else {
6553 basic_front_resource
6554 .display_position_size_config()
6555 .origin_size[1]
6556 }
6557 } else {
6558 0_f32
6559 },
6560 )
6561 .origin_position(
6562 default_x_position,
6563 default_y_position,
6564 ),
6565 );
6566 replace_resource_list.push((
6567 basic_front_resource.display_position_size_config(),
6568 [rcr.id.name.clone(), rcr.id.discern_type.clone()],
6569 ));
6570 if influence_layout {
6571 resource_point_list.push((
6572 [default_x_position - left, default_y_position - top],
6573 [
6574 default_x_position
6575 + basic_front_resource.display_size()[0]
6576 + right,
6577 default_y_position
6578 + basic_front_resource.display_size()[1]
6579 + bottom,
6580 ],
6581 enable_scrolling,
6582 ));
6583 };
6584 }
6585 };
6586 };
6587 }
6588 for (new_position_size_config, [name, discern_type]) in replace_resource_list {
6589 let default_storage = if let Some(resource_storage) =
6590 resource_panel.resource_storage.iter().find(|x| {
6591 x.id == RustConstructorId {
6592 name: name.clone(),
6593 discern_type: discern_type.clone(),
6594 }
6595 }) {
6596 [
6597 true,
6598 resource_storage.ignore_render_layer,
6599 resource_storage.hidden,
6600 ]
6601 } else {
6602 [false, true, true]
6603 };
6604 match &*discern_type {
6605 "rust_constructor::CustomRect" => {
6606 let mut custom_rect = self
6607 .get_resource::<CustomRect>(&name, &discern_type)?
6608 .clone();
6609 custom_rect.basic_front_resource_config.position_size_config =
6610 new_position_size_config;
6611 custom_rect.display_info.ignore_render_layer = if resource_panel
6612 .last_frame_mouse_status
6613 .is_some()
6614 || [x_scroll_delta, y_scroll_delta].iter().any(|x| *x != 0_f32)
6615 {
6616 true
6617 } else if default_storage[0] {
6618 default_storage[1]
6619 } else {
6620 custom_rect.display_info.ignore_render_layer
6621 };
6622 custom_rect.basic_front_resource_config.clip_rect =
6623 Some(position_size_config);
6624 custom_rect.display_info.hidden = if resource_panel.hidden {
6625 true
6626 } else if default_storage[0] {
6627 default_storage[2]
6628 } else {
6629 custom_rect.display_info.hidden
6630 };
6631 self.replace_resource(&name, custom_rect)?;
6632 }
6633 "rust_constructor::Image" => {
6634 let mut image =
6635 self.get_resource::<Image>(&name, &discern_type)?.clone();
6636 image.basic_front_resource_config.position_size_config =
6637 new_position_size_config;
6638 image.display_info.ignore_render_layer = if resource_panel
6639 .last_frame_mouse_status
6640 .is_some()
6641 || [x_scroll_delta, y_scroll_delta].iter().any(|x| *x != 0_f32)
6642 {
6643 true
6644 } else if default_storage[0] {
6645 default_storage[1]
6646 } else {
6647 image.display_info.ignore_render_layer
6648 };
6649 image.basic_front_resource_config.clip_rect =
6650 Some(position_size_config);
6651 image.display_info.hidden = resource_panel.hidden;
6652 self.replace_resource(&name, image)?;
6653 }
6654 "rust_constructor::Text" => {
6655 let mut text =
6656 self.get_resource::<Text>(&name, &discern_type)?.clone();
6657 text.basic_front_resource_config.position_size_config =
6658 new_position_size_config;
6659 text.display_info.ignore_render_layer = if resource_panel
6660 .last_frame_mouse_status
6661 .is_some()
6662 || [x_scroll_delta, y_scroll_delta].iter().any(|x| *x != 0_f32)
6663 {
6664 true
6665 } else if default_storage[0] {
6666 default_storage[1]
6667 } else {
6668 text.display_info.ignore_render_layer
6669 };
6670 text.auto_fit = [false, false];
6671 text.basic_front_resource_config.clip_rect =
6672 Some(position_size_config);
6673 text.display_info.hidden = resource_panel.hidden;
6674 self.replace_resource(&name, text)?;
6675 }
6676 _ => unreachable!(),
6677 }
6678 }
6679 for info in use_resource_list {
6680 self.use_resource(&info[0], &info[1], ui, ctx)?;
6681 }
6682 if let Some(horizontal_scroll_length_method) =
6683 resource_panel.scroll_length_method[0]
6684 {
6685 resource_panel.scroll_length[0] = match horizontal_scroll_length_method {
6686 ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
6687 ScrollLengthMethod::AutoFit(expand) => {
6688 let mut length = -background_resource.display_size()[0];
6689 match resource_panel.layout.panel_margin {
6690 PanelMargin::Horizontal(_, _) => {
6691 for storage in &resource_panel.resource_storage {
6692 length += storage.origin_size[0];
6693 }
6694 }
6695 PanelMargin::Vertical(_, _) | PanelMargin::None(_, _) => {
6696 for storage in &resource_panel.resource_storage {
6697 length = if storage.origin_size[0]
6698 - background_resource.display_size()[0]
6699 > length
6700 {
6701 storage.origin_size[0]
6702 - background_resource.display_size()[0]
6703 } else {
6704 length
6705 };
6706 }
6707 }
6708 }
6709 if length >= 0_f32 {
6710 length + expand.abs()
6711 } else {
6712 0_f32
6713 }
6714 }
6715 };
6716 if resource_panel.scroll_progress[0] > resource_panel.scroll_length[0] {
6717 resource_panel.scroll_progress[0] = resource_panel.scroll_length[0];
6718 };
6719 };
6720 if let Some(vertical_scroll_length_method) =
6721 resource_panel.scroll_length_method[1]
6722 {
6723 resource_panel.scroll_length[1] = match vertical_scroll_length_method {
6724 ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
6725 ScrollLengthMethod::AutoFit(expand) => {
6726 let mut length = -background_resource.display_size()[1];
6727 match resource_panel.layout.panel_margin {
6728 PanelMargin::Vertical(_, _) => {
6729 for storage in &resource_panel.resource_storage {
6730 length += storage.origin_size[1];
6731 }
6732 }
6733 PanelMargin::Horizontal(_, _) | PanelMargin::None(_, _) => {
6734 for storage in &resource_panel.resource_storage {
6735 length = if storage.origin_size[1]
6736 - background_resource.display_size()[1]
6737 > length
6738 {
6739 storage.origin_size[1]
6740 - background_resource.display_size()[1]
6741 } else {
6742 length
6743 };
6744 }
6745 }
6746 }
6747 if length >= 0_f32 {
6748 length + expand.abs()
6749 } else {
6750 0_f32
6751 }
6752 }
6753 };
6754 if resource_panel.scroll_progress[1] > resource_panel.scroll_length[1] {
6755 resource_panel.scroll_progress[1] = resource_panel.scroll_length[1];
6756 };
6757 };
6758 match resource_panel.scroll_bar_display_method {
6759 ScrollBarDisplayMethod::Always(ref config, margin, width) => {
6760 let line_length = if resource_panel.scroll_length[1] == 0_f32 {
6761 (size[0] - margin[0] * 2_f32)
6762 * (size[0] / (resource_panel.scroll_length[0] + size[0]))
6763 } else {
6764 (size[0] - width - margin[1] - margin[0] * 2_f32)
6765 * (size[0] / (resource_panel.scroll_length[0] + size[0]))
6766 };
6767 let line_position = if resource_panel.scroll_length[1] == 0_f32 {
6768 position[0]
6769 + margin[0]
6770 + (size[0] - margin[0] * 2_f32 - line_length)
6771 * (resource_panel.scroll_progress[0]
6772 / resource_panel.scroll_length[0])
6773 } else {
6774 position[0]
6775 + margin[0]
6776 + (size[0]
6777 - margin[0] * 2_f32
6778 - width
6779 - margin[1]
6780 - line_length)
6781 * (resource_panel.scroll_progress[0]
6782 / resource_panel.scroll_length[0])
6783 };
6784 self.replace_resource(
6785 &format!("{name}XScroll"),
6786 background.clone().background_type(&match config.clone() {
6787 BackgroundType::CustomRect(config) => {
6788 BackgroundType::CustomRect(
6789 config
6790 .ignore_render_layer(Some(true))
6791 .hidden(Some(resource_panel.hidden))
6792 .position_size_config(Some(
6793 PositionSizeConfig::default()
6794 .display_method(
6795 HorizontalAlign::Left,
6796 VerticalAlign::Bottom,
6797 )
6798 .origin_position(
6799 line_position,
6800 position[1] + size[1] - margin[1],
6801 )
6802 .origin_size(line_length, width),
6803 )),
6804 )
6805 }
6806 BackgroundType::Image(config) => BackgroundType::Image(
6807 config
6808 .ignore_render_layer(Some(true))
6809 .hidden(Some(resource_panel.hidden))
6810 .position_size_config(Some(
6811 PositionSizeConfig::default()
6812 .display_method(
6813 HorizontalAlign::Left,
6814 VerticalAlign::Bottom,
6815 )
6816 .origin_position(
6817 line_position,
6818 position[1] + size[1] - margin[1],
6819 )
6820 .origin_size(line_length, width),
6821 )),
6822 ),
6823 }),
6824 )?;
6825 self.use_resource(
6826 &format!("{name}XScroll"),
6827 "rust_constructor::Background",
6828 ui,
6829 ctx,
6830 )?;
6831 let line_length = if resource_panel.scroll_length[0] == 0_f32 {
6832 (size[1] - margin[0] * 2_f32)
6833 * (size[1] / (resource_panel.scroll_length[1] + size[1]))
6834 } else {
6835 (size[1] - width - margin[1] - margin[0] * 2_f32)
6836 * (size[1] / (resource_panel.scroll_length[1] + size[1]))
6837 };
6838 let line_position = if resource_panel.scroll_length[0] == 0_f32 {
6839 position[1]
6840 + margin[0]
6841 + (size[1] - margin[0] * 2_f32 - line_length)
6842 * (resource_panel.scroll_progress[1]
6843 / resource_panel.scroll_length[1])
6844 } else {
6845 position[1]
6846 + margin[0]
6847 + (size[1]
6848 - margin[0] * 2_f32
6849 - width
6850 - margin[1]
6851 - line_length)
6852 * (resource_panel.scroll_progress[1]
6853 / resource_panel.scroll_length[1])
6854 };
6855 self.replace_resource(
6856 &format!("{name}YScroll"),
6857 background.background_type(&match config.clone() {
6858 BackgroundType::CustomRect(config) => {
6859 BackgroundType::CustomRect(
6860 config
6861 .ignore_render_layer(Some(true))
6862 .hidden(Some(resource_panel.hidden))
6863 .position_size_config(Some(
6864 PositionSizeConfig::default()
6865 .display_method(
6866 HorizontalAlign::Right,
6867 VerticalAlign::Top,
6868 )
6869 .origin_position(
6870 position[0] + size[0] - margin[1],
6871 line_position,
6872 )
6873 .origin_size(width, line_length),
6874 )),
6875 )
6876 }
6877 BackgroundType::Image(config) => BackgroundType::Image(
6878 config
6879 .ignore_render_layer(Some(true))
6880 .hidden(Some(resource_panel.hidden))
6881 .position_size_config(Some(
6882 PositionSizeConfig::default()
6883 .display_method(
6884 HorizontalAlign::Right,
6885 VerticalAlign::Top,
6886 )
6887 .origin_position(
6888 position[0] + size[0] - margin[1],
6889 line_position,
6890 )
6891 .origin_size(width, line_length),
6892 )),
6893 ),
6894 }),
6895 )?;
6896 self.use_resource(
6897 &format!("{name}YScroll"),
6898 "rust_constructor::Background",
6899 ui,
6900 ctx,
6901 )?;
6902 }
6903 ScrollBarDisplayMethod::OnlyScroll(ref config, margin, width) => {
6904 resource_panel.scroll_bar_alpha[0] = if resource_panel.scrolled[0] {
6905 self.reset_split_time(&format!("{name}ScrollBarXAlphaStart"))?;
6906 255
6907 } else if self.timer.now_time
6908 - self.get_split_time(&format!("{name}ScrollBarXAlphaStart"))?[0]
6909 >= 1_f32
6910 && self.timer.now_time
6911 - self.get_split_time(&format!("{name}ScrollBarXAlpha"))?[0]
6912 >= self.tick_interval
6913 {
6914 self.reset_split_time(&format!("{name}ScrollBarXAlpha"))?;
6915 resource_panel.scroll_bar_alpha[0].saturating_sub(10)
6916 } else {
6917 resource_panel.scroll_bar_alpha[0]
6918 };
6919 resource_panel.scroll_bar_alpha[1] = if resource_panel.scrolled[1] {
6920 self.reset_split_time(&format!("{name}ScrollBarYAlphaStart"))?;
6921 255
6922 } else if self.timer.now_time
6923 - self.get_split_time(&format!("{name}ScrollBarYAlphaStart"))?[0]
6924 >= 1_f32
6925 && self.timer.now_time
6926 - self.get_split_time(&format!("{name}ScrollBarYAlpha"))?[0]
6927 >= self.tick_interval
6928 {
6929 self.reset_split_time(&format!("{name}ScrollBarYAlpha"))?;
6930 resource_panel.scroll_bar_alpha[1].saturating_sub(10)
6931 } else {
6932 resource_panel.scroll_bar_alpha[1]
6933 };
6934 let line_length = if resource_panel.scroll_length[1] == 0_f32 {
6935 (size[0] - margin[0] * 2_f32)
6936 * (size[0] / (resource_panel.scroll_length[0] + size[0]))
6937 } else {
6938 (size[0] - width - margin[1] - margin[0] * 2_f32)
6939 * (size[0] / (resource_panel.scroll_length[0] + size[0]))
6940 };
6941 let line_position = if resource_panel.scroll_length[1] == 0_f32 {
6942 position[0]
6943 + margin[0]
6944 + (size[0] - margin[0] * 2_f32 - line_length)
6945 * (resource_panel.scroll_progress[0]
6946 / resource_panel.scroll_length[0])
6947 } else {
6948 position[0]
6949 + margin[0]
6950 + (size[0]
6951 - margin[0] * 2_f32
6952 - width
6953 - margin[1]
6954 - line_length)
6955 * (resource_panel.scroll_progress[0]
6956 / resource_panel.scroll_length[0])
6957 };
6958 self.replace_resource(
6959 &format!("{name}XScroll"),
6960 background.clone().background_type(&match config.clone() {
6961 BackgroundType::CustomRect(config) => {
6962 BackgroundType::CustomRect(
6963 config
6964 .ignore_render_layer(Some(true))
6965 .hidden(Some(resource_panel.hidden))
6966 .position_size_config(Some(
6967 PositionSizeConfig::default()
6968 .display_method(
6969 HorizontalAlign::Left,
6970 VerticalAlign::Bottom,
6971 )
6972 .origin_position(
6973 line_position,
6974 position[1] + size[1] - margin[1],
6975 )
6976 .origin_size(line_length, width),
6977 ))
6978 .alpha(Some(resource_panel.scroll_bar_alpha[0]))
6979 .border_alpha(Some(
6980 resource_panel.scroll_bar_alpha[0],
6981 )),
6982 )
6983 }
6984 BackgroundType::Image(config) => BackgroundType::Image(
6985 config
6986 .ignore_render_layer(Some(true))
6987 .hidden(Some(resource_panel.hidden))
6988 .position_size_config(Some(
6989 PositionSizeConfig::default()
6990 .display_method(
6991 HorizontalAlign::Left,
6992 VerticalAlign::Bottom,
6993 )
6994 .origin_position(
6995 line_position,
6996 position[1] + size[1] - margin[1],
6997 )
6998 .origin_size(line_length, width),
6999 ))
7000 .alpha(Some(resource_panel.scroll_bar_alpha[0]))
7001 .background_alpha(Some(
7002 resource_panel.scroll_bar_alpha[0],
7003 ))
7004 .overlay_alpha(Some(
7005 resource_panel.scroll_bar_alpha[0],
7006 )),
7007 ),
7008 }),
7009 )?;
7010 self.use_resource(
7011 &format!("{name}XScroll"),
7012 "rust_constructor::Background",
7013 ui,
7014 ctx,
7015 )?;
7016 let line_length = if resource_panel.scroll_length[0] == 0_f32 {
7017 (size[1] - margin[0] * 2_f32)
7018 * (size[1] / (resource_panel.scroll_length[1] + size[1]))
7019 } else {
7020 (size[1] - width - margin[1] - margin[0] * 2_f32)
7021 * (size[1] / (resource_panel.scroll_length[1] + size[1]))
7022 };
7023 let line_position = if resource_panel.scroll_length[0] == 0_f32 {
7024 position[1]
7025 + margin[0]
7026 + (size[1] - margin[0] * 2_f32 - line_length)
7027 * (resource_panel.scroll_progress[1]
7028 / resource_panel.scroll_length[1])
7029 } else {
7030 position[1]
7031 + margin[0]
7032 + (size[1]
7033 - margin[0] * 2_f32
7034 - width
7035 - margin[1]
7036 - line_length)
7037 * (resource_panel.scroll_progress[1]
7038 / resource_panel.scroll_length[1])
7039 };
7040 self.replace_resource(
7041 &format!("{name}YScroll"),
7042 background.clone().background_type(&match config.clone() {
7043 BackgroundType::CustomRect(config) => {
7044 BackgroundType::CustomRect(
7045 config
7046 .ignore_render_layer(Some(true))
7047 .hidden(Some(resource_panel.hidden))
7048 .position_size_config(Some(
7049 PositionSizeConfig::default()
7050 .display_method(
7051 HorizontalAlign::Right,
7052 VerticalAlign::Top,
7053 )
7054 .origin_position(
7055 position[0] + size[0] - margin[1],
7056 line_position,
7057 )
7058 .origin_size(width, line_length),
7059 ))
7060 .alpha(Some(resource_panel.scroll_bar_alpha[1]))
7061 .border_alpha(Some(
7062 resource_panel.scroll_bar_alpha[1],
7063 )),
7064 )
7065 }
7066 BackgroundType::Image(config) => BackgroundType::Image(
7067 config
7068 .ignore_render_layer(Some(true))
7069 .hidden(Some(resource_panel.hidden))
7070 .position_size_config(Some(
7071 PositionSizeConfig::default()
7072 .display_method(
7073 HorizontalAlign::Right,
7074 VerticalAlign::Top,
7075 )
7076 .origin_position(
7077 position[0] + size[0] - margin[1],
7078 line_position,
7079 )
7080 .origin_size(width, line_length),
7081 ))
7082 .alpha(Some(resource_panel.scroll_bar_alpha[1]))
7083 .background_alpha(Some(
7084 resource_panel.scroll_bar_alpha[1],
7085 ))
7086 .overlay_alpha(Some(
7087 resource_panel.scroll_bar_alpha[1],
7088 )),
7089 ),
7090 }),
7091 )?;
7092 self.use_resource(
7093 &format!("{name}YScroll"),
7094 "rust_constructor::Background",
7095 ui,
7096 ctx,
7097 )?;
7098 }
7099 ScrollBarDisplayMethod::Hidden => {}
7100 };
7101 self.replace_resource(name, resource_panel.clone())?;
7102 }
7103 _ => {}
7104 };
7105 Ok(())
7106 } else {
7107 Err(RustConstructorError {
7108 error_id: "ResourceNotFound".to_string(),
7109 description: format!("Resource \"{name}({discern_type})\" not found."),
7110 })
7111 }
7112 }
7113
7114 pub fn switch_page(&mut self, name: &str) -> Result<(), RustConstructorError> {
7116 let page_data = self.get_resource_mut::<PageData>(name, "rust_constructor::PageData")?;
7117 page_data.enter_page_updated = false;
7118 self.timer.start_time = self.timer.total_time;
7119 self.current_page = name.to_string();
7120 self.update_timer();
7121 Ok(())
7122 }
7123
7124 pub fn get_font(&self, name: &str) -> Result<FontDefinitions, RustConstructorError> {
7126 let font = self.get_resource::<Font>(name, "rust_constructor::Font")?;
7127 Ok(font.font_definitions.clone())
7128 }
7129
7130 pub fn register_all_fonts(&self, ctx: &Context) {
7132 let mut font_definitions_amount = FontDefinitions::default();
7133 let mut fonts = Vec::new();
7134 for i in 0..self.rust_constructor_resource.len() {
7135 if let Some(font) = self.rust_constructor_resource[i]
7136 .content
7137 .as_any()
7138 .downcast_ref::<Font>()
7139 {
7140 fonts.push((
7141 self.rust_constructor_resource[i].id.name.clone(),
7142 font.font_definitions.clone(),
7143 ));
7144 };
7145 }
7146 for i in &fonts {
7147 if let Some(font_data) = i.1.font_data.get(&i.0) {
7149 font_definitions_amount
7150 .font_data
7151 .insert(i.0.clone(), Arc::clone(font_data));
7152 font_definitions_amount
7153 .families
7154 .entry(FontFamily::Name(i.0.clone().into()))
7155 .or_default()
7156 .push(i.0.clone());
7157 };
7158
7159 font_definitions_amount
7161 .families
7162 .entry(FontFamily::Proportional)
7163 .or_default()
7164 .insert(0, i.0.to_owned());
7165
7166 font_definitions_amount
7167 .families
7168 .entry(FontFamily::Monospace)
7169 .or_default()
7170 .insert(0, i.0.to_owned());
7171 }
7172 ctx.set_fonts(font_definitions_amount);
7173 }
7174
7175 pub fn position_size_processor(
7177 &self,
7178 position_size_config: PositionSizeConfig,
7179 ctx: &Context,
7180 ) -> [[f32; 2]; 2] {
7181 let mut position = [0_f32, 0_f32];
7182 let mut size = [0_f32, 0_f32];
7183 size[0] = match position_size_config.x_size_grid[0] {
7184 0_f32 => position_size_config.origin_size[0],
7185 _ => {
7186 (ctx.available_rect().width() / position_size_config.x_size_grid[1]
7187 * position_size_config.x_size_grid[0])
7188 + position_size_config.origin_size[0]
7189 }
7190 };
7191 size[1] = match position_size_config.y_size_grid[0] {
7192 0_f32 => position_size_config.origin_size[1],
7193 _ => {
7194 (ctx.available_rect().height() / position_size_config.y_size_grid[1]
7195 * position_size_config.y_size_grid[0])
7196 + position_size_config.origin_size[1]
7197 }
7198 };
7199 position[0] = match position_size_config.x_location_grid[1] {
7200 0_f32 => position_size_config.origin_position[0],
7201 _ => {
7202 (ctx.available_rect().width() / position_size_config.x_location_grid[1]
7203 * position_size_config.x_location_grid[0])
7204 + position_size_config.origin_position[0]
7205 }
7206 };
7207 position[1] = match position_size_config.y_location_grid[1] {
7208 0_f32 => position_size_config.origin_position[1],
7209 _ => {
7210 (ctx.available_rect().height() / position_size_config.y_location_grid[1]
7211 * position_size_config.y_location_grid[0])
7212 + position_size_config.origin_position[1]
7213 }
7214 };
7215 match position_size_config.display_method.0 {
7216 HorizontalAlign::Left => {}
7217 HorizontalAlign::Center => position[0] -= size[0] / 2.0,
7218 HorizontalAlign::Right => position[0] -= size[0],
7219 };
7220 match position_size_config.display_method.1 {
7221 VerticalAlign::Top => {}
7222 VerticalAlign::Center => position[1] -= size[1] / 2.0,
7223 VerticalAlign::Bottom => position[1] -= size[1],
7224 };
7225 position[0] += position_size_config.offset[0];
7226 position[1] += position_size_config.offset[1];
7227 [position, size]
7228 }
7229
7230 pub fn check_updated(&mut self, name: &str) -> Result<bool, RustConstructorError> {
7232 let page_data = self
7233 .get_resource::<PageData>(name, "rust_constructor::PageData")?
7234 .clone();
7235 if !page_data.change_page_updated {
7236 self.new_page_update(name)?;
7237 };
7238 Ok(page_data.change_page_updated)
7239 }
7240
7241 pub fn check_enter_updated(&mut self, name: &str) -> Result<bool, RustConstructorError> {
7243 let page_data = self.get_resource_mut::<PageData>(name, "rust_constructor::PageData")?;
7244 page_data.enter_page_updated = true;
7245 Ok(page_data.enter_page_updated)
7246 }
7247
7248 pub fn new_page_update(&mut self, name: &str) -> Result<(), RustConstructorError> {
7250 let page_data = self.get_resource_mut::<PageData>(name, "rust_constructor::PageData")?;
7251 page_data.change_page_updated = true;
7252 self.timer.start_time = self.timer.total_time;
7253 self.update_timer();
7254 Ok(())
7255 }
7256
7257 pub fn update_frame_stats(&mut self) {
7259 let current_time = self.timer.total_time;
7260 if let Some(last) = self.last_frame_time {
7261 let delta = current_time - last;
7262 self.frame_times.push(delta);
7263 const MAX_SAMPLES: usize = 120;
7264 if self.frame_times.len() > MAX_SAMPLES {
7265 let remove_count = self.frame_times.len() - MAX_SAMPLES;
7266 self.frame_times.drain(0..remove_count);
7267 }
7268 }
7269 self.last_frame_time = Some(current_time);
7270 }
7271
7272 pub fn current_fps(&self) -> f32 {
7274 if self.frame_times.is_empty() {
7275 0.0
7276 } else {
7277 1.0 / (self.frame_times.iter().sum::<f32>() / self.frame_times.len() as f32)
7278 }
7279 }
7280
7281 pub fn reset_split_time(&mut self, name: &str) -> Result<(), RustConstructorError> {
7283 let new_time = [self.timer.now_time, self.timer.total_time];
7284 let split_time = self.get_resource_mut::<SplitTime>(name, "rust_constructor::SplitTime")?;
7285 split_time.time = new_time;
7286 Ok(())
7287 }
7288
7289 pub fn get_split_time(&self, name: &str) -> Result<[f32; 2], RustConstructorError> {
7291 let split_time = self.get_resource::<SplitTime>(name, "rust_constructor::SplitTime")?;
7292 Ok(split_time.time)
7293 }
7294
7295 pub fn update_timer(&mut self) {
7297 let elapsed = self.timer.timer.elapsed();
7298 let seconds = elapsed.as_secs();
7299 let milliseconds = elapsed.subsec_millis();
7300 self.timer.total_time = seconds as f32 + milliseconds as f32 / 1000.0;
7301 self.timer.now_time = self.timer.total_time - self.timer.start_time
7302 }
7303
7304 pub fn modify_variable<T: Debug + 'static>(
7306 &mut self,
7307 name: &str,
7308 value: Option<T>,
7309 ) -> Result<(), RustConstructorError> {
7310 let variable = self.get_resource_mut::<Variable<T>>(name, "rust_constructor::Variable")?;
7311 variable.value = value;
7312 Ok(())
7313 }
7314
7315 pub fn get_variable<T: Debug + Clone + 'static>(
7317 &self,
7318 name: &str,
7319 ) -> Result<Option<T>, RustConstructorError> {
7320 if let Ok(variable) = self.get_resource::<Variable<T>>(name, "rust_constructor::Variable") {
7321 Ok(variable.value.clone())
7322 } else if self
7323 .check_resource_exists(name, "rust_constructor::Variable")
7324 .is_none()
7325 {
7326 Err(RustConstructorError {
7327 error_id: "ResourceNotFound".to_string(),
7328 description: format!(
7329 "Resource \"{name}(rust_constructor::Variable<T>)\" not found."
7330 ),
7331 })
7332 } else {
7333 Err(RustConstructorError {
7334 error_id: "ResourceGenericMismatch".to_string(),
7335 description: format!(
7336 "The generic type of the resource \"{name}(rust_constructor::Variable<T>)\" is mismatched."
7337 ),
7338 })
7339 }
7340 }
7341
7342 pub fn get_image_texture(
7344 &self,
7345 name: &str,
7346 ) -> Result<Option<DebugTextureHandle>, RustConstructorError> {
7347 let image_texture =
7348 self.get_resource::<ImageTexture>(name, "rust_constructor::ImageTexture")?;
7349 Ok(image_texture.texture.clone())
7350 }
7351
7352 pub fn reset_image_texture(
7354 &mut self,
7355 name: &str,
7356 path: &str,
7357 flip: [bool; 2],
7358 ctx: &Context,
7359 ) -> Result<(), RustConstructorError> {
7360 let image_texture =
7361 self.get_resource_mut::<ImageTexture>(name, "rust_constructor::ImageTexture")?;
7362 if let Ok(mut file) = File::open(path) {
7363 let mut buffer = Vec::new();
7364 file.read_to_end(&mut buffer).unwrap();
7365 let img_bytes = buffer;
7366 let img = image::load_from_memory(&img_bytes).unwrap();
7367 let color_data = match flip {
7368 [true, true] => img.fliph().flipv().into_rgba8(),
7369 [true, false] => img.fliph().into_rgba8(),
7370 [false, true] => img.flipv().into_rgba8(),
7371 _ => img.into_rgba8(),
7372 };
7373 let (w, h) = (color_data.width(), color_data.height());
7374 let raw_data: Vec<u8> = color_data.into_raw();
7375
7376 let color_image =
7377 ColorImage::from_rgba_unmultiplied([w as usize, h as usize], &raw_data);
7378 let texture = ctx.load_texture(name, color_image, TextureOptions::LINEAR);
7379 image_texture.texture = Some(DebugTextureHandle::new(&texture));
7380 image_texture.cite_path = path.to_string();
7381 } else {
7382 return Err(RustConstructorError {
7383 error_id: "ImageLoadFailed".to_string(),
7384 description: format!(
7385 "Failed to load an image from the path \"{}\".",
7386 image_texture.cite_path
7387 ),
7388 });
7389 }
7390 Ok(())
7391 }
7392
7393 pub fn set_switch_enable(
7395 &mut self,
7396 name: &str,
7397 enable: bool,
7398 ) -> Result<(), RustConstructorError> {
7399 let switch = self.get_resource_mut::<Switch>(name, "rust_constructor::Switch")?;
7400 switch.enable = enable;
7401 Ok(())
7402 }
7403
7404 pub fn check_switch_data(&self, name: &str) -> Result<SwitchData, RustConstructorError> {
7406 let switch = self.get_resource::<Switch>(name, "rust_constructor::Switch")?;
7407 Ok(SwitchData {
7408 switched: switch.switched,
7409 last_frame_clicked: switch.last_frame_clicked,
7410 state: switch.state,
7411 })
7412 }
7413}