Skip to main content

rust_constructor/
app.rs

1//! Main application struct containing all GUI resources and state management.
2//!
3//! 程序主体,包含所有GUI资源和状态管理。
4use crate::{
5    BasicFrontResource, BorderKind, DisplayInfo, HorizontalAlign, ListInfoDescribeMethod,
6    PositionSizeConfig, RenderConfig, RequestMethod, RequestType, RustConstructorError,
7    RustConstructorId, RustConstructorResource, RustConstructorResourceBox, Timer, VerticalAlign,
8    advance_front::{
9        Background, BackgroundType, ClickAim, CustomPanelLayout, PanelLocation, PanelMargin,
10        PanelStorage, ResourcePanel, ScrollBarDisplayMethod, ScrollLengthMethod, Switch,
11        SwitchData,
12    },
13    background::{PageData, SplitTime, Variable},
14    basic_front::{
15        CustomRect, DebugTextureHandle, HyperlinkSelectMethod, Image, ImageLoadMethod, Text,
16    },
17    downcast_resource, downcast_resource_mut, get_tag, position_size_processor, type_processor,
18};
19use egui::{
20    Color32, ColorImage, CornerRadius, CursorIcon, FontData, FontDefinitions, FontFamily, FontId,
21    Galley, Id, ImageSource, Key, OpenUrl, Pos2, Rect, Sense, Stroke, StrokeKind, Ui, Vec2,
22    text::CCursor,
23};
24use epaint::textures::TextureOptions;
25use std::{
26    char,
27    cmp::Ordering,
28    fmt::Debug,
29    fs::{File, read},
30    io::Read,
31    sync::Arc,
32    vec::Vec,
33};
34
35/// This struct serves as the central hub for the Rust Constructor framework.
36///
37/// 该结构体是Rust Constructor框架的中心枢纽。
38#[derive(Debug)]
39pub struct App {
40    /// Collection of all Rust Constructor resources with type-erased storage.
41    ///
42    /// 所有Rust Constructor资源的集合,使用类型擦除存储。
43    pub rust_constructor_resource: Vec<RustConstructorResourceBox>,
44
45    /// Refresh rate for resource updates in milliseconds.
46    ///
47    /// 资源更新的刷新率(毫秒)。
48    pub tick_interval: u128,
49
50    /// Name of the current active page.
51    ///
52    /// 当前活动页面的名称。
53    pub current_page: String,
54
55    /// Timer for tracking application runtime and page durations.
56    ///
57    /// 用于跟踪应用程序运行时间和页面持续时间的计时器。
58    pub timer: Timer,
59
60    /// Record of recent frame times for performance monitoring.
61    ///
62    /// 最近帧时间的记录,用于性能监控。
63    pub frame_times: Vec<u128>,
64
65    /// The time for rendering the previous frame in milliseconds.
66    ///
67    /// 渲染上一帧的时间(毫秒)。
68    pub last_frame_time: Option<u128>,
69
70    /// List of resource IDs that are basic front resources.
71    ///
72    /// 基本前端资源的资源ID列表。
73    ///
74    /// This list should not be modified manually.
75    ///
76    /// 此列表不应手动修改。
77    pub basic_front_resource_list: Vec<String>,
78
79    /// Rendering layer information: (resource_id, [position, size], ignore_render_layer).
80    ///
81    /// 渲染层级信息:(资源ID, [位置, 尺寸], 是否忽略渲染层级)。
82    pub render_layer: Vec<(RustConstructorId, [[f32; 2]; 2], bool)>,
83
84    /// List of currently active resources.
85    ///
86    /// 当前活动的资源列表。
87    pub active_list: Vec<(RustConstructorId, Option<RustConstructorId>)>,
88
89    /// Queue of resources to be rendered in the current frame.
90    ///
91    /// 要在当前帧中呈现的资源队列。
92    pub render_list: Vec<(RustConstructorId, Option<RustConstructorId>)>,
93
94    /// List the loaded fonts.
95    ///
96    /// 列出已加载的字体。
97    pub loaded_fonts: Vec<[String; 2]>,
98
99    /// List the fonts that are currently loading.
100    ///
101    /// 列出正在加载的字体。
102    pub loading_fonts: Vec<[String; 2]>,
103}
104
105unsafe impl Send for App {}
106
107unsafe impl Sync for App {}
108
109impl Default for App {
110    fn default() -> Self {
111        App {
112            rust_constructor_resource: Vec::new(),
113            tick_interval: 50,
114            current_page: String::new(),
115            timer: Timer::default(),
116            frame_times: Vec::new(),
117            last_frame_time: None,
118            basic_front_resource_list: vec![
119                String::from("Image"),
120                String::from("Text"),
121                String::from("CustomRect"),
122            ],
123            render_layer: Vec::new(),
124            active_list: Vec::new(),
125            render_list: Vec::new(),
126            loaded_fonts: Vec::new(),
127            loading_fonts: Vec::new(),
128        }
129    }
130}
131
132impl App {
133    #[inline]
134    pub fn tick_interval(mut self, tick_interval: u128) -> Self {
135        self.tick_interval = tick_interval;
136        self
137    }
138
139    #[inline]
140    pub fn current_page(mut self, current_page: &str) -> Self {
141        self.current_page = current_page.to_string();
142        self
143    }
144
145    /// Draws all resources in the rendering queue at once, discarding all return values.
146    ///
147    /// 一次性绘制渲染队列中的所有资源,会丢弃所有返回值。
148    ///
149    /// This method iterates through all resources in the render list and draws them.
150    /// It's not recommended for production use due to error handling limitations.
151    ///
152    /// 此方法遍历渲染列表中的所有资源并绘制它们。由于错误处理限制,不建议在生产环境中使用。
153    ///
154    /// # Arguments
155    ///
156    /// * `ui` - The UI context for drawing
157    ///
158    /// # 参数
159    ///
160    /// * `ui` - 用于绘制的UI上下文
161    pub fn draw_resources(&mut self, ui: &mut Ui) {
162        for i in 0..self.render_list.len() {
163            let _ = self.draw_resource_by_index(ui, i);
164        }
165    }
166
167    /// Draws a specific resource by its index in the rendering queue.
168    ///
169    /// 根据资源在渲染队列中的索引值绘制特定资源。
170    ///
171    /// This method handles the rendering of different resource types including:
172    /// - Images with various loading methods and transformations
173    /// - Text with formatting, selection, and hyperlink support
174    /// - Custom rectangles with borders and styling
175    ///
176    /// 此方法处理不同类型资源的渲染,包括:
177    /// - 具有各种加载方法和变换的图像
178    /// - 具有格式设置、选择和超链接支持的文本
179    /// - 具有边框和样式的自定义矩形
180    ///
181    /// # Arguments
182    ///
183    /// * `ui` - The UI context for drawing
184    /// * `index` - The index of the resource in the render list
185    ///
186    /// # Returns
187    ///
188    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource
189    /// cannot be found or drawn.
190    ///
191    /// # 参数
192    ///
193    /// * `ui` - 用于绘制的UI上下文
194    /// * `index` - 资源在渲染列表中的索引
195    ///
196    /// # 返回值
197    ///
198    /// 成功时返回`Ok(())`,如果资源无法找到或绘制则返回`Err(RustConstructorError)`。
199    pub fn draw_resource_by_index(
200        &mut self,
201        ui: &mut Ui,
202        index: usize,
203    ) -> Result<(), RustConstructorError> {
204        if let Some(render_resource) = self.render_list.clone().get(index) {
205            match &*render_resource.0.discern_type {
206                "Image" => {
207                    let image = self.get_resource::<Image>(&RustConstructorId {
208                        name: render_resource.0.name.clone(),
209                        discern_type: "Image".to_string(),
210                    })?;
211                    if image.display_info.enable {
212                        let mut image = image.clone();
213                        match image.image_load_method {
214                            ImageLoadMethod::ByPath((ref path, flip)) => {
215                                if *path != image.last_frame_path {
216                                    if let Ok(mut file) = File::open(path) {
217                                        let mut buffer = Vec::new();
218                                        file.read_to_end(&mut buffer).unwrap();
219                                        let img_bytes = buffer;
220                                        let img = image::load_from_memory(&img_bytes).unwrap();
221                                        let color_data = match flip {
222                                            [true, true] => img.fliph().flipv().into_rgba8(),
223                                            [true, false] => img.fliph().into_rgba8(),
224                                            [false, true] => img.flipv().into_rgba8(),
225                                            _ => img.into_rgba8(),
226                                        };
227                                        let (w, h) = (color_data.width(), color_data.height());
228                                        let raw_data: Vec<u8> = color_data.into_raw();
229
230                                        let color_image = ColorImage::from_rgba_unmultiplied(
231                                            [w as usize, h as usize],
232                                            &raw_data,
233                                        );
234                                        let loaded_image_texture = ui.load_texture(
235                                            &render_resource.0.name,
236                                            color_image,
237                                            TextureOptions::LINEAR,
238                                        );
239                                        image.texture =
240                                            Some(DebugTextureHandle::new(&loaded_image_texture));
241                                    } else {
242                                        return Err(RustConstructorError {
243                                            error_id: "ImageLoadFailed".to_string(),
244                                            description: format!(
245                                                "Failed to load an image from the path '{path}'.",
246                                            ),
247                                        });
248                                    };
249                                };
250                            }
251                            ImageLoadMethod::ByTexture(ref texture) => {
252                                image.texture = Some(texture.clone());
253                            }
254                        };
255                        [image.position, image.size] = position_size_processor(
256                            image.basic_front_resource_config.position_size_config,
257                            ui,
258                        );
259                        if !image.display_info.hidden {
260                            if let Some(clip_rect) = image.basic_front_resource_config.clip_rect {
261                                let [min, size] = position_size_processor(clip_rect, ui);
262                                ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
263                            };
264                            if let Some(texture) = &image.texture {
265                                let rect = Rect::from_min_size(
266                                    Pos2::new(image.position[0], image.position[1]),
267                                    Vec2::new(image.size[0], image.size[1]),
268                                );
269
270                                // 直接绘制图片
271                                egui::Image::new(ImageSource::Texture((&texture.0).into()))
272                                    .tint(Color32::from_rgba_unmultiplied(
273                                        image.overlay_color[0],
274                                        image.overlay_color[1],
275                                        image.overlay_color[2],
276                                        (image.alpha as f32 * image.overlay_alpha as f32 / 255_f32)
277                                            as u8,
278                                    ))
279                                    .bg_fill(Color32::from_rgba_unmultiplied(
280                                        image.background_color[0],
281                                        image.background_color[1],
282                                        image.background_color[2],
283                                        (image.alpha as f32 * image.background_alpha as f32
284                                            / 255_f32)
285                                            as u8,
286                                    ))
287                                    .rotate(
288                                        image.rotate_angle,
289                                        [
290                                            image.rotate_center[0] / image.size[0],
291                                            image.rotate_center[1] / image.size[1],
292                                        ]
293                                        .into(),
294                                    )
295                                    .paint_at(ui, rect)
296                            };
297                            if image.basic_front_resource_config.clip_rect.is_some() {
298                                ui.set_clip_rect(Rect::from_min_size(
299                                    [0_f32, 0_f32].into(),
300                                    [ui.available_width(), ui.available_height()].into(),
301                                ));
302                            };
303                        };
304                        match image.image_load_method {
305                            ImageLoadMethod::ByPath((ref path, _)) => {
306                                image.last_frame_path = path.clone()
307                            }
308                            ImageLoadMethod::ByTexture(_) => {}
309                        };
310                        self.replace_resource(&render_resource.0.name, image)?;
311                    };
312                }
313                "Text" => {
314                    let text = self.get_resource::<Text>(&RustConstructorId {
315                        name: render_resource.0.name.clone(),
316                        discern_type: "Text".to_string(),
317                    })?;
318                    if text.display_info.enable {
319                        let mut text = text.clone();
320                        [_, text.truncate_size] = position_size_processor(
321                            text.basic_front_resource_config.position_size_config,
322                            ui,
323                        );
324                        let display_content = if text.content.is_empty()
325                            || text
326                                .basic_front_resource_config
327                                .position_size_config
328                                .origin_size
329                                .contains(&0_f32)
330                        {
331                            "".to_string()
332                        } else {
333                            let original_galley = ui.fonts_mut(|f| {
334                                f.layout(
335                                    text.content.to_string(),
336                                    FontId::proportional(text.font_size),
337                                    Color32::default(),
338                                    text.truncate_size[0],
339                                )
340                            });
341
342                            let mut truncated = text.content.to_string();
343                            let mut ellipsis = "";
344                            if original_galley.size().y > text.truncate_size[1] {
345                                // 如果超出,逐步缩短文本直到加上省略号后能放下
346                                ellipsis = "...";
347
348                                while !truncated.is_empty() {
349                                    let test_text = format!("{}{}", truncated, ellipsis);
350                                    let test_galley = ui.fonts_mut(|f| {
351                                        f.layout(
352                                            test_text,
353                                            FontId::proportional(text.font_size),
354                                            Color32::default(),
355                                            text.truncate_size[0],
356                                        )
357                                    });
358
359                                    if test_galley.size().y <= text.truncate_size[1] {
360                                        break;
361                                    }
362
363                                    // 移除最后一个字符
364                                    truncated.pop();
365                                }
366                            };
367                            format!("{}{}", truncated, ellipsis)
368                        };
369                        // 计算文本大小
370                        let galley: Arc<Galley> = ui.fonts_mut(|f| {
371                            f.layout(
372                                display_content.to_string(),
373                                if !text.font.is_empty() {
374                                    if self.loaded_fonts.iter().any(|x| x[0] == text.font) {
375                                        FontId::new(
376                                            text.font_size,
377                                            FontFamily::Name(text.font.clone().into()),
378                                        )
379                                    } else {
380                                        FontId::proportional(text.font_size)
381                                    }
382                                } else {
383                                    FontId::proportional(text.font_size)
384                                },
385                                Color32::from_rgba_unmultiplied(
386                                    text.color[0],
387                                    text.color[1],
388                                    text.color[2],
389                                    text.alpha,
390                                ),
391                                text.truncate_size[0],
392                            )
393                        });
394                        text.size = [
395                            if text.auto_fit[0] {
396                                galley.size().x
397                            } else {
398                                text.truncate_size[0]
399                            },
400                            if text.auto_fit[1] {
401                                galley.size().y
402                            } else {
403                                text.truncate_size[1]
404                            },
405                        ];
406                        text.actual_size = [galley.size().x, galley.size().y];
407                        [text.position, _] = position_size_processor(
408                            text.basic_front_resource_config
409                                .position_size_config
410                                .x_size_grid(0_f32, 0_f32)
411                                .y_size_grid(0_f32, 0_f32)
412                                .origin_size(text.size[0], text.size[1]),
413                            ui,
414                        );
415                        // 查找超链接索引值
416                        if text.last_frame_content != display_content {
417                            text.hyperlink_index.clear();
418
419                            // 创建字节索引到字符索引的映射
420                            let byte_to_char_map: std::collections::HashMap<usize, usize> =
421                                display_content
422                                    .char_indices()
423                                    .enumerate()
424                                    .map(|(char_idx, (byte_idx, _))| (byte_idx, char_idx))
425                                    .collect();
426
427                            for (hyperlink_text, method) in &text.hyperlink_text {
428                                let matches: Vec<(usize, &str)> =
429                                    display_content.match_indices(hyperlink_text).collect();
430                                let text_char_count = hyperlink_text.chars().count();
431
432                                if let HyperlinkSelectMethod::All(url) = method {
433                                    for (byte_index, _) in matches {
434                                        if let Some(&start_char_index) =
435                                            byte_to_char_map.get(&byte_index)
436                                        {
437                                            text.hyperlink_index.push((
438                                                start_char_index,
439                                                start_char_index + text_char_count,
440                                                url.clone(),
441                                            ));
442                                        };
443                                    }
444                                } else if let HyperlinkSelectMethod::Segment(list) = method {
445                                    for (index, url) in list {
446                                        if *index >= matches.len() {
447                                            continue;
448                                        };
449                                        let (byte_index, _) = matches[*index];
450                                        if let Some(&start_char_index) =
451                                            byte_to_char_map.get(&byte_index)
452                                        {
453                                            text.hyperlink_index.push((
454                                                start_char_index,
455                                                start_char_index + text_char_count,
456                                                url.clone(),
457                                            ));
458                                        };
459                                    }
460                                };
461                            }
462                        };
463                        if !text.display_info.hidden {
464                            // 使用绝对定位放置文本
465                            let rect =
466                                Rect::from_min_size(text.position.into(), text.actual_size.into());
467                            // 绘制背景颜色
468                            ui.painter().rect_filled(
469                                rect,
470                                text.background_rounding,
471                                Color32::from_rgba_unmultiplied(
472                                    text.background_color[0],
473                                    text.background_color[1],
474                                    text.background_color[2],
475                                    text.background_alpha,
476                                ),
477                            );
478
479                            if let Some(clip_rect) = text.basic_front_resource_config.clip_rect {
480                                let [min, size] = position_size_processor(clip_rect, ui);
481                                ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
482                            };
483
484                            // 绘制文本
485                            ui.painter().galley(
486                                text.position.into(),
487                                galley.clone(),
488                                Color32::from_rgba_unmultiplied(
489                                    text.color[0],
490                                    text.color[1],
491                                    text.color[2],
492                                    text.alpha,
493                                ),
494                            );
495
496                            // 绘制超链接
497                            for (start, end, _) in &text.hyperlink_index {
498                                // 获取超链接文本的范围
499                                let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
500                                let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
501
502                                let start_pos = start_cursor.left_top();
503                                let end_pos = end_cursor.right_top();
504                                // 绘制超链接下划线
505                                // 检查超链接是否跨行
506                                if start_cursor.min.y == end_cursor.min.y {
507                                    // 单行超链接
508                                    let underline_y = text.position[1]
509                                        + start_pos.y
510                                        + galley.rows.first().map_or(14.0, |row| row.height())
511                                        - 2.0;
512
513                                    // 绘制下划线
514                                    let color = Color32::from_rgba_unmultiplied(
515                                        text.color[0],
516                                        text.color[1],
517                                        text.color[2],
518                                        text.alpha,
519                                    );
520
521                                    ui.painter().line_segment(
522                                        [
523                                            Pos2::new(text.position[0] + start_pos.x, underline_y),
524                                            Pos2::new(text.position[0] + end_pos.x, underline_y),
525                                        ],
526                                        Stroke::new(text.font_size / 10_f32, color),
527                                    );
528                                } else {
529                                    // 多行超链接
530                                    let row_height =
531                                        galley.rows.first().map_or(14.0, |row| row.height()); // 默认行高14.0
532
533                                    // 计算起始行和结束行的索引
534                                    let start_row = (start_pos.y / row_height).round() as usize;
535                                    let end_row = (end_pos.y / row_height).round() as usize;
536
537                                    for row in start_row..=end_row {
538                                        let row_y =
539                                            text.position[1] + row as f32 * row_height + row_height
540                                                - 2.0; // 行底部稍微上移一点绘制下划线
541
542                                        // 获取当前行的矩形范围
543                                        if let Some(current_row) = galley.rows.get(row) {
544                                            let row_rect = current_row.rect();
545
546                                            let color = Color32::from_rgba_unmultiplied(
547                                                text.color[0],
548                                                text.color[1],
549                                                text.color[2],
550                                                text.alpha,
551                                            );
552
553                                            if row == start_row {
554                                                // 第一行从文本开始位置到行尾
555                                                ui.painter().line_segment(
556                                                    [
557                                                        Pos2::new(
558                                                            text.position[0] + start_pos.x,
559                                                            row_y,
560                                                        ),
561                                                        Pos2::new(
562                                                            text.position[0] + row_rect.max.x,
563                                                            row_y,
564                                                        ),
565                                                    ],
566                                                    Stroke::new(text.font_size / 10_f32, color),
567                                                );
568                                            } else if row == end_row {
569                                                // 最后一行从行首到文本结束位置
570                                                ui.painter().line_segment(
571                                                    [
572                                                        Pos2::new(
573                                                            text.position[0] + row_rect.min.x,
574                                                            row_y,
575                                                        ),
576                                                        Pos2::new(
577                                                            text.position[0] + end_pos.x,
578                                                            row_y,
579                                                        ),
580                                                    ],
581                                                    Stroke::new(text.font_size / 10_f32, color),
582                                                );
583                                            } else {
584                                                // 中间整行下划线
585                                                ui.painter().line_segment(
586                                                    [
587                                                        Pos2::new(
588                                                            text.position[0] + row_rect.min.x,
589                                                            row_y,
590                                                        ),
591                                                        Pos2::new(
592                                                            text.position[0] + row_rect.max.x,
593                                                            row_y,
594                                                        ),
595                                                    ],
596                                                    Stroke::new(text.font_size / 10_f32, color),
597                                                );
598                                            };
599                                        };
600                                    }
601                                };
602                            }
603
604                            if text.selectable {
605                                // 处理选择逻辑
606                                let cursor_at_pointer = |pointer_pos: Vec2| -> usize {
607                                    let relative_pos = pointer_pos - text.position.into();
608                                    let cursor = galley.cursor_from_pos(relative_pos);
609                                    cursor.index
610                                };
611
612                                let fullscreen_detect_result = ui.input(|i| i.pointer.clone());
613                                let rect = Rect::from_min_size(
614                                    text.position.into(),
615                                    text.actual_size.into(),
616                                );
617                                let detect_result = ui.interact(
618                                    rect,
619                                    Id::new(&render_resource.0.name),
620                                    Sense::click_and_drag(),
621                                );
622
623                                if !detect_result.clicked()
624                                    && (fullscreen_detect_result.any_click()
625                                        || fullscreen_detect_result.any_pressed())
626                                {
627                                    text.selection = None;
628                                };
629
630                                if let Some(index) =
631                                    self.get_render_layer_resource(&RustConstructorId {
632                                        name: render_resource.0.name.clone(),
633                                        discern_type: "Text".to_string(),
634                                    })
635                                    && let Some(mouse_pos) = fullscreen_detect_result.interact_pos()
636                                    && self.resource_get_focus(
637                                        index,
638                                        mouse_pos.into(),
639                                        false,
640                                        vec![],
641                                    )
642                                    && (detect_result.clicked() || detect_result.drag_started())
643                                {
644                                    let cursor = cursor_at_pointer(mouse_pos.to_vec2());
645                                    text.selection = Some((cursor, cursor));
646                                };
647
648                                if detect_result.dragged()
649                                    && text.selection.is_some()
650                                    && let Some(pointer_pos) =
651                                        ui.input(|i| i.pointer.interact_pos())
652                                {
653                                    let cursor = cursor_at_pointer(pointer_pos.to_vec2());
654                                    if let Some((start, _)) = text.selection {
655                                        text.selection = Some((start, cursor));
656                                    };
657                                };
658
659                                if text.selection.is_some()
660                                    && ui.input(|input| {
661                                        input.key_released(Key::A) && input.modifiers.command
662                                    })
663                                {
664                                    text.selection = Some((0, display_content.chars().count()));
665                                };
666
667                                // 处理复制操作
668                                let copy_triggered = ui.input(|input| {
669                                    let c_released = input.key_released(Key::C);
670                                    let cmd_pressed = input.modifiers.command;
671                                    c_released && cmd_pressed
672                                });
673                                if copy_triggered && let Some((start, end)) = text.selection {
674                                    let (start, end) = (start.min(end), start.max(end));
675                                    let chars: Vec<char> = display_content.chars().collect();
676                                    if start <= chars.len() && end <= chars.len() && start < end {
677                                        let selected_text: String =
678                                            chars[start..end].iter().collect();
679                                        ui.copy_text(selected_text);
680                                    };
681                                };
682
683                                // 绘制选择区域背景
684                                if let Some((start, end)) = text.selection {
685                                    let (start, end) = (start.min(end), start.max(end));
686                                    if start != end {
687                                        // 获取选择区域的范围
688                                        let start_cursor =
689                                            galley.pos_from_cursor(CCursor::new(start));
690                                        let end_cursor = galley.pos_from_cursor(CCursor::new(end));
691
692                                        let start_pos = start_cursor.left_top();
693                                        let end_pos = end_cursor.right_top();
694                                        // 选择框绘制
695                                        if start_pos.y == end_pos.y {
696                                            // 单行选择
697                                            let rows = &galley.rows;
698                                            let row_height = if !rows.is_empty() {
699                                                // 获取实际行的高度
700                                                if let Some(row) = rows.first() {
701                                                    row.height()
702                                                } else {
703                                                    text.actual_size[1]
704                                                        / display_content.lines().count() as f32
705                                                }
706                                            } else {
707                                                text.actual_size[1]
708                                                    / display_content.lines().count() as f32
709                                            };
710
711                                            let selection_rect = Rect::from_min_max(
712                                                Pos2::new(
713                                                    text.position[0] + start_pos.x,
714                                                    text.position[1] + start_pos.y,
715                                                ),
716                                                Pos2::new(
717                                                    text.position[0] + end_pos.x,
718                                                    text.position[1] + start_pos.y + row_height,
719                                                ),
720                                            );
721                                            ui.painter().rect_filled(
722                                                selection_rect,
723                                                0.0,
724                                                Color32::from_rgba_unmultiplied(0, 120, 255, 100),
725                                            );
726                                        } else {
727                                            // 多行选择 - 为每行创建精确的矩形
728                                            let rows = &galley.rows;
729                                            let row_height = if !rows.is_empty() {
730                                                rows[0].height()
731                                            } else {
732                                                text.actual_size[1]
733                                                    / display_content.lines().count() as f32
734                                            };
735
736                                            // 计算选择的上下边界
737                                            let selection_top =
738                                                text.position[1] + start_pos.y.min(end_pos.y);
739                                            let selection_bottom =
740                                                text.position[1] + start_pos.y.max(end_pos.y);
741
742                                            // 确定起始行和结束行的索引
743                                            let start_row_index =
744                                                (start_pos.y / row_height).floor() as usize;
745                                            let end_row_index =
746                                                (end_pos.y / row_height).floor() as usize;
747                                            let (first_row_index, last_row_index) =
748                                                if start_row_index <= end_row_index {
749                                                    (start_row_index, end_row_index)
750                                                } else {
751                                                    (end_row_index, start_row_index)
752                                                };
753
754                                            for (i, row) in rows.iter().enumerate() {
755                                                let row_y =
756                                                    text.position[1] + row_height * i as f32;
757                                                let row_bottom = row_y + row_height;
758                                                // 检查当前行是否与选择区域相交
759                                                if row_bottom > selection_top
760                                                    && row_y <= selection_bottom
761                                                {
762                                                    let left = if i == first_row_index {
763                                                        // 首行 - 从选择开始位置开始
764                                                        text.position[0] + start_pos.x
765                                                    } else {
766                                                        // 非首行 - 从行首开始
767                                                        text.position[0] + row.rect().min.x
768                                                    };
769
770                                                    let right = if i == last_row_index {
771                                                        // 尾行 - 到选择结束位置结束
772                                                        text.position[0] + end_pos.x
773                                                    } else {
774                                                        // 非尾行 - 到行尾结束
775                                                        text.position[0] + row.rect().max.x
776                                                    };
777
778                                                    let selection_rect = Rect::from_min_max(
779                                                        Pos2::new(left, row_y),
780                                                        Pos2::new(right, row_bottom),
781                                                    );
782
783                                                    // 确保矩形有效
784                                                    if selection_rect.width() > 0.0
785                                                        && selection_rect.height() > 0.0
786                                                    {
787                                                        ui.painter().rect_filled(
788                                                            selection_rect,
789                                                            0.0,
790                                                            Color32::from_rgba_unmultiplied(
791                                                                0, 120, 255, 100,
792                                                            ),
793                                                        );
794                                                    };
795                                                };
796                                            }
797                                        };
798                                    };
799                                };
800                            };
801
802                            // 处理超链接操作
803                            for (start, end, url) in &text.hyperlink_index {
804                                // 获取超链接文本的范围
805                                let start_cursor = galley.pos_from_cursor(CCursor::new(*start));
806                                let end_cursor = galley.pos_from_cursor(CCursor::new(*end));
807
808                                let start_pos = start_cursor.left_top();
809                                let end_pos = end_cursor.right_top();
810
811                                let row_height =
812                                    galley.rows.first().map_or(14.0, |row| row.height());
813
814                                // 为超链接创建交互响应对象
815                                let link_responses = if start_cursor.min.y == end_cursor.min.y {
816                                    // 单行超链接
817                                    let link_rect = Rect::from_min_max(
818                                        Pos2::new(
819                                            text.position[0] + start_pos.x,
820                                            text.position[1] + start_pos.y,
821                                        ),
822                                        Pos2::new(
823                                            text.position[0] + end_pos.x,
824                                            text.position[1] + start_pos.y + row_height,
825                                        ),
826                                    );
827                                    vec![ui.interact(
828                                        link_rect,
829                                        Id::new(format!(
830                                            "link_{}_{}_{}",
831                                            render_resource.0.name, start, end
832                                        )),
833                                        Sense::click(),
834                                    )]
835                                } else {
836                                    // 多行超链接
837                                    let start_row = (start_pos.y / row_height).round() as usize;
838                                    let end_row = (end_pos.y / row_height).round() as usize;
839                                    let mut responses = Vec::new();
840
841                                    for row in start_row..=end_row {
842                                        if let Some(current_row) = galley.rows.get(row) {
843                                            let row_rect = current_row.rect();
844                                            let row_y = text.position[1] + row as f32 * row_height;
845
846                                            let link_rect = if row == start_row {
847                                                // 第一行从文本开始位置到行尾
848                                                Rect::from_min_max(
849                                                    Pos2::new(
850                                                        text.position[0] + start_pos.x,
851                                                        row_y,
852                                                    ),
853                                                    Pos2::new(
854                                                        text.position[0] + row_rect.max.x,
855                                                        row_y + row_height,
856                                                    ),
857                                                )
858                                            } else if row == end_row {
859                                                // 最后一行从行首到文本结束位置
860                                                Rect::from_min_max(
861                                                    Pos2::new(
862                                                        text.position[0] + row_rect.min.x,
863                                                        row_y,
864                                                    ),
865                                                    Pos2::new(
866                                                        text.position[0] + end_pos.x,
867                                                        row_y + row_height,
868                                                    ),
869                                                )
870                                            } else {
871                                                // 中间整行
872                                                Rect::from_min_max(
873                                                    Pos2::new(
874                                                        text.position[0] + row_rect.min.x,
875                                                        row_y,
876                                                    ),
877                                                    Pos2::new(
878                                                        text.position[0] + row_rect.max.x,
879                                                        row_y + row_height,
880                                                    ),
881                                                )
882                                            };
883
884                                            responses.push(ui.interact(
885                                                link_rect,
886                                                Id::new(format!(
887                                                    "link_{}_{}_{}_row_{}",
888                                                    render_resource.0.name, start, end, row
889                                                )),
890                                                Sense::click(),
891                                            ));
892                                        };
893                                    }
894                                    responses
895                                };
896
897                                // 检查是否正在点击这个超链接
898                                let mut is_pressing_link = false;
899                                for link_response in &link_responses {
900                                    if let Some(index) =
901                                        self.get_render_layer_resource(&RustConstructorId {
902                                            name: render_resource.0.name.clone(),
903                                            discern_type: "Text".to_string(),
904                                        })
905                                        && let Some(mouse_pos) =
906                                            ui.input(|i| i.pointer.interact_pos())
907                                        && self.resource_get_focus(
908                                            index,
909                                            mouse_pos.into(),
910                                            false,
911                                            vec![],
912                                        )
913                                    {
914                                        if link_response.is_pointer_button_down_on()
915                                            && !link_response.drag_started()
916                                        {
917                                            text.selection = None;
918                                            if let Some(pointer_pos) =
919                                                ui.input(|i| i.pointer.interact_pos())
920                                            {
921                                                let relative_pos = pointer_pos
922                                                    - <[f32; 2] as Into<Pos2>>::into(text.position);
923                                                let cursor = galley.cursor_from_pos(relative_pos);
924                                                if cursor.index >= *start && cursor.index <= *end {
925                                                    is_pressing_link = true;
926                                                    break;
927                                                };
928                                            };
929                                        };
930                                        // 检查是否释放了鼠标(点击完成)
931                                        let mut clicked_on_link = false;
932                                        for link_response in &link_responses {
933                                            if link_response.clicked()
934                                                && let Some(pointer_pos) =
935                                                    ui.input(|i| i.pointer.interact_pos())
936                                            {
937                                                let relative_pos = pointer_pos
938                                                    - <[f32; 2] as Into<Pos2>>::into(text.position);
939                                                let cursor = galley.cursor_from_pos(relative_pos);
940                                                if cursor.index >= *start && cursor.index <= *end {
941                                                    clicked_on_link = true;
942                                                    break;
943                                                };
944                                            };
945                                        }
946
947                                        if clicked_on_link {
948                                            // 执行超链接跳转
949                                            if !url.is_empty() {
950                                                ui.open_url(OpenUrl::new_tab(url));
951                                            };
952                                        };
953                                    };
954                                }
955
956                                // 绘制超链接高亮(如果正在点击或悬停)
957                                if is_pressing_link {
958                                    if start_cursor.min.y == end_cursor.min.y {
959                                        // 单行超链接高亮
960                                        let selection_rect = Rect::from_min_max(
961                                            Pos2::new(
962                                                text.position[0] + start_pos.x,
963                                                text.position[1] + start_pos.y,
964                                            ),
965                                            Pos2::new(
966                                                text.position[0] + end_pos.x,
967                                                text.position[1]
968                                                    + start_pos.y
969                                                    + galley
970                                                        .rows
971                                                        .first()
972                                                        .map_or(14.0, |row| row.height()),
973                                            ),
974                                        );
975                                        ui.painter().rect_filled(
976                                            selection_rect,
977                                            0.0,
978                                            Color32::from_rgba_unmultiplied(0, 120, 255, 100),
979                                        );
980                                    } else {
981                                        // 多行超链接高亮
982                                        let row_height =
983                                            galley.rows.first().map_or(14.0, |row| row.height());
984                                        let start_row = (start_pos.y / row_height).round() as usize;
985                                        let end_row = (end_pos.y / row_height).round() as usize;
986
987                                        for row in start_row..=end_row {
988                                            if let Some(current_row) = galley.rows.get(row) {
989                                                let row_rect = current_row.rect();
990
991                                                if row == start_row {
992                                                    // 第一行从文本开始位置到行尾
993                                                    let selection_rect = Rect::from_min_max(
994                                                        Pos2::new(
995                                                            text.position[0] + start_pos.x,
996                                                            text.position[1]
997                                                                + row as f32 * row_height,
998                                                        ),
999                                                        Pos2::new(
1000                                                            text.position[0] + row_rect.max.x,
1001                                                            text.position[1]
1002                                                                + row as f32 * row_height
1003                                                                + row_height,
1004                                                        ),
1005                                                    );
1006                                                    ui.painter().rect_filled(
1007                                                        selection_rect,
1008                                                        0.0,
1009                                                        Color32::from_rgba_unmultiplied(
1010                                                            0, 120, 255, 100,
1011                                                        ),
1012                                                    );
1013                                                } else if row == end_row {
1014                                                    // 最后一行从行首到文本结束位置
1015                                                    let selection_rect = Rect::from_min_max(
1016                                                        Pos2::new(
1017                                                            text.position[0] + row_rect.min.x,
1018                                                            text.position[1]
1019                                                                + row as f32 * row_height,
1020                                                        ),
1021                                                        Pos2::new(
1022                                                            text.position[0] + end_pos.x,
1023                                                            text.position[1]
1024                                                                + row as f32 * row_height
1025                                                                + row_height,
1026                                                        ),
1027                                                    );
1028                                                    ui.painter().rect_filled(
1029                                                        selection_rect,
1030                                                        0.0,
1031                                                        Color32::from_rgba_unmultiplied(
1032                                                            0, 120, 255, 100,
1033                                                        ),
1034                                                    );
1035                                                } else {
1036                                                    // 中间整行高亮
1037                                                    let selection_rect = Rect::from_min_max(
1038                                                        Pos2::new(
1039                                                            text.position[0] + row_rect.min.x,
1040                                                            text.position[1]
1041                                                                + row as f32 * row_height,
1042                                                        ),
1043                                                        Pos2::new(
1044                                                            text.position[0] + row_rect.max.x,
1045                                                            text.position[1]
1046                                                                + row as f32 * row_height
1047                                                                + row_height,
1048                                                        ),
1049                                                    );
1050                                                    ui.painter().rect_filled(
1051                                                        selection_rect,
1052                                                        0.0,
1053                                                        Color32::from_rgba_unmultiplied(
1054                                                            0, 120, 255, 100,
1055                                                        ),
1056                                                    );
1057                                                };
1058                                            };
1059                                        }
1060                                    };
1061                                };
1062                            }
1063                            if text.basic_front_resource_config.clip_rect.is_some() {
1064                                ui.set_clip_rect(Rect::from_min_size(
1065                                    [0_f32, 0_f32].into(),
1066                                    [ui.available_width(), ui.available_height()].into(),
1067                                ));
1068                            };
1069                        } else {
1070                            text.selection = None;
1071                        };
1072                        text.last_frame_content = display_content;
1073                        self.replace_resource(&render_resource.0.name, text)?;
1074                    };
1075                }
1076                "CustomRect" => {
1077                    let custom_rect = self.get_resource::<CustomRect>(&RustConstructorId {
1078                        name: render_resource.0.name.clone(),
1079                        discern_type: "CustomRect".to_string(),
1080                    })?;
1081                    if custom_rect.display_info.enable {
1082                        let mut custom_rect = custom_rect.clone();
1083                        [custom_rect.position, custom_rect.size] = position_size_processor(
1084                            custom_rect.basic_front_resource_config.position_size_config,
1085                            ui,
1086                        );
1087                        if !custom_rect.display_info.hidden {
1088                            if let Some(clip_rect) =
1089                                custom_rect.basic_front_resource_config.clip_rect
1090                            {
1091                                let [min, size] = position_size_processor(clip_rect, ui);
1092                                ui.set_clip_rect(Rect::from_min_size(min.into(), size.into()));
1093                            };
1094                            ui.painter().rect(
1095                                Rect::from_min_max(
1096                                    Pos2::new(custom_rect.position[0], custom_rect.position[1]),
1097                                    Pos2::new(
1098                                        custom_rect.position[0] + custom_rect.size[0],
1099                                        custom_rect.position[1] + custom_rect.size[1],
1100                                    ),
1101                                ),
1102                                custom_rect.rounding,
1103                                if let Some(overlay_alpha) = custom_rect.overlay_alpha {
1104                                    Color32::from_rgba_unmultiplied(
1105                                        (custom_rect.color[0] as f32
1106                                            * custom_rect.overlay_color[0] as f32
1107                                            / 255_f32)
1108                                            as u8,
1109                                        (custom_rect.color[1] as f32
1110                                            * custom_rect.overlay_color[1] as f32
1111                                            / 255_f32)
1112                                            as u8,
1113                                        (custom_rect.color[2] as f32
1114                                            * custom_rect.overlay_color[2] as f32
1115                                            / 255_f32)
1116                                            as u8,
1117                                        (custom_rect.alpha as f32 * overlay_alpha as f32 / 255_f32)
1118                                            as u8,
1119                                    )
1120                                } else {
1121                                    Color32::from_rgba_unmultiplied(
1122                                        custom_rect.color[0],
1123                                        custom_rect.color[1],
1124                                        custom_rect.color[2],
1125                                        custom_rect.alpha,
1126                                    )
1127                                },
1128                                Stroke {
1129                                    width: custom_rect.border_width,
1130                                    color: if let Some(overlay_border_alpha) =
1131                                        custom_rect.overlay_border_alpha
1132                                    {
1133                                        Color32::from_rgba_unmultiplied(
1134                                            (custom_rect.border_color[0] as f32
1135                                                * custom_rect.overlay_border_color[0] as f32
1136                                                / 255_f32)
1137                                                as u8,
1138                                            (custom_rect.border_color[1] as f32
1139                                                * custom_rect.overlay_border_color[1] as f32
1140                                                / 255_f32)
1141                                                as u8,
1142                                            (custom_rect.border_color[2] as f32
1143                                                * custom_rect.overlay_border_color[2] as f32
1144                                                / 255_f32)
1145                                                as u8,
1146                                            (custom_rect.border_alpha as f32
1147                                                * overlay_border_alpha as f32
1148                                                / 255_f32)
1149                                                as u8,
1150                                        )
1151                                    } else {
1152                                        Color32::from_rgba_unmultiplied(
1153                                            custom_rect.border_color[0],
1154                                            custom_rect.border_color[1],
1155                                            custom_rect.border_color[2],
1156                                            custom_rect.border_alpha,
1157                                        )
1158                                    },
1159                                },
1160                                match custom_rect.border_kind {
1161                                    BorderKind::Inside => StrokeKind::Inside,
1162                                    BorderKind::Middle => StrokeKind::Middle,
1163                                    BorderKind::Outside => StrokeKind::Outside,
1164                                },
1165                            );
1166                            if custom_rect.basic_front_resource_config.clip_rect.is_some() {
1167                                ui.set_clip_rect(Rect::from_min_size(
1168                                    [0_f32, 0_f32].into(),
1169                                    [ui.available_width(), ui.available_height()].into(),
1170                                ));
1171                            };
1172                        };
1173                        self.replace_resource(&render_resource.0.name, custom_rect)?;
1174                    };
1175                }
1176                _ => {
1177                    unreachable!()
1178                }
1179            }
1180            Ok(())
1181        } else {
1182            Err(RustConstructorError {
1183                error_id: "IndexOutOfRange".to_string(),
1184                description: format!(
1185                    "The maximum index of the target list is {}, but the index is {index}.",
1186                    self.render_list.len() - 1
1187                ),
1188            })
1189        }
1190    }
1191
1192    /// Generate information for Rust Constructor resources.
1193    ///
1194    /// 生成Rust Constructor资源的信息。
1195    ///
1196    /// This method returns a formatted string containing details about all resources.
1197    /// The level of detail depends on the specified method.
1198    ///
1199    /// 此方法返回一个格式化字符串,包含所有资源的详细信息。
1200    /// 详细程度取决于指定的方法。
1201    ///
1202    /// # Arguments
1203    ///
1204    /// * `describe` - Determines the level of detail in the output
1205    /// * `print` - Determines whether to print
1206    ///
1207    /// # Returns
1208    ///
1209    /// A formatted string with resource information.
1210    ///
1211    /// # 参数
1212    ///
1213    /// * `describe` - 决定输出信息的详细程度
1214    /// * `print` - 决定是否打印
1215    ///
1216    /// # 返回值
1217    ///
1218    /// 包含资源信息的格式化字符串。
1219    pub fn rust_constructor_resource_info(
1220        &self,
1221        describe: ListInfoDescribeMethod,
1222        print: bool,
1223    ) -> String {
1224        let mut text =
1225            String::from("————————————————————————————————————\nRust Constructor Resource Info:\n");
1226        for info in &self.rust_constructor_resource {
1227            if let ListInfoDescribeMethod::Detailed(format) = describe {
1228                text += &if format {
1229                    format!(
1230                        "\nName: {}\nType: {}\nDetail: {:#?}\n",
1231                        info.id.name, info.id.discern_type, info.content,
1232                    )
1233                } else {
1234                    format!(
1235                        "\nName: {}\nType: {}\nDetail: {:?}\n",
1236                        info.id.name, info.id.discern_type, info.content,
1237                    )
1238                };
1239            } else {
1240                text += &format!("\nName: {}\nType: {}\n", info.id.name, info.id.discern_type,)
1241            };
1242        }
1243        if print {
1244            println!("{text}");
1245        };
1246        text
1247    }
1248
1249    /// Generates information about currently active resources.
1250    ///
1251    /// 生成当前活跃资源的信息。
1252    ///
1253    /// This method returns a formatted string containing details about all resources
1254    /// in the active list. The level of detail depends on the specified method.
1255    ///
1256    /// 此方法返回一个格式化字符串,包含活动列表中所有资源的详细信息。
1257    /// 详细程度取决于指定的方法。
1258    ///
1259    /// # Arguments
1260    ///
1261    /// * `describe` - Determines the level of detail in the output
1262    /// * `print` - Determines whether to print
1263    ///
1264    /// # Returns
1265    ///
1266    /// A formatted string with resource information.
1267    ///
1268    /// # 参数
1269    ///
1270    /// * `describe` - 决定输出信息的详细程度
1271    /// * `print` - 决定是否打印
1272    ///
1273    /// # 返回值
1274    ///
1275    /// 包含资源信息的格式化字符串。
1276    pub fn active_list_info(&self, describe: ListInfoDescribeMethod, print: bool) -> String {
1277        let mut text =
1278            String::from("————————————————————————————————————\nResource Active Info:\n");
1279        for info in &self.active_list {
1280            if let ListInfoDescribeMethod::Detailed(format) = describe {
1281                if let Some(index) = self.check_resource_exists(&info.0) {
1282                    text += &if format {
1283                        format!(
1284                            "\nName: {}\nType: {}\nCiter: {:?}\nDetail: {:#?}\n",
1285                            info.0.name,
1286                            info.0.discern_type,
1287                            info.1,
1288                            self.rust_constructor_resource[index],
1289                        )
1290                    } else {
1291                        format!(
1292                            "\nName: {}\nType: {}\nCiter: {:?}\nDetail: {:?}\n",
1293                            info.0.name,
1294                            info.0.discern_type,
1295                            info.1,
1296                            self.rust_constructor_resource[index],
1297                        )
1298                    };
1299                };
1300            } else {
1301                text += &format!(
1302                    "\nName: {}\nType: {}\nCiter: {:?}\n",
1303                    info.0.name, info.0.discern_type, info.1
1304                );
1305            };
1306        }
1307        if print {
1308            println!("{text}");
1309        };
1310        text
1311    }
1312
1313    /// Generates information about the current rendering layers.
1314    ///
1315    /// 生成当前渲染层级的信息。
1316    ///
1317    /// This method returns a formatted string containing details about the rendering
1318    /// layer stack, including resource positions and rendering behavior.
1319    ///
1320    /// 此方法返回一个格式化字符串,包含渲染层级堆栈的详细信息,
1321    /// 包括资源位置和渲染行为。
1322    ///
1323    /// # Arguments
1324    ///
1325    /// * `print` - Determines whether to print
1326    ///
1327    /// # Returns
1328    ///
1329    /// A formatted string with rendering layer information.
1330    ///
1331    /// # 参数
1332    ///
1333    /// * `print` - 决定是否打印
1334    ///
1335    /// # 返回值
1336    ///
1337    /// 包含渲染层级信息的格式化字符串。
1338    pub fn render_layer_info(&self, print: bool) -> String {
1339        let mut text = String::from("————————————————————————————————————\nRender Layer Info:\n");
1340        for (
1341            RustConstructorId { name, discern_type },
1342            [min_position, max_position],
1343            ignore_render_layer,
1344        ) in &self.render_layer
1345        {
1346            text += &format!(
1347                "\nName: {}\nType: {}\nMin Position: {:?}\nMax Position: {:?}\nIgnore Render Layer: {}\n",
1348                name, discern_type, min_position, max_position, ignore_render_layer
1349            )
1350        }
1351        if print {
1352            println!("{text}");
1353        };
1354        text
1355    }
1356
1357    /// Generates information about the current render queue.
1358    ///
1359    /// 生成当前渲染队列的信息。
1360    ///
1361    /// This method returns a formatted string listing all resources in the
1362    /// render queue with their names and types.
1363    ///
1364    /// 此方法返回一个格式化字符串,列出渲染队列中的所有资源及其名称和类型。
1365    ///
1366    /// # Arguments
1367    ///
1368    /// * `print` - Determines whether to print
1369    ///
1370    /// # Returns
1371    ///
1372    /// A formatted string with render queue information.
1373    ///
1374    /// # 参数
1375    ///
1376    /// * `print` - 决定是否打印
1377    ///
1378    /// # 返回值
1379    ///
1380    /// 包含渲染队列信息的格式化字符串。
1381    pub fn render_list_info(&self, print: bool) -> String {
1382        let mut text = String::from("————————————————————————————————————\nRender List Info:\n");
1383        for (RustConstructorId { name, discern_type }, citer) in &self.render_list {
1384            text += &format!(
1385                "\nName: {}\nType: {}\nCiter: {:?}\n",
1386                name, discern_type, citer
1387            )
1388        }
1389        if print {
1390            println!("{text}");
1391        };
1392        text
1393    }
1394
1395    /// Updates the render queue based on active resources.
1396    ///
1397    /// 根据活跃资源更新渲染队列。
1398    ///
1399    /// This method synchronizes the render list with the active list, ensuring that
1400    /// only active basic front resources are included in the rendering queue.
1401    ///
1402    /// 此方法将渲染列表与活跃列表同步,确保只有活跃的基本前端资源包含在渲染队列中。
1403    pub fn update_render_list(&mut self) {
1404        if self.render_list.is_empty() {
1405            for info in &self.active_list {
1406                if self
1407                    .basic_front_resource_list
1408                    .contains(&info.0.discern_type)
1409                {
1410                    self.render_list.push(info.clone());
1411                };
1412            }
1413        } else {
1414            let mut count = 0;
1415            for render_resource in &self.render_list.clone() {
1416                if !self.active_list.contains(render_resource) {
1417                    self.render_list.remove(count);
1418                } else {
1419                    count += 1;
1420                };
1421            }
1422            let mut insert_index = 0;
1423            for info in &self.active_list {
1424                if self
1425                    .basic_front_resource_list
1426                    .contains(&info.0.discern_type)
1427                {
1428                    if !self.render_list.contains(info) {
1429                        self.render_list.insert(insert_index, info.clone());
1430                        insert_index += 1;
1431                    } else if self.render_list[insert_index].cmp(info) == Ordering::Equal {
1432                        insert_index += 1;
1433                    };
1434                };
1435            }
1436        };
1437    }
1438
1439    /// Attempts to move a resource to the front of the render queue, ignoring whether it exists.
1440    ///
1441    /// 请求在渲染队列中插队,且无视申请跳过队列的资源是否存在。
1442    ///
1443    /// This is a safe wrapper around `request_jump_render_list` that suppresses errors.
1444    /// Use when you want to attempt reordering without handling potential errors.
1445    ///
1446    /// 这是`request_jump_render_list`的安全包装器,会抑制错误。当您想要尝试重新排序而不处理潜在错误时使用。
1447    ///
1448    /// # Arguments
1449    ///
1450    /// * `requester` - The resource to move in the queue
1451    /// * `request_type` - How to move the resource (to top or up N layers)
1452    ///
1453    /// # 参数
1454    ///
1455    /// * `requester` - 要在队列中移动的资源
1456    /// * `request_type` - 如何移动资源(到顶部或上移N层)
1457    pub fn try_request_jump_render_list(
1458        &mut self,
1459        requester: RequestMethod,
1460        request_type: RequestType,
1461    ) {
1462        let _ = self.request_jump_render_list(requester, request_type);
1463    }
1464
1465    /// Moves a resource to the front of the render queue with error handling.
1466    ///
1467    /// 将资源移动到渲染队列的前面(含错误处理)。
1468    ///
1469    /// This method allows changing the rendering order of resources by moving a specific
1470    /// resource to the top of the queue or up a specified number of layers.
1471    ///
1472    /// 此方法允许通过将特定资源移动到队列顶部或上移指定层数来更改资源的渲染顺序。
1473    ///
1474    /// # Arguments
1475    ///
1476    /// * `requester` - The resource to move in the queue
1477    /// * `request_type` - How to move the resource (to top or up N layers)
1478    ///
1479    /// # Returns
1480    ///
1481    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource
1482    /// cannot be found.
1483    ///
1484    /// # 参数
1485    ///
1486    /// * `requester` - 要在队列中移动的资源
1487    /// * `request_type` - 如何移动资源(到顶部或上移N层)
1488    ///
1489    /// # 返回值
1490    ///
1491    /// 成功时返回`Ok(())`,如果资源无法找到则返回`Err(RustConstructorError)`。
1492    pub fn request_jump_render_list(
1493        &mut self,
1494        requester: RequestMethod,
1495        request_type: RequestType,
1496    ) -> Result<(), RustConstructorError> {
1497        match requester {
1498            RequestMethod::Id(id) => {
1499                if let Some(index) = self.render_list.iter().position(|x| x.0 == id) {
1500                    self.jump_render_list_processor(index, request_type)?;
1501                    Ok(())
1502                } else {
1503                    Err(RustConstructorError {
1504                        error_id: "RenderResourceNotFound".to_string(),
1505                        description: format!(
1506                            "Render resource '{}({})' not found.",
1507                            id.name, id.discern_type
1508                        ),
1509                    })
1510                }
1511            }
1512            RequestMethod::Citer(citer) => {
1513                for (i, render_resource) in self.render_list.iter().enumerate() {
1514                    if let Some(render_citer) = &render_resource.1
1515                        && render_citer == &citer
1516                    {
1517                        self.jump_render_list_processor(i, request_type)?;
1518                        return Ok(());
1519                    };
1520                }
1521                Err(RustConstructorError {
1522                    error_id: "RenderResourceNotFound".to_string(),
1523                    description: format!(
1524                        "Render resource citer '{}({})' not found.",
1525                        citer.name, citer.discern_type
1526                    ),
1527                })
1528            }
1529        }
1530    }
1531
1532    /// Handle the operation of skipping the rendering queue.
1533    ///
1534    /// 处理跳过渲染队列操作。
1535    ///
1536    /// # Arguments
1537    ///
1538    /// * `requester_index` - The index of the resources to be moved in the queue
1539    /// * `request_type` - How to move the resource (to top or up N layers)
1540    ///
1541    /// # Returns
1542    ///
1543    /// When successful, return `Ok(())`. If the index is out of bounds, return `Err(RustConstructorError)`.
1544    ///
1545    /// # 参数
1546    ///
1547    /// * `requester_index` - 要在队列中移动的资源的索引
1548    /// * `request_type` - 如何移动资源(到顶部或上移N层)
1549    ///
1550    /// # 返回值
1551    ///
1552    /// 成功时返回`Ok(())`,如果索引越界则返回`Err(RustConstructorError)`。
1553    pub fn jump_render_list_processor(
1554        &mut self,
1555        requester_index: usize,
1556        request_type: RequestType,
1557    ) -> Result<(), RustConstructorError> {
1558        if requester_index < self.render_list.len() {
1559            let requester = self.render_list.remove(requester_index);
1560            let new_index = match request_type {
1561                RequestType::Top => self.render_list.len(),
1562                RequestType::Up(up) => {
1563                    if requester_index + up <= self.render_list.len() {
1564                        requester_index + up
1565                    } else {
1566                        self.render_list.len()
1567                    }
1568                }
1569            };
1570            self.render_list.insert(new_index, requester);
1571            Ok(())
1572        } else {
1573            Err(RustConstructorError {
1574                error_id: "IndexOutOfRange".to_string(),
1575                description: format!(
1576                    "The maximum index of the target list is {}, but the index is {requester_index}.",
1577                    self.render_list.len() - 1
1578                ),
1579            })
1580        }
1581    }
1582
1583    /// Updates the rendering layer information for all rendering resources.
1584    ///
1585    /// 更新所有渲染资源的渲染层信息。
1586    ///
1587    /// This method recalculates the rendering layer by processing all resources
1588    /// in the render list and updating their position, size, and rendering properties.
1589    ///
1590    /// 此方法通过处理渲染列表中的所有资源并更新它们的位置、尺寸和渲染属性来重新计算渲染层级。
1591    ///
1592    /// # Arguments
1593    ///
1594    /// * `ui` - The UI context for drawing
1595    ///
1596    /// # Returns
1597    ///
1598    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource
1599    /// cannot be found.
1600    ///
1601    /// # 参数
1602    ///
1603    /// * `ui` - 用于绘制的UI上下文
1604    ///
1605    /// # 返回值
1606    ///
1607    /// 成功时返回`Ok(())`,如果资源无法找到则返回`Err(RustConstructorError)`。
1608    pub fn update_render_layer(&mut self, ui: &Ui) -> Result<(), RustConstructorError> {
1609        self.render_layer.clear();
1610        for info in &self.render_list {
1611            let basic_front_resource = self.get_basic_front_resource(&info.0)?;
1612            if let Some(display_info) = basic_front_resource.display_display_info() {
1613                self.render_layer.push((
1614                    info.0.clone(),
1615                    if let Some(clip_rect) = basic_front_resource
1616                        .display_basic_front_resource_config()
1617                        .clip_rect
1618                    {
1619                        let [position, size] = position_size_processor(clip_rect, ui);
1620                        let [resource_rect, clip_rect] = [
1621                            Rect::from_min_max(
1622                                basic_front_resource.display_position().into(),
1623                                [
1624                                    basic_front_resource.display_position()[0]
1625                                        + basic_front_resource.display_size()[0],
1626                                    basic_front_resource.display_position()[1]
1627                                        + basic_front_resource.display_size()[1],
1628                                ]
1629                                .into(),
1630                            ),
1631                            Rect::from_min_size(position.into(), size.into()),
1632                        ];
1633                        let min = resource_rect.min.max(clip_rect.min);
1634                        let max = resource_rect.max.min(clip_rect.max);
1635
1636                        // 检查是否有交集
1637                        if min.x < max.x && min.y < max.y {
1638                            [min.into(), max.into()]
1639                        } else {
1640                            [[0_f32, 0_f32], [0_f32, 0_f32]]
1641                        }
1642                    } else {
1643                        [
1644                            basic_front_resource.display_position(),
1645                            [
1646                                basic_front_resource.display_position()[0]
1647                                    + basic_front_resource.display_size()[0],
1648                                basic_front_resource.display_position()[1]
1649                                    + basic_front_resource.display_size()[1],
1650                            ],
1651                        ]
1652                    },
1653                    display_info.ignore_render_layer,
1654                ));
1655            };
1656        }
1657        Ok(())
1658    }
1659
1660    /// Draw the rendering layer.
1661    ///
1662    /// 绘制渲染层。
1663    ///
1664    /// This method can visually inspect the rendering status of all rendering
1665    /// resources and promptly correct any issues.
1666    ///
1667    /// 此方法可以直观检查所有渲染资源的渲染情况,并及时修正问题。
1668    ///
1669    /// # Arguments
1670    ///
1671    /// * `ui` - The UI context for drawing
1672    /// * `render_config` - The config of the rendering layer area
1673    /// * `ignore_render` - The config of ignore the rendering layer area
1674    /// * `hover_config` - The config of hover the rendering layer area
1675    ///
1676    /// # 参数
1677    ///
1678    /// * `ui` - 用于绘制的UI上下文
1679    /// * `render_config` - 渲染层区域的配置
1680    /// * `ignore_render_config` - 无视渲染层区域的配置
1681    /// * `hover_config` - 鼠标悬停时的配置
1682    pub fn display_render_layer(
1683        &self,
1684        ui: &mut Ui,
1685        render_config: &RenderConfig,
1686        ignore_render_config: &RenderConfig,
1687        hover_config: Option<&RenderConfig>,
1688    ) {
1689        for (i, (_, point, ignore_render_layer)) in self.render_layer.iter().enumerate() {
1690            match if *ignore_render_layer {
1691                ignore_render_config
1692            } else {
1693                render_config
1694            } {
1695                RenderConfig::Rect(
1696                    corner_radius,
1697                    fill_color,
1698                    border_color,
1699                    border_width,
1700                    border_kind,
1701                ) => {
1702                    let rect = Rect::from_min_max(point[0].into(), point[1].into());
1703                    ui.painter().rect(
1704                        rect,
1705                        CornerRadius {
1706                            nw: corner_radius[0],
1707                            ne: corner_radius[1],
1708                            sw: corner_radius[2],
1709                            se: corner_radius[3],
1710                        },
1711                        Color32::from_rgba_unmultiplied(
1712                            fill_color[0],
1713                            fill_color[1],
1714                            fill_color[2],
1715                            fill_color[3],
1716                        ),
1717                        Stroke::new(
1718                            *border_width,
1719                            Color32::from_rgba_unmultiplied(
1720                                border_color[0],
1721                                border_color[1],
1722                                border_color[2],
1723                                border_color[3],
1724                            ),
1725                        ),
1726                        match *border_kind {
1727                            BorderKind::Inside => StrokeKind::Inside,
1728                            BorderKind::Middle => StrokeKind::Middle,
1729                            BorderKind::Outside => StrokeKind::Outside,
1730                        },
1731                    );
1732                }
1733                RenderConfig::Line(width, color) => {
1734                    ui.painter().line_segment(
1735                        [point[0].into(), point[1].into()],
1736                        Stroke::new(
1737                            *width,
1738                            Color32::from_rgba_unmultiplied(color[0], color[1], color[2], color[3]),
1739                        ),
1740                    );
1741                }
1742            };
1743            if let Some(hover_config) = hover_config
1744                && let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos())
1745                && self.resource_get_focus(i, mouse_pos.into(), true, vec![])
1746            {
1747                match hover_config {
1748                    RenderConfig::Rect(
1749                        corner_radius,
1750                        fill_color,
1751                        border_color,
1752                        border_width,
1753                        border_kind,
1754                    ) => {
1755                        let rect = Rect::from_min_max(point[0].into(), point[1].into());
1756                        ui.painter().rect(
1757                            rect,
1758                            CornerRadius {
1759                                nw: corner_radius[0],
1760                                ne: corner_radius[1],
1761                                sw: corner_radius[2],
1762                                se: corner_radius[3],
1763                            },
1764                            Color32::from_rgba_unmultiplied(
1765                                fill_color[0],
1766                                fill_color[1],
1767                                fill_color[2],
1768                                fill_color[3],
1769                            ),
1770                            Stroke::new(
1771                                *border_width,
1772                                Color32::from_rgba_unmultiplied(
1773                                    border_color[0],
1774                                    border_color[1],
1775                                    border_color[2],
1776                                    border_color[3],
1777                                ),
1778                            ),
1779                            match *border_kind {
1780                                BorderKind::Inside => StrokeKind::Inside,
1781                                BorderKind::Middle => StrokeKind::Middle,
1782                                BorderKind::Outside => StrokeKind::Outside,
1783                            },
1784                        );
1785                    }
1786                    RenderConfig::Line(width, color) => {
1787                        ui.painter().line_segment(
1788                            [point[0].into(), point[1].into()],
1789                            Stroke::new(
1790                                *width,
1791                                Color32::from_rgba_unmultiplied(
1792                                    color[0], color[1], color[2], color[3],
1793                                ),
1794                            ),
1795                        );
1796                    }
1797                };
1798            };
1799        }
1800    }
1801
1802    /// Search for resources in the render list by ID.
1803    ///
1804    /// 通过ID在渲染列表中查找资源。
1805    ///
1806    /// # Arguments
1807    ///
1808    /// * `id` - The ID of the resource to search for
1809    ///
1810    /// # Returns
1811    ///
1812    /// The index of the resource in the render list, or None if not found
1813    ///
1814    /// # 参数
1815    ///
1816    /// * `id` - 要查找的资源的ID
1817    ///
1818    /// # 返回值
1819    ///
1820    /// 渲染列表中的资源索引,如果没有找到则为None
1821    pub fn get_render_layer_resource(&self, id: &RustConstructorId) -> Option<usize> {
1822        self.render_layer.iter().position(|x| &x.0 == id)
1823    }
1824
1825    /// Check whether the resource has obtained the mouse focus.
1826    ///
1827    /// 检查资源是否获取鼠标焦点。
1828    ///
1829    /// Use this method to ensure that mouse operations do not trigger
1830    /// multiple components simultaneously, causing confusion.
1831    ///
1832    /// 使用此方法以保证鼠标操作不会同时触发多个组件产生混乱。
1833    ///
1834    /// # Arguments
1835    ///
1836    /// * `index` - The index value of the rendering resource
1837    /// * `mouse_pos` - The position of the mouse
1838    /// * `need_contains_mouse` - Is it necessary to include the mouse position
1839    /// * `ignore_render_layer` - The range of indices to ignore in the render layer
1840    ///
1841    /// # Returns
1842    ///
1843    /// Return true if the resource is not blocked; otherwise, return false.
1844    ///
1845    /// # 参数
1846    ///
1847    /// * `index` - 渲染资源的索引值
1848    /// * `mouse_pos` - 鼠标的位置
1849    /// * `need_contains_mouse` - 是否需要包含鼠标位置
1850    /// * `ignore_render_layer` - 要忽略的渲染层索引范围
1851    ///
1852    /// # 返回值
1853    ///
1854    /// 如果资源未被阻挡,返回true,否则返回false。
1855    pub fn resource_get_focus(
1856        &self,
1857        index: usize,
1858        mouse_pos: [f32; 2],
1859        need_contains_mouse: bool,
1860        ignore_render_layer: Vec<[usize; 2]>,
1861    ) -> bool {
1862        let mut ignore_list = Vec::new();
1863        for range in ignore_render_layer {
1864            for i in 0..range[1] {
1865                ignore_list.push(range[0] + i);
1866            }
1867        }
1868        for i in index + 1..self.render_layer.len() {
1869            let point = self.render_layer[i].1;
1870            if mouse_pos[0] >= point[0][0]
1871                && mouse_pos[1] >= point[0][1]
1872                && mouse_pos[0] <= point[1][0]
1873                && mouse_pos[1] <= point[1][1]
1874                && !self.render_layer[i].2
1875                && !ignore_list.contains(&i)
1876            {
1877                return false;
1878            };
1879        }
1880        let target_point = self.render_layer[index].1;
1881        !need_contains_mouse
1882            || mouse_pos[0] <= target_point[1][0]
1883                && mouse_pos[0] >= target_point[0][0]
1884                && mouse_pos[1] <= target_point[1][1]
1885                && mouse_pos[1] >= target_point[0][1]
1886    }
1887
1888    /// Mark active resources.
1889    ///
1890    /// 标记活跃资源。
1891    ///
1892    /// This method will be automatically called by the Rust Constructor without
1893    /// the need for manual control.
1894    ///
1895    /// 此方法会被Rust Constructor自动调用,无需手动控制。
1896    ///
1897    /// # Arguments
1898    ///
1899    /// * `id` - The unique identifier of the resource
1900    ///
1901    /// # Returns
1902    ///
1903    /// When a success mark is made, return `Ok(())`, and when the resource is not found,
1904    /// return `Err(RustConstructorError)`.
1905    ///
1906    /// # 参数
1907    ///
1908    /// * `id` - 资源的唯一标识符
1909    ///
1910    /// # 返回值
1911    ///
1912    /// 成功标记时返回`Ok(())`,找不到资源时返回`Err(RustConstructorError)`。
1913    pub fn add_active_resource(
1914        &mut self,
1915        id: &RustConstructorId,
1916    ) -> Result<(), RustConstructorError> {
1917        self.active_list.push((
1918            id.clone(),
1919            if let [Some(citer_name), Some(citer_type)] = [
1920                get_tag("citer_name", &self.get_box_resource(id)?.display_tags()),
1921                get_tag("citer_type", &self.get_box_resource(id)?.display_tags()),
1922            ] {
1923                Some(RustConstructorId {
1924                    name: citer_name.1,
1925                    discern_type: citer_type.1,
1926                })
1927            } else {
1928                None
1929            },
1930        ));
1931        Ok(())
1932    }
1933
1934    /// Adds a new resource to the application with the specified name.
1935    ///
1936    /// 添加一个新资源到应用程序中,并指定名称。
1937    ///
1938    /// This method registers a resource instance with a unique name. If the name is already in use
1939    /// or invalid, an error is returned. For certain resource types like SplitTime, it automatically
1940    /// initializes time values.
1941    ///
1942    /// 此方法使用唯一名称注册资源实例。如果名称已存在或无效,则返回错误。
1943    /// 对于某些资源类型(如 SplitTime),它会自动初始化时间值。
1944    ///
1945    /// # Arguments
1946    ///
1947    /// * `name` - A unique identifier for the resource
1948    /// * `resource` - The resource instance to add
1949    ///
1950    /// # Returns
1951    ///
1952    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be added.
1953    ///
1954    /// # 参数
1955    ///
1956    /// * `name` - 资源的唯一标识符
1957    /// * `resource` - 要添加的资源实例
1958    ///
1959    /// # 返回值
1960    ///
1961    /// 成功时返回 `Ok(())`,如果资源无法添加则返回 `Err(RustConstructorError)`。
1962    pub fn add_resource<T: RustConstructorResource + 'static>(
1963        &mut self,
1964        name: &str,
1965        mut resource: T,
1966    ) -> Result<(), RustConstructorError> {
1967        let discern_type = &*type_processor(&resource);
1968        if self
1969            .check_resource_exists(&RustConstructorId {
1970                name: name.to_string(),
1971                discern_type: discern_type.to_string(),
1972            })
1973            .is_some()
1974        {
1975            return Err(RustConstructorError {
1976                error_id: "ResourceNameRepetition".to_string(),
1977                description: format!("Resource '{name}({discern_type})' has already existed."),
1978            });
1979        };
1980        if name.is_empty() {
1981            return Err(RustConstructorError {
1982                error_id: "ResourceUntitled".to_string(),
1983                description: "All resources must have a valid name.".to_string(),
1984            });
1985        };
1986        match discern_type {
1987            "SplitTime" => {
1988                let split_time = downcast_resource_mut::<SplitTime>(&mut resource)?;
1989                split_time.time = [self.timer.now_time, self.timer.total_time];
1990            }
1991            "Background" => {
1992                let background = downcast_resource_mut::<Background>(&mut resource)?;
1993                match &background.background_type {
1994                    BackgroundType::CustomRect(config) => {
1995                        let mut custom_rect = CustomRect::default().from_config(config);
1996                        if background.use_background_tags {
1997                            custom_rect.modify_tags(&background.tags, false);
1998                        };
1999                        self.add_resource(name, custom_rect)
2000                    }
2001                    BackgroundType::Image(config) => {
2002                        let mut image = Image::default().from_config(config);
2003                        if background.use_background_tags {
2004                            image.modify_tags(&background.tags, false);
2005                        };
2006                        self.add_resource(name, image)
2007                    }
2008                }?;
2009            }
2010            "Switch" => {
2011                let switch = downcast_resource_mut::<Switch>(&mut resource)?;
2012                let count = 1 + switch.enable_animation.iter().filter(|x| **x).count();
2013                if switch.appearance.len() != count * switch.state_amount as usize {
2014                    return Err(RustConstructorError {
2015                        error_id: "SwitchAppearanceConfigMismatch".to_string(),
2016                        description: format!(
2017                            "Expected {} elements, found {}.",
2018                            count * switch.state_amount as usize,
2019                            switch.appearance.len()
2020                        ),
2021                    });
2022                };
2023                if !switch.radio_group.is_empty() {
2024                    if !self.rust_constructor_resource.iter().any(|x| {
2025                        if let Ok(check_switch) = downcast_resource::<Switch>(&*x.content) {
2026                            switch.radio_group == check_switch.radio_group
2027                        } else {
2028                            false
2029                        }
2030                    }) {
2031                        switch.state = 1;
2032                    };
2033                    if switch.state_amount != 2 {
2034                        return Err(RustConstructorError {
2035                            error_id: "SwitchAppearanceConfigMismatch".to_string(),
2036                            description: format!(
2037                                "Radio group is only supported for switches with 2 states, found {}.",
2038                                switch.state_amount
2039                            ),
2040                        });
2041                    };
2042                };
2043                self.add_resource(
2044                    &format!("{name}Background"),
2045                    Background::default()
2046                        .background_type(&switch.background_type)
2047                        .auto_update(true)
2048                        .use_background_tags(true)
2049                        .tags(
2050                            if switch.use_switch_tags {
2051                                &switch.tags
2052                            } else {
2053                                &[]
2054                            },
2055                            false,
2056                        )
2057                        .tags(
2058                            &[
2059                                ["citer_name".to_string(), name.to_string()],
2060                                ["citer_type".to_string(), discern_type.to_string()],
2061                                ["panel_layout_group".to_string(), name.to_string()],
2062                            ],
2063                            false,
2064                        ),
2065                )?;
2066                self.add_resource(
2067                    &format!("{name}Text"),
2068                    Text::default()
2069                        .from_config(&switch.text_config)
2070                        .tags(
2071                            if switch.use_switch_tags {
2072                                &switch.tags
2073                            } else {
2074                                &[]
2075                            },
2076                            false,
2077                        )
2078                        .tags(
2079                            &[
2080                                ["citer_name".to_string(), name.to_string()],
2081                                ["citer_type".to_string(), discern_type.to_string()],
2082                                ["panel_layout_group".to_string(), name.to_string()],
2083                            ],
2084                            false,
2085                        ),
2086                )?;
2087                self.add_resource(
2088                    &format!("{name}HintText"),
2089                    Text::default()
2090                        .from_config(&switch.hint_text_config)
2091                        .ignore_render_layer(true)
2092                        .hidden(true)
2093                        .alpha(0)
2094                        .tags(
2095                            &[
2096                                ["citer_name".to_string(), name.to_string()],
2097                                ["citer_type".to_string(), discern_type.to_string()],
2098                                ["disable_x_scrolling".to_string(), "".to_string()],
2099                                ["disable_y_scrolling".to_string(), "".to_string()],
2100                            ],
2101                            false,
2102                        ),
2103                )?;
2104                self.add_resource(
2105                    &format!("{name}StartHoverTime"),
2106                    SplitTime::default().tags(
2107                        &[
2108                            ["citer_name".to_string(), name.to_string()],
2109                            ["citer_type".to_string(), discern_type.to_string()],
2110                        ],
2111                        false,
2112                    ),
2113                )?;
2114                self.add_resource(
2115                    &format!("{name}HintFadeAnimation"),
2116                    SplitTime::default().tags(
2117                        &[
2118                            ["citer_name".to_string(), name.to_string()],
2119                            ["citer_type".to_string(), discern_type.to_string()],
2120                        ],
2121                        false,
2122                    ),
2123                )?;
2124            }
2125            "ResourcePanel" => {
2126                let resource_panel = downcast_resource_mut::<ResourcePanel>(&mut resource)?;
2127                self.add_resource(
2128                    &format!("{name}Background"),
2129                    Background::default()
2130                        .background_type(&resource_panel.background)
2131                        .auto_update(true)
2132                        .use_background_tags(true)
2133                        .tags(
2134                            &[
2135                                ["citer_name".to_string(), name.to_string()],
2136                                ["citer_type".to_string(), discern_type.to_string()],
2137                            ],
2138                            false,
2139                        ),
2140                )?;
2141                if let ScrollBarDisplayMethod::Always(_, _, _) =
2142                    &resource_panel.scroll_bar_display_method
2143                {
2144                    self.add_resource(
2145                        &format!("{name}XScroll"),
2146                        Background::default()
2147                            .auto_update(true)
2148                            .use_background_tags(true)
2149                            .tags(
2150                                &[
2151                                    ["citer_name".to_string(), name.to_string()],
2152                                    ["citer_type".to_string(), discern_type.to_string()],
2153                                ],
2154                                false,
2155                            ),
2156                    )?;
2157                    self.add_resource(
2158                        &format!("{name}YScroll"),
2159                        Background::default()
2160                            .auto_update(true)
2161                            .use_background_tags(true)
2162                            .tags(
2163                                &[
2164                                    ["citer_name".to_string(), name.to_string()],
2165                                    ["citer_type".to_string(), discern_type.to_string()],
2166                                ],
2167                                false,
2168                            ),
2169                    )?;
2170                };
2171                if let ScrollBarDisplayMethod::OnlyScroll(_, _, _) =
2172                    &resource_panel.scroll_bar_display_method
2173                {
2174                    self.add_resource(
2175                        &format!("{name}XScroll"),
2176                        Background::default()
2177                            .auto_update(true)
2178                            .use_background_tags(true)
2179                            .tags(
2180                                &[
2181                                    ["citer_name".to_string(), name.to_string()],
2182                                    ["citer_type".to_string(), discern_type.to_string()],
2183                                ],
2184                                false,
2185                            ),
2186                    )?;
2187                    self.add_resource(
2188                        &format!("{name}YScroll"),
2189                        Background::default()
2190                            .auto_update(true)
2191                            .use_background_tags(true)
2192                            .tags(
2193                                &[
2194                                    ["citer_name".to_string(), name.to_string()],
2195                                    ["citer_type".to_string(), discern_type.to_string()],
2196                                ],
2197                                false,
2198                            ),
2199                    )?;
2200                    self.add_resource(
2201                        &format!("{name}ScrollBarXAlpha"),
2202                        SplitTime::default().tags(
2203                            &[
2204                                ["citer_name".to_string(), name.to_string()],
2205                                ["citer_type".to_string(), discern_type.to_string()],
2206                            ],
2207                            false,
2208                        ),
2209                    )?;
2210                    self.add_resource(
2211                        &format!("{name}ScrollBarXAlphaStart"),
2212                        SplitTime::default().tags(
2213                            &[
2214                                ["citer_name".to_string(), name.to_string()],
2215                                ["citer_type".to_string(), discern_type.to_string()],
2216                            ],
2217                            false,
2218                        ),
2219                    )?;
2220                    self.add_resource(
2221                        &format!("{name}ScrollBarYAlpha"),
2222                        SplitTime::default().tags(
2223                            &[
2224                                ["citer_name".to_string(), name.to_string()],
2225                                ["citer_type".to_string(), discern_type.to_string()],
2226                            ],
2227                            false,
2228                        ),
2229                    )?;
2230                    self.add_resource(
2231                        &format!("{name}ScrollBarYAlphaStart"),
2232                        SplitTime::default().tags(
2233                            &[
2234                                ["citer_name".to_string(), name.to_string()],
2235                                ["citer_type".to_string(), discern_type.to_string()],
2236                            ],
2237                            false,
2238                        ),
2239                    )?;
2240                };
2241            }
2242            _ => {}
2243        };
2244        self.rust_constructor_resource
2245            .push(RustConstructorResourceBox::new(
2246                name,
2247                discern_type,
2248                Box::new(resource),
2249            ));
2250        Ok(())
2251    }
2252
2253    /// Removes a resource from the application. This method is very dangerous! Ensure the resource is no longer in use before deletion.
2254    ///
2255    /// 移除资源。此方法非常危险!务必确保资源一定不再使用后删除。
2256    ///
2257    /// # Arguments
2258    ///
2259    /// * `id` - The unique identifier of the resource
2260    ///
2261    /// # Returns
2262    ///
2263    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be found.
2264    ///
2265    /// # 参数
2266    ///
2267    /// * `id` - 资源的唯一标识符
2268    ///
2269    /// # 返回值
2270    ///
2271    /// 成功时返回 `Ok(())`,如果资源无法找到则返回 `Err(RustConstructorError)`。
2272    pub fn drop_resource(&mut self, id: &RustConstructorId) -> Result<(), RustConstructorError> {
2273        if let Some(index) = self.check_resource_exists(id) {
2274            self.rust_constructor_resource.remove(index);
2275            if let Some(index) = self.active_list.iter().position(|x| &x.0 == id) {
2276                self.active_list.remove(index);
2277            };
2278            if let Some(index) = self
2279                .render_layer
2280                .iter()
2281                .position(|x| x.0.name == id.name && x.0.discern_type == id.discern_type)
2282            {
2283                self.render_layer.remove(index);
2284            };
2285            Ok(())
2286        } else {
2287            Err(RustConstructorError {
2288                error_id: "ResourceNotFound".to_string(),
2289                description: format!("Resource '{}({})' not found.", id.name, id.discern_type),
2290            })
2291        }
2292    }
2293
2294    /// Replaces an existing resource with a new one in the application.
2295    ///
2296    /// 用应用程序中的新资源替换现有资源。
2297    ///
2298    /// # Arguments
2299    ///
2300    /// * `name` - The name of the resource to replace
2301    /// * `resource` - The new resource instance
2302    ///
2303    /// # Returns
2304    ///
2305    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be found or replaced.
2306    ///
2307    /// # 参数
2308    ///
2309    /// * `name` - 要替换的资源名称
2310    /// * `resource` - 新的资源实例
2311    ///
2312    /// # 返回值
2313    ///
2314    /// 成功时返回 `Ok(())`,如果资源无法找到或替换则返回 `Err(RustConstructorError)`。
2315    pub fn replace_resource<T>(
2316        &mut self,
2317        name: &str,
2318        resource: T,
2319    ) -> Result<(), RustConstructorError>
2320    where
2321        T: RustConstructorResource + 'static,
2322    {
2323        let discern_type = &*type_processor(&resource);
2324        if let Some(index) = self.check_resource_exists(&RustConstructorId {
2325            name: name.to_string(),
2326            discern_type: discern_type.to_string(),
2327        }) {
2328            self.rust_constructor_resource[index] =
2329                RustConstructorResourceBox::new(name, discern_type, Box::new(resource));
2330            Ok(())
2331        } else {
2332            Err(RustConstructorError {
2333                error_id: "ResourceNotFound".to_string(),
2334                description: format!("Resource '{name}({discern_type})' not found."),
2335            })
2336        }
2337    }
2338
2339    /// Obtain basic front resource from the list.
2340    ///
2341    /// 从列表中获取基本前端资源。
2342    ///
2343    /// If you want to use the basic front resource method, please call this method to retrieve the resource.
2344    ///
2345    /// 如果想要使用基本前端资源的方法,请调用此方法来取出资源。
2346    ///
2347    /// # Arguments
2348    ///
2349    /// * `id` - The unique identifier of the resource
2350    ///
2351    /// # Returns
2352    ///
2353    /// If the resource is found, return the reference of the resource; otherwise, return `Err(RustConstructorError)`.
2354    ///
2355    /// # 参数
2356    ///
2357    /// * `id` - 资源的唯一标识符
2358    ///
2359    /// # 返回值
2360    ///
2361    /// 如果找到资源,返回资源的引用,否则返回`Err(RustConstructorError)`。
2362    pub fn get_basic_front_resource(
2363        &self,
2364        id: &RustConstructorId,
2365    ) -> Result<&dyn BasicFrontResource, RustConstructorError> {
2366        match &*id.discern_type {
2367            "Image" => Ok(downcast_resource::<Image>(self.get_box_resource(id)?)?),
2368            "Text" => Ok(downcast_resource::<Text>(self.get_box_resource(id)?)?),
2369            "CustomRect" => Ok(downcast_resource::<CustomRect>(self.get_box_resource(id)?)?),
2370            _ => unreachable!(),
2371        }
2372    }
2373
2374    /// Obtain mutable basic front resource from the list.
2375    ///
2376    /// 从列表中获取可变基本前端资源。
2377    ///
2378    /// If you want to use the basic front resource method and modify the basic front resource, please call
2379    /// this method to retrieve the resource.
2380    ///
2381    /// 如果想要使用基本前端资源的方法并修改基本前端资源,请调用此方法来取出资源。
2382    ///
2383    /// # Arguments
2384    ///
2385    /// * `id` - The unique identifier of the resource
2386    ///
2387    /// # Returns
2388    ///
2389    /// If the resource is found, return the mutable reference of the resource; otherwise, return `Err(RustConstructorError)`.
2390    ///
2391    /// # 参数
2392    ///
2393    /// * `id` - 资源的唯一标识符
2394    ///
2395    /// # 返回值
2396    ///
2397    /// 如果找到资源,返回资源的可变引用,否则返回`Err(RustConstructorError)`。
2398    pub fn get_basic_front_resource_mut(
2399        &mut self,
2400        id: &RustConstructorId,
2401    ) -> Result<&mut dyn BasicFrontResource, RustConstructorError> {
2402        match &*id.discern_type {
2403            "Image" => Ok(downcast_resource_mut::<Image>(
2404                self.get_box_resource_mut(id)?,
2405            )?),
2406            "Text" => Ok(downcast_resource_mut::<Text>(
2407                self.get_box_resource_mut(id)?,
2408            )?),
2409            "CustomRect" => Ok(downcast_resource_mut::<CustomRect>(
2410                self.get_box_resource_mut(id)?,
2411            )?),
2412            _ => unreachable!(),
2413        }
2414    }
2415
2416    /// Obtain the boxed immutable resources from the list.
2417    ///
2418    /// 从列表中获取封装的不可变资源。
2419    ///
2420    /// If you need to use a resource without knowing its type, please use this method to retrieve the resource.
2421    ///
2422    /// 如果需要在不知道类型的情况下使用资源,请使用此方法取出资源。
2423    ///
2424    /// # Arguments
2425    ///
2426    /// * `id` - The unique identifier of the resource
2427    ///
2428    /// # Returns
2429    ///
2430    /// If the resource is found, return the reference of the resource; otherwise, return `Err(RustConstructorError)`.
2431    ///
2432    /// # 参数
2433    ///
2434    /// * `id` - 资源的唯一标识符
2435    ///
2436    /// # 返回值
2437    ///
2438    /// 如果找到资源,返回资源的引用,否则返回`Err(RustConstructorError)`。
2439    pub fn get_box_resource(
2440        &self,
2441        id: &RustConstructorId,
2442    ) -> Result<&dyn RustConstructorResource, RustConstructorError> {
2443        if let Some(index) = self.check_resource_exists(id) {
2444            Ok(&*self.rust_constructor_resource[index].content)
2445        } else {
2446            Err(RustConstructorError {
2447                error_id: "ResourceNotFound".to_string(),
2448                description: format!("Resource '{}({})' not found.", id.name, id.discern_type),
2449            })
2450        }
2451    }
2452
2453    /// Obtain the boxed mutable resources from the list.
2454    ///
2455    /// 从列表中获取封装的可变资源。
2456    ///
2457    /// If you need to use a resource without knowing its type, please use this method to retrieve the resource.
2458    ///
2459    /// 如果需要在不知道类型的情况下使用资源,请使用此方法取出资源。
2460    ///
2461    /// # Arguments
2462    ///
2463    /// * `id` - The unique identifier of the resource
2464    ///
2465    /// # Returns
2466    ///
2467    /// If the resource is found, return the mutable reference of the resource; otherwise, return `Err(RustConstructorError)`.
2468    ///
2469    /// # 参数
2470    ///
2471    /// * `id` - 资源的唯一标识符
2472    ///
2473    /// # 返回值
2474    ///
2475    /// 如果找到资源,返回资源的可变引用,否则返回`Err(RustConstructorError)`。
2476    pub fn get_box_resource_mut(
2477        &mut self,
2478        id: &RustConstructorId,
2479    ) -> Result<&mut dyn RustConstructorResource, RustConstructorError> {
2480        if let Some(index) = self.check_resource_exists(id) {
2481            Ok(&mut *self.rust_constructor_resource[index].content)
2482        } else {
2483            Err(RustConstructorError {
2484                error_id: "ResourceNotFound".to_string(),
2485                description: format!("Resource '{}({})' not found.", id.name, id.discern_type),
2486            })
2487        }
2488    }
2489
2490    /// Obtain the immutable resources from the list.
2491    ///
2492    /// 从列表中获取不可变资源。
2493    ///
2494    /// # Arguments
2495    ///
2496    /// * `id` - The unique identifier of the resource
2497    ///
2498    /// # Returns
2499    ///
2500    /// If the resource is found, return the reference of the resource; otherwise, return `Err(RustConstructorError)`.
2501    ///
2502    /// # 参数
2503    ///
2504    /// * `id` - 资源的唯一标识符
2505    ///
2506    /// # 返回值
2507    ///
2508    /// 如果找到资源,返回资源的引用,否则返回`Err(RustConstructorError)`。
2509    pub fn get_resource<T>(&self, id: &RustConstructorId) -> Result<&T, RustConstructorError>
2510    where
2511        T: RustConstructorResource + 'static,
2512    {
2513        downcast_resource(self.get_box_resource(id)?)
2514    }
2515
2516    /// Obtain the mutable resources from the list.
2517    ///
2518    /// 从列表中获取可变资源。
2519    ///
2520    /// # Arguments
2521    ///
2522    /// * `id` - The unique identifier of the resource
2523    ///
2524    /// # Returns
2525    ///
2526    /// If the resource is found, return the reference of the resource; otherwise, return `Err(RustConstructorError)`.
2527    ///
2528    /// # 参数
2529    ///
2530    /// * `id` - 资源的唯一标识符
2531    ///
2532    /// # 返回值
2533    ///
2534    /// 如果找到资源,返回资源的引用,否则返回`Err(RustConstructorError)`。
2535    pub fn get_resource_mut<T>(
2536        &mut self,
2537        id: &RustConstructorId,
2538    ) -> Result<&mut T, RustConstructorError>
2539    where
2540        T: RustConstructorResource + 'static,
2541    {
2542        downcast_resource_mut(self.get_box_resource_mut(id)?)
2543    }
2544
2545    /// Checks if a specific resource exists in the application.
2546    ///
2547    /// 检查应用程序中是否存在特定资源。
2548    ///
2549    /// # Arguments
2550    ///
2551    /// * `id` - The unique identifier of the resource
2552    ///
2553    /// # Returns
2554    ///
2555    /// Returns `Some(index)` if the resource exists, or `None` if not found.
2556    ///
2557    /// # 参数
2558    ///
2559    /// * `id` - 资源的唯一标识符
2560    ///
2561    /// # 返回值
2562    ///
2563    /// 如果资源存在则返回 `Some(索引)`,否则返回 `None`。
2564    pub fn check_resource_exists(&self, id: &RustConstructorId) -> Option<usize> {
2565        self.rust_constructor_resource
2566            .iter()
2567            .position(|x| &x.id == id)
2568    }
2569
2570    /// Quickly adds and uses a resource in one operation.
2571    ///
2572    /// 快速添加并使用资源。
2573    ///
2574    /// This method combines adding a resource to the application and immediately using it.
2575    ///
2576    /// 此方法将资源添加到应用程序并立即使用它。
2577    ///
2578    /// # Arguments
2579    ///
2580    /// * `name` - The name for the resource
2581    /// * `resource` - The resource instance to add and draw
2582    /// * `ui` - The UI context for drawing
2583    ///
2584    /// # Returns
2585    ///
2586    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be added or drawn.
2587    ///
2588    /// # 参数
2589    ///
2590    /// * `name` - 资源的名称
2591    /// * `resource` - 要添加和绘制的资源实例
2592    /// * `ui` - 用于绘制的UI上下文
2593    ///
2594    /// # 返回值
2595    ///
2596    /// 成功时返回 `Ok(())`,如果资源无法添加或绘制则返回 `Err(RustConstructorError)`。
2597    pub fn quick_place<T: RustConstructorResource + 'static>(
2598        &mut self,
2599        name: &str,
2600        resource: T,
2601        ui: &mut Ui,
2602    ) -> Result<(), RustConstructorError> {
2603        let discern_type = &*type_processor(&resource);
2604        if self
2605            .check_resource_exists(&RustConstructorId {
2606                name: name.to_string(),
2607                discern_type: discern_type.to_string(),
2608            })
2609            .is_none()
2610        {
2611            self.add_resource(name, resource)
2612        } else {
2613            self.use_resource(
2614                &RustConstructorId {
2615                    name: name.to_string(),
2616                    discern_type: discern_type.to_string(),
2617                },
2618                ui,
2619            )
2620        }
2621    }
2622
2623    /// Use the existing resources.
2624    ///
2625    /// 使用已存在的资源。
2626    ///
2627    /// This method invokes existing resources and performs operations.
2628    ///
2629    /// 此方法调用存在的资源并进行操作。
2630    ///
2631    /// # Arguments
2632    ///
2633    /// * `id` - The unique identifier of the resource
2634    /// * `ui` - The UI context for drawing
2635    ///
2636    /// # Returns
2637    ///
2638    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be handled.
2639    ///
2640    /// # 参数
2641    ///
2642    /// * `id` - 资源的唯一标识符
2643    /// * `ui` - 用于绘制的UI上下文
2644    ///
2645    /// # 返回值
2646    ///
2647    /// 成功时返回 `Ok(())`,如果资源无法处理则返回 `Err(RustConstructorError)`。
2648    pub fn use_resource(
2649        &mut self,
2650        id: &RustConstructorId,
2651        ui: &mut Ui,
2652    ) -> Result<(), RustConstructorError> {
2653        if self.check_resource_exists(id).is_some() {
2654            match &*id.discern_type {
2655                "CustomRect" | "Text" | "Image" => {
2656                    self.add_active_resource(id)?;
2657                }
2658                "PageData" => {
2659                    // 更新帧数
2660                    self.update_frame_stats();
2661                    // 更新渲染队列。
2662                    self.update_render_list();
2663                    // 绘制渲染队列中的资源。
2664                    for i in 0..self.render_list.len() {
2665                        self.draw_resource_by_index(ui, i)?;
2666                    }
2667                    // 更新渲染列表。
2668                    self.update_render_layer(ui)?;
2669                    // 更新资源活跃状态。
2670                    self.active_list.clear();
2671                    // 更新字体加载情况。
2672                    if !self.loading_fonts.is_empty() {
2673                        self.loaded_fonts = self.loading_fonts.clone();
2674                        self.loading_fonts.clear();
2675                    };
2676                    // 更新资源启用状态。
2677                    for rcr in &mut self.rust_constructor_resource {
2678                        if let Some(display_info) = &mut rcr.content.display_display_info() {
2679                            rcr.content.modify_display_info(DisplayInfo {
2680                                enable: true,
2681                                hidden: display_info.hidden,
2682                                ignore_render_layer: display_info.ignore_render_layer,
2683                            });
2684                        };
2685                    }
2686                    // 更新计时器
2687                    self.update_timer();
2688                    let page_data = self.get_resource::<PageData>(&RustConstructorId {
2689                        name: self.current_page.clone(),
2690                        discern_type: "PageData".to_string(),
2691                    })?;
2692                    if page_data.forced_update {
2693                        ui.request_repaint();
2694                    };
2695                }
2696                "Background" => {
2697                    let background = self.get_resource::<Background>(id)?.clone();
2698                    if background.auto_update {
2699                        match &background.background_type {
2700                            BackgroundType::CustomRect(config) => {
2701                                let mut custom_rect = self
2702                                    .get_resource::<CustomRect>(&RustConstructorId {
2703                                        name: id.name.clone(),
2704                                        discern_type: "CustomRect".to_string(),
2705                                    })?
2706                                    .clone()
2707                                    .from_config(config);
2708                                if background.use_background_tags {
2709                                    custom_rect.modify_tags(&background.tags, false);
2710                                };
2711                                self.replace_resource(&id.name, custom_rect)?;
2712                            }
2713                            BackgroundType::Image(config) => {
2714                                let mut image = self
2715                                    .get_resource::<Image>(&RustConstructorId {
2716                                        name: id.name.clone(),
2717                                        discern_type: "Image".to_string(),
2718                                    })?
2719                                    .clone()
2720                                    .from_config(config);
2721                                if background.use_background_tags {
2722                                    image.modify_tags(&background.tags, false);
2723                                };
2724                                self.replace_resource(&id.name, image)?;
2725                            }
2726                        };
2727                    };
2728                    match background.background_type {
2729                        BackgroundType::CustomRect(_) => self.use_resource(
2730                            &RustConstructorId {
2731                                name: id.name.clone(),
2732                                discern_type: "CustomRect".to_string(),
2733                            },
2734                            ui,
2735                        ),
2736                        BackgroundType::Image(_) => self.use_resource(
2737                            &RustConstructorId {
2738                                name: id.name.clone(),
2739                                discern_type: "Image".to_string(),
2740                            },
2741                            ui,
2742                        ),
2743                    }?;
2744                }
2745                "Switch" => {
2746                    let mut switch = self.get_resource::<Switch>(id)?.clone();
2747                    let mut background = self
2748                        .get_resource::<Background>(&RustConstructorId {
2749                            name: format!("{}Background", &id.name),
2750                            discern_type: "Background".to_string(),
2751                        })?
2752                        .clone();
2753                    let background_resource_type = match switch.background_type {
2754                        BackgroundType::CustomRect(_) => "CustomRect",
2755                        BackgroundType::Image(_) => "Image",
2756                    };
2757                    let background_resource =
2758                        self.get_basic_front_resource(&RustConstructorId {
2759                            name: format!("{}Background", &id.name),
2760                            discern_type: background_resource_type.to_string(),
2761                        })?;
2762                    let display_info = background_resource.display_display_info();
2763                    let mut text = self
2764                        .get_resource::<Text>(&RustConstructorId {
2765                            name: format!("{}Text", &id.name),
2766                            discern_type: "Text".to_string(),
2767                        })?
2768                        .clone();
2769                    let mut hint_text = self
2770                        .get_resource::<Text>(&RustConstructorId {
2771                            name: format!("{}HintText", &id.name),
2772                            discern_type: "Text".to_string(),
2773                        })?
2774                        .clone();
2775                    switch.switched = false;
2776                    let animation_count =
2777                        1 + switch.enable_animation.iter().filter(|x| **x).count();
2778                    let mut clicked = None;
2779                    let mut hovered = false;
2780                    let mut appearance_count = 0;
2781                    // 处理点击事件
2782                    if let Some(index) = self.get_render_layer_resource(&RustConstructorId {
2783                        name: format!("{}Background", &id.name),
2784                        discern_type: background_resource_type.to_string(),
2785                    }) && switch.enable
2786                        && let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos())
2787                        && self.resource_get_focus(index, mouse_pos.into(), true, vec![])
2788                        && let Some(display_info) = background_resource.display_display_info()
2789                        && !display_info.hidden
2790                    {
2791                        if !switch.last_frame_hovered {
2792                            self.reset_split_time(&format!("{}StartHoverTime", &id.name))?;
2793                        } else if self.timer.total_time
2794                            - self.get_split_time(&format!("{}StartHoverTime", &id.name))?[1]
2795                            >= 2000
2796                            || hint_text.alpha != 0
2797                        {
2798                            hint_text.alpha = 255;
2799                            hint_text
2800                                .basic_front_resource_config
2801                                .position_size_config
2802                                .origin_position = [mouse_pos.x, mouse_pos.y];
2803                        };
2804                        hint_text
2805                            .basic_front_resource_config
2806                            .position_size_config
2807                            .display_method
2808                            .0 = if mouse_pos.x + hint_text.actual_size[0] <= ui.available_width() {
2809                            HorizontalAlign::Left
2810                        } else {
2811                            HorizontalAlign::Right
2812                        };
2813                        hint_text
2814                            .basic_front_resource_config
2815                            .position_size_config
2816                            .display_method
2817                            .1 = if mouse_pos.y + hint_text.actual_size[1] <= ui.available_height()
2818                        {
2819                            VerticalAlign::Top
2820                        } else {
2821                            VerticalAlign::Bottom
2822                        };
2823                        hovered = true;
2824                        for (count, click_method) in switch.click_method.iter().enumerate() {
2825                            if ui.input(|i| {
2826                                switch.last_frame_clicked.is_none()
2827                                    && i.pointer.button_pressed(click_method.click_method)
2828                                    || switch.last_frame_clicked.is_some()
2829                                        && i.pointer.button_down(click_method.click_method)
2830                            }) {
2831                                clicked = Some(count);
2832                                break;
2833                            };
2834                        }
2835                        if let Some(clicked_index) = switch.last_frame_clicked
2836                            && clicked.is_none()
2837                        {
2838                            switch.switched = true;
2839                            if switch.click_method[clicked_index].action {
2840                                if !switch.radio_group.is_empty() {
2841                                    self.rust_constructor_resource
2842                                        .iter_mut()
2843                                        .filter(|x| &x.id.discern_type == "Switch")
2844                                        .for_each(|x| {
2845                                            if let Ok(check_switch) =
2846                                                downcast_resource_mut::<Switch>(&mut *x.content)
2847                                                && switch.radio_group == check_switch.radio_group
2848                                            {
2849                                                check_switch.state = 0;
2850                                            };
2851                                        });
2852                                };
2853                                if switch.radio_group.is_empty() || switch.state == 0 {
2854                                    if switch.state < switch.appearance.len() / animation_count - 1
2855                                    {
2856                                        switch.state += 1;
2857                                    } else {
2858                                        switch.state = 0;
2859                                    };
2860                                }
2861                            };
2862                        };
2863                        appearance_count = if clicked.is_some() {
2864                            match switch.enable_animation {
2865                                [true, true] => 2,
2866                                [true, false] | [false, true] => 1,
2867                                [false, false] => 0,
2868                            }
2869                        } else if switch.enable_animation[0] {
2870                            1
2871                        } else {
2872                            0
2873                        };
2874                    };
2875
2876                    // 若鼠标未悬挂在开关上,逐渐隐藏提示文本
2877                    if !hovered {
2878                        if switch.last_frame_hovered {
2879                            self.reset_split_time(&format!("{}HintFadeAnimation", &id.name))?;
2880                        };
2881                        if self.timer.total_time
2882                            - self.get_split_time(&format!("{}HintFadeAnimation", &id.name))?[1]
2883                            >= self.tick_interval
2884                        {
2885                            self.reset_split_time(&format!("{}HintFadeAnimation", &id.name))?;
2886                            hint_text.alpha = hint_text.alpha.saturating_sub(10);
2887                        };
2888                    };
2889
2890                    hint_text.display_info.hidden = hint_text.alpha == 0;
2891
2892                    // 更新Background样式。
2893                    background.background_type = switch.appearance
2894                        [switch.state * animation_count + appearance_count]
2895                        .background_config
2896                        .clone();
2897
2898                    background.modify_tags(
2899                        if switch.use_switch_tags {
2900                            &switch.tags
2901                        } else {
2902                            &[]
2903                        },
2904                        false,
2905                    );
2906
2907                    // 刷新提示Text。
2908                    let alpha = hint_text.alpha;
2909                    hint_text = hint_text
2910                        .from_config(
2911                            &switch.appearance[switch.state * animation_count + appearance_count]
2912                                .hint_text_config,
2913                        )
2914                        .ignore_render_layer(true);
2915                    hint_text.background_alpha = alpha;
2916                    hint_text.alpha = alpha;
2917                    hint_text.display_info.hidden = if let Some(display_info) = display_info
2918                        && display_info.hidden
2919                    {
2920                        true
2921                    } else {
2922                        hint_text.display_info.hidden
2923                    };
2924
2925                    // 更新Text样式。
2926                    text = text
2927                        .tags(
2928                            if switch.use_switch_tags {
2929                                &switch.tags
2930                            } else {
2931                                &[]
2932                            },
2933                            false,
2934                        )
2935                        .from_config(
2936                            &switch.appearance[switch.state * animation_count + appearance_count]
2937                                .text_config,
2938                        );
2939
2940                    switch.last_frame_hovered = hovered;
2941                    switch.last_frame_clicked = clicked;
2942
2943                    self.replace_resource(&format!("{}Text", &id.name), text)?;
2944                    self.replace_resource(&format!("{}HintText", &id.name), hint_text)?;
2945                    self.replace_resource(&id.name, switch)?;
2946                    self.replace_resource(&format!("{}Background", &id.name), background)?;
2947
2948                    self.use_resource(
2949                        &RustConstructorId {
2950                            name: format!("{}Background", &id.name),
2951                            discern_type: "Background".to_string(),
2952                        },
2953                        ui,
2954                    )?;
2955                    self.use_resource(
2956                        &RustConstructorId {
2957                            name: format!("{}Text", &id.name),
2958                            discern_type: "Text".to_string(),
2959                        },
2960                        ui,
2961                    )?;
2962                    if alpha != 0 {
2963                        self.try_request_jump_render_list(
2964                            RequestMethod::Id(RustConstructorId {
2965                                name: format!("{}HintText", &id.name),
2966                                discern_type: "Text".to_string(),
2967                            }),
2968                            RequestType::Top,
2969                        );
2970                        self.use_resource(
2971                            &RustConstructorId {
2972                                name: format!("{}HintText", &id.name),
2973                                discern_type: "Text".to_string(),
2974                            },
2975                            ui,
2976                        )?;
2977                    };
2978                }
2979                "ResourcePanel" => {
2980                    let mut resource_panel = self
2981                        .get_resource::<ResourcePanel>(&RustConstructorId {
2982                            name: id.name.clone(),
2983                            discern_type: "ResourcePanel".to_string(),
2984                        })?
2985                        .clone();
2986                    let background = self
2987                        .get_resource::<Background>(&RustConstructorId {
2988                            name: format!("{}Background", &id.name),
2989                            discern_type: "Background".to_string(),
2990                        })?
2991                        .clone();
2992                    let background_resource: Box<dyn BasicFrontResource> =
2993                        match background.background_type.clone() {
2994                            BackgroundType::CustomRect(_) => Box::new(
2995                                self.get_resource::<CustomRect>(&RustConstructorId {
2996                                    name: format!("{}Background", &id.name),
2997                                    discern_type: "CustomRect".to_string(),
2998                                })?
2999                                .clone(),
3000                            ),
3001                            BackgroundType::Image(_) => Box::new(
3002                                self.get_resource::<Image>(&RustConstructorId {
3003                                    name: format!("{}Background", &id.name),
3004                                    discern_type: "Image".to_string(),
3005                                })?
3006                                .clone(),
3007                            ),
3008                        };
3009                    let (mut position_size_config, mut position, mut size) = (
3010                        background_resource
3011                            .display_basic_front_resource_config()
3012                            .position_size_config,
3013                        background_resource.display_position(),
3014                        background_resource.display_size(),
3015                    );
3016                    let rect = Rect::from_min_size(position.into(), size.into());
3017                    resource_panel.scrolled = [false, false];
3018                    if resource_panel.resizable.contains(&true)
3019                        || resource_panel.movable.contains(&true)
3020                    {
3021                        position_size_config.x_location_grid = [0_f32, 0_f32];
3022                        position_size_config.y_location_grid = [0_f32, 0_f32];
3023                        position_size_config.x_size_grid = [0_f32, 0_f32];
3024                        position_size_config.y_size_grid = [0_f32, 0_f32];
3025                        position_size_config.display_method =
3026                            (HorizontalAlign::Left, VerticalAlign::Top);
3027                    };
3028                    if resource_panel.min_size[0] < 10_f32 {
3029                        resource_panel.min_size[0] = 10_f32;
3030                    };
3031                    if resource_panel.min_size[1] < 10_f32 {
3032                        resource_panel.min_size[1] = 10_f32;
3033                    };
3034                    if position_size_config.origin_size[0] < resource_panel.min_size[0] {
3035                        position_size_config.origin_size[0] = resource_panel.min_size[0];
3036                    };
3037                    if position_size_config.origin_size[1] < resource_panel.min_size[1] {
3038                        position_size_config.origin_size[1] = resource_panel.min_size[1];
3039                    };
3040                    [position, size] = position_size_processor(position_size_config, ui);
3041                    let scroll_delta: [f32; 2] = ui.input(|i| i.smooth_scroll_delta).into();
3042                    let [x_scroll_delta, y_scroll_delta] =
3043                        if scroll_delta[0].abs() >= scroll_delta[1].abs() {
3044                            [
3045                                if resource_panel.reverse_scroll_direction[0] {
3046                                    -scroll_delta[0]
3047                                } else {
3048                                    scroll_delta[0]
3049                                },
3050                                0_f32,
3051                            ]
3052                        } else {
3053                            [
3054                                0_f32,
3055                                if resource_panel.reverse_scroll_direction[1] {
3056                                    -scroll_delta[1]
3057                                } else {
3058                                    scroll_delta[1]
3059                                },
3060                            ]
3061                        };
3062                    let mut resource_get_focus = [false, false];
3063                    if let Some(mouse_pos) = ui.input(|i| i.pointer.hover_pos())
3064                        && !resource_panel.hidden
3065                        && let Some(index) = self.get_render_layer_resource(&RustConstructorId {
3066                            name: format!("{}Background", &id.name),
3067                            discern_type: match background.background_type {
3068                                BackgroundType::CustomRect(_) => "CustomRect",
3069                                BackgroundType::Image(_) => "Image",
3070                            }
3071                            .to_string(),
3072                        })
3073                    {
3074                        resource_get_focus = [
3075                            self.resource_get_focus(index, mouse_pos.into(), false, vec![]),
3076                            self.resource_get_focus(
3077                                index,
3078                                mouse_pos.into(),
3079                                true,
3080                                vec![[index + 1, resource_panel.resource_storage.len()]],
3081                            ),
3082                        ];
3083                        if resource_get_focus[1] {
3084                            if resource_panel.scroll_length_method[0].is_some()
3085                                && x_scroll_delta != 0_f32
3086                            {
3087                                resource_panel.scrolled[0] = true;
3088                                resource_panel.scroll_progress[0] = if resource_panel
3089                                    .scroll_progress[0]
3090                                    + -x_scroll_delta * resource_panel.scroll_sensitivity
3091                                    > resource_panel.scroll_length[0]
3092                                {
3093                                    resource_panel.scroll_length[0]
3094                                } else if resource_panel.scroll_progress[0]
3095                                    + -x_scroll_delta * resource_panel.scroll_sensitivity
3096                                    > 0_f32
3097                                {
3098                                    resource_panel.scroll_progress[0]
3099                                        + -x_scroll_delta * resource_panel.scroll_sensitivity
3100                                } else {
3101                                    0_f32
3102                                };
3103                            };
3104                            if resource_panel.scroll_length_method[1].is_some()
3105                                && y_scroll_delta != 0_f32
3106                            {
3107                                resource_panel.scrolled[1] = true;
3108                                resource_panel.scroll_progress[1] = if resource_panel
3109                                    .scroll_progress[1]
3110                                    + -y_scroll_delta * resource_panel.scroll_sensitivity
3111                                    > resource_panel.scroll_length[1]
3112                                {
3113                                    resource_panel.scroll_length[1]
3114                                } else if resource_panel.scroll_progress[1]
3115                                    + -y_scroll_delta * resource_panel.scroll_sensitivity
3116                                    > 0_f32
3117                                {
3118                                    resource_panel.scroll_progress[1]
3119                                        + -y_scroll_delta * resource_panel.scroll_sensitivity
3120                                } else {
3121                                    0_f32
3122                                };
3123                            };
3124                            if resource_panel.raise_on_focus
3125                                && ui.input(|i| i.pointer.primary_pressed())
3126                            {
3127                                self.request_jump_render_list(
3128                                    RequestMethod::Id(RustConstructorId {
3129                                        name: format!("{}Background", &id.name),
3130                                        discern_type: match background.background_type {
3131                                            BackgroundType::CustomRect(_) => "CustomRect",
3132                                            BackgroundType::Image(_) => "Image",
3133                                        }
3134                                        .to_string(),
3135                                    }),
3136                                    RequestType::Top,
3137                                )
3138                                .unwrap();
3139                                let mut update_list = Vec::new();
3140                                for rcr in &self.rust_constructor_resource {
3141                                    if self
3142                                        .basic_front_resource_list
3143                                        .contains(&rcr.id.discern_type)
3144                                        && let Some(panel_name) =
3145                                            get_tag("panel_name", &rcr.content.display_tags())
3146                                        && panel_name.1 == id.name
3147                                    {
3148                                        update_list.push(rcr.id.clone());
3149                                    };
3150                                }
3151                                for id in update_list {
3152                                    self.try_request_jump_render_list(
3153                                        RequestMethod::Id(id),
3154                                        RequestType::Top,
3155                                    );
3156                                }
3157                                if let ScrollBarDisplayMethod::Always(ref background_type, _, _) =
3158                                    resource_panel.scroll_bar_display_method
3159                                {
3160                                    self.try_request_jump_render_list(
3161                                        RequestMethod::Id(RustConstructorId {
3162                                            name: format!("{}XScroll", &id.name),
3163                                            discern_type: match background_type {
3164                                                BackgroundType::CustomRect(_) => "CustomRect",
3165                                                BackgroundType::Image(_) => "Image",
3166                                            }
3167                                            .to_string(),
3168                                        }),
3169                                        RequestType::Top,
3170                                    );
3171                                    self.try_request_jump_render_list(
3172                                        RequestMethod::Id(RustConstructorId {
3173                                            name: format!("{}YScroll", &id.name),
3174                                            discern_type: match background_type {
3175                                                BackgroundType::CustomRect(_) => "CustomRect",
3176                                                BackgroundType::Image(_) => "Image",
3177                                            }
3178                                            .to_string(),
3179                                        }),
3180                                        RequestType::Top,
3181                                    );
3182                                };
3183                                if let ScrollBarDisplayMethod::OnlyScroll(
3184                                    ref background_type,
3185                                    _,
3186                                    _,
3187                                ) = resource_panel.scroll_bar_display_method
3188                                {
3189                                    self.try_request_jump_render_list(
3190                                        RequestMethod::Id(RustConstructorId {
3191                                            name: format!("{}XScroll", &id.name),
3192                                            discern_type: match background_type {
3193                                                BackgroundType::CustomRect(_) => "CustomRect",
3194                                                BackgroundType::Image(_) => "Image",
3195                                            }
3196                                            .to_string(),
3197                                        }),
3198                                        RequestType::Top,
3199                                    );
3200                                    self.try_request_jump_render_list(
3201                                        RequestMethod::Id(RustConstructorId {
3202                                            name: format!("{}YScroll", &id.name),
3203                                            discern_type: match background_type {
3204                                                BackgroundType::CustomRect(_) => "CustomRect",
3205                                                BackgroundType::Image(_) => "Image",
3206                                            }
3207                                            .to_string(),
3208                                        }),
3209                                        RequestType::Top,
3210                                    );
3211                                };
3212                            };
3213                        }
3214                        if resource_get_focus[0] {
3215                            let top_rect = Rect::from_min_size(
3216                                [position[0], position[1]].into(),
3217                                [size[0], 3_f32].into(),
3218                            );
3219                            let bottom_rect = Rect::from_min_size(
3220                                [position[0], position[1] + size[1] - 3_f32].into(),
3221                                [size[0], 3_f32].into(),
3222                            );
3223                            let left_rect = Rect::from_min_size(
3224                                [position[0], position[1]].into(),
3225                                [3_f32, size[1]].into(),
3226                            );
3227                            let right_rect = Rect::from_min_size(
3228                                [position[0] + size[0] - 3_f32, position[1]].into(),
3229                                [3_f32, size[1]].into(),
3230                            );
3231                            match [
3232                                top_rect.contains(mouse_pos),
3233                                bottom_rect.contains(mouse_pos),
3234                                left_rect.contains(mouse_pos),
3235                                right_rect.contains(mouse_pos),
3236                            ] {
3237                                [true, false, false, false] if resource_panel.resizable[0] => {
3238                                    if resource_panel.last_frame_mouse_status.is_none()
3239                                        && ui.input(|i| i.pointer.primary_pressed())
3240                                    {
3241                                        resource_panel.last_frame_mouse_status = Some((
3242                                            mouse_pos.into(),
3243                                            ClickAim::TopResize,
3244                                            [mouse_pos.x - position[0], mouse_pos.y - position[1]],
3245                                        ))
3246                                    };
3247                                    if size[1] > resource_panel.min_size[1]
3248                                        && (resource_panel.max_size.is_none()
3249                                            || size[1] < resource_panel.max_size.unwrap()[1])
3250                                    {
3251                                        ui.set_cursor_icon(CursorIcon::ResizeVertical);
3252                                    } else if resource_panel.max_size.is_some()
3253                                        && size[1] >= resource_panel.max_size.unwrap()[1]
3254                                    {
3255                                        ui.set_cursor_icon(CursorIcon::ResizeSouth);
3256                                    } else {
3257                                        ui.set_cursor_icon(CursorIcon::ResizeNorth);
3258                                    };
3259                                }
3260                                [false, true, false, false] if resource_panel.resizable[1] => {
3261                                    if resource_panel.last_frame_mouse_status.is_none()
3262                                        && ui.input(|i| i.pointer.primary_pressed())
3263                                    {
3264                                        resource_panel.last_frame_mouse_status = Some((
3265                                            mouse_pos.into(),
3266                                            ClickAim::BottomResize,
3267                                            [mouse_pos.x - position[0], mouse_pos.y - position[1]],
3268                                        ))
3269                                    };
3270                                    if size[1] > resource_panel.min_size[1]
3271                                        && (resource_panel.max_size.is_none()
3272                                            || size[1] < resource_panel.max_size.unwrap()[1])
3273                                    {
3274                                        ui.set_cursor_icon(CursorIcon::ResizeVertical);
3275                                    } else if resource_panel.max_size.is_some()
3276                                        && size[1] >= resource_panel.max_size.unwrap()[1]
3277                                    {
3278                                        ui.set_cursor_icon(CursorIcon::ResizeNorth);
3279                                    } else {
3280                                        ui.set_cursor_icon(CursorIcon::ResizeSouth);
3281                                    };
3282                                }
3283                                [false, false, true, false] if resource_panel.resizable[2] => {
3284                                    if resource_panel.last_frame_mouse_status.is_none()
3285                                        && ui.input(|i| i.pointer.primary_pressed())
3286                                    {
3287                                        resource_panel.last_frame_mouse_status = Some((
3288                                            mouse_pos.into(),
3289                                            ClickAim::LeftResize,
3290                                            [mouse_pos.x - position[0], mouse_pos.y - position[1]],
3291                                        ))
3292                                    };
3293                                    if size[0] > resource_panel.min_size[0]
3294                                        && (resource_panel.max_size.is_none()
3295                                            || size[0] < resource_panel.max_size.unwrap()[0])
3296                                    {
3297                                        ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3298                                    } else if resource_panel.max_size.is_some()
3299                                        && size[0] >= resource_panel.max_size.unwrap()[0]
3300                                    {
3301                                        ui.set_cursor_icon(CursorIcon::ResizeEast);
3302                                    } else {
3303                                        ui.set_cursor_icon(CursorIcon::ResizeWest);
3304                                    };
3305                                }
3306                                [false, false, false, true] if resource_panel.resizable[3] => {
3307                                    if resource_panel.last_frame_mouse_status.is_none()
3308                                        && ui.input(|i| i.pointer.primary_pressed())
3309                                    {
3310                                        resource_panel.last_frame_mouse_status = Some((
3311                                            mouse_pos.into(),
3312                                            ClickAim::RightResize,
3313                                            [mouse_pos.x - position[0], mouse_pos.y - position[1]],
3314                                        ))
3315                                    };
3316                                    if size[0] > resource_panel.min_size[0]
3317                                        && (resource_panel.max_size.is_none()
3318                                            || size[0] < resource_panel.max_size.unwrap()[0])
3319                                    {
3320                                        ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3321                                    } else if resource_panel.max_size.is_some()
3322                                        && size[0] >= resource_panel.max_size.unwrap()[0]
3323                                    {
3324                                        ui.set_cursor_icon(CursorIcon::ResizeWest);
3325                                    } else {
3326                                        ui.set_cursor_icon(CursorIcon::ResizeEast);
3327                                    };
3328                                }
3329                                [true, false, true, false] => {
3330                                    match [resource_panel.resizable[0], resource_panel.resizable[2]]
3331                                    {
3332                                        [true, true] => {
3333                                            if resource_panel.last_frame_mouse_status.is_none()
3334                                                && ui.input(|i| i.pointer.primary_pressed())
3335                                            {
3336                                                resource_panel.last_frame_mouse_status = Some((
3337                                                    mouse_pos.into(),
3338                                                    ClickAim::LeftTopResize,
3339                                                    [
3340                                                        mouse_pos.x - position[0],
3341                                                        mouse_pos.y - position[1],
3342                                                    ],
3343                                                ))
3344                                            };
3345                                            if size[0] > resource_panel.min_size[0]
3346                                                && (resource_panel.max_size.is_none()
3347                                                    || size[0]
3348                                                        < resource_panel.max_size.unwrap()[0])
3349                                                || size[1] > resource_panel.min_size[1]
3350                                                    && (resource_panel.max_size.is_none()
3351                                                        || size[1]
3352                                                            < resource_panel.max_size.unwrap()[1])
3353                                            {
3354                                                ui.set_cursor_icon(CursorIcon::ResizeNwSe);
3355                                            } else if resource_panel.max_size.is_some()
3356                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3357                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3358                                            {
3359                                                ui.set_cursor_icon(CursorIcon::ResizeSouthEast);
3360                                            } else {
3361                                                ui.set_cursor_icon(CursorIcon::ResizeNorthWest)
3362                                            };
3363                                        }
3364                                        [false, true] => {
3365                                            if resource_panel.last_frame_mouse_status.is_none()
3366                                                && ui.input(|i| i.pointer.primary_pressed())
3367                                            {
3368                                                resource_panel.last_frame_mouse_status = Some((
3369                                                    mouse_pos.into(),
3370                                                    ClickAim::LeftResize,
3371                                                    [
3372                                                        mouse_pos.x - position[0],
3373                                                        mouse_pos.y - position[1],
3374                                                    ],
3375                                                ))
3376                                            };
3377                                            if size[0] > resource_panel.min_size[0]
3378                                                && (resource_panel.max_size.is_none()
3379                                                    || size[0]
3380                                                        < resource_panel.max_size.unwrap()[0])
3381                                            {
3382                                                ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3383                                            } else if resource_panel.max_size.is_some()
3384                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3385                                            {
3386                                                ui.set_cursor_icon(CursorIcon::ResizeEast);
3387                                            } else {
3388                                                ui.set_cursor_icon(CursorIcon::ResizeWest);
3389                                            };
3390                                        }
3391                                        [true, false] => {
3392                                            if resource_panel.last_frame_mouse_status.is_none()
3393                                                && ui.input(|i| i.pointer.primary_pressed())
3394                                            {
3395                                                resource_panel.last_frame_mouse_status = Some((
3396                                                    mouse_pos.into(),
3397                                                    ClickAim::TopResize,
3398                                                    [
3399                                                        mouse_pos.x - position[0],
3400                                                        mouse_pos.y - position[1],
3401                                                    ],
3402                                                ))
3403                                            };
3404                                            if size[1] > resource_panel.min_size[1]
3405                                                && (resource_panel.max_size.is_none()
3406                                                    || size[1]
3407                                                        < resource_panel.max_size.unwrap()[1])
3408                                            {
3409                                                ui.set_cursor_icon(CursorIcon::ResizeVertical);
3410                                            } else if resource_panel.max_size.is_some()
3411                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3412                                            {
3413                                                ui.set_cursor_icon(CursorIcon::ResizeSouth);
3414                                            } else {
3415                                                ui.set_cursor_icon(CursorIcon::ResizeNorth);
3416                                            };
3417                                        }
3418                                        [false, false] => {}
3419                                    }
3420                                }
3421                                [false, true, false, true] => {
3422                                    match [resource_panel.resizable[1], resource_panel.resizable[3]]
3423                                    {
3424                                        [true, true] => {
3425                                            if resource_panel.last_frame_mouse_status.is_none()
3426                                                && ui.input(|i| i.pointer.primary_pressed())
3427                                            {
3428                                                resource_panel.last_frame_mouse_status = Some((
3429                                                    mouse_pos.into(),
3430                                                    ClickAim::RightBottomResize,
3431                                                    [
3432                                                        mouse_pos.x - position[0],
3433                                                        mouse_pos.y - position[1],
3434                                                    ],
3435                                                ))
3436                                            };
3437                                            if size[0] > resource_panel.min_size[0]
3438                                                && (resource_panel.max_size.is_none()
3439                                                    || size[0]
3440                                                        < resource_panel.max_size.unwrap()[0])
3441                                                || size[1] > resource_panel.min_size[1]
3442                                                    && (resource_panel.max_size.is_none()
3443                                                        || size[1]
3444                                                            < resource_panel.max_size.unwrap()[1])
3445                                            {
3446                                                ui.set_cursor_icon(CursorIcon::ResizeNwSe);
3447                                            } else if resource_panel.max_size.is_some()
3448                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3449                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3450                                            {
3451                                                ui.set_cursor_icon(CursorIcon::ResizeNorthWest);
3452                                            } else {
3453                                                ui.set_cursor_icon(CursorIcon::ResizeSouthEast)
3454                                            };
3455                                        }
3456                                        [false, true] => {
3457                                            if resource_panel.last_frame_mouse_status.is_none()
3458                                                && ui.input(|i| i.pointer.primary_pressed())
3459                                            {
3460                                                resource_panel.last_frame_mouse_status = Some((
3461                                                    mouse_pos.into(),
3462                                                    ClickAim::RightResize,
3463                                                    [
3464                                                        mouse_pos.x - position[0],
3465                                                        mouse_pos.y - position[1],
3466                                                    ],
3467                                                ))
3468                                            };
3469                                            if size[0] > resource_panel.min_size[0]
3470                                                && (resource_panel.max_size.is_none()
3471                                                    || size[0]
3472                                                        < resource_panel.max_size.unwrap()[0])
3473                                            {
3474                                                ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3475                                            } else if resource_panel.max_size.is_some()
3476                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3477                                            {
3478                                                ui.set_cursor_icon(CursorIcon::ResizeWest);
3479                                            } else {
3480                                                ui.set_cursor_icon(CursorIcon::ResizeEast);
3481                                            };
3482                                        }
3483                                        [true, false] => {
3484                                            if resource_panel.last_frame_mouse_status.is_none()
3485                                                && ui.input(|i| i.pointer.primary_pressed())
3486                                            {
3487                                                resource_panel.last_frame_mouse_status = Some((
3488                                                    mouse_pos.into(),
3489                                                    ClickAim::BottomResize,
3490                                                    [
3491                                                        mouse_pos.x - position[0],
3492                                                        mouse_pos.y - position[1],
3493                                                    ],
3494                                                ))
3495                                            };
3496                                            if size[1] > resource_panel.min_size[1]
3497                                                && (resource_panel.max_size.is_none()
3498                                                    || size[1]
3499                                                        < resource_panel.max_size.unwrap()[1])
3500                                            {
3501                                                ui.set_cursor_icon(CursorIcon::ResizeVertical);
3502                                            } else if resource_panel.max_size.is_some()
3503                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3504                                            {
3505                                                ui.set_cursor_icon(CursorIcon::ResizeNorth);
3506                                            } else {
3507                                                ui.set_cursor_icon(CursorIcon::ResizeSouth);
3508                                            };
3509                                        }
3510                                        [false, false] => {}
3511                                    }
3512                                }
3513                                [true, false, false, true] => {
3514                                    match [resource_panel.resizable[0], resource_panel.resizable[3]]
3515                                    {
3516                                        [true, true] => {
3517                                            if resource_panel.last_frame_mouse_status.is_none()
3518                                                && ui.input(|i| i.pointer.primary_pressed())
3519                                            {
3520                                                resource_panel.last_frame_mouse_status = Some((
3521                                                    mouse_pos.into(),
3522                                                    ClickAim::RightTopResize,
3523                                                    [
3524                                                        mouse_pos.x - position[0],
3525                                                        mouse_pos.y - position[1],
3526                                                    ],
3527                                                ))
3528                                            };
3529                                            if size[0] > resource_panel.min_size[0]
3530                                                && (resource_panel.max_size.is_none()
3531                                                    || size[0]
3532                                                        < resource_panel.max_size.unwrap()[0])
3533                                                || size[1] > resource_panel.min_size[1]
3534                                                    && (resource_panel.max_size.is_none()
3535                                                        || size[1]
3536                                                            < resource_panel.max_size.unwrap()[1])
3537                                            {
3538                                                ui.set_cursor_icon(CursorIcon::ResizeNeSw);
3539                                            } else if resource_panel.max_size.is_some()
3540                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3541                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3542                                            {
3543                                                ui.set_cursor_icon(CursorIcon::ResizeSouthWest);
3544                                            } else {
3545                                                ui.set_cursor_icon(CursorIcon::ResizeNorthEast)
3546                                            };
3547                                        }
3548                                        [false, true] => {
3549                                            if resource_panel.last_frame_mouse_status.is_none()
3550                                                && ui.input(|i| i.pointer.primary_pressed())
3551                                            {
3552                                                resource_panel.last_frame_mouse_status = Some((
3553                                                    mouse_pos.into(),
3554                                                    ClickAim::RightResize,
3555                                                    [
3556                                                        mouse_pos.x - position[0],
3557                                                        mouse_pos.y - position[1],
3558                                                    ],
3559                                                ))
3560                                            };
3561                                            if size[0] > resource_panel.min_size[0]
3562                                                && (resource_panel.max_size.is_none()
3563                                                    || size[0]
3564                                                        < resource_panel.max_size.unwrap()[0])
3565                                            {
3566                                                ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3567                                            } else if resource_panel.max_size.is_some()
3568                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3569                                            {
3570                                                ui.set_cursor_icon(CursorIcon::ResizeWest);
3571                                            } else {
3572                                                ui.set_cursor_icon(CursorIcon::ResizeEast);
3573                                            };
3574                                        }
3575                                        [true, false] => {
3576                                            if resource_panel.last_frame_mouse_status.is_none()
3577                                                && ui.input(|i| i.pointer.primary_pressed())
3578                                            {
3579                                                resource_panel.last_frame_mouse_status = Some((
3580                                                    mouse_pos.into(),
3581                                                    ClickAim::TopResize,
3582                                                    [
3583                                                        mouse_pos.x - position[0],
3584                                                        mouse_pos.y - position[1],
3585                                                    ],
3586                                                ))
3587                                            };
3588                                            if size[1] > resource_panel.min_size[1]
3589                                                && (resource_panel.max_size.is_none()
3590                                                    || size[1]
3591                                                        < resource_panel.max_size.unwrap()[1])
3592                                            {
3593                                                ui.set_cursor_icon(CursorIcon::ResizeVertical);
3594                                            } else if resource_panel.max_size.is_some()
3595                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3596                                            {
3597                                                ui.set_cursor_icon(CursorIcon::ResizeSouth);
3598                                            } else {
3599                                                ui.set_cursor_icon(CursorIcon::ResizeNorth);
3600                                            };
3601                                        }
3602                                        [false, false] => {}
3603                                    }
3604                                }
3605                                [false, true, true, false] => {
3606                                    match [resource_panel.resizable[1], resource_panel.resizable[2]]
3607                                    {
3608                                        [true, true] => {
3609                                            if resource_panel.last_frame_mouse_status.is_none()
3610                                                && ui.input(|i| i.pointer.primary_pressed())
3611                                            {
3612                                                resource_panel.last_frame_mouse_status = Some((
3613                                                    mouse_pos.into(),
3614                                                    ClickAim::LeftBottomResize,
3615                                                    [
3616                                                        mouse_pos.x - position[0],
3617                                                        mouse_pos.y - position[1],
3618                                                    ],
3619                                                ))
3620                                            };
3621                                            if size[0] > resource_panel.min_size[0]
3622                                                && (resource_panel.max_size.is_none()
3623                                                    || size[0]
3624                                                        < resource_panel.max_size.unwrap()[0])
3625                                                || size[1] > resource_panel.min_size[1]
3626                                                    && (resource_panel.max_size.is_none()
3627                                                        || size[1]
3628                                                            < resource_panel.max_size.unwrap()[1])
3629                                            {
3630                                                ui.set_cursor_icon(CursorIcon::ResizeNeSw);
3631                                            } else if resource_panel.max_size.is_some()
3632                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3633                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3634                                            {
3635                                                ui.set_cursor_icon(CursorIcon::ResizeNorthEast);
3636                                            } else {
3637                                                ui.set_cursor_icon(CursorIcon::ResizeSouthWest)
3638                                            };
3639                                        }
3640                                        [false, true] => {
3641                                            if resource_panel.last_frame_mouse_status.is_none()
3642                                                && ui.input(|i| i.pointer.primary_pressed())
3643                                            {
3644                                                resource_panel.last_frame_mouse_status = Some((
3645                                                    mouse_pos.into(),
3646                                                    ClickAim::LeftResize,
3647                                                    [
3648                                                        mouse_pos.x - position[0],
3649                                                        mouse_pos.y - position[1],
3650                                                    ],
3651                                                ))
3652                                            };
3653                                            if size[0] > resource_panel.min_size[0]
3654                                                && (resource_panel.max_size.is_none()
3655                                                    || size[0]
3656                                                        < resource_panel.max_size.unwrap()[0])
3657                                            {
3658                                                ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
3659                                            } else if resource_panel.max_size.is_some()
3660                                                && size[0] >= resource_panel.max_size.unwrap()[0]
3661                                            {
3662                                                ui.set_cursor_icon(CursorIcon::ResizeEast);
3663                                            } else {
3664                                                ui.set_cursor_icon(CursorIcon::ResizeWest);
3665                                            };
3666                                        }
3667                                        [true, false] => {
3668                                            if resource_panel.last_frame_mouse_status.is_none()
3669                                                && ui.input(|i| i.pointer.primary_pressed())
3670                                            {
3671                                                resource_panel.last_frame_mouse_status = Some((
3672                                                    mouse_pos.into(),
3673                                                    ClickAim::BottomResize,
3674                                                    [
3675                                                        mouse_pos.x - position[0],
3676                                                        mouse_pos.y - position[1],
3677                                                    ],
3678                                                ))
3679                                            };
3680                                            if size[1] > resource_panel.min_size[1]
3681                                                && (resource_panel.max_size.is_none()
3682                                                    || size[1]
3683                                                        < resource_panel.max_size.unwrap()[1])
3684                                            {
3685                                                ui.set_cursor_icon(CursorIcon::ResizeVertical);
3686                                            } else if resource_panel.max_size.is_some()
3687                                                && size[1] >= resource_panel.max_size.unwrap()[1]
3688                                            {
3689                                                ui.set_cursor_icon(CursorIcon::ResizeNorth);
3690                                            } else {
3691                                                ui.set_cursor_icon(CursorIcon::ResizeSouth);
3692                                            };
3693                                        }
3694                                        [false, false] => {}
3695                                    }
3696                                }
3697                                _ => {}
3698                            };
3699                            resource_panel.last_frame_mouse_status =
3700                                if resource_panel.last_frame_mouse_status.is_none()
3701                                    && rect.contains(mouse_pos)
3702                                    && ui.input(|i| i.pointer.primary_pressed())
3703                                {
3704                                    Some((
3705                                        [mouse_pos.x, mouse_pos.y],
3706                                        ClickAim::Move,
3707                                        [mouse_pos.x - position[0], mouse_pos.y - position[1]],
3708                                    ))
3709                                } else if resource_panel.last_frame_mouse_status.is_some()
3710                                    && !ui.input(|i| i.pointer.primary_released())
3711                                {
3712                                    Some((
3713                                        [mouse_pos.x, mouse_pos.y],
3714                                        resource_panel.last_frame_mouse_status.unwrap().1,
3715                                        resource_panel.last_frame_mouse_status.unwrap().2,
3716                                    ))
3717                                } else {
3718                                    None
3719                                };
3720                        } else if ui.input(|i| i.pointer.primary_released()) {
3721                            resource_panel.last_frame_mouse_status = None;
3722                        };
3723                    };
3724                    if let Some((mouse_pos, click_aim, offset)) =
3725                        resource_panel.last_frame_mouse_status
3726                    {
3727                        match click_aim {
3728                            ClickAim::LeftTopResize => {
3729                                if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
3730                                    && (resource_panel.max_size.is_none()
3731                                        || position[0] - mouse_pos[0] + size[0]
3732                                            < resource_panel.max_size.unwrap()[0])
3733                                {
3734                                    position_size_config.origin_size[0] +=
3735                                        position[0] - mouse_pos[0];
3736                                    position_size_config.origin_position[0] = mouse_pos[0];
3737                                } else if resource_panel.max_size.is_some()
3738                                    && position[0] - mouse_pos[0] + size[0]
3739                                        >= resource_panel.max_size.unwrap()[0]
3740                                {
3741                                    position_size_config.origin_position[0] -=
3742                                        resource_panel.max_size.unwrap()[0]
3743                                            - position_size_config.origin_size[0];
3744                                    position_size_config.origin_size[0] =
3745                                        resource_panel.max_size.unwrap()[0];
3746                                } else {
3747                                    position_size_config.origin_position[0] += position_size_config
3748                                        .origin_size[0]
3749                                        - resource_panel.min_size[0];
3750                                    position_size_config.origin_size[0] =
3751                                        resource_panel.min_size[0];
3752                                };
3753                                if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
3754                                    && (resource_panel.max_size.is_none()
3755                                        || position[1] - mouse_pos[1] + size[1]
3756                                            < resource_panel.max_size.unwrap()[1])
3757                                {
3758                                    position_size_config.origin_size[1] +=
3759                                        position[1] - mouse_pos[1];
3760                                    position_size_config.origin_position[1] = mouse_pos[1];
3761                                } else if resource_panel.max_size.is_some()
3762                                    && position[1] - mouse_pos[1] + size[1]
3763                                        >= resource_panel.max_size.unwrap()[1]
3764                                {
3765                                    position_size_config.origin_position[1] -=
3766                                        resource_panel.max_size.unwrap()[1]
3767                                            - position_size_config.origin_size[1];
3768                                    position_size_config.origin_size[1] =
3769                                        resource_panel.max_size.unwrap()[1];
3770                                } else {
3771                                    position_size_config.origin_position[1] += position_size_config
3772                                        .origin_size[1]
3773                                        - resource_panel.min_size[1];
3774                                    position_size_config.origin_size[1] =
3775                                        resource_panel.min_size[1];
3776                                };
3777                                if size[0] > resource_panel.min_size[0]
3778                                    && (resource_panel.max_size.is_none()
3779                                        || size[0] < resource_panel.max_size.unwrap()[0])
3780                                    || size[1] > resource_panel.min_size[1]
3781                                        && (resource_panel.max_size.is_none()
3782                                            || size[1] < resource_panel.max_size.unwrap()[1])
3783                                {
3784                                    ui.set_cursor_icon(CursorIcon::ResizeNwSe);
3785                                } else if resource_panel.max_size.is_some()
3786                                    && size[0] >= resource_panel.max_size.unwrap()[0]
3787                                    && size[1] >= resource_panel.max_size.unwrap()[1]
3788                                {
3789                                    ui.set_cursor_icon(CursorIcon::ResizeSouthEast);
3790                                } else {
3791                                    ui.set_cursor_icon(CursorIcon::ResizeNorthWest)
3792                                };
3793                            }
3794                            ClickAim::RightBottomResize => {
3795                                if mouse_pos[0] - position[0] > resource_panel.min_size[0]
3796                                    && (resource_panel.max_size.is_none()
3797                                        || mouse_pos[0] - position[0]
3798                                            < resource_panel.max_size.unwrap()[0])
3799                                {
3800                                    position_size_config.origin_size[0] =
3801                                        mouse_pos[0] - position[0];
3802                                } else if resource_panel.max_size.is_some()
3803                                    && mouse_pos[0] - position[0]
3804                                        >= resource_panel.max_size.unwrap()[0]
3805                                {
3806                                    position_size_config.origin_size[0] =
3807                                        resource_panel.max_size.unwrap()[0];
3808                                } else {
3809                                    position_size_config.origin_size[0] =
3810                                        resource_panel.min_size[0];
3811                                };
3812                                if mouse_pos[1] - position[1] > resource_panel.min_size[1]
3813                                    && (resource_panel.max_size.is_none()
3814                                        || mouse_pos[1] - position[1]
3815                                            < resource_panel.max_size.unwrap()[1])
3816                                {
3817                                    position_size_config.origin_size[1] =
3818                                        mouse_pos[1] - position[1];
3819                                } else if resource_panel.max_size.is_some()
3820                                    && mouse_pos[1] - position[1]
3821                                        >= resource_panel.max_size.unwrap()[1]
3822                                {
3823                                    position_size_config.origin_size[1] =
3824                                        resource_panel.max_size.unwrap()[1];
3825                                } else {
3826                                    position_size_config.origin_size[1] =
3827                                        resource_panel.min_size[1];
3828                                };
3829                                if size[0] > resource_panel.min_size[0]
3830                                    && (resource_panel.max_size.is_none()
3831                                        || size[0] < resource_panel.max_size.unwrap()[0])
3832                                    || size[1] > resource_panel.min_size[1]
3833                                        && (resource_panel.max_size.is_none()
3834                                            || size[1] < resource_panel.max_size.unwrap()[1])
3835                                {
3836                                    ui.set_cursor_icon(CursorIcon::ResizeNwSe);
3837                                } else if resource_panel.max_size.is_some()
3838                                    && size[0] >= resource_panel.max_size.unwrap()[0]
3839                                    && size[1] >= resource_panel.max_size.unwrap()[1]
3840                                {
3841                                    ui.set_cursor_icon(CursorIcon::ResizeNorthWest);
3842                                } else {
3843                                    ui.set_cursor_icon(CursorIcon::ResizeSouthEast)
3844                                };
3845                            }
3846                            ClickAim::RightTopResize => {
3847                                if mouse_pos[0] - position[0] > resource_panel.min_size[0]
3848                                    && (resource_panel.max_size.is_none()
3849                                        || mouse_pos[0] - position[0]
3850                                            < resource_panel.max_size.unwrap()[0])
3851                                {
3852                                    position_size_config.origin_size[0] =
3853                                        mouse_pos[0] - position[0];
3854                                } else if resource_panel.max_size.is_some()
3855                                    && mouse_pos[0] - position[0]
3856                                        >= resource_panel.max_size.unwrap()[0]
3857                                {
3858                                    position_size_config.origin_size[0] =
3859                                        resource_panel.max_size.unwrap()[0];
3860                                } else {
3861                                    position_size_config.origin_size[0] =
3862                                        resource_panel.min_size[0];
3863                                };
3864                                if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
3865                                    && (resource_panel.max_size.is_none()
3866                                        || position[1] - mouse_pos[1] + size[1]
3867                                            < resource_panel.max_size.unwrap()[1])
3868                                {
3869                                    position_size_config.origin_size[1] +=
3870                                        position[1] - mouse_pos[1];
3871                                    position_size_config.origin_position[1] = mouse_pos[1];
3872                                } else if resource_panel.max_size.is_some()
3873                                    && position[1] - mouse_pos[1] + size[1]
3874                                        >= resource_panel.max_size.unwrap()[1]
3875                                {
3876                                    position_size_config.origin_position[1] -=
3877                                        resource_panel.max_size.unwrap()[1]
3878                                            - position_size_config.origin_size[1];
3879                                    position_size_config.origin_size[1] =
3880                                        resource_panel.max_size.unwrap()[1];
3881                                } else {
3882                                    position_size_config.origin_position[1] += position_size_config
3883                                        .origin_size[1]
3884                                        - resource_panel.min_size[1];
3885                                    position_size_config.origin_size[1] =
3886                                        resource_panel.min_size[1];
3887                                };
3888                                if size[0] > resource_panel.min_size[0]
3889                                    && (resource_panel.max_size.is_none()
3890                                        || size[0] < resource_panel.max_size.unwrap()[0])
3891                                    || size[1] > resource_panel.min_size[1]
3892                                        && (resource_panel.max_size.is_none()
3893                                            || size[1] < resource_panel.max_size.unwrap()[1])
3894                                {
3895                                    ui.set_cursor_icon(CursorIcon::ResizeNeSw);
3896                                } else if resource_panel.max_size.is_some()
3897                                    && size[0] >= resource_panel.max_size.unwrap()[0]
3898                                    && size[1] >= resource_panel.max_size.unwrap()[1]
3899                                {
3900                                    ui.set_cursor_icon(CursorIcon::ResizeSouthWest);
3901                                } else {
3902                                    ui.set_cursor_icon(CursorIcon::ResizeNorthEast)
3903                                };
3904                            }
3905                            ClickAim::LeftBottomResize => {
3906                                if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
3907                                    && (resource_panel.max_size.is_none()
3908                                        || position[0] - mouse_pos[0] + size[0]
3909                                            < resource_panel.max_size.unwrap()[0])
3910                                {
3911                                    position_size_config.origin_size[0] +=
3912                                        position[0] - mouse_pos[0];
3913                                    position_size_config.origin_position[0] = mouse_pos[0];
3914                                } else if resource_panel.max_size.is_some()
3915                                    && position[0] - mouse_pos[0] + size[0]
3916                                        >= resource_panel.max_size.unwrap()[0]
3917                                {
3918                                    position_size_config.origin_position[0] -=
3919                                        resource_panel.max_size.unwrap()[0]
3920                                            - position_size_config.origin_size[0];
3921                                    position_size_config.origin_size[0] =
3922                                        resource_panel.max_size.unwrap()[0];
3923                                } else {
3924                                    position_size_config.origin_position[0] += position_size_config
3925                                        .origin_size[0]
3926                                        - resource_panel.min_size[0];
3927                                    position_size_config.origin_size[0] =
3928                                        resource_panel.min_size[0];
3929                                };
3930                                if mouse_pos[1] - position[1] > resource_panel.min_size[1]
3931                                    && (resource_panel.max_size.is_none()
3932                                        || mouse_pos[1] - position[1]
3933                                            < resource_panel.max_size.unwrap()[1])
3934                                {
3935                                    position_size_config.origin_size[1] =
3936                                        mouse_pos[1] - position[1];
3937                                } else if resource_panel.max_size.is_some()
3938                                    && mouse_pos[1] - position[1]
3939                                        >= resource_panel.max_size.unwrap()[1]
3940                                {
3941                                    position_size_config.origin_size[1] =
3942                                        resource_panel.max_size.unwrap()[1];
3943                                } else {
3944                                    position_size_config.origin_size[1] =
3945                                        resource_panel.min_size[1];
3946                                };
3947                                if size[0] > resource_panel.min_size[0]
3948                                    && (resource_panel.max_size.is_none()
3949                                        || size[0] < resource_panel.max_size.unwrap()[0])
3950                                    || size[1] > resource_panel.min_size[1]
3951                                        && (resource_panel.max_size.is_none()
3952                                            || size[1] < resource_panel.max_size.unwrap()[1])
3953                                {
3954                                    ui.set_cursor_icon(CursorIcon::ResizeNeSw);
3955                                } else if resource_panel.max_size.is_some()
3956                                    && size[0] >= resource_panel.max_size.unwrap()[0]
3957                                    && size[1] >= resource_panel.max_size.unwrap()[1]
3958                                {
3959                                    ui.set_cursor_icon(CursorIcon::ResizeNorthEast);
3960                                } else {
3961                                    ui.set_cursor_icon(CursorIcon::ResizeSouthWest)
3962                                };
3963                            }
3964                            ClickAim::TopResize => {
3965                                if position[1] - mouse_pos[1] + size[1] > resource_panel.min_size[1]
3966                                    && (resource_panel.max_size.is_none()
3967                                        || position[1] - mouse_pos[1] + size[1]
3968                                            < resource_panel.max_size.unwrap()[1])
3969                                {
3970                                    position_size_config.origin_size[1] +=
3971                                        position[1] - mouse_pos[1];
3972                                    position_size_config.origin_position[1] = mouse_pos[1];
3973                                    ui.set_cursor_icon(CursorIcon::ResizeVertical);
3974                                } else if resource_panel.max_size.is_some()
3975                                    && position[1] - mouse_pos[1] + size[1]
3976                                        >= resource_panel.max_size.unwrap()[1]
3977                                {
3978                                    position_size_config.origin_position[1] -=
3979                                        resource_panel.max_size.unwrap()[1]
3980                                            - position_size_config.origin_size[1];
3981                                    position_size_config.origin_size[1] =
3982                                        resource_panel.max_size.unwrap()[1];
3983                                    ui.set_cursor_icon(CursorIcon::ResizeSouth);
3984                                } else {
3985                                    position_size_config.origin_position[1] += position_size_config
3986                                        .origin_size[1]
3987                                        - resource_panel.min_size[1];
3988                                    position_size_config.origin_size[1] =
3989                                        resource_panel.min_size[1];
3990                                    ui.set_cursor_icon(CursorIcon::ResizeNorth);
3991                                };
3992                            }
3993                            ClickAim::BottomResize => {
3994                                if mouse_pos[1] - position[1] > resource_panel.min_size[1]
3995                                    && (resource_panel.max_size.is_none()
3996                                        || mouse_pos[1] - position[1]
3997                                            < resource_panel.max_size.unwrap()[1])
3998                                {
3999                                    position_size_config.origin_size[1] =
4000                                        mouse_pos[1] - position[1];
4001                                    ui.set_cursor_icon(CursorIcon::ResizeVertical);
4002                                } else if resource_panel.max_size.is_some()
4003                                    && mouse_pos[1] - position[1]
4004                                        >= resource_panel.max_size.unwrap()[1]
4005                                {
4006                                    position_size_config.origin_size[1] =
4007                                        resource_panel.max_size.unwrap()[1];
4008                                    ui.set_cursor_icon(CursorIcon::ResizeNorth);
4009                                } else {
4010                                    position_size_config.origin_size[1] =
4011                                        resource_panel.min_size[1];
4012                                    ui.set_cursor_icon(CursorIcon::ResizeSouth);
4013                                };
4014                            }
4015                            ClickAim::LeftResize => {
4016                                if position[0] - mouse_pos[0] + size[0] > resource_panel.min_size[0]
4017                                    && (resource_panel.max_size.is_none()
4018                                        || position[0] - mouse_pos[0] + size[0]
4019                                            < resource_panel.max_size.unwrap()[0])
4020                                {
4021                                    position_size_config.origin_size[0] +=
4022                                        position[0] - mouse_pos[0];
4023                                    position_size_config.origin_position[0] = mouse_pos[0];
4024                                    ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
4025                                } else if resource_panel.max_size.is_some()
4026                                    && position[0] - mouse_pos[0] + size[0]
4027                                        >= resource_panel.max_size.unwrap()[0]
4028                                {
4029                                    position_size_config.origin_position[0] -=
4030                                        resource_panel.max_size.unwrap()[0]
4031                                            - position_size_config.origin_size[0];
4032                                    position_size_config.origin_size[0] =
4033                                        resource_panel.max_size.unwrap()[0];
4034                                    ui.set_cursor_icon(CursorIcon::ResizeEast);
4035                                } else {
4036                                    position_size_config.origin_position[0] += position_size_config
4037                                        .origin_size[0]
4038                                        - resource_panel.min_size[0];
4039                                    position_size_config.origin_size[0] =
4040                                        resource_panel.min_size[0];
4041                                    ui.set_cursor_icon(CursorIcon::ResizeWest);
4042                                };
4043                            }
4044                            ClickAim::RightResize => {
4045                                if mouse_pos[0] - position[0] > resource_panel.min_size[0]
4046                                    && (resource_panel.max_size.is_none()
4047                                        || mouse_pos[0] - position[0]
4048                                            < resource_panel.max_size.unwrap()[0])
4049                                {
4050                                    position_size_config.origin_size[0] =
4051                                        mouse_pos[0] - position[0];
4052                                    ui.set_cursor_icon(CursorIcon::ResizeHorizontal);
4053                                } else if resource_panel.max_size.is_some()
4054                                    && mouse_pos[0] - position[0]
4055                                        >= resource_panel.max_size.unwrap()[0]
4056                                {
4057                                    position_size_config.origin_size[0] =
4058                                        resource_panel.max_size.unwrap()[0];
4059                                    ui.set_cursor_icon(CursorIcon::ResizeWest);
4060                                } else {
4061                                    position_size_config.origin_size[0] =
4062                                        resource_panel.min_size[0];
4063                                    ui.set_cursor_icon(CursorIcon::ResizeEast);
4064                                };
4065                            }
4066                            ClickAim::Move => {
4067                                ui.set_cursor_icon(match resource_panel.movable {
4068                                    [true, true] => CursorIcon::Move,
4069                                    [true, false] => CursorIcon::ResizeColumn,
4070                                    [false, true] => CursorIcon::ResizeRow,
4071                                    [false, false] => CursorIcon::NotAllowed,
4072                                });
4073                                if resource_panel.movable[0] {
4074                                    position_size_config.origin_position[0] =
4075                                        mouse_pos[0] - offset[0];
4076                                };
4077                                if resource_panel.movable[1] {
4078                                    position_size_config.origin_position[1] =
4079                                        mouse_pos[1] - offset[1];
4080                                };
4081                            }
4082                        };
4083                    };
4084                    [position, size] = position_size_processor(position_size_config, ui);
4085                    let background_type = match background.background_type.clone() {
4086                        BackgroundType::CustomRect(config) => BackgroundType::CustomRect(
4087                            config
4088                                .position_size_config(Some(position_size_config))
4089                                .hidden(Some(resource_panel.hidden)),
4090                        ),
4091                        BackgroundType::Image(config) => BackgroundType::Image(
4092                            config
4093                                .position_size_config(Some(position_size_config))
4094                                .hidden(Some(resource_panel.hidden)),
4095                        ),
4096                    };
4097                    self.replace_resource(
4098                        &format!("{}Background", &id.name),
4099                        background.clone().background_type(&background_type).clone(),
4100                    )?;
4101                    self.use_resource(
4102                        &RustConstructorId {
4103                            name: format!("{}Background", &id.name),
4104                            discern_type: "Background".to_string(),
4105                        },
4106                        ui,
4107                    )?;
4108                    type PointList = Vec<([f32; 2], [f32; 2], [bool; 2], Option<String>)>;
4109                    let mut resource_point_list: PointList = Vec::new();
4110                    let mut use_resource_list = Vec::new();
4111                    let mut replace_resource_list = Vec::new();
4112                    for rcr in &self.rust_constructor_resource {
4113                        if self
4114                            .basic_front_resource_list
4115                            .contains(&rcr.id.discern_type)
4116                            && let Some(panel_name) =
4117                                get_tag("panel_name", &rcr.content.display_tags())
4118                            && panel_name.1 == id.name
4119                        {
4120                            if let [Some(citer_name), Some(citer_type)] = [
4121                                get_tag("citer_name", &rcr.content.display_tags()),
4122                                get_tag("citer_type", &rcr.content.display_tags()),
4123                            ] {
4124                                if !use_resource_list
4125                                    .iter()
4126                                    .any(|x| x == &[citer_name.1.clone(), citer_type.1.clone()])
4127                                {
4128                                    use_resource_list.push([citer_name.1, citer_type.1]);
4129                                };
4130                            } else if !use_resource_list
4131                                .iter()
4132                                .any(|x| x == &[rcr.id.name.clone(), rcr.id.discern_type.clone()])
4133                            {
4134                                use_resource_list
4135                                    .push([rcr.id.name.clone(), rcr.id.discern_type.clone()]);
4136                            };
4137                            let mut basic_front_resource: Box<dyn BasicFrontResource> =
4138                                match &*rcr.id.discern_type {
4139                                    "Image" => {
4140                                        Box::new(downcast_resource::<Image>(&*rcr.content)?.clone())
4141                                    }
4142                                    "Text" => {
4143                                        Box::new(downcast_resource::<Text>(&*rcr.content)?.clone())
4144                                    }
4145                                    "CustomRect" => Box::new(
4146                                        downcast_resource::<CustomRect>(&*rcr.content)?.clone(),
4147                                    ),
4148                                    _ => {
4149                                        unreachable!()
4150                                    }
4151                                };
4152                            if !resource_panel
4153                                .resource_storage
4154                                .iter()
4155                                .any(|x| x.id == rcr.id)
4156                            {
4157                                resource_panel.resource_storage.push(PanelStorage {
4158                                    id: rcr.id.clone(),
4159                                    ignore_render_layer: if let Some(display_info) =
4160                                        basic_front_resource.display_display_info()
4161                                    {
4162                                        display_info.ignore_render_layer
4163                                    } else {
4164                                        false
4165                                    },
4166                                    hidden: if let Some(display_info) =
4167                                        basic_front_resource.display_display_info()
4168                                    {
4169                                        display_info.hidden
4170                                    } else {
4171                                        false
4172                                    },
4173                                });
4174                            };
4175                            let enable_scrolling = [
4176                                get_tag("disable_x_scrolling", &rcr.content.display_tags())
4177                                    .is_none(),
4178                                get_tag("disable_y_scrolling", &rcr.content.display_tags())
4179                                    .is_none(),
4180                            ];
4181                            let offset = basic_front_resource.display_position_size_config().offset;
4182                            basic_front_resource.modify_position_size_config(
4183                                basic_front_resource
4184                                    .display_position_size_config()
4185                                    .x_location_grid(0_f32, 0_f32)
4186                                    .y_location_grid(0_f32, 0_f32)
4187                                    .x_size_grid(0_f32, 0_f32)
4188                                    .y_size_grid(0_f32, 0_f32)
4189                                    .offset(
4190                                        if enable_scrolling[0] {
4191                                            -resource_panel.scroll_progress[0]
4192                                        } else {
4193                                            offset[0]
4194                                        },
4195                                        if enable_scrolling[1] {
4196                                            -resource_panel.scroll_progress[1]
4197                                        } else {
4198                                            offset[1]
4199                                        },
4200                                    ),
4201                            );
4202                            let mut layout = resource_panel.overall_layout;
4203                            for custom_layout in &resource_panel.custom_layout {
4204                                match custom_layout {
4205                                    CustomPanelLayout::Id(layout_id, panel_layout) => {
4206                                        if rcr.id.cmp(layout_id) == Ordering::Equal {
4207                                            layout = *panel_layout;
4208                                            break;
4209                                        };
4210                                    }
4211                                    CustomPanelLayout::Type(layout_type, panel_layout) => {
4212                                        if *layout_type == rcr.id.discern_type {
4213                                            layout = *panel_layout;
4214                                        }
4215                                    }
4216                                };
4217                            }
4218                            let panel_layout_group = if let Some(panel_layout_group) =
4219                                get_tag("panel_layout_group", &basic_front_resource.display_tags())
4220                            {
4221                                Some(panel_layout_group.1)
4222                            } else {
4223                                None
4224                            };
4225                            match layout.panel_margin {
4226                                PanelMargin::Vertical(
4227                                    [top, bottom, left, right],
4228                                    move_to_bottom,
4229                                ) => {
4230                                    let mut modify_y = 0_f32;
4231                                    let [default_x_position, default_y_position] =
4232                                        match layout.panel_location {
4233                                            PanelLocation::Absolute([x, y]) => {
4234                                                [position[0] + x, position[1] + y]
4235                                            }
4236                                            PanelLocation::Relative([x, y]) => [
4237                                                position[0]
4238                                                    + if x[1] != 0_f32 {
4239                                                        size[0] / x[1] * x[0]
4240                                                    } else {
4241                                                        0_f32
4242                                                    },
4243                                                position[1]
4244                                                    + if y[1] != 0_f32 {
4245                                                        size[1] / y[1] * y[0]
4246                                                    } else {
4247                                                        0_f32
4248                                                    },
4249                                            ],
4250                                        };
4251                                    let default_x_position = match basic_front_resource
4252                                        .display_position_size_config()
4253                                        .display_method
4254                                        .0
4255                                    {
4256                                        HorizontalAlign::Left => default_x_position,
4257                                        HorizontalAlign::Center => {
4258                                            default_x_position
4259                                                - basic_front_resource.display_size()[0] / 2.0
4260                                        }
4261                                        HorizontalAlign::Right => {
4262                                            default_x_position
4263                                                - basic_front_resource.display_size()[0]
4264                                        }
4265                                    };
4266                                    let default_y_position = match basic_front_resource
4267                                        .display_position_size_config()
4268                                        .display_method
4269                                        .1
4270                                    {
4271                                        VerticalAlign::Top => default_y_position,
4272                                        VerticalAlign::Center => {
4273                                            default_y_position
4274                                                - basic_front_resource.display_size()[1] / 2.0
4275                                        }
4276                                        VerticalAlign::Bottom => {
4277                                            default_y_position
4278                                                - basic_front_resource.display_size()[1]
4279                                        }
4280                                    };
4281                                    for point in &resource_point_list {
4282                                        if let Some(ref point_panel_layout_group) = point.3
4283                                            && let Some(ref panel_layout_group) = panel_layout_group
4284                                            && panel_layout_group == point_panel_layout_group
4285                                        {
4286                                            continue;
4287                                        };
4288                                        if default_x_position - left < point.1[0]
4289                                            && default_y_position - top + modify_y < point.1[1]
4290                                            && default_x_position
4291                                                + basic_front_resource.display_size()[0]
4292                                                + right
4293                                                > point.0[0]
4294                                            && default_y_position
4295                                                + basic_front_resource.display_size()[1]
4296                                                + bottom
4297                                                + modify_y
4298                                                > point.0[1]
4299                                        {
4300                                            if move_to_bottom
4301                                                && point.1[1] - default_y_position + top > modify_y
4302                                            {
4303                                                modify_y = point.1[1] - default_y_position + top;
4304                                            } else if !move_to_bottom
4305                                                && point.0[1]
4306                                                    - default_y_position
4307                                                    - basic_front_resource.display_size()[1]
4308                                                    - bottom
4309                                                    < modify_y
4310                                            {
4311                                                modify_y = point.0[1]
4312                                                    - default_y_position
4313                                                    - basic_front_resource.display_size()[1]
4314                                                    - bottom;
4315                                            };
4316                                        };
4317                                    }
4318                                    let real_x_position = match basic_front_resource
4319                                        .display_position_size_config()
4320                                        .display_method
4321                                        .0
4322                                    {
4323                                        HorizontalAlign::Left => default_x_position,
4324                                        HorizontalAlign::Center => {
4325                                            default_x_position
4326                                                + basic_front_resource.display_size()[0] / 2.0
4327                                        }
4328                                        HorizontalAlign::Right => {
4329                                            default_x_position
4330                                                + basic_front_resource.display_size()[0]
4331                                        }
4332                                    };
4333                                    let real_y_position = match basic_front_resource
4334                                        .display_position_size_config()
4335                                        .display_method
4336                                        .1
4337                                    {
4338                                        VerticalAlign::Top => default_y_position + modify_y,
4339                                        VerticalAlign::Center => {
4340                                            default_y_position
4341                                                + modify_y
4342                                                + basic_front_resource.display_size()[1] / 2.0
4343                                        }
4344                                        VerticalAlign::Bottom => {
4345                                            default_y_position
4346                                                + modify_y
4347                                                + basic_front_resource.display_size()[1]
4348                                        }
4349                                    };
4350                                    basic_front_resource.modify_position_size_config(
4351                                        basic_front_resource
4352                                            .display_position_size_config()
4353                                            .origin_position(
4354                                                real_x_position
4355                                                    + left
4356                                                    + resource_panel.inner_margin[2],
4357                                                real_y_position
4358                                                    + top
4359                                                    + resource_panel.inner_margin[0],
4360                                            ),
4361                                    );
4362                                    replace_resource_list.push((
4363                                        basic_front_resource.display_position_size_config(),
4364                                        [rcr.id.name.clone(), rcr.id.discern_type.clone()],
4365                                    ));
4366                                    resource_point_list.push((
4367                                        [real_x_position - left, real_y_position - top],
4368                                        [
4369                                            real_x_position
4370                                                + basic_front_resource.display_size()[0]
4371                                                + right,
4372                                            real_y_position
4373                                                + basic_front_resource.display_size()[1]
4374                                                + bottom,
4375                                        ],
4376                                        enable_scrolling,
4377                                        panel_layout_group,
4378                                    ));
4379                                }
4380                                PanelMargin::Horizontal(
4381                                    [top, bottom, left, right],
4382                                    move_to_right,
4383                                ) => {
4384                                    let mut modify_x = 0_f32;
4385                                    let [default_x_position, default_y_position] =
4386                                        match layout.panel_location {
4387                                            PanelLocation::Absolute([x, y]) => {
4388                                                [position[0] + x, position[1] + y]
4389                                            }
4390                                            PanelLocation::Relative([x, y]) => [
4391                                                position[0]
4392                                                    + if x[1] != 0_f32 {
4393                                                        size[0] / x[1] * x[0]
4394                                                    } else {
4395                                                        0_f32
4396                                                    },
4397                                                position[1]
4398                                                    + if y[1] != 0_f32 {
4399                                                        size[1] / y[1] * y[0]
4400                                                    } else {
4401                                                        0_f32
4402                                                    },
4403                                            ],
4404                                        };
4405                                    let default_x_position = match basic_front_resource
4406                                        .display_position_size_config()
4407                                        .display_method
4408                                        .0
4409                                    {
4410                                        HorizontalAlign::Left => default_x_position,
4411                                        HorizontalAlign::Center => {
4412                                            default_x_position
4413                                                - basic_front_resource.display_size()[0] / 2.0
4414                                        }
4415                                        HorizontalAlign::Right => {
4416                                            default_x_position
4417                                                - basic_front_resource.display_size()[0]
4418                                        }
4419                                    };
4420                                    let default_y_position = match basic_front_resource
4421                                        .display_position_size_config()
4422                                        .display_method
4423                                        .1
4424                                    {
4425                                        VerticalAlign::Top => default_y_position,
4426                                        VerticalAlign::Center => {
4427                                            default_y_position
4428                                                - basic_front_resource.display_size()[1] / 2.0
4429                                        }
4430                                        VerticalAlign::Bottom => {
4431                                            default_y_position
4432                                                - basic_front_resource.display_size()[1]
4433                                        }
4434                                    };
4435                                    for point in &resource_point_list {
4436                                        if let Some(ref point_panel_layout_group) = point.3
4437                                            && let Some(ref panel_layout_group) = panel_layout_group
4438                                            && panel_layout_group == point_panel_layout_group
4439                                        {
4440                                            continue;
4441                                        };
4442                                        if default_x_position - left + modify_x < point.1[0]
4443                                            && default_y_position - top < point.1[1]
4444                                            && default_x_position
4445                                                + basic_front_resource.display_size()[0]
4446                                                + right
4447                                                + modify_x
4448                                                > point.0[0]
4449                                            && default_y_position
4450                                                + basic_front_resource.display_size()[1]
4451                                                + bottom
4452                                                > point.0[1]
4453                                        {
4454                                            if move_to_right
4455                                                && point.1[0] - default_x_position + left > modify_x
4456                                            {
4457                                                modify_x = point.1[0] - default_x_position + left;
4458                                            } else if !move_to_right
4459                                                && point.0[0]
4460                                                    - default_x_position
4461                                                    - basic_front_resource.display_size()[0]
4462                                                    - right
4463                                                    < modify_x
4464                                            {
4465                                                modify_x = point.0[0]
4466                                                    - default_x_position
4467                                                    - basic_front_resource.display_size()[0]
4468                                                    - right;
4469                                            };
4470                                        };
4471                                    }
4472                                    let real_x_position = match basic_front_resource
4473                                        .display_position_size_config()
4474                                        .display_method
4475                                        .0
4476                                    {
4477                                        HorizontalAlign::Left => default_x_position + modify_x,
4478                                        HorizontalAlign::Center => {
4479                                            default_x_position
4480                                                + modify_x
4481                                                + basic_front_resource.display_size()[0] / 2.0
4482                                        }
4483                                        HorizontalAlign::Right => {
4484                                            default_x_position
4485                                                + modify_x
4486                                                + basic_front_resource.display_size()[0]
4487                                        }
4488                                    };
4489                                    let real_y_position = match basic_front_resource
4490                                        .display_position_size_config()
4491                                        .display_method
4492                                        .1
4493                                    {
4494                                        VerticalAlign::Top => default_y_position,
4495                                        VerticalAlign::Center => {
4496                                            default_y_position
4497                                                + basic_front_resource.display_size()[1] / 2.0
4498                                        }
4499                                        VerticalAlign::Bottom => {
4500                                            default_y_position
4501                                                + basic_front_resource.display_size()[1]
4502                                        }
4503                                    };
4504                                    basic_front_resource.modify_position_size_config(
4505                                        basic_front_resource
4506                                            .display_position_size_config()
4507                                            .origin_position(
4508                                                real_x_position
4509                                                    + left
4510                                                    + resource_panel.inner_margin[2],
4511                                                real_y_position
4512                                                    + top
4513                                                    + resource_panel.inner_margin[0],
4514                                            ),
4515                                    );
4516                                    replace_resource_list.push((
4517                                        basic_front_resource.display_position_size_config(),
4518                                        [rcr.id.name.clone(), rcr.id.discern_type.clone()],
4519                                    ));
4520                                    resource_point_list.push((
4521                                        [real_x_position - left, real_y_position - top],
4522                                        [
4523                                            real_x_position
4524                                                + basic_front_resource.display_size()[0]
4525                                                + right,
4526                                            real_y_position
4527                                                + basic_front_resource.display_size()[1]
4528                                                + bottom,
4529                                        ],
4530                                        enable_scrolling,
4531                                        panel_layout_group,
4532                                    ));
4533                                }
4534                                PanelMargin::None([top, bottom, left, right], influence_layout) => {
4535                                    let [default_x_position, default_y_position] =
4536                                        match layout.panel_location {
4537                                            PanelLocation::Absolute([x, y]) => {
4538                                                [position[0] + x, position[1] + y]
4539                                            }
4540                                            PanelLocation::Relative([x, y]) => [
4541                                                position[0]
4542                                                    + if x[1] != 0_f32 {
4543                                                        size[0] / x[1] * x[0]
4544                                                    } else {
4545                                                        0_f32
4546                                                    },
4547                                                position[1]
4548                                                    + if y[1] != 0_f32 {
4549                                                        size[1] / y[1] * y[0]
4550                                                    } else {
4551                                                        0_f32
4552                                                    },
4553                                            ],
4554                                        };
4555                                    basic_front_resource.modify_position_size_config(
4556                                        basic_front_resource
4557                                            .display_position_size_config()
4558                                            .origin_position(
4559                                                default_x_position
4560                                                    + left
4561                                                    + resource_panel.inner_margin[2],
4562                                                default_y_position
4563                                                    + top
4564                                                    + resource_panel.inner_margin[0],
4565                                            ),
4566                                    );
4567                                    replace_resource_list.push((
4568                                        basic_front_resource.display_position_size_config(),
4569                                        [rcr.id.name.clone(), rcr.id.discern_type.clone()],
4570                                    ));
4571                                    if influence_layout {
4572                                        resource_point_list.push((
4573                                            [default_x_position - left, default_y_position - top],
4574                                            [
4575                                                default_x_position
4576                                                    + basic_front_resource.display_size()[0]
4577                                                    + right,
4578                                                default_y_position
4579                                                    + basic_front_resource.display_size()[1]
4580                                                    + bottom,
4581                                            ],
4582                                            enable_scrolling,
4583                                            panel_layout_group,
4584                                        ));
4585                                    };
4586                                }
4587                            };
4588                        };
4589                    }
4590                    for (new_position_size_config, [name, discern_type]) in replace_resource_list {
4591                        let id = RustConstructorId {
4592                            name: name.clone(),
4593                            discern_type: discern_type.clone(),
4594                        };
4595                        let default_storage = if let Some(resource_storage) =
4596                            resource_panel.resource_storage.iter().find(|x| x.id == id)
4597                        {
4598                            [
4599                                true,
4600                                resource_storage.ignore_render_layer,
4601                                resource_storage.hidden,
4602                            ]
4603                        } else {
4604                            [false, true, true]
4605                        };
4606                        let basic_front_resource = self.get_basic_front_resource_mut(&id)?;
4607                        basic_front_resource.modify_position_size_config(new_position_size_config);
4608                        basic_front_resource.modify_clip_rect(Some(
4609                            position_size_config
4610                                .origin_size(
4611                                    position_size_config.origin_size[0]
4612                                        - resource_panel.inner_margin[2]
4613                                        - resource_panel.inner_margin[3],
4614                                    position_size_config.origin_size[1]
4615                                        - resource_panel.inner_margin[0]
4616                                        - resource_panel.inner_margin[1],
4617                                )
4618                                .origin_position(
4619                                    position_size_config.origin_position[0]
4620                                        + resource_panel.inner_margin[2],
4621                                    position_size_config.origin_position[1]
4622                                        + resource_panel.inner_margin[0],
4623                                ),
4624                        ));
4625                        basic_front_resource.modify_display_info({
4626                            let mut display_info =
4627                                basic_front_resource.display_display_info().unwrap();
4628                            display_info.ignore_render_layer =
4629                                if resource_panel.last_frame_mouse_status.is_some()
4630                                    && resource_get_focus[1]
4631                                {
4632                                    true
4633                                } else if default_storage[0] {
4634                                    default_storage[1]
4635                                } else {
4636                                    display_info.ignore_render_layer
4637                                };
4638                            display_info.hidden = if resource_panel.hidden {
4639                                true
4640                            } else if default_storage[0] {
4641                                default_storage[2]
4642                            } else {
4643                                display_info.hidden
4644                            };
4645                            display_info
4646                        });
4647                    }
4648                    for info in use_resource_list {
4649                        self.use_resource(
4650                            &RustConstructorId {
4651                                name: info[0].clone(),
4652                                discern_type: info[1].clone(),
4653                            },
4654                            ui,
4655                        )?;
4656                    }
4657                    let mut resource_length = [None, None];
4658                    for point in resource_point_list {
4659                        resource_length = [
4660                            if resource_length[0].is_none()
4661                                || resource_length[0].is_some()
4662                                    && point.1[0] > resource_length[0].unwrap()
4663                                    && point.2[0]
4664                            {
4665                                Some(point.1[0])
4666                            } else {
4667                                resource_length[0]
4668                            },
4669                            if resource_length[1].is_none()
4670                                || resource_length[1].is_some()
4671                                    && point.1[1] > resource_length[1].unwrap()
4672                                    && point.2[1]
4673                            {
4674                                Some(point.1[1])
4675                            } else {
4676                                resource_length[1]
4677                            },
4678                        ]
4679                    }
4680                    if let Some(horizontal_scroll_length_method) =
4681                        resource_panel.scroll_length_method[0]
4682                    {
4683                        let margin = match resource_panel.overall_layout.panel_margin {
4684                            PanelMargin::Horizontal([_, _, left, right], _) => left + right,
4685                            PanelMargin::Vertical([_, _, left, right], _) => left + right,
4686                            PanelMargin::None([_, _, left, right], _) => left + right,
4687                        };
4688                        resource_panel.scroll_length[0] = match horizontal_scroll_length_method {
4689                            ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
4690                            ScrollLengthMethod::AutoFit(expand) => {
4691                                if let Some(max) = resource_length[0] {
4692                                    let width = max - position[0];
4693                                    if width - size[0]
4694                                        + expand
4695                                        + margin
4696                                        + resource_panel.inner_margin[3]
4697                                        + resource_panel.inner_margin[2]
4698                                        > 0_f32
4699                                    {
4700                                        width - size[0]
4701                                            + expand
4702                                            + margin
4703                                            + resource_panel.inner_margin[3]
4704                                            + resource_panel.inner_margin[2]
4705                                    } else {
4706                                        0_f32
4707                                    }
4708                                } else {
4709                                    0_f32
4710                                }
4711                            }
4712                        };
4713                        if resource_panel.scroll_progress[0] > resource_panel.scroll_length[0] {
4714                            resource_panel.scroll_progress[0] = resource_panel.scroll_length[0];
4715                        };
4716                    };
4717                    if let Some(vertical_scroll_length_method) =
4718                        resource_panel.scroll_length_method[1]
4719                    {
4720                        let margin = match resource_panel.overall_layout.panel_margin {
4721                            PanelMargin::Horizontal([top, bottom, _, _], _) => top + bottom,
4722                            PanelMargin::Vertical([top, bottom, _, _], _) => top + bottom,
4723                            PanelMargin::None([top, bottom, _, _], _) => top + bottom,
4724                        };
4725                        resource_panel.scroll_length[1] = match vertical_scroll_length_method {
4726                            ScrollLengthMethod::Fixed(fixed_length) => fixed_length,
4727                            ScrollLengthMethod::AutoFit(expand) => {
4728                                if let Some(max) = resource_length[1] {
4729                                    let height = max - position[1];
4730                                    if height - size[1]
4731                                        + expand
4732                                        + margin
4733                                        + resource_panel.inner_margin[1]
4734                                        + resource_panel.inner_margin[0]
4735                                        > 0_f32
4736                                    {
4737                                        height - size[1]
4738                                            + expand
4739                                            + margin
4740                                            + resource_panel.inner_margin[1]
4741                                            + resource_panel.inner_margin[0]
4742                                    } else {
4743                                        0_f32
4744                                    }
4745                                } else {
4746                                    0_f32
4747                                }
4748                            }
4749                        };
4750                        if resource_panel.scroll_progress[1] > resource_panel.scroll_length[1] {
4751                            resource_panel.scroll_progress[1] = resource_panel.scroll_length[1];
4752                        };
4753                    };
4754                    match resource_panel.scroll_bar_display_method {
4755                        ScrollBarDisplayMethod::Always(ref config, margin, width) => {
4756                            let line_length = if resource_panel.scroll_length[1] == 0_f32 {
4757                                (size[0] - margin[0] * 2_f32)
4758                                    * (size[0] / (resource_panel.scroll_length[0] + size[0]))
4759                            } else {
4760                                (size[0] - width - margin[1] - margin[0] * 2_f32)
4761                                    * (size[0] / (resource_panel.scroll_length[0] + size[0]))
4762                            };
4763                            let line_position = if resource_panel.scroll_length[1] == 0_f32 {
4764                                position[0]
4765                                    + margin[0]
4766                                    + (size[0] - margin[0] * 2_f32 - line_length)
4767                                        * (resource_panel.scroll_progress[0]
4768                                            / resource_panel.scroll_length[0])
4769                            } else {
4770                                position[0]
4771                                    + margin[0]
4772                                    + (size[0]
4773                                        - margin[0] * 2_f32
4774                                        - width
4775                                        - margin[1]
4776                                        - line_length)
4777                                        * (resource_panel.scroll_progress[0]
4778                                            / resource_panel.scroll_length[0])
4779                            };
4780                            self.replace_resource(
4781                                &format!("{}XScroll", &id.name),
4782                                background.clone().background_type(&match config.clone() {
4783                                    BackgroundType::CustomRect(config) => {
4784                                        BackgroundType::CustomRect(
4785                                            config
4786                                                .ignore_render_layer(Some(true))
4787                                                .hidden(Some(resource_panel.hidden))
4788                                                .position_size_config(Some(
4789                                                    PositionSizeConfig::default()
4790                                                        .display_method(
4791                                                            HorizontalAlign::Left,
4792                                                            VerticalAlign::Bottom,
4793                                                        )
4794                                                        .origin_position(
4795                                                            line_position,
4796                                                            position[1] + size[1] - margin[1],
4797                                                        )
4798                                                        .origin_size(line_length, width),
4799                                                )),
4800                                        )
4801                                    }
4802                                    BackgroundType::Image(config) => BackgroundType::Image(
4803                                        config
4804                                            .ignore_render_layer(Some(true))
4805                                            .hidden(Some(resource_panel.hidden))
4806                                            .position_size_config(Some(
4807                                                PositionSizeConfig::default()
4808                                                    .display_method(
4809                                                        HorizontalAlign::Left,
4810                                                        VerticalAlign::Bottom,
4811                                                    )
4812                                                    .origin_position(
4813                                                        line_position,
4814                                                        position[1] + size[1] - margin[1],
4815                                                    )
4816                                                    .origin_size(line_length, width),
4817                                            )),
4818                                    ),
4819                                }),
4820                            )?;
4821                            self.use_resource(
4822                                &RustConstructorId {
4823                                    name: format!("{}XScroll", &id.name),
4824                                    discern_type: "Background".to_string(),
4825                                },
4826                                ui,
4827                            )?;
4828                            let line_length = if resource_panel.scroll_length[0] == 0_f32 {
4829                                (size[1] - margin[0] * 2_f32)
4830                                    * (size[1] / (resource_panel.scroll_length[1] + size[1]))
4831                            } else {
4832                                (size[1] - width - margin[1] - margin[0] * 2_f32)
4833                                    * (size[1] / (resource_panel.scroll_length[1] + size[1]))
4834                            };
4835                            let line_position = if resource_panel.scroll_length[0] == 0_f32 {
4836                                position[1]
4837                                    + margin[0]
4838                                    + (size[1] - margin[0] * 2_f32 - line_length)
4839                                        * (resource_panel.scroll_progress[1]
4840                                            / resource_panel.scroll_length[1])
4841                            } else {
4842                                position[1]
4843                                    + margin[0]
4844                                    + (size[1]
4845                                        - margin[0] * 2_f32
4846                                        - width
4847                                        - margin[1]
4848                                        - line_length)
4849                                        * (resource_panel.scroll_progress[1]
4850                                            / resource_panel.scroll_length[1])
4851                            };
4852                            self.replace_resource(
4853                                &format!("{}YScroll", &id.name),
4854                                background.background_type(&match config.clone() {
4855                                    BackgroundType::CustomRect(config) => {
4856                                        BackgroundType::CustomRect(
4857                                            config
4858                                                .ignore_render_layer(Some(true))
4859                                                .hidden(Some(resource_panel.hidden))
4860                                                .position_size_config(Some(
4861                                                    PositionSizeConfig::default()
4862                                                        .display_method(
4863                                                            HorizontalAlign::Right,
4864                                                            VerticalAlign::Top,
4865                                                        )
4866                                                        .origin_position(
4867                                                            position[0] + size[0] - margin[1],
4868                                                            line_position,
4869                                                        )
4870                                                        .origin_size(width, line_length),
4871                                                )),
4872                                        )
4873                                    }
4874                                    BackgroundType::Image(config) => BackgroundType::Image(
4875                                        config
4876                                            .ignore_render_layer(Some(true))
4877                                            .hidden(Some(resource_panel.hidden))
4878                                            .position_size_config(Some(
4879                                                PositionSizeConfig::default()
4880                                                    .display_method(
4881                                                        HorizontalAlign::Right,
4882                                                        VerticalAlign::Top,
4883                                                    )
4884                                                    .origin_position(
4885                                                        position[0] + size[0] - margin[1],
4886                                                        line_position,
4887                                                    )
4888                                                    .origin_size(width, line_length),
4889                                            )),
4890                                    ),
4891                                }),
4892                            )?;
4893                            self.use_resource(
4894                                &RustConstructorId {
4895                                    name: format!("{}YScroll", &id.name),
4896                                    discern_type: "Background".to_string(),
4897                                },
4898                                ui,
4899                            )?;
4900                        }
4901                        ScrollBarDisplayMethod::OnlyScroll(ref config, margin, width) => {
4902                            resource_panel.scroll_bar_alpha[0] = if resource_panel.scrolled[0] {
4903                                self.reset_split_time(&format!(
4904                                    "{}ScrollBarXAlphaStart",
4905                                    &id.name
4906                                ))?;
4907                                255
4908                            } else if self.timer.now_time
4909                                - self
4910                                    .get_split_time(&format!("{}ScrollBarXAlphaStart", &id.name))?
4911                                    [0]
4912                                >= 1000
4913                                && self.timer.now_time
4914                                    - self
4915                                        .get_split_time(&format!("{}ScrollBarXAlpha", &id.name))?[0]
4916                                    >= self.tick_interval
4917                            {
4918                                self.reset_split_time(&format!("{}ScrollBarXAlpha", &id.name))?;
4919                                resource_panel.scroll_bar_alpha[0].saturating_sub(10)
4920                            } else {
4921                                resource_panel.scroll_bar_alpha[0]
4922                            };
4923                            resource_panel.scroll_bar_alpha[1] = if resource_panel.scrolled[1] {
4924                                self.reset_split_time(&format!(
4925                                    "{}ScrollBarYAlphaStart",
4926                                    &id.name
4927                                ))?;
4928                                255
4929                            } else if self.timer.now_time
4930                                - self
4931                                    .get_split_time(&format!("{}ScrollBarYAlphaStart", &id.name))?
4932                                    [0]
4933                                >= 1000
4934                                && self.timer.now_time
4935                                    - self
4936                                        .get_split_time(&format!("{}ScrollBarYAlpha", &id.name))?[0]
4937                                    >= self.tick_interval
4938                            {
4939                                self.reset_split_time(&format!("{}ScrollBarYAlpha", &id.name))?;
4940                                resource_panel.scroll_bar_alpha[1].saturating_sub(10)
4941                            } else {
4942                                resource_panel.scroll_bar_alpha[1]
4943                            };
4944                            let line_length = if resource_panel.scroll_length[1] == 0_f32 {
4945                                (size[0] - margin[0] * 2_f32)
4946                                    * (size[0] / (resource_panel.scroll_length[0] + size[0]))
4947                            } else {
4948                                (size[0] - width - margin[1] - margin[0] * 2_f32)
4949                                    * (size[0] / (resource_panel.scroll_length[0] + size[0]))
4950                            };
4951                            let line_position = if resource_panel.scroll_length[1] == 0_f32 {
4952                                position[0]
4953                                    + margin[0]
4954                                    + (size[0] - margin[0] * 2_f32 - line_length)
4955                                        * (resource_panel.scroll_progress[0]
4956                                            / resource_panel.scroll_length[0])
4957                            } else {
4958                                position[0]
4959                                    + margin[0]
4960                                    + (size[0]
4961                                        - margin[0] * 2_f32
4962                                        - width
4963                                        - margin[1]
4964                                        - line_length)
4965                                        * (resource_panel.scroll_progress[0]
4966                                            / resource_panel.scroll_length[0])
4967                            };
4968                            self.replace_resource(
4969                                &format!("{}XScroll", &id.name),
4970                                background.clone().background_type(&match config.clone() {
4971                                    BackgroundType::CustomRect(config) => {
4972                                        BackgroundType::CustomRect(
4973                                            config
4974                                                .ignore_render_layer(Some(true))
4975                                                .hidden(Some(resource_panel.hidden))
4976                                                .position_size_config(Some(
4977                                                    PositionSizeConfig::default()
4978                                                        .display_method(
4979                                                            HorizontalAlign::Left,
4980                                                            VerticalAlign::Bottom,
4981                                                        )
4982                                                        .origin_position(
4983                                                            line_position,
4984                                                            position[1] + size[1] - margin[1],
4985                                                        )
4986                                                        .origin_size(line_length, width),
4987                                                ))
4988                                                .alpha(Some(resource_panel.scroll_bar_alpha[0]))
4989                                                .border_alpha(Some(
4990                                                    resource_panel.scroll_bar_alpha[0],
4991                                                )),
4992                                        )
4993                                    }
4994                                    BackgroundType::Image(config) => BackgroundType::Image(
4995                                        config
4996                                            .ignore_render_layer(Some(true))
4997                                            .hidden(Some(resource_panel.hidden))
4998                                            .position_size_config(Some(
4999                                                PositionSizeConfig::default()
5000                                                    .display_method(
5001                                                        HorizontalAlign::Left,
5002                                                        VerticalAlign::Bottom,
5003                                                    )
5004                                                    .origin_position(
5005                                                        line_position,
5006                                                        position[1] + size[1] - margin[1],
5007                                                    )
5008                                                    .origin_size(line_length, width),
5009                                            ))
5010                                            .alpha(Some(resource_panel.scroll_bar_alpha[0]))
5011                                            .background_alpha(Some(
5012                                                resource_panel.scroll_bar_alpha[0],
5013                                            ))
5014                                            .overlay_alpha(Some(
5015                                                resource_panel.scroll_bar_alpha[0],
5016                                            )),
5017                                    ),
5018                                }),
5019                            )?;
5020                            self.use_resource(
5021                                &RustConstructorId {
5022                                    name: format!("{}XScroll", &id.name),
5023                                    discern_type: "Background".to_string(),
5024                                },
5025                                ui,
5026                            )?;
5027                            let line_length = if resource_panel.scroll_length[0] == 0_f32 {
5028                                (size[1] - margin[0] * 2_f32)
5029                                    * (size[1] / (resource_panel.scroll_length[1] + size[1]))
5030                            } else {
5031                                (size[1] - width - margin[1] - margin[0] * 2_f32)
5032                                    * (size[1] / (resource_panel.scroll_length[1] + size[1]))
5033                            };
5034                            let line_position = if resource_panel.scroll_length[0] == 0_f32 {
5035                                position[1]
5036                                    + margin[0]
5037                                    + (size[1] - margin[0] * 2_f32 - line_length)
5038                                        * (resource_panel.scroll_progress[1]
5039                                            / resource_panel.scroll_length[1])
5040                            } else {
5041                                position[1]
5042                                    + margin[0]
5043                                    + (size[1]
5044                                        - margin[0] * 2_f32
5045                                        - width
5046                                        - margin[1]
5047                                        - line_length)
5048                                        * (resource_panel.scroll_progress[1]
5049                                            / resource_panel.scroll_length[1])
5050                            };
5051                            self.replace_resource(
5052                                &format!("{}YScroll", &id.name),
5053                                background.clone().background_type(&match config.clone() {
5054                                    BackgroundType::CustomRect(config) => {
5055                                        BackgroundType::CustomRect(
5056                                            config
5057                                                .ignore_render_layer(Some(true))
5058                                                .hidden(Some(resource_panel.hidden))
5059                                                .position_size_config(Some(
5060                                                    PositionSizeConfig::default()
5061                                                        .display_method(
5062                                                            HorizontalAlign::Right,
5063                                                            VerticalAlign::Top,
5064                                                        )
5065                                                        .origin_position(
5066                                                            position[0] + size[0] - margin[1],
5067                                                            line_position,
5068                                                        )
5069                                                        .origin_size(width, line_length),
5070                                                ))
5071                                                .alpha(Some(resource_panel.scroll_bar_alpha[1]))
5072                                                .border_alpha(Some(
5073                                                    resource_panel.scroll_bar_alpha[1],
5074                                                )),
5075                                        )
5076                                    }
5077                                    BackgroundType::Image(config) => BackgroundType::Image(
5078                                        config
5079                                            .ignore_render_layer(Some(true))
5080                                            .hidden(Some(resource_panel.hidden))
5081                                            .position_size_config(Some(
5082                                                PositionSizeConfig::default()
5083                                                    .display_method(
5084                                                        HorizontalAlign::Right,
5085                                                        VerticalAlign::Top,
5086                                                    )
5087                                                    .origin_position(
5088                                                        position[0] + size[0] - margin[1],
5089                                                        line_position,
5090                                                    )
5091                                                    .origin_size(width, line_length),
5092                                            ))
5093                                            .alpha(Some(resource_panel.scroll_bar_alpha[1]))
5094                                            .background_alpha(Some(
5095                                                resource_panel.scroll_bar_alpha[1],
5096                                            ))
5097                                            .overlay_alpha(Some(
5098                                                resource_panel.scroll_bar_alpha[1],
5099                                            )),
5100                                    ),
5101                                }),
5102                            )?;
5103                            self.use_resource(
5104                                &RustConstructorId {
5105                                    name: format!("{}YScroll", &id.name),
5106                                    discern_type: "Background".to_string(),
5107                                },
5108                                ui,
5109                            )?;
5110                        }
5111                        ScrollBarDisplayMethod::Hidden => {}
5112                    };
5113                    self.replace_resource(&id.name, resource_panel.clone())?;
5114                }
5115                _ => {}
5116            };
5117            Ok(())
5118        } else {
5119            Err(RustConstructorError {
5120                error_id: "ResourceNotFound".to_string(),
5121                description: format!("Resource '{}({})' not found.", id.name, id.discern_type),
5122            })
5123        }
5124    }
5125
5126    /// Switches to a different page and resets page-specific state.
5127    ///
5128    /// 切换到不同页面并重置页面特定状态。
5129    ///
5130    /// # Arguments
5131    ///
5132    /// * `name` - The name of the page to switch to
5133    ///
5134    /// # Returns
5135    ///
5136    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the page cannot be found.
5137    ///
5138    /// # 参数
5139    ///
5140    /// * `name` - 要切换到的页面名称
5141    ///
5142    /// # 返回值
5143    ///
5144    /// 成功时返回 `Ok(())`,如果页面无法找到则返回 `Err(RustConstructorError)`。
5145    pub fn switch_page(&mut self, name: &str) -> Result<(), RustConstructorError> {
5146        let page_data = self.get_resource_mut::<PageData>(&RustConstructorId {
5147            name: name.to_string(),
5148            discern_type: "PageData".to_string(),
5149        })?;
5150        page_data.enter_page_updated = false;
5151        self.timer.start_time = self.timer.total_time;
5152        self.current_page = name.to_string();
5153        self.update_timer();
5154        Ok(())
5155    }
5156
5157    /// Try to register all fonts in the egui context.
5158    ///
5159    /// 尝试向egui上下文中注册所有字体。
5160    ///
5161    /// This method loads and registers all fonts with the egui rendering system for
5162    /// text display.
5163    ///
5164    /// 此方法加载并注册所有字体到egui渲染系统中,用于文本显示。
5165    ///
5166    /// # Arguments
5167    ///
5168    /// * `ui` - The UI context for drawing
5169    /// * `font_info` - Font information, including font names and paths
5170    ///
5171    /// # 参数
5172    ///
5173    /// * `ui` - 用于绘制的UI上下文
5174    /// * `font_info` - 字体信息,包含字体名称和路径
5175    pub fn try_register_all_fonts(&mut self, ui: &Ui, font_info: Vec<[&str; 2]>) {
5176        let mut font_definitions_amount = FontDefinitions::default();
5177        let mut loaded_fonts = Vec::new();
5178        for font_info in font_info {
5179            let mut font = FontDefinitions::default();
5180            if let Ok(font_read_data) = read(font_info[1]) {
5181                let font_data: Arc<Vec<u8>> = Arc::new(font_read_data);
5182                font.font_data.insert(
5183                    font_info[0].to_owned(),
5184                    Arc::new(FontData::from_owned(
5185                        Arc::try_unwrap(font_data).ok().unwrap(),
5186                    )),
5187                );
5188                // 将字体添加到字体列表中
5189                font.families
5190                    .entry(FontFamily::Proportional)
5191                    .or_default()
5192                    .insert(0, font_info[0].to_owned());
5193
5194                font.families
5195                    .entry(FontFamily::Monospace)
5196                    .or_default()
5197                    .insert(0, font_info[0].to_owned());
5198                if let Some(font_data) = font.font_data.get(font_info[0]) {
5199                    font_definitions_amount
5200                        .font_data
5201                        .insert(font_info[0].to_string(), Arc::clone(font_data));
5202                    font_definitions_amount
5203                        .families
5204                        .entry(FontFamily::Name(font_info[0].into()))
5205                        .or_default()
5206                        .push(font_info[0].to_string());
5207                    // 将字体添加到字体列表中
5208                    font_definitions_amount
5209                        .families
5210                        .entry(FontFamily::Proportional)
5211                        .or_default()
5212                        .insert(0, font_info[0].to_owned());
5213
5214                    font_definitions_amount
5215                        .families
5216                        .entry(FontFamily::Monospace)
5217                        .or_default()
5218                        .insert(0, font_info[0].to_owned());
5219                    loaded_fonts.push(font_info);
5220                };
5221            }
5222        }
5223        self.loading_fonts = loaded_fonts
5224            .iter()
5225            .map(|x| [x[0].to_string(), x[1].to_string()])
5226            .collect();
5227        ui.set_fonts(font_definitions_amount);
5228    }
5229
5230    /// Registers all fonts with the egui context.
5231    ///
5232    /// 向egui上下文中注册所有字体。
5233    ///
5234    /// This method loads and registers all fonts with the egui rendering system for
5235    /// text display.
5236    ///
5237    /// 此方法加载并注册所有字体到egui渲染系统中,用于文本显示。
5238    ///
5239    /// # Arguments
5240    ///
5241    /// * `ui` - The UI context for drawing
5242    /// * `font_info` - Font information, including font names and paths
5243    ///
5244    /// # Returns
5245    ///
5246    /// If the loading is successfully completed, return `Ok(())`; otherwise,
5247    /// return `Err(RustConstructorError)`.
5248    ///
5249    /// # 参数
5250    ///
5251    /// * `ui` - 用于绘制的UI上下文
5252    /// * `font_info` - 字体信息,包含字体名称和路径
5253    ///
5254    /// # 返回值
5255    ///
5256    /// 如果成功完成加载返回`Ok(())`,否则返回`Err(RustConstructorError)`。
5257    pub fn register_all_fonts(
5258        &mut self,
5259        ui: &Ui,
5260        font_info: Vec<[&str; 2]>,
5261    ) -> Result<(), RustConstructorError> {
5262        let mut font_definitions_amount = FontDefinitions::default();
5263        let mut loaded_fonts = Vec::new();
5264        for font_info in font_info {
5265            let mut font = FontDefinitions::default();
5266            if let Ok(font_read_data) = read(font_info[1]) {
5267                let font_data: Arc<Vec<u8>> = Arc::new(font_read_data);
5268                font.font_data.insert(
5269                    font_info[0].to_owned(),
5270                    Arc::new(FontData::from_owned(
5271                        Arc::try_unwrap(font_data).ok().unwrap(),
5272                    )),
5273                );
5274                // 将字体添加到字体列表中
5275                font.families
5276                    .entry(FontFamily::Proportional)
5277                    .or_default()
5278                    .insert(0, font_info[0].to_owned());
5279
5280                font.families
5281                    .entry(FontFamily::Monospace)
5282                    .or_default()
5283                    .insert(0, font_info[0].to_owned());
5284                if let Some(font_data) = font.font_data.get(font_info[0]) {
5285                    font_definitions_amount
5286                        .font_data
5287                        .insert(font_info[0].to_string(), Arc::clone(font_data));
5288                    font_definitions_amount
5289                        .families
5290                        .entry(FontFamily::Name(font_info[0].into()))
5291                        .or_default()
5292                        .push(font_info[0].to_string());
5293                    // 将字体添加到字体列表中
5294                    font_definitions_amount
5295                        .families
5296                        .entry(FontFamily::Proportional)
5297                        .or_default()
5298                        .insert(0, font_info[0].to_owned());
5299
5300                    font_definitions_amount
5301                        .families
5302                        .entry(FontFamily::Monospace)
5303                        .or_default()
5304                        .insert(0, font_info[0].to_owned());
5305                    loaded_fonts.push(font_info);
5306                };
5307            } else {
5308                return Err(RustConstructorError {
5309                    error_id: "FontLoadFailed".to_string(),
5310                    description: format!("Failed to load a font from the path '{}'.", font_info[1]),
5311                });
5312            }
5313        }
5314        self.loading_fonts = loaded_fonts
5315            .iter()
5316            .map(|x| [x[0].to_string(), x[1].to_string()])
5317            .collect();
5318        ui.set_fonts(font_definitions_amount);
5319        Ok(())
5320    }
5321
5322    /// Checks if a page has completed its initial loading phase.
5323    ///
5324    /// 检查页面是否已完成首次加载。
5325    ///
5326    /// # Arguments
5327    ///
5328    /// * `name` - The name of the page to check
5329    ///
5330    /// # Returns
5331    ///
5332    /// Returns `Ok(true)` if the page has completed loading, or `Ok(false)` if the page has not completed loading.
5333    /// Returns `Err(RustConstructorError)` if the page cannot be found.
5334    ///
5335    /// # 参数
5336    ///
5337    /// * `name` - 要检查的页面名称
5338    ///
5339    /// # 返回值
5340    ///
5341    /// 如果页面已完成加载则返回 `Ok(true)`,如果未加载则返回 `Ok(false)`。
5342    /// 如果页面无法找到则返回 `Err(RustConstructorError)`。
5343    pub fn check_updated(&mut self, name: &str) -> Result<bool, RustConstructorError> {
5344        let page_data = self
5345            .get_resource::<PageData>(&RustConstructorId {
5346                name: name.to_string(),
5347                discern_type: "PageData".to_string(),
5348            })?
5349            .clone();
5350        if !page_data.change_page_updated {
5351            self.new_page_update(name)?;
5352        };
5353        Ok(page_data.change_page_updated)
5354    }
5355
5356    /// Checks if a page has completed its enter transition.
5357    ///
5358    /// 检查页面是否已完成进入过渡。
5359    ///
5360    /// # Arguments
5361    ///
5362    /// * `name` - The name of the page to check
5363    ///
5364    /// # Returns
5365    ///
5366    /// Returns `Ok(true)` if the page has completed entering, or `Ok(false)` if the page has not completed entering.
5367    /// Returns `Err(RustConstructorError)` if the page cannot be found.
5368    ///
5369    /// # 参数
5370    ///
5371    /// * `name` - 要检查的页面名称
5372    ///
5373    /// # 返回值
5374    ///
5375    /// 如果页面已完成进入则返回 `Ok(true)`,如果未过渡则返回 `Ok(false)`。
5376    /// 如果页面无法找到则返回 `Err(RustConstructorError)`。
5377    pub fn check_enter_updated(&mut self, name: &str) -> Result<bool, RustConstructorError> {
5378        let page_data = self.get_resource_mut::<PageData>(&RustConstructorId {
5379            name: name.to_string(),
5380            discern_type: "PageData".to_string(),
5381        })?;
5382        let enter_page_updated = page_data.enter_page_updated;
5383        page_data.enter_page_updated = true;
5384        Ok(enter_page_updated)
5385    }
5386
5387    /// Updates when entering a new page.
5388    ///
5389    /// 进入新页面时的更新。
5390    ///
5391    /// This method is used to ensure the accuracy of the content based on the page, and the Rust Constructor will automatically call this method.
5392    ///
5393    /// 此方法用于确保基于页面的内容的准确性,Rust Constructor会自动调用此方法。
5394    ///
5395    /// # Arguments
5396    ///
5397    /// * `name` - The name of the page to be updated
5398    ///
5399    /// # Returns
5400    ///
5401    /// If the update is successful, return `Ok(())`; if the resource is not found, return `Err(RustConstructorError)`.
5402    ///
5403    /// # 参数
5404    ///
5405    /// * `name` - 要更新的页面名称
5406    ///
5407    /// # 返回值
5408    ///
5409    /// 如果更新成功则返回`Ok(())`,找不到资源则返回`Err(RustConstructorError)`。
5410    pub fn new_page_update(&mut self, name: &str) -> Result<(), RustConstructorError> {
5411        let page_data = self.get_resource_mut::<PageData>(&RustConstructorId {
5412            name: name.to_string(),
5413            discern_type: "PageData".to_string(),
5414        })?;
5415        page_data.change_page_updated = true;
5416        self.timer.start_time = self.timer.total_time;
5417        self.update_timer();
5418        Ok(())
5419    }
5420
5421    /// Updates frame timing statistics for performance monitoring.
5422    ///
5423    /// 更新帧数统计信息用于性能监控。
5424    ///
5425    /// This method maintains a rolling window of frame times and calculates
5426    /// performance metrics like frame rate.
5427    ///
5428    /// 此方法维护帧时间的滚动窗口并计算帧率等性能指标。
5429    pub fn update_frame_stats(&mut self) {
5430        let current_time = self.timer.total_time;
5431        if let Some(last) = self.last_frame_time {
5432            let delta = current_time - last;
5433            self.frame_times.push(delta);
5434            if self.frame_times.len() > 120 {
5435                self.frame_times.drain(0..120);
5436            }
5437        }
5438        self.last_frame_time = Some(current_time);
5439    }
5440
5441    /// Update the frame rate.
5442    ///
5443    /// 更新帧数。
5444    ///
5445    /// This method is used to obtain the number of program frames and conduct analysis.
5446    ///
5447    /// 此方法用于获取程序帧数并进行分析。
5448    ///
5449    /// # Returns
5450    ///
5451    /// Return the number of frames.
5452    ///
5453    /// # 返回值
5454    ///
5455    /// 返回帧数。
5456    pub fn current_fps(&self) -> f32 {
5457        if self.frame_times.is_empty() {
5458            0.0
5459        } else {
5460            1000_f32
5461                / (self.frame_times.iter().sum::<u128>() as f32 / self.frame_times.len() as f32)
5462        }
5463    }
5464
5465    /// Resets the split time for a specific resource.
5466    ///
5467    /// 重置特定资源的分段计时器。
5468    ///
5469    /// # Arguments
5470    ///
5471    /// * `name` - The name of the split time resource to reset
5472    ///
5473    /// # Returns
5474    ///
5475    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be found.
5476    ///
5477    /// # 参数
5478    ///
5479    /// * `name` - 要重置的分段时间资源名称
5480    ///
5481    /// # 返回值
5482    ///
5483    /// 成功时返回 `Ok(())`,如果资源无法找到则返回 `Err(RustConstructorError)`。
5484    pub fn reset_split_time(&mut self, name: &str) -> Result<(), RustConstructorError> {
5485        let new_time = [self.timer.now_time, self.timer.total_time];
5486        let split_time = self.get_resource_mut::<SplitTime>(&RustConstructorId {
5487            name: name.to_string(),
5488            discern_type: "SplitTime".to_string(),
5489        })?;
5490        split_time.time = new_time;
5491        Ok(())
5492    }
5493
5494    /// Retrieves the timing information from a split time resource.
5495    ///
5496    /// 获取分段计时器资源的时间信息。
5497    ///
5498    /// # Arguments
5499    ///
5500    /// * `name` - The name of the split time resource
5501    ///
5502    /// # Returns
5503    ///
5504    /// Returns `Ok([page_runtime, total_runtime])` if found, or `Err(RustConstructorError)` if not found.
5505    ///
5506    /// # 参数
5507    ///
5508    /// * `name` - 分段计时器资源的名称
5509    ///
5510    /// # 返回值
5511    ///
5512    /// 如果找到则返回 `Ok([页面运行时间, 总运行时间])`,否则返回 `Err(RustConstructorError)`。
5513    pub fn get_split_time(&self, name: &str) -> Result<[u128; 2], RustConstructorError> {
5514        let split_time = self.get_resource::<SplitTime>(&RustConstructorId {
5515            name: name.to_string(),
5516            discern_type: "SplitTime".to_string(),
5517        })?;
5518        Ok(split_time.time)
5519    }
5520
5521    /// Updates the application timer with current timing information.
5522    ///
5523    /// 更新应用程序计时器的当前时间信息。
5524    ///
5525    /// This method updates both the total runtime and current page runtime.
5526    ///
5527    /// 此方法更新总运行时间和当前页面运行时间。
5528    pub fn update_timer(&mut self) {
5529        let elapsed = self.timer.timer.elapsed();
5530        self.timer.total_time = elapsed.as_millis();
5531        self.timer.now_time = self.timer.total_time - self.timer.start_time
5532    }
5533
5534    /// Modifies the value of a variable resource.
5535    ///
5536    /// 修改变量资源的值。
5537    ///
5538    /// # Arguments
5539    ///
5540    /// * `name` - The name of the variable resource
5541    /// * `value` - The new value to set (use `None` to clear)
5542    ///
5543    /// # Returns
5544    ///
5545    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be found.
5546    ///
5547    /// # 参数
5548    ///
5549    /// * `name` - 变量资源的名称
5550    /// * `value` - 要设置的新值(使用 `None` 来清除)
5551    ///
5552    /// # 返回值
5553    ///
5554    /// 成功时返回 `Ok(())`,如果资源无法找到则返回 `Err(RustConstructorError)`。
5555    pub fn modify_variable<T: Debug + Send + Sync + 'static>(
5556        &mut self,
5557        name: &str,
5558        value: Option<T>,
5559    ) -> Result<(), RustConstructorError> {
5560        let variable = self.get_resource_mut::<Variable<T>>(&RustConstructorId {
5561            name: name.to_string(),
5562            discern_type: "Variable".to_string(),
5563        })?;
5564        variable.value = value;
5565        Ok(())
5566    }
5567
5568    /// Take the variable out of the list.
5569    ///
5570    /// 从列表中取出变量。
5571    ///
5572    /// # Arguments
5573    ///
5574    /// * `name` - The name of the variable resource
5575    ///
5576    /// # Returns
5577    ///
5578    /// Returns `Ok(Option<T>)` on success, or `Err(RustConstructorError)` if the resource cannot be found.
5579    ///
5580    /// # 参数
5581    ///
5582    /// * `name` - 变量资源的名称
5583    ///
5584    /// # 返回值
5585    ///
5586    /// 成功时返回 `Ok(Option<T>)`,如果资源无法找到则返回 `Err(RustConstructorError)`。
5587    pub fn get_variable<T: Debug + Clone + Send + Sync + 'static>(
5588        &self,
5589        name: &str,
5590    ) -> Result<Option<T>, RustConstructorError> {
5591        if let Ok(variable) = self.get_resource::<Variable<T>>(&RustConstructorId {
5592            name: name.to_string(),
5593            discern_type: "Variable".to_string(),
5594        }) {
5595            Ok(variable.value.clone())
5596        } else if self
5597            .check_resource_exists(&RustConstructorId {
5598                name: name.to_string(),
5599                discern_type: "Variable".to_string(),
5600            })
5601            .is_none()
5602        {
5603            Err(RustConstructorError {
5604                error_id: "ResourceNotFound".to_string(),
5605                description: format!("Resource '{name}(Variable<T>)' not found."),
5606            })
5607        } else {
5608            Err(RustConstructorError {
5609                error_id: "ResourceGenericMismatch".to_string(),
5610                description: format!(
5611                    "The generic type of the resource '{name}(Variable<T>)' is mismatched."
5612                ),
5613            })
5614        }
5615    }
5616
5617    /// Modify the enable status of the switch.
5618    ///
5619    /// 修改开关的启用状态。
5620    ///
5621    /// # Arguments
5622    ///
5623    /// * `name` - The name of the switch resource
5624    /// * `enable` - The new enable status
5625    ///
5626    /// # Returns
5627    ///
5628    /// Returns `Ok(())` on success, or `Err(RustConstructorError)` if the resource cannot be found.
5629    ///
5630    /// # 参数
5631    ///
5632    /// * `name` - 开关资源的名称
5633    /// * `enable` - 新的启用状态
5634    ///
5635    /// # 返回值
5636    ///
5637    /// 成功时返回 `Ok(())`,如果资源无法找到则返回 `Err(RustConstructorError)`。
5638    pub fn set_switch_enable(
5639        &mut self,
5640        name: &str,
5641        enable: bool,
5642    ) -> Result<(), RustConstructorError> {
5643        let switch = self.get_resource_mut::<Switch>(&RustConstructorId {
5644            name: name.to_string(),
5645            discern_type: "Switch".to_string(),
5646        })?;
5647        switch.enable = enable;
5648        Ok(())
5649    }
5650
5651    /// Retrieves the current state and interaction data from a switch resource.
5652    ///
5653    /// 获取开关资源的当前状态和交互数据。
5654    ///
5655    /// # Arguments
5656    ///
5657    /// * `name` - The name of the switch resource
5658    ///
5659    /// # Returns
5660    ///
5661    /// Returns `Ok(SwitchData)` containing the switch state and interaction history,
5662    /// or `Err(RustConstructorError)` if the resource cannot be found.
5663    ///
5664    /// # 参数
5665    ///
5666    /// * `name` - 开关资源的名称
5667    ///
5668    /// # 返回值
5669    ///
5670    /// 返回包含开关状态和交互历史的 `Ok(SwitchData)`,
5671    /// 如果资源无法找到则返回 `Err(RustConstructorError)`。
5672    pub fn check_switch_data(&self, name: &str) -> Result<SwitchData, RustConstructorError> {
5673        let switch = self.get_resource::<Switch>(&RustConstructorId {
5674            name: name.to_string(),
5675            discern_type: "Switch".to_string(),
5676        })?;
5677        Ok(SwitchData {
5678            switched: switch.switched,
5679            last_frame_clicked: switch.last_frame_clicked,
5680            state: switch.state,
5681        })
5682    }
5683
5684    /// Find out which switch in the radio switch group is activated.
5685    ///
5686    /// 查找单选开关组中哪个开关被激活了。
5687    ///
5688    /// # Arguments
5689    ///
5690    /// * `radio_group` - The name of the radio switch group
5691    ///
5692    /// # Returns
5693    ///
5694    /// Returns the name of the activated switch. If there is no activated switch or the
5695    /// radio switch group does not exist, return an empty string.
5696    ///
5697    /// # 参数
5698    ///
5699    /// * `radio_group` - 单选开关组的名称
5700    ///
5701    /// # 返回值
5702    ///
5703    /// 返回激活的开关的名称,如果没有激活的开关或单选开关组不存在则返回空字符串。
5704    pub fn check_radio_switch(&self, radio_group: &str) -> String {
5705        let mut activate_switch = String::new();
5706        for rcr in &self.rust_constructor_resource {
5707            if let Ok(switch) = downcast_resource::<Switch>(&*rcr.content)
5708                && switch.radio_group == radio_group
5709                && switch.state == 1
5710            {
5711                activate_switch = rcr.id.name.clone();
5712                break;
5713            };
5714        }
5715        activate_switch
5716    }
5717}