466 lines
26 KiB
Python
466 lines
26 KiB
Python
from imgui_bundle import imgui, imgui_ctx
|
|
|
|
class EditorPanelsTopMixin:
|
|
"""Auto-split mixin from editor_panels.py."""
|
|
|
|
@staticmethod
|
|
def _draw_toolbar_text_button(label, active=False, tooltip=None, enabled=True):
|
|
"""Draw a text-only toolbar action with no filled background."""
|
|
text_color = (0.84, 0.87, 0.91, 1.0)
|
|
hover_color = (0.96, 0.98, 1.0, 1.0)
|
|
active_color = (0.24, 0.58, 1.0, 1.0)
|
|
disabled_color = (0.45, 0.48, 0.53, 0.75)
|
|
|
|
if not enabled:
|
|
current_color = disabled_color
|
|
elif active:
|
|
current_color = active_color
|
|
else:
|
|
current_color = text_color
|
|
|
|
imgui.push_style_color(imgui.Col_.button, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_color(imgui.Col_.button_hovered, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_color(imgui.Col_.button_active, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_color(imgui.Col_.border, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_color(imgui.Col_.text, current_color)
|
|
imgui.push_style_var(imgui.StyleVar_.frame_padding, (6.0, 4.0))
|
|
imgui.push_style_var(imgui.StyleVar_.frame_border_size, 0.0)
|
|
imgui.push_style_var(imgui.StyleVar_.frame_rounding, 0.0)
|
|
|
|
if not enabled:
|
|
imgui.begin_disabled()
|
|
clicked = imgui.button(label)
|
|
hovered = imgui.is_item_hovered()
|
|
if not enabled:
|
|
imgui.end_disabled()
|
|
|
|
if active:
|
|
min_pos = imgui.get_item_rect_min()
|
|
max_pos = imgui.get_item_rect_max()
|
|
draw_list = imgui.get_window_draw_list()
|
|
accent = imgui.color_convert_float4_to_u32(active_color)
|
|
draw_list.add_line(
|
|
(min_pos.x + 1.0, max_pos.y + 1.0),
|
|
(max_pos.x - 1.0, max_pos.y + 1.0),
|
|
accent,
|
|
3.0,
|
|
)
|
|
elif hovered and enabled:
|
|
min_pos = imgui.get_item_rect_min()
|
|
max_pos = imgui.get_item_rect_max()
|
|
draw_list = imgui.get_window_draw_list()
|
|
hover_u32 = imgui.color_convert_float4_to_u32((hover_color[0], hover_color[1], hover_color[2], 0.75))
|
|
draw_list.add_line(
|
|
(min_pos.x + 2.0, max_pos.y + 1.0),
|
|
(max_pos.x - 2.0, max_pos.y + 1.0),
|
|
hover_u32,
|
|
1.0,
|
|
)
|
|
|
|
if tooltip and hovered:
|
|
imgui.set_tooltip(tooltip)
|
|
|
|
imgui.pop_style_var(3)
|
|
imgui.pop_style_color(5)
|
|
return clicked
|
|
|
|
@staticmethod
|
|
def _draw_toolbar_text_chip(label, active=False):
|
|
"""Draw a text-only status label without a background block."""
|
|
base_color = (0.72, 0.75, 0.8, 0.92)
|
|
active_color = (0.88, 0.91, 0.96, 1.0)
|
|
imgui.push_style_color(imgui.Col_.text, active_color if active else base_color)
|
|
imgui.text_unformatted(label)
|
|
imgui.pop_style_color()
|
|
|
|
@staticmethod
|
|
def _draw_toolbar_divider():
|
|
imgui.push_style_color(imgui.Col_.text, (0.38, 0.41, 0.46, 0.85))
|
|
imgui.text_unformatted("|")
|
|
imgui.pop_style_color()
|
|
|
|
@staticmethod
|
|
def _truncate_toolbar_text(text, limit=20):
|
|
text = text or ""
|
|
if len(text) <= limit:
|
|
return text
|
|
return text[: max(0, limit - 1)] + "…"
|
|
|
|
def _get_toolbar_project_name(self):
|
|
project_manager = getattr(self.app, "project_manager", None)
|
|
project_path = getattr(project_manager, "current_project_path", None) if project_manager else None
|
|
if not project_path:
|
|
return "未命名项目"
|
|
import os
|
|
return os.path.basename(project_path) or "未命名项目"
|
|
|
|
def _get_toolbar_selection_name(self):
|
|
selected_node = self.app._get_selection_node()
|
|
if selected_node and not selected_node.isEmpty():
|
|
return selected_node.getName() or "未命名对象"
|
|
ssbo_summary = self.app._get_ssbo_selection_summary()
|
|
if ssbo_summary:
|
|
return ssbo_summary.get("display_name") or "SSBO 选择"
|
|
return "未选择"
|
|
|
|
def draw_menu_bar(self):
|
|
"""绘制菜单栏"""
|
|
with imgui_ctx.begin_main_menu_bar() as main_menu:
|
|
if main_menu:
|
|
# 文件菜单
|
|
with imgui_ctx.begin_menu("文件") as file_menu:
|
|
if file_menu:
|
|
if imgui.menu_item("新建项目", "Ctrl+N", False, True)[1]:
|
|
self.app._on_new_project()
|
|
if imgui.menu_item("打开项目", "Ctrl+O", False, True)[1]:
|
|
self.app._on_open_project()
|
|
imgui.separator()
|
|
if imgui.menu_item("保存", "Ctrl+S", False, True)[1]:
|
|
self.app._on_save_project()
|
|
if imgui.menu_item("另存为", "", False, True)[1]:
|
|
self.app._on_save_as_project()
|
|
imgui.separator()
|
|
if imgui.menu_item("退出", "Alt+F4", False, True)[1]:
|
|
self.app._on_exit()
|
|
|
|
# 编辑菜单
|
|
with imgui_ctx.begin_menu("编辑") as edit_menu:
|
|
if edit_menu:
|
|
if imgui.menu_item("撤销", "Ctrl+Z", False, True)[1]:
|
|
self.app._on_undo()
|
|
if imgui.menu_item("重做", "Ctrl+Y", False, True)[1]:
|
|
self.app._on_redo()
|
|
imgui.separator()
|
|
if imgui.menu_item("剪切", "Ctrl+X", False, True)[1]:
|
|
self.app._on_cut()
|
|
if imgui.menu_item("复制", "Ctrl+C", False, True)[1]:
|
|
self.app._on_copy()
|
|
if imgui.menu_item("粘贴", "Ctrl+V", False, True)[1]:
|
|
self.app._on_paste()
|
|
imgui.separator()
|
|
if imgui.menu_item("删除", "Del", False, True)[1]:
|
|
self.app._on_delete()
|
|
|
|
# 创建菜单
|
|
with imgui_ctx.begin_menu("创建") as create_menu:
|
|
if create_menu:
|
|
if imgui.menu_item("导入模型", "", False, True)[1]:
|
|
self.app._on_import_model()
|
|
|
|
imgui.separator()
|
|
|
|
if imgui.menu_item("空对象", "", False, True)[1]:
|
|
self.app._on_create_empty_object()
|
|
|
|
# 3D对象子菜单
|
|
with imgui_ctx.begin_menu("3D对象") as three_d_menu:
|
|
if three_d_menu:
|
|
if imgui.menu_item("立方体", "", False, True)[1]:
|
|
self.app._on_create_cube()
|
|
if imgui.menu_item("球体", "", False, True)[1]:
|
|
self.app._on_create_sphere()
|
|
if imgui.menu_item("圆柱体", "", False, True)[1]:
|
|
self.app._on_create_cylinder()
|
|
if imgui.menu_item("平面", "", False, True)[1]:
|
|
self.app._on_create_plane()
|
|
|
|
# 3D GUI子菜单
|
|
# with imgui_ctx.begin_menu("3D GUI") as three_d_gui_menu:
|
|
# if three_d_gui_menu:
|
|
# if imgui.menu_item("3D文本", "", False, True)[1]:
|
|
# self.app._on_create_3d_text()
|
|
# if imgui.menu_item("3D图片", "", False, True)[1]:
|
|
# self.app._on_create_3d_image()
|
|
|
|
# # GUI子菜单
|
|
# with imgui_ctx.begin_menu("GUI") as gui_menu:
|
|
# if gui_menu:
|
|
# if imgui.menu_item("创建按钮", "", False, True)[1]:
|
|
# self.app._on_create_gui_button()
|
|
# if imgui.menu_item("创建标签", "", False, True)[1]:
|
|
# self.app._on_create_gui_label()
|
|
# if imgui.menu_item("创建输入框", "", False, True)[1]:
|
|
# self.app._on_create_gui_entry()
|
|
# if imgui.menu_item("创建图片", "", False, True)[1]:
|
|
# self.app._on_create_gui_image()
|
|
# imgui.separator()
|
|
# if imgui.menu_item("创建视频屏幕", "", False, True)[1]:
|
|
# self.app._on_create_video_screen()
|
|
# if imgui.menu_item("创建2D视频屏幕", "", False, True)[1]:
|
|
# self.app._on_create_2d_video_screen()
|
|
# if imgui.menu_item("创建球形视频", "", False, True)[1]:
|
|
# self.app._on_create_spherical_video()
|
|
# if imgui.menu_item("创建虚拟屏幕", "", False, True)[1]:
|
|
# self.app._on_create_virtual_screen()
|
|
|
|
# 光源子菜单
|
|
with imgui_ctx.begin_menu("光源") as light_menu:
|
|
if light_menu:
|
|
if imgui.menu_item("聚光灯", "", False, True)[1]:
|
|
self.app._on_create_spot_light()
|
|
if imgui.menu_item("点光源", "", False, True)[1]:
|
|
self.app._on_create_point_light()
|
|
|
|
# 地形子菜单
|
|
with imgui_ctx.begin_menu("地形") as terrain_menu:
|
|
if terrain_menu:
|
|
if imgui.menu_item("创建平面地形", "", False, True)[1]:
|
|
self.app._on_create_flat_terrain()
|
|
if imgui.menu_item("从高度图创建地形", "", False, True)[1]:
|
|
self.app._on_create_heightmap_terrain()
|
|
|
|
# 脚本子菜单
|
|
with imgui_ctx.begin_menu("脚本") as script_menu:
|
|
if script_menu:
|
|
hot_reload_enabled = False
|
|
if getattr(self.app, "script_manager", None):
|
|
hot_reload_enabled = bool(self.app.script_manager.hot_reload_enabled)
|
|
if imgui.menu_item("创建脚本...", "", False, True)[1]:
|
|
self.app._on_create_script()
|
|
if imgui.menu_item("加载脚本文件...", "", False, True)[1]:
|
|
self.app._on_load_script()
|
|
imgui.separator()
|
|
if imgui.menu_item("重载所有脚本", "", False, True)[1]:
|
|
self.app._on_reload_all_scripts()
|
|
changed, new_hot_reload = imgui.menu_item("启用热重载", "", hot_reload_enabled, True)
|
|
if changed:
|
|
self.app._set_hot_reload_enabled(new_hot_reload)
|
|
if imgui.menu_item("脚本管理器", "", False, True)[1]:
|
|
self.app._on_open_scripts_manager()
|
|
|
|
# 信息面板子菜单
|
|
with imgui_ctx.begin_menu("信息面板") as info_panel_menu:
|
|
if info_panel_menu:
|
|
# if imgui.menu_item("创建2D示例面板", "", False, True)[1]:
|
|
# self.app._on_create_2d_sample_panel()
|
|
# if imgui.menu_item("创建3D实例面板", "", False, True)[1]:
|
|
# self.app._on_create_3d_sample_panel()
|
|
if imgui.menu_item("Web面板", "", False, True)[1]:
|
|
self.app._on_create_web_panel()
|
|
|
|
# 视图菜单
|
|
with imgui_ctx.begin_menu("视图") as view_menu:
|
|
if view_menu:
|
|
changed, visible = imgui.menu_item("工具栏", "", self.app.is_panel_visible("toolbar"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("toolbar", visible)
|
|
changed, visible = imgui.menu_item("场景树", "", self.app.is_panel_visible("scene_tree"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("scene_tree", visible)
|
|
changed, visible = imgui.menu_item("资源管理器", "", self.app.is_panel_visible("resources"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("resources", visible)
|
|
changed, visible = imgui.menu_item("属性面板", "", self.app.is_panel_visible("property"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("property", visible)
|
|
changed, visible = imgui.menu_item("控制台", "", self.app.is_panel_visible("console"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("console", visible)
|
|
changed, visible = imgui.menu_item("脚本管理", "", self.app.is_panel_visible("script"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("script", visible)
|
|
changed, visible = imgui.menu_item("LUI编辑器", "", self.app.is_panel_visible("lui_editor"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("lui_editor", visible)
|
|
changed, visible = imgui.menu_item("Web面板", "", self.app.is_panel_visible("web"), True)
|
|
if changed:
|
|
self.app.set_panel_visible("web", visible)
|
|
imgui.separator()
|
|
if imgui.menu_item("恢复默认面板", "", False, True)[1]:
|
|
self.app.reset_panel_visibility_to_defaults()
|
|
if imgui.menu_item("重置布局", "", False, True)[1]:
|
|
self.app._reset_imgui_layout()
|
|
|
|
# 工具菜单
|
|
with imgui_ctx.begin_menu("工具") as tools_menu:
|
|
if tools_menu:
|
|
# 工具切换选项
|
|
if imgui.menu_item("选择工具", "", False, True)[1]:
|
|
self.app.tool_manager.setCurrentTool("选择")
|
|
if imgui.menu_item("移动工具", "", False, True)[1]:
|
|
self.app.tool_manager.setCurrentTool("移动")
|
|
if imgui.menu_item("旋转工具", "", False, True)[1]:
|
|
self.app.tool_manager.setCurrentTool("旋转")
|
|
if imgui.menu_item("缩放工具", "", False, True)[1]:
|
|
self.app.tool_manager.setCurrentTool("缩放")
|
|
|
|
imgui.separator()
|
|
|
|
# 编辑工具
|
|
# if imgui.menu_item("光照编辑", "", False, True)[1]:
|
|
# self.app.tool_manager.setCurrentTool("光照编辑")
|
|
# if imgui.menu_item("图形编辑", "", False, True)[1]:
|
|
# self.app.tool_manager.setCurrentTool("图形编辑")
|
|
|
|
imgui.separator()
|
|
|
|
# VR子菜单
|
|
with imgui_ctx.begin_menu("VR") as vr_menu:
|
|
if vr_menu:
|
|
if imgui.menu_item("进入VR模式", "", False, True)[1]:
|
|
self.app._toggle_vr_mode()
|
|
if imgui.menu_item("退出VR模式", "", False, True)[1]:
|
|
self.app._exit_vr_mode()
|
|
|
|
imgui.separator()
|
|
|
|
if imgui.menu_item("VR状态", "", False, True)[1]:
|
|
self.app._show_vr_status()
|
|
if imgui.menu_item("VR设置", "", False, True)[1]:
|
|
self.app._show_vr_settings()
|
|
|
|
imgui.separator()
|
|
|
|
# VR调试子菜单
|
|
with imgui_ctx.begin_menu("VR调试") as vr_debug_menu:
|
|
if vr_debug_menu:
|
|
_, self.app.vr_debug_enabled = imgui.menu_item("启用调试输出", "", self.app.vr_debug_enabled, True)
|
|
|
|
if imgui.menu_item("立即显示性能报告", "", False, True)[1]:
|
|
self.app._show_vr_performance_report()
|
|
|
|
imgui.separator()
|
|
|
|
# 输出模式
|
|
with imgui_ctx.begin_menu("输出模式") as output_menu:
|
|
if output_menu:
|
|
if imgui.menu_item("简短模式", "", not self.app.vr_detailed_mode, True)[1]:
|
|
self.app.vr_detailed_mode = False
|
|
if imgui.menu_item("详细模式", "", self.app.vr_detailed_mode, True)[1]:
|
|
self.app.vr_detailed_mode = True
|
|
|
|
imgui.separator()
|
|
|
|
_, self.app.vr_performance_monitor = imgui.menu_item("启用性能监控", "", self.app.vr_performance_monitor, True)
|
|
|
|
# 窗口菜单 - 已隐藏
|
|
# with imgui_ctx.begin_menu("窗口") as window_menu:
|
|
# if window_menu:
|
|
# _, self.app.showDemoWindow = imgui.menu_item("ImGui演示", "", self.app.showDemoWindow, True)
|
|
# if self.app.testTexture:
|
|
# imgui.menu_item("关闭纹理测试", "", False, True)
|
|
# else:
|
|
# imgui.menu_item("显示纹理测试", "", False, True)
|
|
|
|
# 帮助菜单
|
|
with imgui_ctx.begin_menu("帮助") as help_menu:
|
|
if help_menu:
|
|
if imgui.menu_item("关于", "", False, True)[1]:
|
|
self.app._show_about_dialog()
|
|
if imgui.menu_item("文档", "", False, True)[1]:
|
|
self.app._open_documentation()
|
|
|
|
# 右侧显示FPS
|
|
imgui.set_cursor_pos_x(imgui.get_window_size().x - 140)
|
|
imgui.text("%.2f FPS (%.2f ms)" % (imgui.get_io().framerate, 1000.0 / imgui.get_io().framerate))
|
|
|
|
def draw_toolbar(self):
|
|
"""绘制工具栏"""
|
|
viewport = imgui.get_main_viewport()
|
|
menu_bar_height = imgui.get_frame_height()
|
|
toolbar_y = viewport.pos.y + menu_bar_height + 6.0
|
|
toolbar_x = viewport.pos.x + 8.0
|
|
|
|
scene_tree_rect = getattr(self.app, "_scene_tree_window_rect", None)
|
|
if self.app.is_panel_visible("scene_tree") and scene_tree_rect:
|
|
scene_tree_right = float(scene_tree_rect[0]) + float(scene_tree_rect[2])
|
|
toolbar_x = max(toolbar_x, scene_tree_right + 12.0)
|
|
|
|
toolbar_width = max(320.0, viewport.pos.x + viewport.size.x - toolbar_x - 12.0)
|
|
|
|
imgui.set_next_window_pos((toolbar_x, toolbar_y), imgui.Cond_.always)
|
|
imgui.set_next_window_size((toolbar_width, 34.0), imgui.Cond_.always)
|
|
imgui.set_next_window_bg_alpha(0.0)
|
|
|
|
flags = (
|
|
imgui.WindowFlags_.no_title_bar |
|
|
imgui.WindowFlags_.no_resize |
|
|
imgui.WindowFlags_.no_move |
|
|
imgui.WindowFlags_.no_scrollbar |
|
|
imgui.WindowFlags_.no_scroll_with_mouse |
|
|
imgui.WindowFlags_.no_saved_settings |
|
|
imgui.WindowFlags_.no_collapse |
|
|
imgui.WindowFlags_.no_background
|
|
)
|
|
|
|
imgui.push_style_color(imgui.Col_.window_bg, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_color(imgui.Col_.border, (0.0, 0.0, 0.0, 0.0))
|
|
imgui.push_style_var(imgui.StyleVar_.window_padding, (0.0, 2.0))
|
|
imgui.push_style_var(imgui.StyleVar_.window_border_size, 0.0)
|
|
imgui.push_style_var(imgui.StyleVar_.window_rounding, 0.0)
|
|
|
|
with imgui_ctx.begin("工具栏", self.app.showToolbar, flags) as (_, opened):
|
|
if not opened:
|
|
self.app.showToolbar = False
|
|
self.app._toolbar_window_rect = None
|
|
imgui.pop_style_var(3)
|
|
imgui.pop_style_color(2)
|
|
return
|
|
|
|
self.app.showToolbar = opened
|
|
command_manager = getattr(self.app, "command_manager", None)
|
|
can_undo = command_manager.can_undo() if command_manager else False
|
|
can_redo = command_manager.can_redo() if command_manager else False
|
|
selection_name = self._truncate_toolbar_text(self._get_toolbar_selection_name(), 18)
|
|
project_name = self._truncate_toolbar_text(self._get_toolbar_project_name(), 18)
|
|
tool_name = getattr(self.app.tool_manager, "getCurrentTool", lambda: "选择")()
|
|
|
|
imgui.push_style_var(imgui.StyleVar_.item_spacing, (14.0, 4.0))
|
|
|
|
tool_buttons = [
|
|
("Q 选择", "选择", self.app.tool_manager.isSelectionTool(), "选择工具 (Q)"),
|
|
("W 移动", "移动", self.app.tool_manager.isMoveTool(), "移动工具 (W)"),
|
|
("E 旋转", "旋转", self.app.tool_manager.isRotateTool(), "旋转工具 (E)"),
|
|
("R 缩放", "缩放", self.app.tool_manager.isScaleTool(), "缩放工具 (R)"),
|
|
]
|
|
|
|
for index, (label, tool_id, is_active, tooltip) in enumerate(tool_buttons):
|
|
if self._draw_toolbar_text_button(label, active=is_active, tooltip=tooltip):
|
|
self.app.tool_manager.setCurrentTool(tool_id)
|
|
if index != len(tool_buttons) - 1:
|
|
imgui.same_line()
|
|
|
|
imgui.same_line()
|
|
self._draw_toolbar_divider()
|
|
imgui.same_line()
|
|
|
|
if self._draw_toolbar_text_button("撤销", tooltip="撤销上一步 (Ctrl+Z)", enabled=can_undo):
|
|
self.app._on_undo()
|
|
imgui.same_line()
|
|
if self._draw_toolbar_text_button("重做", tooltip="重做上一步 (Ctrl+Y)", enabled=can_redo):
|
|
self.app._on_redo()
|
|
imgui.same_line()
|
|
if self._draw_toolbar_text_button(
|
|
"聚焦",
|
|
tooltip="聚焦当前选择 (F)",
|
|
enabled=selection_name != "未选择",
|
|
):
|
|
self.app.onFocusKeyPressed()
|
|
|
|
imgui.same_line()
|
|
self._draw_toolbar_divider()
|
|
imgui.same_line()
|
|
self._draw_toolbar_text_chip(f"项目 {project_name}")
|
|
imgui.same_line()
|
|
self._draw_toolbar_text_chip(f"工具 {tool_name}", active=True)
|
|
imgui.same_line()
|
|
self._draw_toolbar_text_chip(f"选择 {selection_name}")
|
|
imgui.same_line()
|
|
self._draw_toolbar_text_chip(
|
|
f"历史 {command_manager.get_undo_count() if command_manager else 0}/{command_manager.get_redo_count() if command_manager else 0}",
|
|
)
|
|
|
|
window_pos = imgui.get_window_pos()
|
|
window_size = imgui.get_window_size()
|
|
self.app._toolbar_window_rect = (
|
|
float(window_pos.x),
|
|
float(window_pos.y),
|
|
float(window_pos.x + window_size.x),
|
|
float(window_pos.y + window_size.y),
|
|
)
|
|
|
|
imgui.pop_style_var()
|
|
imgui.pop_style_var(3)
|
|
imgui.pop_style_color(2)
|
|
|