687 lines
29 KiB
Python
687 lines
29 KiB
Python
"""
|
|
主窗口设置模块
|
|
|
|
负责主窗口的界面构建和事件绑定:
|
|
- 菜单栏、工具栏创建
|
|
- 停靠窗口设置
|
|
- 事件连接和信号处理
|
|
"""
|
|
|
|
import sys
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction,
|
|
QDockWidget, QTreeWidget, QListWidget, QWidget, QVBoxLayout, QTreeWidgetItem,
|
|
QLabel, QLineEdit, QFormLayout, QDoubleSpinBox, QScrollArea,
|
|
QFileSystemModel, QButtonGroup, QToolButton, QPushButton, QHBoxLayout,
|
|
QComboBox, QGroupBox, QInputDialog, QFileDialog, QMessageBox, QDesktopWidget)
|
|
from PyQt5.QtCore import Qt, QDir, QTimer
|
|
from ui.widgets import CustomPanda3DWidget, CustomFileView, CustomTreeWidget
|
|
|
|
class MainWindow(QMainWindow):
|
|
"""主窗口类"""
|
|
|
|
def __init__(self, world):
|
|
super().__init__()
|
|
self.world = world
|
|
self.setupCenterWidget() # 创建中间部分Panda3D
|
|
self.setupMenus() # 创建菜单栏
|
|
self.setupDockWindows()
|
|
self.setupToolbar()
|
|
self.connectEvents()
|
|
|
|
# 移动窗口到屏幕中央
|
|
self.move_center()
|
|
|
|
# 创建定时器来更新脚本管理面板状态
|
|
self.updateTimer = QTimer()
|
|
self.updateTimer.timeout.connect(self.updateScriptPanel)
|
|
self.updateTimer.start(500) # 每500毫秒更新一次
|
|
|
|
def setupCenterWidget(self):
|
|
"""设置窗口基本属性"""
|
|
self.setWindowTitle("引擎编辑器")
|
|
|
|
# 使用自定义的 Panda3D 部件作为中央部件
|
|
self.pandaWidget = CustomPanda3DWidget(self.world)
|
|
self.setCentralWidget(self.pandaWidget)
|
|
|
|
def move_center(self):
|
|
"""设置窗口居中显示"""
|
|
self.setGeometry(50, 50, 1920, 1080)
|
|
|
|
screen = QDesktopWidget().screenGeometry()
|
|
self.move(
|
|
int(screen.width() / 2 - self.width() / 2),
|
|
int(screen.height() / 2 - self.height() / 2),
|
|
)
|
|
|
|
def setupMenus(self):
|
|
"""创建菜单栏"""
|
|
menubar = self.menuBar()
|
|
|
|
# 文件菜单
|
|
self.fileMenu = menubar.addMenu('文件')
|
|
self.newAction = self.fileMenu.addAction('新建')
|
|
self.openAction = self.fileMenu.addAction('打开')
|
|
self.saveAction = self.fileMenu.addAction('保存')
|
|
self.buildAction = self.fileMenu.addAction('打包')
|
|
self.fileMenu.addSeparator()
|
|
self.exitAction = self.fileMenu.addAction('退出')
|
|
|
|
# 编辑菜单
|
|
self.editMenu = menubar.addMenu('编辑')
|
|
self.undoAction = self.editMenu.addAction('撤销')
|
|
self.redoAction = self.editMenu.addAction('重做')
|
|
self.editMenu.addSeparator()
|
|
self.cutAction = self.editMenu.addAction('剪切')
|
|
self.copyAction = self.editMenu.addAction('复制')
|
|
self.pasteAction = self.editMenu.addAction('粘贴')
|
|
|
|
# 视图菜单
|
|
self.viewMenu = menubar.addMenu('视图')
|
|
self.viewPerspectiveAction = self.viewMenu.addAction('透视图')
|
|
self.viewTopAction = self.viewMenu.addAction('俯视图')
|
|
self.viewFrontAction = self.viewMenu.addAction('前视图')
|
|
self.viewMenu.addSeparator()
|
|
self.viewGridAction = self.viewMenu.addAction('显示网格')
|
|
|
|
# 工具菜单
|
|
self.toolsMenu = menubar.addMenu('工具')
|
|
self.selectAction = self.toolsMenu.addAction('选择工具')
|
|
self.moveAction = self.toolsMenu.addAction('移动工具')
|
|
self.rotateAction = self.toolsMenu.addAction('旋转工具')
|
|
self.scaleAction = self.toolsMenu.addAction('缩放工具')
|
|
self.sunsetAction = self.toolsMenu.addAction('光照编辑')
|
|
self.pluginAction = self.toolsMenu.addAction('图形编辑')
|
|
|
|
# GUI菜单
|
|
self.guiMenu = menubar.addMenu('GUI')
|
|
self.guiEditModeAction = self.guiMenu.addAction('进入GUI编辑模式')
|
|
self.guiMenu.addSeparator()
|
|
self.createButtonAction = self.guiMenu.addAction('创建按钮')
|
|
self.createLabelAction = self.guiMenu.addAction('创建标签')
|
|
self.createEntryAction = self.guiMenu.addAction('创建输入框')
|
|
self.guiMenu.addSeparator()
|
|
self.create3DTextAction = self.guiMenu.addAction('创建3D文本')
|
|
self.createVirtualScreenAction = self.guiMenu.addAction('创建虚拟屏幕')
|
|
|
|
# 脚本菜单
|
|
self.scriptMenu = menubar.addMenu('脚本')
|
|
self.createScriptAction = self.scriptMenu.addAction('创建脚本...')
|
|
self.loadScriptAction = self.scriptMenu.addAction('加载脚本文件...')
|
|
self.loadAllScriptsAction = self.scriptMenu.addAction('重载所有脚本')
|
|
self.scriptMenu.addSeparator()
|
|
self.toggleHotReloadAction = self.scriptMenu.addAction('启用热重载')
|
|
self.toggleHotReloadAction.setCheckable(True)
|
|
self.toggleHotReloadAction.setChecked(True) # 默认启用
|
|
self.scriptMenu.addSeparator()
|
|
self.openScriptsManagerAction = self.scriptMenu.addAction('脚本管理器')
|
|
|
|
# 帮助菜单
|
|
self.helpMenu = menubar.addMenu('帮助')
|
|
self.aboutAction = self.helpMenu.addAction('关于')
|
|
|
|
def setupDockWindows(self):
|
|
"""创建停靠窗口"""
|
|
# 创建左侧停靠窗口(层级窗口)
|
|
self.leftDock = QDockWidget("层级", self)
|
|
self.leftDock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
|
|
self.treeWidget = CustomTreeWidget(self.world)
|
|
self.world.setTreeWidget(self.treeWidget) # 设置树形控件引用
|
|
self.leftDock.setWidget(self.treeWidget)
|
|
# self.leftDock.setMinimumWidth(300)
|
|
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.leftDock)
|
|
|
|
# 创建右侧停靠窗口(属性窗口)
|
|
self.rightDock = QDockWidget("属性", self)
|
|
self.rightDock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
|
|
|
|
# 创建属性面板的主容器和布局
|
|
self.propertyContainer = QWidget()
|
|
self.propertyContainer.setObjectName("PropertyContainer")
|
|
self.propertyLayout = QVBoxLayout(self.propertyContainer)
|
|
# self.propertyLayout = QFormLayout(self.propertyContainer)
|
|
|
|
# 添加初始提示信息
|
|
tipLabel = QLabel("")
|
|
tipLabel.setStyleSheet("color: gray;") # 使用灰色字体
|
|
# self.propertyLayout.addRow(tipLabel)
|
|
self.propertyLayout.addWidget(tipLabel)
|
|
|
|
# 创建滚动区域并设置属性
|
|
self.scrollArea = QScrollArea()
|
|
self.scrollArea.setWidgetResizable(True)
|
|
self.scrollArea.setWidget(self.propertyContainer)
|
|
|
|
# 设置滚动区域为停靠窗口的主部件
|
|
self.rightDock.setWidget(self.scrollArea)
|
|
self.rightDock.setMinimumWidth(300)
|
|
self.addDockWidget(Qt.RightDockWidgetArea, self.rightDock)
|
|
|
|
# 设置属性面板到世界对象
|
|
self.world.setPropertyLayout(self.propertyLayout)
|
|
|
|
|
|
# 创建脚本管理停靠窗口
|
|
self.scriptDock = QDockWidget("脚本管理", self)
|
|
self.scriptDock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
|
|
self.setupScriptPanel()
|
|
self.addDockWidget(Qt.RightDockWidgetArea, self.scriptDock)
|
|
|
|
# 将右侧停靠窗口设为标签形式
|
|
self.tabifyDockWidget(self.rightDock, self.scriptDock)
|
|
|
|
# 创建底部停靠窗口(资源窗口)
|
|
self.bottomDock = QDockWidget("资源", self)
|
|
self.bottomDock.setAllowedAreas(Qt.BottomDockWidgetArea)
|
|
|
|
# 创建文件系统模型
|
|
self.fileModel = QFileSystemModel()
|
|
self.fileModel.setRootPath(QDir.homePath()) # 设置为用户主目录
|
|
|
|
# 创建树形视图显示文件系统
|
|
self.fileView = CustomFileView(self.world)
|
|
self.fileView.setModel(self.fileModel)
|
|
self.fileView.setRootIndex(self.fileModel.index(QDir.homePath())) # 设置为用户主目录索引
|
|
|
|
# 设置列宽
|
|
self.fileView.setColumnWidth(0, 250) # 名称列
|
|
self.fileView.setColumnWidth(1, 100) # 大小列
|
|
self.fileView.setColumnWidth(2, 100) # 类型列
|
|
self.fileView.setColumnWidth(3, 150) # 修改日期列
|
|
|
|
# 设置视图属性
|
|
self.fileView.setMinimumHeight(200) # 设置最小高度
|
|
|
|
self.bottomDock.setWidget(self.fileView)
|
|
self.addDockWidget(Qt.BottomDockWidgetArea, self.bottomDock)
|
|
|
|
def setupToolbar(self):
|
|
"""创建工具栏"""
|
|
self.toolbar = self.addToolBar('工具栏')
|
|
|
|
# 创建工具按钮组
|
|
self.toolGroup = QButtonGroup()
|
|
|
|
# 选择工具
|
|
self.selectTool = QToolButton()
|
|
self.selectTool.setText("选择")
|
|
self.selectTool.setCheckable(True)
|
|
self.toolGroup.addButton(self.selectTool)
|
|
self.toolbar.addWidget(self.selectTool)
|
|
|
|
# 旋转工具
|
|
self.rotateTool = QToolButton()
|
|
self.rotateTool.setText("旋转")
|
|
self.rotateTool.setCheckable(True)
|
|
self.toolGroup.addButton(self.rotateTool)
|
|
self.toolbar.addWidget(self.rotateTool)
|
|
|
|
# 缩放工具
|
|
self.scaleTool = QToolButton()
|
|
self.scaleTool.setText("缩放")
|
|
self.scaleTool.setCheckable(True)
|
|
self.toolGroup.addButton(self.scaleTool)
|
|
self.toolbar.addWidget(self.scaleTool)
|
|
|
|
# 添加分隔符
|
|
self.toolbar.addSeparator()
|
|
|
|
# GUI创建工具
|
|
self.createButtonTool = QToolButton()
|
|
self.createButtonTool.setText("创建按钮")
|
|
self.toolbar.addWidget(self.createButtonTool)
|
|
|
|
self.createLabelTool = QToolButton()
|
|
self.createLabelTool.setText("创建标签")
|
|
self.toolbar.addWidget(self.createLabelTool)
|
|
|
|
self.create3DTextTool = QToolButton()
|
|
self.create3DTextTool.setText("3D文本")
|
|
self.toolbar.addWidget(self.create3DTextTool)
|
|
|
|
self.createSpotLight = QToolButton()
|
|
self.createSpotLight.setText("聚光灯")
|
|
self.toolbar.addWidget(self.createSpotLight)
|
|
|
|
self.createPointLight = QToolButton()
|
|
self.createPointLight.setText("点光灯")
|
|
self.toolbar.addWidget(self.createPointLight)
|
|
|
|
# 默认选择"选择"工具
|
|
self.selectTool.setChecked(True)
|
|
self.world.setCurrentTool("选择")
|
|
|
|
def setupScriptPanel(self):
|
|
"""创建脚本管理面板"""
|
|
# 创建主容器
|
|
scriptContainer = QWidget()
|
|
layout = QVBoxLayout(scriptContainer)
|
|
|
|
# 脚本状态组
|
|
statusGroup = QGroupBox("脚本系统状态")
|
|
statusLayout = QVBoxLayout()
|
|
|
|
self.scriptStatusLabel = QLabel("脚本系统: 已启动")
|
|
self.scriptStatusLabel.setStyleSheet("color: green; font-weight: bold;")
|
|
statusLayout.addWidget(self.scriptStatusLabel)
|
|
|
|
self.hotReloadLabel = QLabel("热重载: 已启用")
|
|
self.hotReloadLabel.setStyleSheet("color: blue;")
|
|
statusLayout.addWidget(self.hotReloadLabel)
|
|
|
|
statusGroup.setLayout(statusLayout)
|
|
layout.addWidget(statusGroup)
|
|
|
|
# 脚本创建组
|
|
createGroup = QGroupBox("创建脚本")
|
|
createLayout = QVBoxLayout()
|
|
|
|
# 脚本名称输入
|
|
nameLayout = QHBoxLayout()
|
|
nameLayout.addWidget(QLabel("脚本名称:"))
|
|
self.scriptNameEdit = QLineEdit()
|
|
self.scriptNameEdit.setPlaceholderText("输入脚本名称...")
|
|
nameLayout.addWidget(self.scriptNameEdit)
|
|
createLayout.addLayout(nameLayout)
|
|
|
|
# 模板选择
|
|
templateLayout = QHBoxLayout()
|
|
templateLayout.addWidget(QLabel("模板:"))
|
|
self.templateCombo = QComboBox()
|
|
self.templateCombo.addItems(["basic", "movement", "animation"])
|
|
templateLayout.addWidget(self.templateCombo)
|
|
createLayout.addLayout(templateLayout)
|
|
|
|
# 创建按钮
|
|
self.createScriptBtn = QPushButton("创建脚本")
|
|
self.createScriptBtn.clicked.connect(self.onCreateScript)
|
|
createLayout.addWidget(self.createScriptBtn)
|
|
|
|
createGroup.setLayout(createLayout)
|
|
layout.addWidget(createGroup)
|
|
|
|
# 可用脚本组
|
|
scriptsGroup = QGroupBox("可用脚本")
|
|
scriptsLayout = QVBoxLayout()
|
|
|
|
# 脚本列表
|
|
self.scriptsList = QListWidget()
|
|
self.scriptsList.itemDoubleClicked.connect(self.onScriptDoubleClick)
|
|
scriptsLayout.addWidget(self.scriptsList)
|
|
|
|
# 脚本操作按钮
|
|
scriptButtonsLayout = QHBoxLayout()
|
|
|
|
self.loadScriptBtn = QPushButton("加载脚本")
|
|
self.loadScriptBtn.clicked.connect(self.onLoadScript)
|
|
scriptButtonsLayout.addWidget(self.loadScriptBtn)
|
|
|
|
self.reloadAllBtn = QPushButton("重载全部")
|
|
self.reloadAllBtn.clicked.connect(self.onReloadAllScripts)
|
|
scriptButtonsLayout.addWidget(self.reloadAllBtn)
|
|
|
|
scriptsLayout.addLayout(scriptButtonsLayout)
|
|
scriptsGroup.setLayout(scriptsLayout)
|
|
layout.addWidget(scriptsGroup)
|
|
|
|
# 脚本挂载组
|
|
mountGroup = QGroupBox("脚本挂载")
|
|
mountLayout = QVBoxLayout()
|
|
|
|
# 当前选中对象显示
|
|
self.selectedObjectLabel = QLabel("未选择对象")
|
|
self.selectedObjectLabel.setStyleSheet("color: gray; font-style: italic;")
|
|
mountLayout.addWidget(self.selectedObjectLabel)
|
|
|
|
# 脚本选择和挂载
|
|
mountControlLayout = QHBoxLayout()
|
|
|
|
self.mountScriptCombo = QComboBox()
|
|
self.mountScriptCombo.setEnabled(False)
|
|
mountControlLayout.addWidget(self.mountScriptCombo)
|
|
|
|
self.mountBtn = QPushButton("挂载")
|
|
self.mountBtn.setEnabled(False)
|
|
self.mountBtn.clicked.connect(self.onMountScript)
|
|
mountControlLayout.addWidget(self.mountBtn)
|
|
|
|
mountLayout.addLayout(mountControlLayout)
|
|
|
|
# 已挂载脚本列表
|
|
self.mountedScriptsList = QListWidget()
|
|
self.mountedScriptsList.setMaximumHeight(100)
|
|
mountLayout.addWidget(QLabel("已挂载脚本:"))
|
|
mountLayout.addWidget(self.mountedScriptsList)
|
|
|
|
# 卸载按钮
|
|
self.unmountBtn = QPushButton("卸载选中脚本")
|
|
self.unmountBtn.clicked.connect(self.onUnmountScript)
|
|
mountLayout.addWidget(self.unmountBtn)
|
|
|
|
mountGroup.setLayout(mountLayout)
|
|
layout.addWidget(mountGroup)
|
|
|
|
# 添加拉伸以填充剩余空间
|
|
layout.addStretch()
|
|
|
|
# 设置到停靠窗口
|
|
self.scriptDock.setWidget(scriptContainer)
|
|
|
|
# 初始化脚本列表
|
|
self.refreshScriptsList()
|
|
|
|
def connectEvents(self):
|
|
"""连接事件信号"""
|
|
# 导入项目管理功能函数
|
|
from main import createNewProject, saveProject, openProject, buildPackage
|
|
|
|
# 连接文件菜单事件
|
|
self.newAction.triggered.connect(lambda: createNewProject(self))
|
|
self.openAction.triggered.connect(lambda: openProject(self))
|
|
self.saveAction.triggered.connect(lambda: saveProject(self))
|
|
self.buildAction.triggered.connect(lambda: buildPackage(self))
|
|
self.exitAction.triggered.connect(QApplication.instance().quit)
|
|
|
|
#连接工具事件
|
|
self.sunsetAction.triggered.connect(lambda : self.world.setCurrentTool("光照编辑"))
|
|
self.pluginAction.triggered.connect(lambda : self.world.setCurrentTool("图形编辑"))
|
|
|
|
# 连接GUI编辑模式事件
|
|
self.guiEditModeAction.triggered.connect(lambda: self.world.toggleGUIEditMode())
|
|
|
|
# 连接GUI创建按钮事件
|
|
self.createButtonAction.triggered.connect(lambda: self.world.createGUIButton())
|
|
self.createLabelAction.triggered.connect(lambda: self.world.createGUILabel())
|
|
self.createEntryAction.triggered.connect(lambda: self.world.createGUIEntry())
|
|
self.create3DTextAction.triggered.connect(lambda: self.world.createGUI3DText())
|
|
#self.createSpotLightAction.triggered.connect(lambda :self.world.createSpotLight())
|
|
self.createVirtualScreenAction.triggered.connect(lambda: self.world.createGUIVirtualScreen())
|
|
|
|
# 连接工具栏GUI创建按钮事件
|
|
self.createButtonTool.clicked.connect(lambda: self.world.createGUIButton())
|
|
self.createLabelTool.clicked.connect(lambda: self.world.createGUILabel())
|
|
self.create3DTextTool.clicked.connect(lambda: self.world.createGUI3DText())
|
|
self.createSpotLight.clicked.connect(lambda :self.world.createSpotLight())
|
|
self.createPointLight.clicked.connect(lambda :self.world.createPointLight())
|
|
|
|
# 连接树节点点击信号
|
|
# self.treeWidget.itemClicked.connect(self.world.onTreeItemClicked)
|
|
self.treeWidget.itemSelectionChanged.connect(lambda :self.world.onTreeItemClicked(self.treeWidget.currentItem(), 0))
|
|
print("已连接点击信号")
|
|
|
|
# 连接工具切换信号
|
|
self.toolGroup.buttonClicked.connect(self.onToolChanged)
|
|
|
|
# 连接脚本菜单事件
|
|
self.createScriptAction.triggered.connect(self.onCreateScriptDialog)
|
|
self.loadScriptAction.triggered.connect(self.onLoadScriptFile)
|
|
self.loadAllScriptsAction.triggered.connect(self.onReloadAllScripts)
|
|
self.toggleHotReloadAction.triggered.connect(self.onToggleHotReload)
|
|
self.openScriptsManagerAction.triggered.connect(self.onOpenScriptsManager)
|
|
|
|
def onToolChanged(self, button):
|
|
"""工具切换事件处理"""
|
|
if button.isChecked():
|
|
tool_name = button.text()
|
|
self.world.setCurrentTool(tool_name)
|
|
print(f"工具栏: 选择了 {tool_name} 工具")
|
|
else:
|
|
self.world.setCurrentTool(None)
|
|
print("工具栏: 取消选择工具")
|
|
|
|
# ==================== 脚本管理事件处理 ====================
|
|
|
|
def refreshScriptsList(self):
|
|
"""刷新脚本列表"""
|
|
self.scriptsList.clear()
|
|
self.mountScriptCombo.clear()
|
|
|
|
available_scripts = self.world.getAvailableScripts()
|
|
for script_name in available_scripts:
|
|
self.scriptsList.addItem(script_name)
|
|
self.mountScriptCombo.addItem(script_name)
|
|
|
|
def updateScriptPanel(self):
|
|
"""更新脚本面板状态"""
|
|
# 更新热重载状态
|
|
hot_reload_enabled = self.world.script_manager.hot_reload_enabled
|
|
self.hotReloadLabel.setText(f"热重载: {'已启用' if hot_reload_enabled else '已禁用'}")
|
|
self.hotReloadLabel.setStyleSheet(f"color: {'blue' if hot_reload_enabled else 'gray'};")
|
|
|
|
# 更新热重载菜单状态
|
|
self.toggleHotReloadAction.setChecked(hot_reload_enabled)
|
|
|
|
# 更新选中对象信息
|
|
selected_object = getattr(self.world.selection, 'selectedObject', None)
|
|
if selected_object:
|
|
self.selectedObjectLabel.setText(f"选中对象: {selected_object.getName()}")
|
|
self.selectedObjectLabel.setStyleSheet("color: green; font-weight: bold;")
|
|
self.mountScriptCombo.setEnabled(True)
|
|
self.mountBtn.setEnabled(True)
|
|
|
|
# 更新已挂载脚本列表
|
|
self.updateMountedScriptsList(selected_object)
|
|
else:
|
|
self.selectedObjectLabel.setText("未选择对象")
|
|
self.selectedObjectLabel.setStyleSheet("color: gray; font-style: italic;")
|
|
self.mountScriptCombo.setEnabled(False)
|
|
self.mountBtn.setEnabled(False)
|
|
self.mountedScriptsList.clear()
|
|
|
|
def updateMountedScriptsList(self, game_object):
|
|
"""更新已挂载脚本列表"""
|
|
# 保存当前选中项的脚本名(去除状态前缀)
|
|
current_item = self.mountedScriptsList.currentItem()
|
|
selected_script_name = None
|
|
if current_item:
|
|
# 提取脚本名(移除 "✓ " 或 "✗ " 前缀)
|
|
selected_script_name = current_item.text()[2:]
|
|
|
|
# 清空并重新填充列表
|
|
self.mountedScriptsList.clear()
|
|
scripts = self.world.getScripts(game_object)
|
|
for script_component in scripts:
|
|
script_name = script_component.script_name
|
|
enabled = "✓" if script_component.enabled else "✗"
|
|
item_text = f"{enabled} {script_name}"
|
|
self.mountedScriptsList.addItem(item_text)
|
|
|
|
# 恢复选中状态(根据脚本名匹配)
|
|
if selected_script_name:
|
|
for i in range(self.mountedScriptsList.count()):
|
|
item = self.mountedScriptsList.item(i)
|
|
# 提取当前项的脚本名进行比较
|
|
current_script_name = item.text()[2:]
|
|
if current_script_name == selected_script_name:
|
|
self.mountedScriptsList.setCurrentItem(item)
|
|
break
|
|
|
|
def onCreateScript(self):
|
|
"""创建脚本按钮事件"""
|
|
script_name = self.scriptNameEdit.text().strip()
|
|
if not script_name:
|
|
QMessageBox.warning(self, "错误", "请输入脚本名称!")
|
|
return
|
|
|
|
template = self.templateCombo.currentText()
|
|
|
|
try:
|
|
success = self.world.createScript(script_name, template)
|
|
if success:
|
|
QMessageBox.information(self, "成功", f"脚本 '{script_name}' 创建成功!")
|
|
self.scriptNameEdit.clear()
|
|
self.refreshScriptsList()
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"脚本 '{script_name}' 创建失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"创建脚本时出错: {str(e)}")
|
|
|
|
def onCreateScriptDialog(self):
|
|
"""菜单创建脚本事件"""
|
|
script_name, ok = QInputDialog.getText(self, "创建脚本", "输入脚本名称:")
|
|
if ok and script_name.strip():
|
|
try:
|
|
success = self.world.createScript(script_name.strip(), "basic")
|
|
if success:
|
|
QMessageBox.information(self, "成功", f"脚本 '{script_name}' 创建成功!")
|
|
self.refreshScriptsList()
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"脚本 '{script_name}' 创建失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"创建脚本时出错: {str(e)}")
|
|
|
|
def onLoadScript(self):
|
|
"""加载脚本按钮事件"""
|
|
current_item = self.scriptsList.currentItem()
|
|
if not current_item:
|
|
QMessageBox.warning(self, "错误", "请选择要加载的脚本!")
|
|
return
|
|
|
|
script_name = current_item.text()
|
|
try:
|
|
success = self.world.reloadScript(script_name)
|
|
if success:
|
|
QMessageBox.information(self, "成功", f"脚本 '{script_name}' 重载成功!")
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"脚本 '{script_name}' 重载失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"重载脚本时出错: {str(e)}")
|
|
|
|
def onLoadScriptFile(self):
|
|
"""加载脚本文件菜单事件"""
|
|
file_path, _ = QFileDialog.getOpenFileName(
|
|
self, "选择脚本文件", "", "Python文件 (*.py)"
|
|
)
|
|
if file_path:
|
|
try:
|
|
success = self.world.loadScript(file_path)
|
|
if success:
|
|
QMessageBox.information(self, "成功", "脚本文件加载成功!")
|
|
self.refreshScriptsList()
|
|
else:
|
|
QMessageBox.warning(self, "错误", "脚本文件加载失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"加载脚本文件时出错: {str(e)}")
|
|
|
|
def onReloadAllScripts(self):
|
|
"""重载所有脚本事件"""
|
|
try:
|
|
scripts_loaded = self.world.loadAllScripts()
|
|
QMessageBox.information(self, "成功", f"重载完成,共加载 {len(scripts_loaded)} 个脚本!")
|
|
self.refreshScriptsList()
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"重载脚本时出错: {str(e)}")
|
|
|
|
def onToggleHotReload(self):
|
|
"""切换热重载状态"""
|
|
enabled = self.toggleHotReloadAction.isChecked()
|
|
self.world.enableHotReload(enabled)
|
|
status = "启用" if enabled else "禁用"
|
|
QMessageBox.information(self, "热重载", f"热重载已{status}")
|
|
|
|
def onOpenScriptsManager(self):
|
|
"""打开脚本管理器"""
|
|
# 显示脚本管理停靠窗口
|
|
self.scriptDock.show()
|
|
self.scriptDock.raise_()
|
|
|
|
def onScriptDoubleClick(self, item):
|
|
"""脚本列表双击事件"""
|
|
# 可以在这里添加打开外部编辑器的功能
|
|
script_name = item.text()
|
|
QMessageBox.information(self, "提示", f"双击了脚本: {script_name}\n\n可以使用外部编辑器编辑脚本文件。")
|
|
|
|
def onMountScript(self):
|
|
"""挂载脚本事件"""
|
|
selected_object = getattr(self.world.selection, 'selectedObject', None)
|
|
if not selected_object:
|
|
QMessageBox.warning(self, "错误", "请先选择一个对象!")
|
|
return
|
|
|
|
script_name = self.mountScriptCombo.currentText()
|
|
if not script_name:
|
|
QMessageBox.warning(self, "错误", "请选择要挂载的脚本!")
|
|
return
|
|
|
|
try:
|
|
success = self.world.addScript(selected_object, script_name)
|
|
if success:
|
|
QMessageBox.information(self, "成功", f"脚本 '{script_name}' 已挂载到对象!")
|
|
self.updateMountedScriptsList(selected_object)
|
|
|
|
# 同时更新属性面板
|
|
if self.treeWidget and self.treeWidget.currentItem():
|
|
self.world.updatePropertyPanel(self.treeWidget.currentItem())
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"挂载脚本失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"挂载脚本时出错: {str(e)}")
|
|
|
|
def onUnmountScript(self):
|
|
"""卸载脚本事件"""
|
|
selected_object = getattr(self.world.selection, 'selectedObject', None)
|
|
if not selected_object:
|
|
QMessageBox.warning(self, "错误", "请先选择一个对象!")
|
|
return
|
|
|
|
current_item = self.mountedScriptsList.currentItem()
|
|
if not current_item:
|
|
QMessageBox.warning(self, "错误", "请选择要卸载的脚本!")
|
|
return
|
|
|
|
# 解析脚本名称(移除状态标记)
|
|
item_text = current_item.text()
|
|
script_name = item_text[2:] # 移除 "✓ " 或 "✗ " 前缀
|
|
|
|
try:
|
|
success = self.world.removeScript(selected_object, script_name)
|
|
if success:
|
|
QMessageBox.information(self, "成功", f"脚本 '{script_name}' 已从对象卸载!")
|
|
self.updateMountedScriptsList(selected_object)
|
|
|
|
# 同时更新属性面板
|
|
if self.treeWidget and self.treeWidget.currentItem():
|
|
self.world.updatePropertyPanel(self.treeWidget.currentItem())
|
|
else:
|
|
QMessageBox.warning(self, "错误", f"卸载脚本失败!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "错误", f"卸载脚本时出错: {str(e)}")
|
|
|
|
def closeEvent(self, event):
|
|
"""处理窗口关闭事件"""
|
|
try:
|
|
print("🔄 正在关闭应用程序...")
|
|
|
|
# 清理工具管理器中的进程
|
|
if hasattr(self.world, 'tool_manager') and self.world.tool_manager:
|
|
print("🧹 清理工具管理器进程...")
|
|
self.world.tool_manager.cleanup_processes()
|
|
|
|
# 停止更新定时器
|
|
if hasattr(self, 'updateTimer') and self.updateTimer:
|
|
self.updateTimer.stop()
|
|
print("⏹️ 更新定时器已停止")
|
|
|
|
# 清理Panda3D资源
|
|
if hasattr(self, 'pandaWidget') and self.pandaWidget:
|
|
print("🧹 清理Panda3D资源...")
|
|
self.pandaWidget.cleanup()
|
|
|
|
print("✅ 应用程序清理完成")
|
|
event.accept()
|
|
|
|
except Exception as e:
|
|
print(f"⚠️ 关闭应用程序时出错: {e}")
|
|
event.accept() # 即使出错也要关闭
|
|
|
|
|
|
def setup_main_window(world):
|
|
"""设置主窗口的便利函数"""
|
|
app = QApplication.instance()
|
|
if app is None:
|
|
app = QApplication(sys.argv)
|
|
|
|
main_window = MainWindow(world)
|
|
main_window.show()
|
|
|
|
return app, main_window |