EG/ui/panels/script_panels.py
2026-04-21 15:57:20 +08:00

336 lines
14 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.

from imgui_bundle import imgui, imgui_ctx
class ScriptPanels:
"""Script and console related editor 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_console(self):
"""绘制控制台面板"""
# 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("控制台", self.app.showConsole, flags) as (_, opened):
if not opened:
self.app.showConsole = False
self.app._console_window_rect = None
return
self.app.showConsole = opened
window_pos = imgui.get_window_pos()
window_size = imgui.get_window_size()
self.app._console_window_rect = (
float(window_pos.x),
float(window_pos.y),
float(window_size.x),
float(window_size.y),
)
imgui.text("控制台输出")
imgui.separator()
# 显示消息系统中的消息
if hasattr(self, 'messages') and self.messages:
for message in self.messages:
# 显示时间戳
imgui.text_colored((0.7, 0.7, 0.7, 1.0), f"[{message['timestamp']}]")
imgui.same_line()
# 根据消息类型显示图标
if message['text'].startswith(''):
if self.icons.get('success'):
imgui.image(self.icons['success'], (12, 12))
imgui.same_line()
elif message['text'].startswith(''):
if self.icons.get('delete_fail_icon'):
imgui.image(self.icons['delete_fail_icon'], (12, 12))
imgui.same_line()
elif message['text'].startswith(''):
if self.icons.get('warning'):
imgui.image(self.icons['warning'], (12, 12))
imgui.same_line()
# 显示消息文本
imgui.text_colored(message['color'], message['text'])
else:
# 默认消息
imgui.text_colored((0.157, 0.620, 1.0, 1.0), "[系统]")
imgui.same_line()
imgui.text("引擎已就绪")
# 输入框
imgui.separator()
submit, new_command = imgui.input_text(
">",
self.console_command_input,
flags=imgui.InputTextFlags_.enter_returns_true.value,
)
if new_command != self.console_command_input:
self.console_command_input = new_command
imgui.same_line()
execute_clicked = imgui.button("执行")
if (submit or execute_clicked) and self.console_command_input.strip():
command = self.console_command_input.strip()
self.add_info_message(f"执行命令: {command}")
self.console_command_input = ""
# TODO: 实现命令执行逻辑
imgui.separator()
# 视角控制信息
imgui.text("视角控制:")
imgui.text(" WASD - 移动")
imgui.text(" Q/E - 上下")
imgui.text(" 右键拖拽 - 旋转视角")
imgui.text(" 滚轮 - 前进/后退")
# 相机位置信息
cam_pos = self.camera.getPos()
cam_hpr = self.camera.getHpr()
imgui.text(f"位置: X={cam_pos.x:.1f}, Y={cam_pos.y:.1f}, Z={cam_pos.z:.1f}")
imgui.text(f"旋转: H={cam_hpr.x:.1f}, P={cam_hpr.y:.1f}, R={cam_hpr.z:.1f}")
# 控制状态
imgui.checkbox("启用视角控制", self.camera_control_enabled)
# 重置按钮
if imgui.button("重置相机"):
self.camera.setPos(0, -20, 5)
self.camera.setHpr(0, 0, 0)
self.add_info_message("相机位置已重置")
def _draw_script_panel(self):
"""绘制脚本管理面板。"""
# 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("脚本管理", self.app.showScriptPanel, flags) as (_, opened):
if not opened:
self.app.showScriptPanel = False
self.app._script_panel_window_rect = None
return
self.app.showScriptPanel = opened
window_pos = imgui.get_window_pos()
window_size = imgui.get_window_size()
self.app._script_panel_window_rect = (
float(window_pos.x),
float(window_pos.y),
float(window_size.x),
float(window_size.y),
)
# 1. 脚本系统状态组
self._draw_script_status_group()
imgui.spacing()
# 2. 创建脚本组
self._draw_create_script_group()
imgui.spacing()
# 3. 可用脚本组
self._draw_available_scripts_group()
imgui.spacing()
# 4. 脚本挂载组
self._draw_script_mounting_group()
def _draw_script_status_group(self):
"""绘制脚本系统状态组"""
if imgui.collapsing_header("脚本系统状态", imgui.TreeNodeFlags_.default_open):
# 脚本系统状态
imgui.text("脚本引擎状态:")
imgui.same_line()
# 检查脚本管理器是否正常工作
if hasattr(self, 'script_manager') and self.script_manager:
if hasattr(self.script_manager, 'engine') and self.script_manager.engine:
imgui.text_colored((0.0, 1.0, 0.0, 1.0), "✓ 已启动")
else:
imgui.text_colored((1.0, 0.5, 0.0, 1.0), "⚠ 引擎未初始化")
else:
imgui.text_colored((1.0, 0.0, 0.0, 1.0), "✗ 未启动")
# 热重载状态
imgui.text("热重载状态:")
imgui.same_line()
hot_reload_enabled = False
if hasattr(self, 'script_manager') and self.script_manager:
hot_reload_enabled = getattr(self.script_manager, 'hot_reload_enabled', False)
if hot_reload_enabled:
imgui.text_colored((0.0, 1.0, 0.0, 1.0), "✓ 已启用")
else:
imgui.text_colored((1.0, 0.5, 0.0, 1.0), "✗ 已禁用")
imgui.same_line()
if imgui.button("切换热重载##toggle_hot_reload"):
self._toggle_hot_reload()
def _draw_create_script_group(self):
"""绘制创建脚本组"""
if imgui.collapsing_header("创建脚本"):
# 脚本名称输入
imgui.text("脚本名称:")
imgui.same_line()
# 获取当前脚本名称
if not hasattr(self, '_new_script_name'):
self._new_script_name = "new_script"
changed, new_name = imgui.input_text("##script_name", self._new_script_name, 256)
if changed:
self._new_script_name = new_name
# 模板选择
imgui.text("脚本模板:")
imgui.same_line()
if not hasattr(self, '_selected_template'):
self._selected_template = 0
templates = ["基础脚本", "移动脚本", "旋转脚本", "缩放脚本", "动画脚本"]
changed, selected = imgui.combo("##script_template", self._selected_template, templates)
if changed:
self._selected_template = selected
# 创建按钮
if imgui.button("创建脚本##create_script"):
self._create_new_script()
imgui.same_line()
if imgui.button("从文件创建##create_from_file"):
self._on_create_script()
def _draw_available_scripts_group(self):
"""绘制可用脚本组"""
if imgui.collapsing_header("可用脚本"):
# 刷新脚本列表
if imgui.button("刷新列表##refresh_scripts"):
self._refresh_scripts_list()
imgui.same_line()
if imgui.button("重载全部##reload_all_scripts"):
self._reload_all_scripts()
imgui.separator()
# 获取可用脚本列表
available_scripts = []
if hasattr(self, 'script_manager') and self.script_manager:
try:
available_scripts = self.script_manager.get_available_scripts()
except Exception as e:
print(f"获取脚本列表失败: {e}")
# 显示脚本列表
if available_scripts:
for i, script_name in enumerate(available_scripts):
selected, _ = imgui.selectable(f"{script_name}##script_{i}", False)
if selected:
self._on_script_selected(script_name)
# 双击编辑
if imgui.is_item_hovered() and imgui.is_mouse_double_clicked(0):
self._edit_script(script_name)
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "无可用脚本")
def _draw_script_mounting_group(self):
"""绘制脚本挂载组"""
if imgui.collapsing_header("脚本挂载"):
# 与挂载/卸载操作保持一致:统一使用脚本实际挂载目标节点。
selected_node = self._get_script_target_node() if hasattr(self, "_get_script_target_node") else self._get_selection_node()
if (not selected_node) or selected_node.isEmpty():
selected_node = self._get_selection_source_node()
if selected_node and not selected_node.isEmpty():
imgui.text("选中对象:")
imgui.same_line()
imgui.text_colored((0.0, 1.0, 0.0, 1.0), selected_node.getName() or "未命名对象")
imgui.spacing()
# 脚本选择和挂载
imgui.text("选择脚本:")
imgui.same_line()
# 获取可用脚本
available_scripts = []
if hasattr(self, 'script_manager') and self.script_manager:
try:
available_scripts = self.script_manager.get_available_scripts()
except Exception as e:
print(f"获取脚本列表失败: {e}")
if available_scripts:
if not hasattr(self, '_mount_script_index'):
self._mount_script_index = 0
changed, selected = imgui.combo("##mount_script", self._mount_script_index, available_scripts)
if changed:
self._mount_script_index = selected
imgui.same_line()
if imgui.button("挂载##mount_script"):
if self._mount_script_index < len(available_scripts):
script_name = available_scripts[self._mount_script_index]
self._mount_script_to_selected(script_name)
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "无可用脚本")
imgui.spacing()
# 显示已挂载的脚本
imgui.text("已挂载脚本:")
mounted_scripts = []
if hasattr(self, 'script_manager') and self.script_manager:
try:
mounted_scripts = self.script_manager.get_scripts_on_object(selected_node)
except Exception as e:
print(f"获取已挂载脚本失败: {e}")
if mounted_scripts:
for i, script_component in enumerate(mounted_scripts):
# 从ScriptComponent获取脚本名称
script_name = getattr(script_component, 'script_name', None)
if not script_name and hasattr(script_component, '__class__'):
script_name = script_component.__class__.__name__
if not script_name:
script_name = f"Script_{i}"
imgui.text(f"{script_name}")
imgui.same_line()
if imgui.button(f"卸载##unmount_{i}"):
self._unmount_script_from_selected(script_name)
imgui.same_line()
if imgui.button(f"编辑##edit_mounted_{i}"):
self._edit_script(script_name)
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "无挂载脚本")
else:
imgui.text_colored((0.7, 0.7, 0.7, 1.0), "请先选择一个对象")