重启N1资源管理器面板拆分(保留布局)

This commit is contained in:
ayuan9957 2026-03-01 12:50:14 +08:00
parent 4f70cc113b
commit c006b69613

View File

@ -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: