512 lines
19 KiB
Python
512 lines
19 KiB
Python
import warnings
|
|
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
|
|
|
import sys
|
|
import builtins # 添加这一行
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QMenuBar, QMenu, QAction,
|
|
QDockWidget, QTreeWidget, QListWidget, QWidget, QVBoxLayout, QTreeWidgetItem,
|
|
QLabel, QLineEdit, QFormLayout, QDoubleSpinBox, QScrollArea, QTreeView, QInputDialog, QFileDialog, QMessageBox, QDialog, QGroupBox, QHBoxLayout, QPushButton, QDialogButtonBox)
|
|
from PyQt5.QtCore import Qt, QDir, QUrl
|
|
from PyQt5.QtGui import QDrag, QPainter, QPixmap
|
|
from PyQt5.QtWidgets import QFileSystemModel
|
|
from QPanda3D.QPanda3DWidget import QPanda3DWidget
|
|
from core.world import CoreWorld
|
|
from core.selection import SelectionSystem
|
|
from core.event_handler import EventHandler
|
|
from core.tool_manager import ToolManager
|
|
from core.script_system import ScriptManager
|
|
from gui.gui_manager import GUIManager
|
|
from scene.scene_manager import SceneManager
|
|
from project.project_manager import ProjectManager
|
|
from ui.widgets import CustomPanda3DWidget, CustomFileView, CustomTreeWidget
|
|
from ui.property_panel import PropertyPanelManager
|
|
from ui.interface_manager import InterfaceManager
|
|
from panda3d.core import (CardMaker, Vec4, Vec3, ColorAttrib, MaterialAttrib,
|
|
GeomNode, NodePath, Material, CollisionTraverser,
|
|
CollisionHandlerQueue, CollisionNode, CollisionRay,
|
|
Plane, Point3, Point2, BitMask32, CollisionSphere,
|
|
CollisionPlane, ModelPool, Filename, ModelRoot,
|
|
AmbientLight, DirectionalLight, TextureAttrib, DriveInterface, WindowProperties)
|
|
from panda3d.egg import EggData, EggVertexPool, EggPolygon
|
|
from direct.task import Task
|
|
from direct.task.TaskManagerGlobal import taskMgr
|
|
from direct.showbase.ShowBase import ShowBase
|
|
from direct.showbase.DirectObject import DirectObject
|
|
from direct.showbase.ShowBaseGlobal import globalClock
|
|
import os
|
|
import json
|
|
import datetime
|
|
from direct.actor.Actor import Actor
|
|
from PyQt5.sip import wrapinstance
|
|
|
|
class MyWorld(CoreWorld):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
# 初始化选择和变换系统
|
|
self.selection = SelectionSystem(self)
|
|
|
|
# 初始化事件处理系统
|
|
self.event_handler = EventHandler(self)
|
|
|
|
# 初始化工具管理系统
|
|
self.tool_manager = ToolManager(self)
|
|
|
|
# 初始化脚本管理系统
|
|
self.script_manager = ScriptManager(self)
|
|
|
|
# 初始化GUI管理系统
|
|
self.gui_manager = GUIManager(self)
|
|
|
|
# 初始化场景管理系统
|
|
self.scene_manager = SceneManager(self)
|
|
|
|
# 初始化项目管理系统
|
|
self.project_manager = ProjectManager(self)
|
|
|
|
# 初始化属性面板管理系统
|
|
self.property_panel = PropertyPanelManager(self)
|
|
|
|
# 初始化界面管理系统
|
|
self.interface_manager = InterfaceManager(self)
|
|
|
|
# 启动脚本系统
|
|
self.script_manager.start_system()
|
|
|
|
print("✓ MyWorld 初始化完成")
|
|
|
|
# ==================== 兼容性属性 ====================
|
|
|
|
# 保留models属性以兼容现有代码
|
|
@property
|
|
def models(self):
|
|
"""模型列表的兼容性属性"""
|
|
return self.scene_manager.models
|
|
|
|
@models.setter
|
|
def models(self, value):
|
|
"""模型列表的兼容性设置器"""
|
|
self.scene_manager.models = value
|
|
|
|
# 保留gui_elements属性以兼容现有代码
|
|
@property
|
|
def gui_elements(self):
|
|
"""GUI元素列表的兼容性属性"""
|
|
return self.gui_manager.gui_elements
|
|
|
|
@gui_elements.setter
|
|
def gui_elements(self, value):
|
|
"""GUI元素列表的兼容性设置器"""
|
|
self.gui_manager.gui_elements = value
|
|
|
|
# 保留guiEditMode属性以兼容现有代码
|
|
@property
|
|
def guiEditMode(self):
|
|
"""GUI编辑模式的兼容性属性"""
|
|
return self.gui_manager.guiEditMode
|
|
|
|
@guiEditMode.setter
|
|
def guiEditMode(self, value):
|
|
"""GUI编辑模式的兼容性设置器"""
|
|
self.gui_manager.guiEditMode = value
|
|
|
|
# 保留currentTool属性以兼容现有代码
|
|
@property
|
|
def currentTool(self):
|
|
"""当前工具的兼容性属性"""
|
|
return self.tool_manager.currentTool
|
|
|
|
@currentTool.setter
|
|
def currentTool(self, value):
|
|
"""当前工具的兼容性设置器"""
|
|
self.tool_manager.currentTool = value
|
|
|
|
# 保留treeWidget属性以兼容现有代码
|
|
@property
|
|
def treeWidget(self):
|
|
"""树形控件的兼容性属性"""
|
|
return self.interface_manager.treeWidget
|
|
|
|
@treeWidget.setter
|
|
def treeWidget(self, value):
|
|
"""树形控件的兼容性设置器"""
|
|
self.interface_manager.treeWidget = value
|
|
|
|
# ==================== GUI管理功能代理 ====================
|
|
|
|
# GUI元素创建方法 - 代理到gui_manager
|
|
def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1):
|
|
"""创建2D GUI按钮"""
|
|
return self.gui_manager.createGUIButton(pos, text, size)
|
|
|
|
def createGUILabel(self, pos=(0, 0, 0), text="标签", size=0.08):
|
|
"""创建2D GUI标签"""
|
|
return self.gui_manager.createGUILabel(pos, text, size)
|
|
|
|
def createGUIEntry(self, pos=(0, 0, 0), placeholder="输入文本...", size=0.08):
|
|
"""创建2D GUI文本输入框"""
|
|
return self.gui_manager.createGUIEntry(pos, placeholder, size)
|
|
|
|
def createGUI3DText(self, pos=(0, 0, 0), text="3D文本", size=0.5):
|
|
"""创建3D空间文本"""
|
|
return self.gui_manager.createGUI3DText(pos, text, size)
|
|
|
|
def createGUIVirtualScreen(self, pos=(0, 0, 0), size=(2, 1), text="虚拟屏幕"):
|
|
"""创建3D虚拟屏幕"""
|
|
return self.gui_manager.createGUIVirtualScreen(pos, size, text)
|
|
|
|
def createGUISlider(self, pos=(0, 0, 0), text="滑块", scale=0.3):
|
|
"""创建2D GUI滑块"""
|
|
return self.gui_manager.createGUISlider(pos, text, scale)
|
|
|
|
# GUI元素管理方法 - 代理到gui_manager
|
|
def deleteGUIElement(self, gui_element):
|
|
"""删除GUI元素"""
|
|
return self.gui_manager.deleteGUIElement(gui_element)
|
|
|
|
def editGUIElement(self, gui_element, property_name, value):
|
|
"""编辑GUI元素属性"""
|
|
return self.gui_manager.editGUIElement(gui_element, property_name, value)
|
|
|
|
def duplicateGUIElement(self, gui_element):
|
|
"""复制GUI元素"""
|
|
return self.gui_manager.duplicateGUIElement(gui_element)
|
|
|
|
def editGUIElementDialog(self, gui_element):
|
|
"""显示GUI元素编辑对话框"""
|
|
return self.gui_manager.editGUIElementDialog(gui_element)
|
|
|
|
# GUI事件处理方法 - 代理到gui_manager
|
|
def onGUIButtonClick(self, button_id):
|
|
"""GUI按钮点击事件处理"""
|
|
return self.gui_manager.onGUIButtonClick(button_id)
|
|
|
|
def onGUIEntrySubmit(self, text, entry_id):
|
|
"""GUI输入框提交事件处理"""
|
|
return self.gui_manager.onGUIEntrySubmit(text, entry_id)
|
|
|
|
# GUI编辑模式方法 - 代理到gui_manager
|
|
def toggleGUIEditMode(self):
|
|
"""切换GUI编辑模式"""
|
|
return self.gui_manager.toggleGUIEditMode()
|
|
|
|
def enterGUIEditMode(self):
|
|
"""进入GUI编辑模式"""
|
|
return self.gui_manager.enterGUIEditMode()
|
|
|
|
def exitGUIEditMode(self):
|
|
"""退出GUI编辑模式"""
|
|
return self.gui_manager.exitGUIEditMode()
|
|
|
|
def createGUIEditPanel(self):
|
|
"""创建GUI编辑面板"""
|
|
return self.gui_manager.createGUIEditPanel()
|
|
|
|
def openGUIPreviewWindow(self):
|
|
"""打开独立的GUI预览窗口"""
|
|
return self.gui_manager.openGUIPreviewWindow()
|
|
|
|
def closeGUIPreviewWindow(self):
|
|
"""关闭GUI预览窗口"""
|
|
return self.gui_manager.closeGUIPreviewWindow()
|
|
|
|
# GUI工具和选择方法 - 代理到gui_manager
|
|
def setGUICreateTool(self, tool_type):
|
|
"""设置GUI创建工具"""
|
|
return self.gui_manager.setGUICreateTool(tool_type)
|
|
|
|
def deleteSelectedGUI(self):
|
|
"""删除选中的GUI元素"""
|
|
return self.gui_manager.deleteSelectedGUI()
|
|
|
|
def copySelectedGUI(self):
|
|
"""复制选中的GUI元素"""
|
|
return self.gui_manager.copySelectedGUI()
|
|
|
|
def handleGUIEditClick(self, hitPos):
|
|
"""处理GUI编辑模式下的点击"""
|
|
return self.gui_manager.handleGUIEditClick(hitPos)
|
|
|
|
def createGUIAtPosition(self, world_pos, gui_type):
|
|
"""在指定位置创建GUI元素"""
|
|
return self.gui_manager.createGUIAtPosition(world_pos, gui_type)
|
|
|
|
def findClickedGUI(self, hitNode):
|
|
"""查找被点击的GUI元素"""
|
|
return self.gui_manager.findClickedGUI(hitNode)
|
|
|
|
def selectGUIInTree(self, gui_element):
|
|
"""在树形控件中选中GUI元素"""
|
|
return self.gui_manager.selectGUIInTree(gui_element)
|
|
|
|
def updateGUISelection(self, gui_element):
|
|
"""更新GUI元素选择状态"""
|
|
return self.gui_manager.updateGUISelection(gui_element)
|
|
|
|
# GUI属性面板方法 - 代理到gui_manager
|
|
def selectGUIColor(self, gui_element):
|
|
"""选择GUI元素颜色"""
|
|
return self.gui_manager.selectGUIColor(gui_element)
|
|
|
|
def editGUI2DPosition(self, gui_element, axis, value):
|
|
"""编辑2D GUI元素位置"""
|
|
return self.gui_manager.editGUI2DPosition(gui_element, axis, value)
|
|
|
|
# ==================== 事件处理代理 ====================
|
|
|
|
def onTreeItemClicked(self, item, column):
|
|
"""处理树形控件项目点击事件 - 代理到interface_manager"""
|
|
return self.interface_manager.onTreeItemClicked(item, column)
|
|
|
|
def setTreeWidget(self, treeWidget):
|
|
"""设置树形控件引用 - 代理到interface_manager"""
|
|
return self.interface_manager.setTreeWidget(treeWidget)
|
|
|
|
def mousePressEventLeft(self, evt):
|
|
"""处理鼠标左键按下事件 - 代理到event_handler"""
|
|
return self.event_handler.mousePressEventLeft(evt)
|
|
|
|
def mouseReleaseEventLeft(self, evt):
|
|
"""处理鼠标左键释放事件 - 代理到event_handler"""
|
|
return self.event_handler.mouseReleaseEventLeft(evt)
|
|
|
|
def wheelForward(self, data=None):
|
|
"""处理滚轮向前滚动(前进) - 代理到event_handler"""
|
|
return self.event_handler.wheelForward(data)
|
|
|
|
def wheelBackward(self, data=None):
|
|
"""处理滚轮向后滚动(后退) - 代理到event_handler"""
|
|
return self.event_handler.wheelBackward(data)
|
|
|
|
def mousePressEventMiddle(self, evt):
|
|
"""处理鼠标中键按下事件 - 代理到event_handler"""
|
|
return self.event_handler.mousePressEventMiddle(evt)
|
|
|
|
def mouseReleaseEventMiddle(self, evt):
|
|
"""处理鼠标中键释放事件 - 代理到event_handler"""
|
|
return self.event_handler.mouseReleaseEventMiddle(evt)
|
|
|
|
def mouseMoveEvent(self, evt):
|
|
"""处理鼠标移动事件 - 代理到event_handler"""
|
|
return self.event_handler.mouseMoveEvent(evt)
|
|
|
|
# ==================== 射线显示控制 ====================
|
|
|
|
def toggleRayDisplay(self):
|
|
"""切换射线显示状态 - 代理到event_handler"""
|
|
return self.event_handler.toggleRayDisplay()
|
|
|
|
def setRayDisplay(self, show=True):
|
|
"""设置射线显示状态 - 代理到event_handler"""
|
|
self.event_handler.showRay = show
|
|
if not show:
|
|
self.event_handler.clearRay()
|
|
return show
|
|
|
|
def getRayDisplay(self):
|
|
"""获取射线显示状态 - 代理到event_handler"""
|
|
return self.event_handler.showRay
|
|
|
|
def setRayLifetime(self, seconds):
|
|
"""设置射线显示时长(秒) - 代理到event_handler"""
|
|
self.event_handler.rayLifetime = seconds
|
|
print(f"射线显示时长设置为: {seconds}秒")
|
|
|
|
def getRayLifetime(self):
|
|
"""获取射线显示时长 - 代理到event_handler"""
|
|
return self.event_handler.rayLifetime
|
|
|
|
# ==================== 属性面板代理 ====================
|
|
|
|
def setPropertyLayout(self, layout):
|
|
"""设置属性面板布局引用 - 代理到property_panel"""
|
|
return self.property_panel.setPropertyLayout(layout)
|
|
|
|
def clearPropertyPanel(self):
|
|
"""清空属性面板 - 代理到property_panel"""
|
|
return self.property_panel.clearPropertyPanel()
|
|
|
|
def updatePropertyPanel(self, item):
|
|
"""更新属性面板显示 - 代理到property_panel"""
|
|
return self.property_panel.updatePropertyPanel(item)
|
|
|
|
def updateGUIPropertyPanel(self, gui_element):
|
|
"""更新GUI元素属性面板 - 代理到property_panel"""
|
|
return self.property_panel.updateGUIPropertyPanel(gui_element)
|
|
|
|
# ==================== 工具管理代理 ====================
|
|
|
|
def setCurrentTool(self, tool):
|
|
"""设置当前工具 - 代理到tool_manager"""
|
|
return self.tool_manager.setCurrentTool(tool)
|
|
|
|
# ==================== 场景管理功能代理 ====================
|
|
|
|
# 模型导入和处理方法 - 代理到scene_manager
|
|
def importModel(self, filepath):
|
|
"""导入模型到场景"""
|
|
return self.scene_manager.importModel(filepath)
|
|
|
|
def importModelAsync(self, filepath):
|
|
"""异步导入模型"""
|
|
return self.scene_manager.importModelAsync(filepath)
|
|
|
|
def loadAnimatedModel(self, model_path, anims=None):
|
|
"""加载带动画的模型"""
|
|
return self.scene_manager.loadAnimatedModel(model_path, anims)
|
|
|
|
# 材质和几何体处理方法 - 代理到scene_manager
|
|
def processMaterials(self, model):
|
|
"""处理模型材质"""
|
|
return self.scene_manager.processMaterials(model)
|
|
|
|
def processModelGeometry(self, model):
|
|
"""处理模型几何体"""
|
|
return self.scene_manager.processModelGeometry(model)
|
|
|
|
# 碰撞系统方法 - 代理到scene_manager
|
|
def setupCollision(self, model):
|
|
"""为模型设置碰撞检测"""
|
|
return self.scene_manager.setupCollision(model)
|
|
|
|
# 场景树管理方法 - 代理到scene_manager
|
|
def updateSceneTree(self):
|
|
"""更新场景树显示"""
|
|
return self.scene_manager.updateSceneTree()
|
|
|
|
# 场景保存和加载方法 - 代理到scene_manager
|
|
def saveScene(self, filename):
|
|
"""保存场景到BAM文件"""
|
|
return self.scene_manager.saveScene(filename)
|
|
|
|
def loadScene(self, filename):
|
|
"""从BAM文件加载场景"""
|
|
return self.scene_manager.loadScene(filename)
|
|
|
|
# 模型管理方法 - 代理到scene_manager
|
|
def deleteModel(self, model):
|
|
"""删除模型"""
|
|
return self.scene_manager.deleteModel(model)
|
|
|
|
def clearAllModels(self):
|
|
"""清除所有模型"""
|
|
return self.scene_manager.clearAllModels()
|
|
|
|
def getModels(self):
|
|
"""获取模型列表"""
|
|
return self.scene_manager.getModels()
|
|
|
|
def getModelCount(self):
|
|
"""获取模型数量"""
|
|
return self.scene_manager.getModelCount()
|
|
|
|
def findModelByName(self, name):
|
|
"""根据名称查找模型"""
|
|
return self.scene_manager.findModelByName(name)
|
|
|
|
# ==================== 脚本系统功能代理 ====================
|
|
|
|
# 脚本系统控制方法 - 代理到script_manager
|
|
def startScriptSystem(self):
|
|
"""启动脚本系统"""
|
|
return self.script_manager.start_system()
|
|
|
|
def stopScriptSystem(self):
|
|
"""停止脚本系统"""
|
|
return self.script_manager.stop_system()
|
|
|
|
def enableHotReload(self, enabled=True):
|
|
"""启用/禁用热重载"""
|
|
self.script_manager.hot_reload_enabled = enabled
|
|
if enabled:
|
|
self.script_manager.start_hot_reload()
|
|
else:
|
|
self.script_manager.stop_hot_reload()
|
|
|
|
# 脚本创建和加载方法 - 代理到script_manager
|
|
def createScript(self, script_name, template="basic"):
|
|
"""创建新脚本文件"""
|
|
return self.script_manager.create_script_file(script_name, template)
|
|
|
|
def loadScript(self, script_path):
|
|
"""从文件加载脚本"""
|
|
return self.script_manager.load_script_from_file(script_path)
|
|
|
|
def loadAllScripts(self, directory=None):
|
|
"""从目录加载所有脚本"""
|
|
return self.script_manager.load_all_scripts_from_directory(directory)
|
|
|
|
def reloadScript(self, script_name):
|
|
"""重新加载脚本"""
|
|
return self.script_manager.reload_script(script_name)
|
|
|
|
# 脚本挂载和管理方法 - 代理到script_manager
|
|
def addScript(self, game_object, script_name):
|
|
"""为游戏对象添加脚本"""
|
|
return self.script_manager.add_script_to_object(game_object, script_name)
|
|
|
|
def removeScript(self, game_object, script_name):
|
|
"""从游戏对象移除脚本"""
|
|
return self.script_manager.remove_script_from_object(game_object, script_name)
|
|
|
|
def getScripts(self, game_object):
|
|
"""获取对象上的所有脚本"""
|
|
return self.script_manager.get_scripts_on_object(game_object)
|
|
|
|
def getScript(self, game_object, script_name):
|
|
"""获取对象上的特定脚本"""
|
|
return self.script_manager.get_script_on_object(game_object, script_name)
|
|
|
|
# 脚本信息查询方法 - 代理到script_manager
|
|
def getAvailableScripts(self):
|
|
"""获取所有可用的脚本名称"""
|
|
return self.script_manager.get_available_scripts()
|
|
|
|
def getScriptInfo(self, script_name):
|
|
"""获取脚本信息"""
|
|
return self.script_manager.get_script_info(script_name)
|
|
|
|
def listAllScripts(self):
|
|
"""列出所有脚本信息"""
|
|
return self.script_manager.list_all_scripts()
|
|
|
|
|
|
# ==================== 项目管理功能代理 ====================
|
|
# 以下函数代理到project_manager模块的对应功能
|
|
|
|
def updateWindowTitle(window, project_name=None):
|
|
"""更新窗口标题 - 代理到project_manager"""
|
|
from project.project_manager import updateWindowTitle as pm_updateWindowTitle
|
|
return pm_updateWindowTitle(window, project_name)
|
|
|
|
def createNewProject(parent_window):
|
|
"""创建新项目 - 代理到project_manager"""
|
|
world = parent_window.centralWidget().world
|
|
return world.project_manager.createNewProject(parent_window)
|
|
|
|
def saveProject(appw):
|
|
"""保存项目 - 代理到project_manager"""
|
|
world = appw.centralWidget().world
|
|
return world.project_manager.saveProject(appw)
|
|
|
|
def openProject(appw):
|
|
"""打开项目 - 代理到project_manager"""
|
|
world = appw.centralWidget().world
|
|
return world.project_manager.openProject(appw)
|
|
|
|
def buildPackage(appw):
|
|
"""打包项目 - 代理到project_manager"""
|
|
world = appw.centralWidget().world
|
|
return world.project_manager.buildPackage(appw)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
world = MyWorld()
|
|
|
|
# 使用新的UI模块创建主窗口
|
|
from ui.main_window import setup_main_window
|
|
|
|
app, main_window = setup_main_window(world)
|
|
|
|
# 启动应用程序
|
|
sys.exit(app.exec_()) |