EG/main.py
Rowland 72819341ef docs(README): 添加项目README文档
- 创建详细的README文档,介绍项目功能、架构、使用方法等
- 新增.pyc文件和目录,用于缓存编译后的Python代码
- 添加.lingma规则文件,用于代码格式检查
- 删除ALVR串流处理器代码,准备替换为OpenXR输入处理器
- 新增OpenXR输入处理器代码,处理VR控制器输入
2025-07-29 17:46:08 +08:00

702 lines
26 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.

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 core.openxr_manager import OpenXRManager
from core.openxr_input_handler import OpenXRInputHandler
from core.openxr_streamer import OpenXRStreamer
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
# RenderPipelineFile.toolkit.material_editor.main import MaterialEditor
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)
# 初始化OpenXR系统
self.openxr_manager = OpenXRManager(self)
self.openxr_input_handler = OpenXRInputHandler(self, self.openxr_manager)
self.openxr_streamer = OpenXRStreamer(self, self.openxr_manager)
# 启动脚本系统
self.script_manager.start_system()
#self.material_editor = None
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
# 保留gui_elements属性以兼容现有代码
@property
def Spotlight(self):
"""GUI元素列表的兼容性属性"""
return self.scene_manager.Spotlight
@Spotlight.setter
def Spotlight(self, value):
"""GUI元素列表的兼容性设置器"""
self.scene_manager.Spotlight = value
@property
def Pointlight(self):
return self.scene_manager.Pointlight
@Pointlight.setter
def Pointlight(self,value):
self.scene_manager.Pointlight = 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 createSpotLight(self,pos=(-20,0,5)):
"""创建聚光灯"""
return self.scene_manager.createSpotLight(pos)
def createPointLight(self,pos=(20,0,5)):
"""创建点光源"""
return self.scene_manager.createPointLight(pos)
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)
# ==================== OpenXR系统功能代理 ====================
# OpenXR系统控制方法 - 代理到openxr_manager
def initializeOpenXR(self):
"""初始化OpenXR系统"""
return self.openxr_manager.initialize_openxr()
def shutdownOpenXR(self):
"""关闭OpenXR系统"""
return self.openxr_manager.shutdown_openxr()
def isOpenXREnabled(self):
"""检查OpenXR是否启用"""
return self.openxr_manager.is_openxr_enabled()
def getOpenXRInfo(self):
"""获取OpenXR系统信息"""
return self.openxr_manager.get_openxr_info()
# OpenXR输入处理方法 - 代理到openxr_input_handler
def startOpenXRInput(self):
"""启动OpenXR输入处理"""
return self.openxr_input_handler.start_input_handling()
def stopOpenXRInput(self):
"""停止OpenXR输入处理"""
return self.openxr_input_handler.stop_input_handling()
def showControllerRays(self, show=True):
"""显示/隐藏控制器射线"""
return self.openxr_input_handler.show_controller_rays(show)
def getControllerState(self, controller_id):
"""获取控制器状态"""
return self.openxr_input_handler.get_controller_state(controller_id)
def getAllControllers(self):
"""获取所有控制器"""
return self.openxr_input_handler.get_all_controllers()
def setVRGestureEnabled(self, enabled):
"""设置OpenXR手势识别启用状态"""
return self.openxr_input_handler.set_gesture_enabled(enabled)
def setVRInteractionEnabled(self, enabled):
"""设置OpenXR交互启用状态"""
return self.openxr_input_handler.set_interaction_enabled(enabled)
# OpenXR串流方法 - 代理到openxr_streamer
def initializeOpenXRStreaming(self):
"""初始化OpenXR串流"""
return self.openxr_streamer.initialize()
def startOpenXRStreaming(self):
"""开始OpenXR串流"""
return self.openxr_streamer.start_streaming()
def stopOpenXRStreaming(self):
"""停止OpenXR串流"""
return self.openxr_streamer.stop_streaming()
def getOpenXRStreamingStatus(self):
"""获取OpenXR串流状态"""
return self.openxr_streamer.get_streaming_status()
def setOpenXRStreamQuality(self, width, height, fps, bitrate):
"""设置OpenXR串流质量"""
return self.openxr_streamer.set_stream_quality(width, height, fps, bitrate)
def sendHapticFeedback(self, controller_id, duration, intensity):
"""发送触觉反馈"""
return self.openxr_streamer.send_haptic_feedback(controller_id, duration, intensity)
def shutdownOpenXRStreaming(self):
"""关闭OpenXR串流"""
return self.openxr_streamer.shutdown()
def isOpenXRConnected(self):
"""检查OpenXR是否连接"""
return self.openxr_streamer.is_connected()
def isOpenXRStreaming(self):
"""检查OpenXR是否在串流"""
return self.openxr_streamer.is_streaming()
# 便捷方法
def enableOpenXRMode(self):
"""启用OpenXR模式一键启动"""
print("启用OpenXR模式...")
# 1. 初始化OpenXR系统
if not self.initializeOpenXR():
print("OpenXR系统初始化失败")
return False
# 2. 启动OpenXR输入处理
if not self.startOpenXRInput():
print("OpenXR输入处理启动失败")
return False
# 3. 初始化OpenXR串流
if self.initializeOpenXRStreaming():
print("✓ OpenXR串流已启用")
# 自动开始串流
self.startOpenXRStreaming()
else:
print("⚠ OpenXR串流启用失败但OpenXR系统仍可用")
print("✓ OpenXR模式已启用")
return True
def disableOpenXRMode(self):
"""禁用OpenXR模式一键关闭"""
print("禁用OpenXR模式...")
# 1. 停止OpenXR串流
self.stopOpenXRStreaming()
self.shutdownOpenXRStreaming()
# 2. 停止OpenXR输入处理
self.stopOpenXRInput()
# 3. 关闭OpenXR系统
self.shutdownOpenXR()
print("✓ OpenXR模式已禁用")
def getOpenXRStatus(self):
"""获取OpenXR系统总体状态"""
return {
"openxr_enabled": self.isOpenXREnabled(),
"openxr_info": self.getOpenXRInfo(),
"controllers": self.getAllControllers(),
"openxr_connected": self.isOpenXRConnected(),
"openxr_streaming": self.isOpenXRStreaming(),
"streaming_status": self.getOpenXRStreamingStatus() if self.isOpenXRConnected() else None
}
# ==================== 脚本系统功能代理 ====================
# 脚本系统控制方法 - 代理到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)
# def open_material_editor(self):
# """打开材质编辑器作为子窗口"""
# if not self.material_editor:
# # self.material_editor = MaterialEditor()
# # # 设置为子窗口
# # self.material_editor.setParent(self)
# # self.material_editor.setWindowFlags(Qt.Window)
# #
# # self.material_editor.show()
# #
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_())