316 lines
13 KiB
Python
316 lines
13 KiB
Python
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
|
||
return
|
||
|
||
self.app.showConsole = opened
|
||
|
||
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
|
||
return
|
||
|
||
self.app.showScriptPanel = opened
|
||
|
||
# 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_selection_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), "请先选择一个对象")
|