This commit is contained in:
Rowland 2026-01-23 16:39:51 +08:00
parent fbf71fd6a2
commit 99d4979af8
2 changed files with 1226 additions and 881 deletions

File diff suppressed because it is too large Load Diff

390
demo.py
View File

@ -257,6 +257,12 @@ class MyWorld(CoreWorld):
self.showToolbar = True
self.showResourceManager = True
# 脚本系统状态变量
self.hotReloadEnabled = True
self._new_script_name = "new_script"
self._selected_template = 0
self._mount_script_index = 0
# 变换监控相关
self._transform_monitoring = False
self._monitored_node = None
@ -4390,44 +4396,380 @@ class MyWorld(CoreWorld):
self.add_info_message("相机位置已重置")
def _draw_script_panel(self):
"""绘制脚本管理面板"""
"""绘制脚本管理面板与Qt版本功能一致"""
# 使用面板类型的窗口标志支持docking
flags = self.style_manager.get_window_flags("panel")
with self.style_manager.begin_styled_window("脚本管理", self.showScriptPanel, flags):
self.showScriptPanel = True # 确保窗口保持打开
imgui.text("脚本列表")
imgui.separator()
# 1. 脚本系统状态组
self._draw_script_status_group()
# 模拟脚本列表
selected, _ = imgui.selectable("main.py", False)
if selected:
print("选择脚本: main.py")
selected, _ = imgui.selectable("player_controller.py", False)
if selected:
print("选择脚本: player_controller.py")
selected, _ = imgui.selectable("ui_manager.py", False)
if selected:
print("选择脚本: ui_manager.py")
imgui.spacing()
imgui.separator()
# 2. 创建脚本组
self._draw_create_script_group()
# 脚本操作按钮
if imgui.button("新建脚本"):
print("新建脚本")
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 imgui.button("编辑"):
print("编辑脚本")
# 检查脚本管理器是否正常工作
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()
if imgui.button("重载"):
print("重载脚本")
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()
imgui.text("脚本输出:")
imgui.text("脚本引擎已启动")
imgui.text("热重载监控已启动")
# 获取可用脚本列表
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 = None
if hasattr(self, 'selection') and self.selection and hasattr(self.selection, 'selectedNode'):
selected_node = self.selection.selectedNode
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), "请先选择一个对象")
def _toggle_hot_reload(self):
"""切换热重载状态"""
if hasattr(self, 'script_manager') and self.script_manager:
try:
current_state = getattr(self.script_manager, 'hot_reload_enabled', False)
self.script_manager.hot_reload_enabled = not current_state
new_state = "启用" if not current_state else "禁用"
self.add_success_message(f"热重载已{new_state}")
print(f"[脚本系统] 热重载已{new_state}")
except Exception as e:
self.add_error_message(f"切换热重载失败: {str(e)}")
print(f"[脚本系统] 切换热重载失败: {e}")
def _create_new_script(self):
"""创建新脚本"""
if not hasattr(self, '_new_script_name') or not self._new_script_name.strip():
self.add_error_message("请输入脚本名称")
return
script_name = self._new_script_name.strip()
if not script_name.endswith('.py'):
script_name += '.py'
# 确定模板类型
template_map = {
0: "basic",
1: "movement",
2: "rotation",
3: "scale",
4: "animation"
}
template_type = template_map.get(getattr(self, '_selected_template', 0), "basic")
try:
if hasattr(self, 'script_manager') and self.script_manager:
result = self.script_manager.create_script_file(script_name, template_type)
if result:
self.add_success_message(f"脚本 {script_name} 创建成功")
print(f"[脚本系统] 创建脚本成功: {script_name}")
# 刷新脚本列表
self._refresh_scripts_list()
else:
self.add_error_message(f"脚本 {script_name} 创建失败")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"创建脚本失败: {str(e)}")
print(f"[脚本系统] 创建脚本失败: {e}")
def _refresh_scripts_list(self):
"""刷新脚本列表"""
try:
if hasattr(self, 'script_manager') and self.script_manager:
# 这里可以添加缓存逻辑,避免频繁刷新
available_scripts = self.script_manager.get_available_scripts()
print(f"[脚本系统] 刷新脚本列表: {len(available_scripts)} 个脚本")
self.add_success_message(f"脚本列表已刷新,共 {len(available_scripts)} 个脚本")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"刷新脚本列表失败: {str(e)}")
print(f"[脚本系统] 刷新脚本列表失败: {e}")
def _reload_all_scripts(self):
"""重载所有脚本"""
try:
if hasattr(self, 'script_manager') and self.script_manager:
# 获取所有可用脚本并逐个重载
available_scripts = self.script_manager.get_available_scripts()
success_count = 0
for script_name in available_scripts:
if self.script_manager.reload_script(script_name):
success_count += 1
self.add_success_message(f"重载完成: {success_count}/{len(available_scripts)} 个脚本成功")
print(f"[脚本系统] 重载脚本: {success_count}/{len(available_scripts)} 成功")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"重载脚本失败: {str(e)}")
print(f"[脚本系统] 重载脚本失败: {e}")
def _on_script_selected(self, script_name):
"""处理脚本选择事件"""
print(f"[脚本系统] 选择脚本: {script_name}")
self.add_info_message(f"已选择脚本: {script_name}")
def _edit_script(self, script_name):
"""编辑脚本"""
try:
if hasattr(self, 'script_manager') and self.script_manager:
# 获取脚本信息
script_info = self.script_manager.get_script_info(script_name)
if script_info and script_info.get("file"):
script_path = script_info["file"]
# 打开系统默认编辑器
import subprocess
import platform
system = platform.system()
try:
if system == "Windows":
subprocess.run(['notepad', script_path])
elif system == "Darwin": # macOS
subprocess.run(['open', script_path])
else: # Linux
subprocess.run(['xdg-open', script_path])
self.add_success_message(f"已打开脚本编辑器: {script_name}")
print(f"[脚本系统] 编辑脚本: {script_path}")
except Exception as e:
self.add_error_message(f"打开编辑器失败: {str(e)}")
else:
self.add_error_message(f"找不到脚本文件: {script_name}")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"编辑脚本失败: {str(e)}")
print(f"[脚本系统] 编辑脚本失败: {e}")
def _mount_script_to_selected(self, script_name):
"""挂载脚本到选中对象"""
selected_node = None
if hasattr(self, 'selection') and self.selection and hasattr(self.selection, 'selectedNode'):
selected_node = self.selection.selectedNode
if not selected_node or selected_node.isEmpty():
self.add_error_message("请先选择一个对象")
return
try:
if hasattr(self, 'script_manager') and self.script_manager:
script_component = self.script_manager.add_script_to_object(selected_node, script_name)
if script_component:
self.add_success_message(f"脚本 {script_name} 已挂载到 {selected_node.getName()}")
print(f"[脚本系统] 挂载脚本: {script_name} -> {selected_node.getName()}")
else:
self.add_error_message(f"挂载脚本 {script_name} 失败")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"挂载脚本失败: {str(e)}")
print(f"[脚本系统] 挂载脚本失败: {e}")
def _unmount_script_from_selected(self, script_name):
"""从选中对象卸载脚本"""
selected_node = None
if hasattr(self, 'selection') and self.selection and hasattr(self.selection, 'selectedNode'):
selected_node = self.selection.selectedNode
if not selected_node or selected_node.isEmpty():
self.add_error_message("请先选择一个对象")
return
try:
if hasattr(self, 'script_manager') and self.script_manager:
result = self.script_manager.remove_script_from_object(selected_node, script_name)
if result:
self.add_success_message(f"脚本 {script_name} 已从 {selected_node.getName()} 卸载")
print(f"[脚本系统] 卸载脚本: {script_name} <- {selected_node.getName()}")
else:
self.add_error_message(f"卸载脚本 {script_name} 失败")
else:
self.add_error_message("脚本管理器未初始化")
except Exception as e:
self.add_error_message(f"卸载脚本失败: {str(e)}")
print(f"[脚本系统] 卸载脚本失败: {e}")
# ==================== 菜单处理函数 ====================