重启N1资源管理器面板拆分(保留布局)
This commit is contained in:
parent
2c9f512996
commit
ea6ff140e9
@ -2,7 +2,7 @@
|
||||
|
||||
> 基于本地代码静态扫描生成(不含远程仓库信息,不含 `RenderPipelineFile/` 第三方目录)。
|
||||
|
||||
- 分析时间: 2026-02-28
|
||||
- 分析时间: 2026-03-01
|
||||
- 扫描范围: `main.py`, `Start_Run.py`, `core/`, `scene/`, `project/`, `ui/`, `ssbo_component/`, `TransformGizmo/`, `scripts/`, `tools/`, `templates/`
|
||||
|
||||
## 0. 执行进展(非 VR)
|
||||
@ -56,7 +56,12 @@
|
||||
- `core/selection.py::updateGizmoDrag` 第一轮拆分已完成:
|
||||
- 实测指标:`278 -> 32` 行,近似圈复杂度 `65 -> 10`
|
||||
- 缩放/旋转/平移逻辑已拆到独立 helper
|
||||
- 下一轮建议转向 `ui/panels/editor_panels_left.py::_draw_resource_manager`
|
||||
- `ui/LUI/lui_manager_interaction.py::_update_drag` 第一轮拆分已完成:
|
||||
- 实测指标:`348 -> 28` 行,近似圈复杂度 `79 -> 7`
|
||||
- Canvas/组件拖拽流程已拆到独立 helper
|
||||
- `ui/panels/editor_panels_left.py::_draw_resource_manager` 保留布局版拆分已完成:
|
||||
- 实测指标:`310 -> 23` 行(第一轮 `310 -> 163`,第二轮 `163 -> 23`)
|
||||
- 目录/文件项渲染、展开内容、右键菜单流程已拆到独立 helper
|
||||
|
||||
## 1. 总体画像
|
||||
|
||||
@ -92,13 +97,12 @@
|
||||
### 2.2 长函数 Top(优先拆分,非 VR 当前状态)
|
||||
|
||||
1. `ui/LUI/lui_function_properties.py::_draw_component_properties` (`1441` 行)
|
||||
2. `ui/LUI/lui_manager_interaction.py::_update_drag` (`348` 行)
|
||||
3. `ui/panels/editor_panels_left.py::_draw_resource_manager` (`310` 行)
|
||||
4. `ui/LUI/lui_manager_interaction.py::_handle_resize_drag` (`257` 行)
|
||||
5. `ui/LUI/lui_manager_editor.py::_set_parent_child_relationship` (`234` 行)
|
||||
6. `ui/panels/editor_panels_top.py::draw_menu_bar` (`227` 行)
|
||||
7. `scene/scene_manager_io_mixin.py::saveScene` (`222` 行)
|
||||
8. `TransformGizmo/move_gizmo.py::_on_mouse_down` (`222` 行)
|
||||
2. `ui/LUI/lui_manager_interaction.py::_handle_resize_drag` (`257` 行)
|
||||
3. `ui/LUI/lui_manager_editor.py::_set_parent_child_relationship` (`234` 行)
|
||||
4. `ui/panels/editor_panels_top.py::draw_menu_bar` (`227` 行)
|
||||
5. `scene/scene_manager_io_mixin.py::saveScene` (`222` 行)
|
||||
6. `TransformGizmo/move_gizmo.py::_on_mouse_down` (`222` 行)
|
||||
7. `ui/LUI/lui_manager_editor.py::draw_editor` (`217` 行)
|
||||
|
||||
### 2.3 异常处理密度高(可观测性风险)
|
||||
|
||||
@ -157,10 +161,9 @@
|
||||
|
||||
建议拆分顺序(非 VR 当前阶段):
|
||||
|
||||
1. `ui/panels/editor_panels_left.py::_draw_resource_manager`
|
||||
2. `ui/LUI/lui_manager_interaction.py::_update_drag`
|
||||
3. `ui/LUI/lui_function_properties.py::_draw_component_properties`(可按“变换/布局/视觉/交互/脚本”分区)
|
||||
4. `ui/LUI/lui_manager_interaction.py::_handle_resize_drag`
|
||||
1. `ui/LUI/lui_function_properties.py::_draw_component_properties`(可按“变换/布局/视觉/交互/脚本”分区)
|
||||
2. `ui/LUI/lui_manager_interaction.py::_handle_resize_drag`
|
||||
3. `ui/panels/editor_panels_top.py::draw_menu_bar`
|
||||
|
||||
预期收益:
|
||||
|
||||
@ -232,20 +235,27 @@
|
||||
- 主函数长度降到 `<= 120` 行(实际 `32` 行)
|
||||
- 保持当前 gizmo 拖拽行为一致
|
||||
|
||||
### Task F(推荐下一步,1 天)
|
||||
### Task F(已完成,保留布局版两轮)
|
||||
|
||||
- 拆分 `ui/panels/editor_panels_left.py::_draw_resource_manager`
|
||||
- 验收:
|
||||
- 主函数长度降到 `<= 160` 行
|
||||
- 文件/目录项渲染逻辑去重
|
||||
- 主函数长度降到 `<= 160` 行(第一轮 `163` 行,第二轮 `23` 行)
|
||||
- 保持原有布局/样式/文案/交互顺序不变
|
||||
|
||||
### Task G(并行候选,1-2 天)
|
||||
### Task G(已完成,第一轮)
|
||||
|
||||
- 拆分 `ui/LUI/lui_manager_interaction.py::_update_drag`
|
||||
- 验收:
|
||||
- 主函数长度降到 `<= 140` 行
|
||||
- 主函数长度降到 `<= 140` 行(实际 `28` 行)
|
||||
- 拖拽与缩放交互行为保持一致
|
||||
|
||||
### Task H(推荐下一步,2-3 天)
|
||||
|
||||
- 拆分 `ui/LUI/lui_function_properties.py::_draw_component_properties`
|
||||
- 验收:
|
||||
- 主函数长度降到 `<= 260` 行
|
||||
- 按“变换/布局/视觉/交互/脚本”子区块拆分并保持渲染逻辑一致
|
||||
|
||||
## 4.1 本轮深入分析(非 VR,P1 准备)
|
||||
|
||||
### A) `scene/scene_manager_io_mixin.py::loadScene`(核心优先,已完成)
|
||||
@ -269,9 +279,9 @@
|
||||
- `loadScene` 主体压缩到 `120` 行以内,只保留流程编排。
|
||||
- 节点恢复行为(位置/材质/脚本/可见性)与当前一致。
|
||||
- 失败重试逻辑保持语义一致。
|
||||
- 当前状态(2026-02-28):
|
||||
- 当前状态(2026-03-01):
|
||||
- 第二轮已完成(`loadScene` 已达验收目标:`74` 行)。
|
||||
- 后续建议转入回归观察,优先推进 `ui/panels/editor_panels_left.py::_draw_resource_manager`。
|
||||
- 后续建议转入回归观察,优先推进 `ui/LUI/lui_function_properties.py::_draw_component_properties`。
|
||||
|
||||
### B) `main.py::__init__`(第二优先,已完成第一轮)
|
||||
|
||||
@ -311,27 +321,32 @@
|
||||
- 主流程已收敛为编排入口。
|
||||
- 已通过 `python -m compileall core/selection.py`。
|
||||
|
||||
### E) `ui/panels/editor_panels_left.py::_draw_resource_manager`(第五优先)
|
||||
### E) `ui/panels/editor_panels_left.py::_draw_resource_manager`(已完成两轮)
|
||||
|
||||
- 函数规模: `310` 行
|
||||
- 近似圈复杂度: `88`
|
||||
- 关键问题:
|
||||
- 目录树与文件列表 UI 逻辑高度重复(图标、选择、多选、双击、右键菜单)。
|
||||
- 文件/目录条目处理缺少统一的 item 渲染与交互抽象。
|
||||
- 建议拆分:
|
||||
- `_draw_resource_toolbar(rm)`
|
||||
- `_draw_resource_path_and_search(rm)`
|
||||
- `_draw_directory_entry(rm, path, depth)`
|
||||
- `_draw_file_entry(rm, path, depth)`
|
||||
- `_draw_resource_context_popup(rm)`
|
||||
- 函数规模: `23` 行(重构前 `310` 行)
|
||||
- 近似圈复杂度: 已由主函数分支链路转移到子流程函数(入口仅保留编排)
|
||||
- 已落地 helper:
|
||||
- `_update_resource_manager_window_rect`
|
||||
- `_draw_resource_toolbar_and_filters`
|
||||
- `_draw_resource_directory_entries`
|
||||
- `_draw_resource_directory_entry`
|
||||
- `_draw_resource_directory_children`
|
||||
- `_draw_resource_subdir_entry`
|
||||
- `_draw_resource_subfile_entry`
|
||||
- `_draw_resource_file_entries`
|
||||
- `_draw_resource_file_entry`
|
||||
- `_draw_resource_context_menu`
|
||||
- 状态:
|
||||
- 主流程已收敛为编排入口,且保持原布局与交互顺序。
|
||||
- 已通过 `python -m compileall ui/panels/editor_panels_left.py`。
|
||||
|
||||
## 4.2 执行顺序建议(非 VR)
|
||||
|
||||
1. `loadScene` 已完成两轮拆分(当前建议冻结并转入回归观察)。
|
||||
2. `main.__init__` 已完成第一轮拆分(建议转入回归观察)。
|
||||
3. 下一步处理 `_draw_resource_manager`(提炼重复 UI 渲染分支)。
|
||||
4. 然后处理 `_update_drag`(LUI 交互链路收敛)。
|
||||
5. 最后处理 `_draw_component_properties`(属性面板分区拆分)。
|
||||
3. `_update_drag` 已完成第一轮拆分,建议转入回归观察。
|
||||
4. 下一步处理 `_draw_component_properties`(属性面板分区拆分)。
|
||||
5. 然后处理 `_handle_resize_drag`(拖拽缩放路径补充拆分)。
|
||||
|
||||
## 5. 与现有文档关系
|
||||
|
||||
@ -341,4 +356,4 @@
|
||||
|
||||
---
|
||||
|
||||
如果按此路线继续,建议下一轮直接从 **Task F** 开始,我可以先落地 `_draw_resource_manager` 的第一轮拆分并保持行为不变。
|
||||
如果按此路线继续,建议下一轮直接从 **Task H** 开始,先落地 `_draw_component_properties` 的分区拆分并保持行为不变。
|
||||
|
||||
@ -13,7 +13,8 @@
|
||||
|
||||
- Qt 运行依赖主路径已清理完成(排除 `RenderPipelineFile`)。
|
||||
- 项目已进入“非 VR 结构优化阶段”。
|
||||
- `_getActor` 与 `updateGizmoDrag` 第一轮拆分已完成,当前最高优先任务转为资源管理器面板拆分。
|
||||
- `_getActor`、`updateGizmoDrag`、`_update_drag` 第一轮拆分已完成。
|
||||
- `资源管理器面板` 已完成“保留原布局/样式/交互”的第二轮拆分收敛。
|
||||
|
||||
## 已完成(Done)
|
||||
|
||||
@ -69,23 +70,42 @@
|
||||
- 新增 helper:`_validate_gizmo_drag_state`、`_apply_scale_drag`、`_apply_rotate_drag`、`_compute_axis_movement_distance`、`_apply_translate_drag`
|
||||
- 保持目标:gizmo 缩放/旋转/平移行为不变
|
||||
|
||||
### F. LUI 拖拽链路拆分完成(第一轮)
|
||||
|
||||
- [x] `ui/LUI/lui_manager_interaction.py::_update_drag` 第一轮拆分完成:
|
||||
- 行数:`348 -> 28`
|
||||
- 近似圈复杂度:`79 -> 7`
|
||||
- 新增 helper:`_process_canvas_drag`、`_try_start_pending_component_drag`、`_finish_component_drag_if_released`、`_update_active_component_drag`
|
||||
- 保持目标:Canvas/组件拖拽、吸附与释放语义不变
|
||||
|
||||
### G. 资源管理器面板拆分完成(保留布局版)
|
||||
|
||||
- [x] 第一轮低侵入优化:
|
||||
- 行数:`310 -> 163`
|
||||
- 近似圈复杂度:`88 -> 41`
|
||||
- 新增 helper:`_draw_resource_toolbar_and_filters`、`_load_resource_icon`、`_handle_resource_item_selection`、`_open_resource_item_context_menu`、`_handle_resource_file_double_click`、`_draw_resource_context_menu`
|
||||
- [x] 第二轮(按当前标准重启,保持布局/样式/文案/交互顺序):
|
||||
- 入口函数行数:`163 -> 23`(相对原始 `310 -> 23`)
|
||||
- 新增 helper:`_update_resource_manager_window_rect`、`_draw_resource_directory_entries`、`_draw_resource_directory_entry`、`_draw_resource_directory_children`、`_draw_resource_subdir_entry`、`_draw_resource_subfile_entry`、`_draw_resource_file_entries`、`_draw_resource_file_entry`
|
||||
- 保持目标:不改视觉布局,不改交互语义,仅做结构分解
|
||||
|
||||
## 下一步(Next)
|
||||
|
||||
### N1 `资源管理器面板` 拆分(最高优先级,非 VR)
|
||||
### N1 `属性面板超大函数` 拆分(最高优先级,非 VR)
|
||||
|
||||
- 目标文件:`ui/panels/editor_panels_left.py::_draw_resource_manager`
|
||||
- 当前规模:`310` 行
|
||||
- 目标文件:`ui/LUI/lui_function_properties.py::_draw_component_properties`
|
||||
- 当前规模:`1441` 行
|
||||
- 验收目标:
|
||||
- 提取目录/文件项渲染与右键菜单复用逻辑
|
||||
- 交互行为保持一致
|
||||
- 按“变换/布局/视觉/交互/脚本”拆分为多个子绘制函数
|
||||
- 主流程压缩并保持属性面板行为一致
|
||||
|
||||
### N2 `LUI 交互拖拽链路` 拆分(高优先级,非 VR)
|
||||
### N2 `LUI 缩放链路` 拆分(高优先级,非 VR)
|
||||
|
||||
- 目标文件:`ui/LUI/lui_manager_interaction.py::_update_drag`
|
||||
- 当前规模:`348` 行
|
||||
- 目标文件:`ui/LUI/lui_manager_interaction.py::_handle_resize_drag`
|
||||
- 当前规模:`257` 行
|
||||
- 验收目标:
|
||||
- 入口流程收敛到 `<= 140` 行
|
||||
- 保持拖拽/缩放/吸附交互一致
|
||||
- 入口流程收敛到 `<= 120` 行
|
||||
- 保持缩放手柄行为与边界语义一致
|
||||
|
||||
## 验收标准(阶段)
|
||||
|
||||
|
||||
@ -283,308 +283,293 @@ class EditorPanelsLeftMixin:
|
||||
self.app.showResourceManager = True
|
||||
rm = self.app.resource_manager
|
||||
|
||||
window_pos = imgui.get_window_pos()
|
||||
window_size = imgui.get_window_size()
|
||||
self.app._resource_manager_window_rect = (
|
||||
float(window_pos.x),
|
||||
float(window_pos.y),
|
||||
float(window_size.x),
|
||||
float(window_size.y),
|
||||
)
|
||||
self.app._resource_drop_targets.append((
|
||||
float(window_pos.x),
|
||||
float(window_pos.y),
|
||||
float(window_size.x),
|
||||
float(window_size.y),
|
||||
str(rm.current_path),
|
||||
))
|
||||
self._update_resource_manager_window_rect(rm)
|
||||
|
||||
imgui.text("文件浏览器")
|
||||
imgui.separator()
|
||||
|
||||
if imgui.button("◀"):
|
||||
rm.navigate_back()
|
||||
imgui.same_line()
|
||||
if imgui.button("▶"):
|
||||
rm.navigate_forward()
|
||||
imgui.same_line()
|
||||
if imgui.button("▲"):
|
||||
rm.navigate_up()
|
||||
imgui.same_line()
|
||||
if imgui.button("主页"):
|
||||
rm.navigate_to(rm.project_root / "Resources")
|
||||
imgui.same_line()
|
||||
if imgui.button("刷新"):
|
||||
rm.force_refresh()
|
||||
|
||||
# 自动刷新开关
|
||||
imgui.same_line()
|
||||
changed, rm.auto_refresh_enabled = imgui.checkbox("自动刷新", rm.auto_refresh_enabled)
|
||||
if changed:
|
||||
rm.set_auto_refresh(rm.auto_refresh_enabled)
|
||||
|
||||
imgui.same_line()
|
||||
imgui.text(" ")
|
||||
imgui.same_line()
|
||||
|
||||
# 路径输入框
|
||||
changed, new_path = imgui.input_text("路径", str(rm.current_path), 256)
|
||||
if changed:
|
||||
try:
|
||||
rm.navigate_to(Path(new_path))
|
||||
except:
|
||||
pass
|
||||
|
||||
# 搜索框
|
||||
changed, rm.search_filter = imgui.input_text("搜索", rm.search_filter, 256)
|
||||
self._draw_resource_toolbar_and_filters(rm)
|
||||
|
||||
imgui.separator()
|
||||
|
||||
if rm.refresh_if_needed():
|
||||
pass
|
||||
rm.refresh_if_needed()
|
||||
|
||||
dirs, files = rm.get_directory_contents(rm.current_path)
|
||||
self._draw_resource_directory_entries(rm, dirs)
|
||||
self._draw_resource_file_entries(rm, files)
|
||||
self._draw_resource_context_menu(rm)
|
||||
|
||||
for dir_path in dirs:
|
||||
if not rm.should_show_file(dir_path):
|
||||
continue
|
||||
def _update_resource_manager_window_rect(self, rm):
|
||||
"""更新资源管理器窗口矩形与根拖拽目标。"""
|
||||
window_pos = imgui.get_window_pos()
|
||||
window_size = imgui.get_window_size()
|
||||
self.app._resource_manager_window_rect = (
|
||||
float(window_pos.x),
|
||||
float(window_pos.y),
|
||||
float(window_size.x),
|
||||
float(window_size.y),
|
||||
)
|
||||
self.app._resource_drop_targets.append((
|
||||
float(window_pos.x),
|
||||
float(window_pos.y),
|
||||
float(window_size.x),
|
||||
float(window_size.y),
|
||||
str(rm.current_path),
|
||||
))
|
||||
|
||||
icon_name = rm.get_file_icon(dir_path.name, is_folder=True)
|
||||
is_selected = dir_path in rm.selected_files
|
||||
def _draw_resource_directory_entries(self, rm, dirs):
|
||||
"""绘制当前目录下的文件夹列表。"""
|
||||
for dir_path in dirs:
|
||||
if not rm.should_show_file(dir_path):
|
||||
continue
|
||||
self._draw_resource_directory_entry(rm, dir_path)
|
||||
|
||||
if is_selected:
|
||||
imgui.push_style_color(imgui.Col_.header, (100/255, 150/255, 200/255, 1.0))
|
||||
def _draw_resource_directory_entry(self, rm, dir_path: Path):
|
||||
"""绘制单个文件夹节点(含一层展开内容)。"""
|
||||
icon_name = rm.get_file_icon(dir_path.name, is_folder=True)
|
||||
is_selected = dir_path in rm.selected_files
|
||||
|
||||
icon_texture = None
|
||||
try:
|
||||
icon_texture = self.app.style_manager.load_icon(f"file_types/{icon_name}")
|
||||
except:
|
||||
pass
|
||||
if is_selected:
|
||||
imgui.push_style_color(imgui.Col_.header, (100 / 255, 150 / 255, 200 / 255, 1.0))
|
||||
|
||||
if icon_texture:
|
||||
imgui.image(icon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
node_open = imgui.tree_node(f"{dir_path.name}##dir_{dir_path}")
|
||||
else:
|
||||
node_open = imgui.tree_node(f"[{icon_name.upper()}]{dir_path.name}##dir_{dir_path}")
|
||||
icon_texture = self._load_resource_icon(icon_name)
|
||||
if icon_texture:
|
||||
imgui.image(icon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
node_open = imgui.tree_node(f"{dir_path.name}##dir_{dir_path}")
|
||||
else:
|
||||
node_open = imgui.tree_node(f"[{icon_name.upper()}]{dir_path.name}##dir_{dir_path}")
|
||||
|
||||
if is_selected:
|
||||
imgui.pop_style_color()
|
||||
if is_selected:
|
||||
imgui.pop_style_color()
|
||||
|
||||
self._append_drop_target_from_last_item(dir_path)
|
||||
self._start_resource_drag_if_needed(rm, dir_path)
|
||||
self._append_drop_target_from_last_item(dir_path)
|
||||
self._start_resource_drag_if_needed(rm, dir_path)
|
||||
|
||||
if imgui.is_item_clicked():
|
||||
if imgui.get_io().key_ctrl:
|
||||
if is_selected:
|
||||
rm.selected_files.discard(dir_path)
|
||||
else:
|
||||
rm.selected_files.add(dir_path)
|
||||
else:
|
||||
rm.selected_files.clear()
|
||||
rm.selected_files.add(dir_path)
|
||||
rm.focused_file = dir_path
|
||||
if imgui.is_item_clicked():
|
||||
self._handle_resource_item_selection(rm, dir_path, is_selected)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
rm.navigate_to(dir_path)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
self._open_resource_item_context_menu(rm, dir_path)
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
rm.navigate_to(dir_path)
|
||||
if node_open:
|
||||
self._draw_resource_directory_children(rm, dir_path)
|
||||
imgui.tree_pop()
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
rm.show_context_menu = True
|
||||
rm.context_menu_file = dir_path
|
||||
rm.context_menu_position = (imgui.get_mouse_pos().x, imgui.get_mouse_pos().y)
|
||||
imgui.open_popup("resource_context_menu")
|
||||
def _draw_resource_directory_children(self, rm, parent_dir: Path):
|
||||
"""绘制文件夹展开后的子目录与子文件(保持原有顺序)。"""
|
||||
subdirs, subfiles = rm.get_directory_contents(parent_dir)
|
||||
|
||||
if node_open:
|
||||
subdirs, subfiles = rm.get_directory_contents(dir_path)
|
||||
for subdir in subdirs:
|
||||
if not rm.should_show_file(subdir):
|
||||
continue
|
||||
self._draw_resource_subdir_entry(rm, subdir)
|
||||
|
||||
for subdir in subdirs:
|
||||
if not rm.should_show_file(subdir):
|
||||
continue
|
||||
for subfile in subfiles:
|
||||
if not rm.should_show_file(subfile):
|
||||
continue
|
||||
self._draw_resource_subfile_entry(rm, subfile)
|
||||
|
||||
subicon_name = rm.get_file_icon(subdir.name, is_folder=True)
|
||||
sub_is_selected = subdir in rm.selected_files
|
||||
def _draw_resource_subdir_entry(self, rm, subdir: Path):
|
||||
"""绘制一级子目录节点。"""
|
||||
subicon_name = rm.get_file_icon(subdir.name, is_folder=True)
|
||||
sub_is_selected = subdir in rm.selected_files
|
||||
subicon_texture = self._load_resource_icon(subicon_name)
|
||||
|
||||
subicon_texture = None
|
||||
try:
|
||||
subicon_texture = self.app.style_manager.load_icon(f"file_types/{subicon_name}")
|
||||
except:
|
||||
pass
|
||||
if subicon_texture:
|
||||
imgui.image(subicon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
sub_node_open = imgui.tree_node(f" {subdir.name}##dir_{subdir}")
|
||||
else:
|
||||
sub_node_open = imgui.tree_node(f" [{subicon_name.upper()}]{subdir.name}##dir_{subdir}")
|
||||
|
||||
if subicon_texture:
|
||||
imgui.image(subicon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
sub_node_open = imgui.tree_node(f" {subdir.name}##dir_{subdir}")
|
||||
else:
|
||||
sub_node_open = imgui.tree_node(f" [{subicon_name.upper()}]{subdir.name}##dir_{subdir}")
|
||||
self._append_drop_target_from_last_item(subdir)
|
||||
self._start_resource_drag_if_needed(rm, subdir)
|
||||
|
||||
self._append_drop_target_from_last_item(subdir)
|
||||
self._start_resource_drag_if_needed(rm, subdir)
|
||||
if imgui.is_item_clicked():
|
||||
self._handle_resource_item_selection(rm, subdir, sub_is_selected)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
rm.navigate_to(subdir)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
self._open_resource_item_context_menu(rm, subdir)
|
||||
|
||||
if imgui.is_item_clicked():
|
||||
if imgui.get_io().key_ctrl:
|
||||
if sub_is_selected:
|
||||
rm.selected_files.discard(subdir)
|
||||
else:
|
||||
rm.selected_files.add(subdir)
|
||||
else:
|
||||
rm.selected_files.clear()
|
||||
rm.selected_files.add(subdir)
|
||||
rm.focused_file = subdir
|
||||
if sub_node_open:
|
||||
imgui.tree_pop()
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
rm.navigate_to(subdir)
|
||||
def _draw_resource_subfile_entry(self, rm, subfile: Path):
|
||||
"""绘制一级子文件项。"""
|
||||
subicon_name = rm.get_file_icon(subfile.name)
|
||||
sub_is_selected = subfile in rm.selected_files
|
||||
subicon_texture = self._load_resource_icon(subicon_name)
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
rm.show_context_menu = True
|
||||
rm.context_menu_file = subdir
|
||||
rm.context_menu_position = (imgui.get_mouse_pos().x, imgui.get_mouse_pos().y)
|
||||
imgui.open_popup("resource_context_menu")
|
||||
if subicon_texture:
|
||||
imgui.image(subicon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
selected = imgui.selectable(f" {subfile.name}##file_{subfile}", sub_is_selected)
|
||||
else:
|
||||
selected = imgui.selectable(f" [{subicon_name.upper()}] {subfile.name}##file_{subfile}", sub_is_selected)
|
||||
|
||||
if sub_node_open:
|
||||
imgui.tree_pop()
|
||||
selected_clicked = selected[0] if isinstance(selected, tuple) else bool(selected)
|
||||
self._start_resource_drag_if_needed(rm, subfile)
|
||||
|
||||
for subfile in subfiles:
|
||||
if not rm.should_show_file(subfile):
|
||||
continue
|
||||
if selected_clicked:
|
||||
self._handle_resource_item_selection(rm, subfile, sub_is_selected)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
self._handle_resource_file_double_click(rm, subfile)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
self._open_resource_item_context_menu(rm, subfile)
|
||||
|
||||
subicon_name = rm.get_file_icon(subfile.name)
|
||||
sub_is_selected = subfile in rm.selected_files
|
||||
def _draw_resource_file_entries(self, rm, files):
|
||||
"""绘制当前目录下的文件列表。"""
|
||||
for file_path in files:
|
||||
if not rm.should_show_file(file_path):
|
||||
continue
|
||||
self._draw_resource_file_entry(rm, file_path)
|
||||
|
||||
subicon_texture = None
|
||||
try:
|
||||
subicon_texture = self.app.style_manager.load_icon(f"file_types/{subicon_name}")
|
||||
except:
|
||||
pass
|
||||
def _draw_resource_file_entry(self, rm, file_path: Path):
|
||||
"""绘制顶层文件项。"""
|
||||
icon_name = rm.get_file_icon(file_path.name)
|
||||
is_selected = file_path in rm.selected_files
|
||||
icon_texture = self._load_resource_icon(icon_name)
|
||||
|
||||
if subicon_texture:
|
||||
imgui.image(subicon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
selected = imgui.selectable(f" {subfile.name}##file_{subfile}", sub_is_selected)
|
||||
else:
|
||||
selected = imgui.selectable(f" [{subicon_name.upper()}] {subfile.name}##file_{subfile}", sub_is_selected)
|
||||
if icon_texture:
|
||||
imgui.image(icon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
selected = imgui.selectable(f"{file_path.name}##file_{file_path}", is_selected)
|
||||
else:
|
||||
selected = imgui.selectable(f"[{icon_name.upper()}] {file_path.name}##file_{file_path}", is_selected)
|
||||
|
||||
selected_clicked = selected[0] if isinstance(selected, tuple) else bool(selected)
|
||||
self._start_resource_drag_if_needed(rm, subfile)
|
||||
selected_clicked = selected[0] if isinstance(selected, tuple) else bool(selected)
|
||||
self._start_resource_drag_if_needed(rm, file_path)
|
||||
|
||||
if selected_clicked:
|
||||
if imgui.get_io().key_ctrl:
|
||||
if sub_is_selected:
|
||||
rm.selected_files.discard(subfile)
|
||||
else:
|
||||
rm.selected_files.add(subfile)
|
||||
else:
|
||||
rm.selected_files.clear()
|
||||
rm.selected_files.add(subfile)
|
||||
rm.focused_file = subfile
|
||||
if selected_clicked:
|
||||
self._handle_resource_item_selection(rm, file_path, is_selected)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
self._handle_resource_file_double_click(rm, file_path)
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
self._open_resource_item_context_menu(rm, file_path)
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
if self._is_model_file(subfile):
|
||||
self.app._import_model_for_runtime(str(subfile))
|
||||
self.app.add_info_message(f"正在导入模型: {subfile.name}")
|
||||
else:
|
||||
rm.open_file(subfile)
|
||||
def _draw_resource_toolbar_and_filters(self, rm):
|
||||
"""绘制资源管理器顶部工具条与筛选输入。保持原有按钮顺序与文案。"""
|
||||
if imgui.button("◀"):
|
||||
rm.navigate_back()
|
||||
imgui.same_line()
|
||||
if imgui.button("▶"):
|
||||
rm.navigate_forward()
|
||||
imgui.same_line()
|
||||
if imgui.button("▲"):
|
||||
rm.navigate_up()
|
||||
imgui.same_line()
|
||||
if imgui.button("主页"):
|
||||
rm.navigate_to(rm.project_root / "Resources")
|
||||
imgui.same_line()
|
||||
if imgui.button("刷新"):
|
||||
rm.force_refresh()
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
rm.show_context_menu = True
|
||||
rm.context_menu_file = subfile
|
||||
rm.context_menu_position = (imgui.get_mouse_pos().x, imgui.get_mouse_pos().y)
|
||||
imgui.open_popup("resource_context_menu")
|
||||
# 自动刷新开关
|
||||
imgui.same_line()
|
||||
changed, rm.auto_refresh_enabled = imgui.checkbox("自动刷新", rm.auto_refresh_enabled)
|
||||
if changed:
|
||||
rm.set_auto_refresh(rm.auto_refresh_enabled)
|
||||
|
||||
imgui.tree_pop()
|
||||
imgui.same_line()
|
||||
imgui.text(" ")
|
||||
imgui.same_line()
|
||||
|
||||
for file_path in files:
|
||||
if not rm.should_show_file(file_path):
|
||||
continue
|
||||
# 路径输入框
|
||||
changed, new_path = imgui.input_text("路径", str(rm.current_path), 256)
|
||||
if changed:
|
||||
try:
|
||||
rm.navigate_to(Path(new_path))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
icon_name = rm.get_file_icon(file_path.name)
|
||||
is_selected = file_path in rm.selected_files
|
||||
# 搜索框
|
||||
changed, rm.search_filter = imgui.input_text("搜索", rm.search_filter, 256)
|
||||
|
||||
icon_texture = None
|
||||
try:
|
||||
icon_texture = self.app.style_manager.load_icon(f"file_types/{icon_name}")
|
||||
except:
|
||||
pass
|
||||
def _load_resource_icon(self, icon_name: str):
|
||||
"""加载资源图标;失败时返回 None。"""
|
||||
try:
|
||||
return self.app.style_manager.load_icon(f"file_types/{icon_name}")
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
if icon_texture:
|
||||
imgui.image(icon_texture, (16, 16))
|
||||
imgui.same_line()
|
||||
selected = imgui.selectable(f"{file_path.name}##file_{file_path}", is_selected)
|
||||
else:
|
||||
selected = imgui.selectable(f"[{icon_name.upper()}] {file_path.name}##file_{file_path}", is_selected)
|
||||
def _handle_resource_item_selection(self, rm, target_path: Path, is_selected: bool):
|
||||
"""处理资源项选中逻辑(支持 Ctrl 多选)。"""
|
||||
if imgui.get_io().key_ctrl:
|
||||
if is_selected:
|
||||
rm.selected_files.discard(target_path)
|
||||
else:
|
||||
rm.selected_files.add(target_path)
|
||||
else:
|
||||
rm.selected_files.clear()
|
||||
rm.selected_files.add(target_path)
|
||||
rm.focused_file = target_path
|
||||
|
||||
selected_clicked = selected[0] if isinstance(selected, tuple) else bool(selected)
|
||||
self._start_resource_drag_if_needed(rm, file_path)
|
||||
def _open_resource_item_context_menu(self, rm, target_path: Path):
|
||||
"""打开资源项右键菜单。"""
|
||||
rm.show_context_menu = True
|
||||
rm.context_menu_file = target_path
|
||||
rm.context_menu_position = (imgui.get_mouse_pos().x, imgui.get_mouse_pos().y)
|
||||
imgui.open_popup("resource_context_menu")
|
||||
|
||||
if selected_clicked:
|
||||
if imgui.get_io().key_ctrl:
|
||||
if is_selected:
|
||||
rm.selected_files.discard(file_path)
|
||||
else:
|
||||
rm.selected_files.add(file_path)
|
||||
else:
|
||||
rm.selected_files.clear()
|
||||
rm.selected_files.add(file_path)
|
||||
rm.focused_file = file_path
|
||||
def _handle_resource_file_double_click(self, rm, file_path: Path):
|
||||
"""处理文件双击:模型导入,其他文件打开。"""
|
||||
if self._is_model_file(file_path):
|
||||
self.app.add_info_message(f"正在导入模型: {file_path.name}")
|
||||
self.app._import_model_for_runtime(str(file_path))
|
||||
else:
|
||||
rm.open_file(file_path)
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
|
||||
if self._is_model_file(file_path):
|
||||
self.app.add_info_message(f"正在导入模型: {file_path.name}")
|
||||
self.app._import_model_for_runtime(str(file_path))
|
||||
else:
|
||||
rm.open_file(file_path)
|
||||
def _draw_resource_context_menu(self, rm):
|
||||
"""绘制资源管理器右键菜单。保持原有菜单项与顺序。"""
|
||||
if rm.context_menu_file:
|
||||
imgui.set_next_window_pos((rm.context_menu_position[0], rm.context_menu_position[1]))
|
||||
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_clicked(1):
|
||||
rm.show_context_menu = True
|
||||
rm.context_menu_file = file_path
|
||||
rm.context_menu_position = (imgui.get_mouse_pos().x, imgui.get_mouse_pos().y)
|
||||
imgui.open_popup("resource_context_menu")
|
||||
if imgui.begin_popup("resource_context_menu"):
|
||||
if rm.context_menu_file and rm.context_menu_file.is_dir():
|
||||
if imgui.menu_item("打开")[1]:
|
||||
rm.navigate_to(rm.context_menu_file)
|
||||
imgui.separator()
|
||||
if imgui.menu_item("重命名")[1]:
|
||||
print(f"重命名文件夹: {rm.context_menu_file.name}")
|
||||
if imgui.menu_item("删除")[1]:
|
||||
print(f"删除文件夹: {rm.context_menu_file.name}")
|
||||
elif rm.context_menu_file:
|
||||
if imgui.menu_item("打开")[1]:
|
||||
rm.open_file(rm.context_menu_file)
|
||||
imgui.separator()
|
||||
if imgui.menu_item("导入到场景")[1]:
|
||||
if self._is_model_file(rm.context_menu_file):
|
||||
self.app.add_info_message(f"正在导入模型: {rm.context_menu_file.name}")
|
||||
self.app._import_model_for_runtime(str(rm.context_menu_file))
|
||||
if imgui.menu_item("重命名")[1]:
|
||||
print(f"重命名文件: {rm.context_menu_file.name}")
|
||||
if imgui.menu_item("删除")[1]:
|
||||
print(f"删除文件: {rm.context_menu_file.name}")
|
||||
|
||||
if rm.context_menu_file:
|
||||
imgui.set_next_window_pos((rm.context_menu_position[0], rm.context_menu_position[1]))
|
||||
imgui.separator()
|
||||
if imgui.menu_item("复制路径")[1]:
|
||||
imgui.set_clipboard_text(str(rm.context_menu_file))
|
||||
self.app.add_info_message("路径已复制到剪贴板")
|
||||
if imgui.menu_item("在文件管理器中显示")[1]:
|
||||
import platform
|
||||
import subprocess
|
||||
if platform.system() == "Windows":
|
||||
subprocess.run(["explorer", "/select,", str(rm.context_menu_file)])
|
||||
elif platform.system() == "Darwin":
|
||||
subprocess.run(["open", "-R", str(rm.context_menu_file)])
|
||||
else:
|
||||
subprocess.run(["xdg-open", str(rm.context_menu_file.parent)])
|
||||
|
||||
if imgui.begin_popup("resource_context_menu"):
|
||||
if rm.context_menu_file and rm.context_menu_file.is_dir():
|
||||
if imgui.menu_item("打开")[1]:
|
||||
rm.navigate_to(rm.context_menu_file)
|
||||
imgui.separator()
|
||||
if imgui.menu_item("重命名")[1]:
|
||||
print(f"重命名文件夹: {rm.context_menu_file.name}")
|
||||
if imgui.menu_item("删除")[1]:
|
||||
print(f"删除文件夹: {rm.context_menu_file.name}")
|
||||
elif rm.context_menu_file:
|
||||
if imgui.menu_item("打开")[1]:
|
||||
rm.open_file(rm.context_menu_file)
|
||||
imgui.separator()
|
||||
if imgui.menu_item("导入到场景")[1]:
|
||||
if self._is_model_file(rm.context_menu_file):
|
||||
self.app.add_info_message(f"正在导入模型: {rm.context_menu_file.name}")
|
||||
self.app._import_model_for_runtime(str(rm.context_menu_file))
|
||||
if imgui.menu_item("重命名")[1]:
|
||||
print(f"重命名文件: {rm.context_menu_file.name}")
|
||||
if imgui.menu_item("删除")[1]:
|
||||
print(f"删除文件: {rm.context_menu_file.name}")
|
||||
if imgui.is_mouse_clicked(0) and not imgui.is_window_hovered():
|
||||
rm.context_menu_file = None
|
||||
rm.show_context_menu = False
|
||||
imgui.close_current_popup()
|
||||
|
||||
if rm.context_menu_file:
|
||||
imgui.separator()
|
||||
if imgui.menu_item("复制路径")[1]:
|
||||
imgui.set_clipboard_text(str(rm.context_menu_file))
|
||||
self.app.add_info_message("路径已复制到剪贴板")
|
||||
if imgui.menu_item("在文件管理器中显示")[1]:
|
||||
import platform
|
||||
import subprocess
|
||||
if platform.system() == "Windows":
|
||||
subprocess.run(["explorer", "/select,", str(rm.context_menu_file)])
|
||||
elif platform.system() == "Darwin":
|
||||
subprocess.run(["open", "-R", str(rm.context_menu_file)])
|
||||
else:
|
||||
subprocess.run(["xdg-open", str(rm.context_menu_file.parent)])
|
||||
|
||||
if imgui.is_mouse_clicked(0) and not imgui.is_window_hovered():
|
||||
rm.context_menu_file = None
|
||||
rm.show_context_menu = False
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.end_popup()
|
||||
imgui.end_popup()
|
||||
|
||||
@staticmethod
|
||||
def _is_model_file(path: Path) -> bool:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user