EG/ui/panels/interaction_panels.py
2026-02-25 11:49:31 +08:00

254 lines
9.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from imgui_bundle import imgui, imgui_ctx
class InteractionPanels:
"""Drag-and-drop and context menu interaction panels."""
def __init__(self, app):
self.app = app
def __getattr__(self, name):
return getattr(self.app, name)
def __setattr__(self, name, value):
if name == "app" or name in self.__dict__ or hasattr(type(self), name):
object.__setattr__(self, name, value)
else:
setattr(self.app, name, value)
def _draw_drag_drop_interface(self):
"""绘制拖拽界面"""
# 检查资源管理器的拖拽状态
if self.resource_manager.is_dragging():
self.is_dragging = True
self.dragged_files = self.resource_manager.get_dragged_files()
self.show_drag_overlay = True
# 绘制拖拽覆盖层
if self.show_drag_overlay:
self._draw_drag_overlay()
# 检查是否有拖拽的文件需要处理
if self.is_dragging and self.dragged_files:
# 显示拖拽状态
self._draw_drag_status()
# 检查是否释放鼠标(结束拖拽)
if imgui.is_mouse_released(0):
self._handle_drag_drop_completion()
def _handle_drag_drop_completion(self):
"""处理拖拽完成"""
# 检查是否在3D视图中释放
mouse_pos = imgui.get_mouse_pos()
viewport = imgui.get_main_viewport()
# 简单检查如果不在任何ImGui窗口上则认为是在3D视图中
if not imgui.is_any_window_hovered():
# 导入支持的3D模型文件
imported_count = 0
for file_path in self.dragged_files:
if file_path.suffix.lower() in ['.gltf', '.glb', '.fbx', '.bam', '.egg', '.obj']:
try:
self._import_model_for_runtime(str(file_path))
self.add_success_message(f"成功导入模型: {file_path.name}")
imported_count += 1
except Exception as e:
self.add_error_message(f"导入模型失败 {file_path.name}: {e}")
if imported_count > 0:
self.add_success_message(f"共导入 {imported_count} 个模型")
# 清除拖拽状态
self.is_dragging = False
self.dragged_files.clear()
self.show_drag_overlay = False
self.resource_manager.clear_drag()
def _draw_drag_overlay(self):
"""绘制拖拽覆盖层"""
viewport = imgui.get_main_viewport()
imgui.set_next_window_pos((0, 0))
imgui.set_next_window_size(viewport.work_size)
flags = (
imgui.WindowFlags_.no_title_bar |
imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_move |
imgui.WindowFlags_.no_scrollbar |
imgui.WindowFlags_.no_saved_settings |
imgui.WindowFlags_.no_background |
imgui.WindowFlags_.no_focus_on_appearing
)
imgui.begin("##DragOverlay", True, flags)
# 绘制半透明背景
draw_list = imgui.get_window_draw_list()
draw_list.add_rect_filled(
(0, 0), viewport.work_size,
imgui.get_color_u32((0, 0, 0, 0.1))
)
# 绘制提示文本
text_size = imgui.calc_text_size("释放以导入文件")
text_pos = (
(viewport.work_size.x - text_size.x) / 2,
(viewport.work_size.y - text_size.y) / 2
)
draw_list.add_text(
text_pos,
imgui.get_color_u32((1, 1, 1, 1)),
"释放以导入文件"
)
imgui.end()
def _draw_drag_status(self):
"""绘制拖拽状态"""
viewport = imgui.get_main_viewport()
# 在右下角显示拖拽状态
imgui.set_next_window_pos(
(viewport.work_size.x - 300, viewport.work_size.y - 150),
imgui.Cond_.first_use_ever
)
flags = (
imgui.WindowFlags_.no_title_bar |
imgui.WindowFlags_.no_resize |
imgui.WindowFlags_.no_move |
imgui.WindowFlags_.no_scrollbar |
imgui.WindowFlags_.no_saved_settings
)
with imgui_ctx.begin("拖拽状态", True, flags):
imgui.text("拖拽的文件:")
for file_path in self.dragged_files:
filename = os.path.basename(file_path)
imgui.text(f"{filename}")
imgui.separator()
if imgui.button("导入所有文件"):
self.process_dragged_files()
imgui.same_line()
if imgui.button("取消"):
self.clear_dragged_files()
def _draw_context_menus(self):
"""绘制右键菜单"""
# 节点右键菜单
if hasattr(self, '_context_menu_node') and self._context_menu_node:
imgui.open_popup("节点右键菜单")
self._context_menu_node = None
if imgui.begin_popup("节点右键菜单"):
if imgui.menu_item("删除节点", "", False, True)[1]:
if hasattr(self, '_context_menu_target') and self._context_menu_target:
self._delete_node(self._context_menu_target)
imgui.close_current_popup()
if imgui.menu_item("重命名", "", False, True)[1]:
self._renaming_node = True
imgui.close_current_popup()
imgui.separator()
if imgui.menu_item("复制", "", False, True)[1]:
if hasattr(self, '_context_menu_target') and self._context_menu_target:
self._copy_node(self._context_menu_target)
imgui.close_current_popup()
if imgui.menu_item("聚焦", "", False, True)[1]:
if hasattr(self, '_context_menu_target') and self._context_menu_target:
if hasattr(self, 'selection') and self.selection:
self.selection.updateSelection(self._context_menu_target)
self.selection.focusCameraOnSelectedNodeAdvanced()
imgui.close_current_popup()
imgui.end_popup()
# 重命名对话框
if hasattr(self, '_renaming_node') and self._renaming_node:
imgui.open_popup("重命名节点")
if not hasattr(self, '_rename_buffer'):
self._rename_buffer = ""
if hasattr(self, '_context_menu_target') and self._context_menu_target:
self._rename_buffer = self._context_menu_target.getName() or ""
if imgui.begin_popup("重命名节点"):
changed, new_name = imgui.input_text("新名称", self._rename_buffer, 256)
if changed:
self._rename_buffer = new_name
if imgui.button("确定"):
if hasattr(self, '_context_menu_target') and self._context_menu_target:
self._context_menu_target.setName(self._rename_buffer)
self._renaming_node = False
imgui.close_current_popup()
imgui.same_line()
if imgui.button("取消"):
self._renaming_node = False
imgui.close_current_popup()
imgui.end_popup()
def _delete_node_simple(self, node):
"""删除节点 - 简化版本"""
if not node or node.isEmpty():
return
# 从场景管理器中删除
if hasattr(self, 'scene_manager') and self.scene_manager:
if hasattr(self.scene_manager, 'models') and node in self.scene_manager.models:
self.scene_manager.models.remove(node)
# 从GUI管理器中删除
if hasattr(self, 'gui_manager') and self.gui_manager:
gui_element = None
if hasattr(node, 'getPythonTag'):
gui_element = node.getPythonTag('gui_element')
if gui_element and hasattr(self.gui_manager, 'gui_elements'):
if gui_element in self.gui_manager.gui_elements:
self.gui_manager.gui_elements.remove(gui_element)
# 使用主删除方法
self._delete_node(node)
# 获取节点名称(在删除之前)
node_name = node.getName() if not node.isEmpty() else '未命名节点'
# 删除节点本身
node.removeNode()
# 清除选择
if hasattr(self, 'selection') and self.selection:
if self.selection.selectedNode == node:
self.selection.clearSelection()
# 添加成功消息
self.add_success_message(f"已删除节点: {node_name}")
def _copy_node(self, node):
"""复制节点"""
if not node or node.isEmpty():
return
# 这里可以实现节点复制逻辑
# 暂时只显示消息
self.add_info_message(f"复制功能暂未实现: {node.getName() or '未命名节点'}")
# ==================== 创建功能实现 ====================