This commit is contained in:
Rowland 2026-01-08 14:25:40 +08:00
parent 69e2bda47e
commit 1fc3e154d1
5 changed files with 5551 additions and 5573 deletions

View File

@ -1,192 +1,188 @@
import sys
import os
from core.CustomMouseController import CustomMouseController
# 获取 RenderPipelineFile 的路径
render_pipeline_path = './RenderPipelineFile'
# 将该路径添加到 sys.path 中,确保 Python 能够找到它
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
sys.path.insert(0, render_pipeline_path)
from RenderPipelineFile.rpcore import RenderPipeline
_global_render_pipeline = None
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from panda3d.core import *
from panda3d.core import GraphicsOutput, Texture, ConfigVariableManager, WindowProperties
from direct.showbase.ShowBase import ShowBase
import platform
from QMeta3D.QMouseWatcherNode import QMouseWatcherNode
from RenderPipelineFile.rpcore.render_target import RenderTarget
__all__ = ["Meta3DWorld"]
_global_world_instance=None
import builtins
class Meta3DWorld(ShowBase):
def __init__(self, width=1380, height=750, is_fullscreen=False, size=1.0, clear_color=LVecBase4f(0, 0.5, 0, 1),
name="qMeta3D"):
global _global_world_instance
global _global_render_pipeline
_global_world_instance = self
sort = -100
self.parent = None
# 设置基本配置
loadPrcFileData("", "show-frame-rate-meter 0")
loadPrcFileData("", "window-type offscreen") # 设置为离屏渲染
loadPrcFileData("", f"win-size {width} {height}")
loadPrcFileData("", "win-fixed-size #f") # 允许窗口调整大小
# 🚀 VR性能优化配置
loadPrcFileData("", "prefer-single-buffer true") # 减少缓冲区交换开销
loadPrcFileData("", "gl-force-flush false") # 避免强制glFlush导致的性能损失
loadPrcFileData("", "sync-video false") # 禁用默认VSync让OpenVR控制
loadPrcFileData("", "support-stencil false") # 禁用不必要的模板缓冲区
loadPrcFileData("", "clock-mode non-real-time")
# loadPrcFileData("", "gl-debug true")
if (is_fullscreen):
loadPrcFileData("", "fullscreen #t")
self.render_pipeline = RenderPipeline()
self.render_pipeline.pre_showbase_init()
ShowBase.__init__(self)
# 初始化渲染管线并设置可调整大小的标志
self.render_pipeline.create(self)
_global_render_pipeline = self.render_pipeline
# 创建 Qt 能读的 RGBA8 贴图
self.qt_output_tex = Texture("qt_output_tex")
self.qt_output_tex.set_format(Texture.F_rgba8)
self.qt_output_tex.set_component_type(Texture.T_unsigned_byte)
# # 获取图形管线对象
# gsg = self.win.getGsg()
# host = gsg.getEngine().getHost()
self.win.add_render_texture(self.qt_output_tex, GraphicsOutput.RTM_copy_ram)
#self.screenTexture = Texture()
#self.screenTexture.setMinfilter(Texture.FTLinear)
#self.screenTexture.setFormat(Texture.FRgba32)
#self.screenTexture.set_wrap_u(Texture.WM_clamp)
#self.screenTexture.set_wrap_v(Texture.WM_clamp)
# buff_size_x = int(self.win.get_x_size() * size)
# buff_size_y = int(self.win.get_y_size() * size)
# winprops = WindowProperties()
# winprops.set_size(buff_size_x, buff_size_y)
#
#
# props = FrameBufferProperties()
# props.set_rgb_color(True)
# props.set_rgba_bits(8, 8, 8, 8)
# props.set_depth_bits(8)
# self.buff = self.graphicsEngine.make_output(
# self.pipe, name, sort,
# props, winprops,
# GraphicsPipe.BF_resizeable,
# self.win.get_gsg(), self.win)
#self.screenTexture = render_pipeline._final_stage.target.color_tex
#self.buff.addRenderTexture(self.screenTexture, GraphicsOutput.RTMCopyRam)
# self.buff.set_sort(sort)
#self.cam = self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.camera.reparentTo(self.render)
#base.camera.reparentTo(self.render)
#self.cam.reparentTo(self.render) # 可选同步
#render_pipeline.set_camera(self.cam)
#添加渲染效果
#self.cam = self.render_pipeline._showbase.cam
#self.camNode = self.cam.node()
#self.camLens = self.camNode.get_lens()
self.render_pipeline._showbase.camera = self.render_pipeline._showbase.cam
#self.render_pipeline.daytime_mgr.update()
# if clear_color is None:
# self.buff.set_clear_active(GraphicsOutput.RTPColor, False)
# else:
# self.buff.set_clear_color(clear_color)
# self.buff.set_clear_active(GraphicsOutput.RTPColor, True)
# self.disableMouse()
self.mouse_controller = CustomMouseController(self)
self.mouse_controller.setUp()
# 添加错误处理钩子
self.accept("transform_state_error", self._handle_transform_error)
def _handle_transform_error(self):
"""处理TransformState相关的错误"""
try:
from panda3d.core import TransformState, RenderState
TransformState.clear_cache()
RenderState.clear_cache()
print("已清理TransformState和RenderState缓存")
except Exception as e:
print(f"清理缓存时出错: {e}")
def render_pipeline(self):
"""获取 RenderPipeline 实例"""
return self._render_pipeline
def set_parent(self, parent: QWidget):
self.parent = parent
self.mouseWatcherNode = QMouseWatcherNode(parent)
def getAspectRatio(self, win = None):
if win is None and self.parent is not None:
return float(self.parent.width()) / float(self.parent.height())
else:
return super().getAspectRatio(win)
def get_render_pipeline():
"""获取全局 RenderPipeline 单例"""
if _global_render_pipeline is None:
raise RuntimeError(
"RenderPipeline has not been initialized yet. Please create a 3DWorld instance first.")
return _global_render_pipeline
def resize_buffer(self, width: int, height: int):
props = WindowProperties()
props.set_size(width, height)
self.win.request_properties(props)
# 重新分配输出贴图的大小
self.qt_output_tex.set_x_size(width)
self.qt_output_tex.set_y_size(height)
# 更新 lens 的 aspect ratio
if self.camLens:
self.camLens.set_film_size(width, height) # 或 set_aspect_ratio(width / height)
# 强制更新窗口(有时在 Qt 内嵌时需要)
import sys
import os
from core.CustomMouseController import CustomMouseController
# 获取 RenderPipelineFile 的路径
render_pipeline_path = './RenderPipelineFile'
# 将该路径添加到 sys.path 中,确保 Python 能够找到它
project_root = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, project_root)
sys.path.insert(0, render_pipeline_path)
from RenderPipelineFile.rpcore import RenderPipeline
_global_render_pipeline = None
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from panda3d.core import *
from panda3d.core import GraphicsOutput, Texture, ConfigVariableManager, WindowProperties
from direct.showbase.ShowBase import ShowBase
import platform
from QMeta3D.QMouseWatcherNode import QMouseWatcherNode
from RenderPipelineFile.rpcore.render_target import RenderTarget
__all__ = ["Meta3DWorld"]
_global_world_instance=None
import builtins
class Meta3DWorld(ShowBase):
def __init__(self, width=1380, height=750, is_fullscreen=False, size=1.0, clear_color=LVecBase4f(0, 0.5, 0, 1),
name="qMeta3D"):
global _global_world_instance
global _global_render_pipeline
_global_world_instance = self
sort = -100
self.parent = None
# 设置基本配置
loadPrcFileData("", "show-frame-rate-meter 0")
loadPrcFileData("", "window-type onscreen") # 改为正常窗口渲染
loadPrcFileData("", f"win-size {width} {height}")
loadPrcFileData("", "win-fixed-size #f") # 允许窗口调整大小
# 🚀 VR性能优化配置
loadPrcFileData("", "prefer-single-buffer true") # 减少缓冲区交换开销
loadPrcFileData("", "gl-force-flush false") # 避免强制glFlush导致的性能损失
loadPrcFileData("", "sync-video false") # 禁用默认VSync让OpenVR控制
loadPrcFileData("", "support-stencil false") # 禁用不必要的模板缓冲区
loadPrcFileData("", "clock-mode non-real-time")
# loadPrcFileData("", "gl-debug true")
if (is_fullscreen):
loadPrcFileData("", "fullscreen #t")
self.render_pipeline = RenderPipeline()
self.render_pipeline.pre_showbase_init()
ShowBase.__init__(self)
# 初始化渲染管线并设置可调整大小的标志
self.render_pipeline.create(self)
_global_render_pipeline = self.render_pipeline
# 正常窗口渲染不需要额外的输出纹理
# 注释掉离屏渲染相关的纹理创建
# self.qt_output_tex = Texture("qt_output_tex")
# self.qt_output_tex.set_format(Texture.F_rgba8)
# self.qt_output_tex.set_component_type(Texture.T_unsigned_byte)
# self.win.add_render_texture(self.qt_output_tex, GraphicsOutput.RTM_copy_ram)
#self.screenTexture = Texture()
#self.screenTexture.setMinfilter(Texture.FTLinear)
#self.screenTexture.setFormat(Texture.FRgba32)
#self.screenTexture.set_wrap_u(Texture.WM_clamp)
#self.screenTexture.set_wrap_v(Texture.WM_clamp)
# buff_size_x = int(self.win.get_x_size() * size)
# buff_size_y = int(self.win.get_y_size() * size)
# winprops = WindowProperties()
# winprops.set_size(buff_size_x, buff_size_y)
#
#
# props = FrameBufferProperties()
# props.set_rgb_color(True)
# props.set_rgba_bits(8, 8, 8, 8)
# props.set_depth_bits(8)
# self.buff = self.graphicsEngine.make_output(
# self.pipe, name, sort,
# props, winprops,
# GraphicsPipe.BF_resizeable,
# self.win.get_gsg(), self.win)
#self.screenTexture = render_pipeline._final_stage.target.color_tex
#self.buff.addRenderTexture(self.screenTexture, GraphicsOutput.RTMCopyRam)
# self.buff.set_sort(sort)
#self.cam = self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.cam=self.makeCamera(self.buff)
#self.render_pipeline._showbase.camera.reparentTo(self.render)
#base.camera.reparentTo(self.render)
#self.cam.reparentTo(self.render) # 可选同步
#render_pipeline.set_camera(self.cam)
#添加渲染效果
#self.cam = self.render_pipeline._showbase.cam
#self.camNode = self.cam.node()
#self.camLens = self.camNode.get_lens()
self.render_pipeline._showbase.camera = self.render_pipeline._showbase.cam
#self.render_pipeline.daytime_mgr.update()
# if clear_color is None:
# self.buff.set_clear_active(GraphicsOutput.RTPColor, False)
# else:
# self.buff.set_clear_color(clear_color)
# self.buff.set_clear_active(GraphicsOutput.RTPColor, True)
# self.disableMouse()
self.mouse_controller = CustomMouseController(self)
self.mouse_controller.setUp()
# 添加错误处理钩子
self.accept("transform_state_error", self._handle_transform_error)
def _handle_transform_error(self):
"""处理TransformState相关的错误"""
try:
from panda3d.core import TransformState, RenderState
TransformState.clear_cache()
RenderState.clear_cache()
print("已清理TransformState和RenderState缓存")
except Exception as e:
print(f"清理缓存时出错: {e}")
def render_pipeline(self):
"""获取 RenderPipeline 实例"""
return self._render_pipeline
def set_parent(self, parent: QWidget):
self.parent = parent
self.mouseWatcherNode = QMouseWatcherNode(parent)
def getAspectRatio(self, win = None):
if win is None and self.parent is not None:
return float(self.parent.width()) / float(self.parent.height())
else:
return super().getAspectRatio(win)
def get_render_pipeline():
"""获取全局 RenderPipeline 单例"""
if _global_render_pipeline is None:
raise RuntimeError(
"RenderPipeline has not been initialized yet. Please create a 3DWorld instance first.")
return _global_render_pipeline
def resize_buffer(self, width: int, height: int):
props = WindowProperties()
props.set_size(width, height)
self.win.request_properties(props)
# 重新分配输出贴图的大小
self.qt_output_tex.set_x_size(width)
self.qt_output_tex.set_y_size(height)
# 更新 lens 的 aspect ratio
if self.camLens:
self.camLens.set_film_size(width, height) # 或 set_aspect_ratio(width / height)
# 强制更新窗口(有时在 Qt 内嵌时需要)
self.graphicsEngine.open_windows()

View File

@ -1,252 +1,236 @@
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from direct.task.TaskManagerGlobal import taskMgr
from QMeta3D.QMeta3D_Buttons_Translation import QMeta3D_Button_translation
from QMeta3D.QMeta3D_Keys_Translation import QMeta3D_Key_translation
from QMeta3D.QMeta3D_Modifiers_Translation import QMeta3D_Modifier_translation
__all__ = ["QMeta3DWidget"]
class QMeta3DSynchronizer(QTimer):
def __init__(self, qMeta3DWidget, FPS=60):
QTimer.__init__(self)
self.qMeta3DWidget = qMeta3DWidget
dt = 1000 / FPS
self.setInterval(int(dt))
self.timeout.connect(self.tick)
def tick(self):
try:
# 在渲染前清理可能损坏的TransformState对象
from panda3d.core import TransformState
TransformState.clear_cache()
taskMgr.step()
self.qMeta3DWidget.update()
except AssertionError as e:
# 专门处理 TransformState has_mat() 断言错误
if "has_mat" in str(e):
print(f"警告: 检测到TransformState断言错误已静默处理: {e}")
# 尝试恢复渲染状态
try:
# 强制清理缓存并重试
from panda3d.core import TransformState, RenderState
TransformState.clear_cache()
RenderState.clear_cache()
taskMgr.step()
self.qMeta3DWidget.update()
except:
pass
else:
# 重新抛出其他断言错误
raise
except Exception as e:
# 静默处理其他所有异常
print(f"警告: 检测到异常,已静默处理: {e}")
def get_panda_key_modifiers(evt):
panda_mods = []
qt_mods = evt.modifiers()
for qt_mod, panda_mod in QMeta3D_Modifier_translation.items():
if (qt_mods & qt_mod) == qt_mod:
panda_mods.append(panda_mod)
return panda_mods
def get_panda_key_modifiers_prefix(evt):
# join all modifiers (except NoModifier, which is None) with '-'
prefix = "-".join([mod for mod in get_panda_key_modifiers(evt) if mod is not None])
# if the prefix is not empty, append a '-'
if prefix:
prefix += '-'
return prefix
class QMeta3DWidget(QWidget):
def __init__(self, Meta3DWorld, parent=None, FPS=60, debug=False):
QWidget.__init__(self, parent)
self.rp_sync_requested = False
# set fixed geometry
self.Meta3DWorld = Meta3DWorld
self.Meta3DWorld.set_parent(self)
# Setup a timer in Qt that runs taskMgr.step() to simulate Panda's own main loop
# pandaTimer = QTimer(self)
# pandaTimer.timeout.connect()
# pandaTimer.start(0)
self.setFocusPolicy(Qt.StrongFocus)
# Setup another timer that redraws this widget in a specific FPS
# redrawTimer = QTimer(self)
# redrawTimer.timeout.connect(self.update)
# redrawTimer.start(1000/FPS)
self.paintSurface = QPainter()
self.rotate = QTransform()
self.rotate.rotate(180)
self.out_image = QImage()
size = self.Meta3DWorld.cam.node().get_lens().get_film_size()
self.initial_film_size = QSizeF(size.x, size.y)
self.initial_size = self.size()
self.synchronizer = QMeta3DSynchronizer(self, FPS)
self.synchronizer.start()
self.debug = debug
def mousePressEvent(self, evt):
button = evt.button()
try:
b = "{}{}".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseMoveEvent(self, evt:QtGui.QMouseEvent):
button = evt.button()
try:
b = "mouse-move"
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseReleaseEvent(self, evt):
button = evt.button()
try:
b = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def wheelEvent(self, evt):
delta = evt.angleDelta().y()
try:
if self.debug:
print(f"wheel {delta}")
messenger.send('wheel',[{"delta":delta}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def keyPressEvent(self, evt):
key = evt.key()
try:
k = "{}{}".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def keyReleaseEvent(self, evt):
key = evt.key()
try:
k = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def resizeEvent(self, evt):
width = evt.size().width()
height = evt.size().height()
#print(f"width:{width}")
#print(f"height:{height}")
from Meta3DWorld import resize_buffer
lens = self.Meta3DWorld.cam.node().get_lens()
def minimumSizeHint(self):
return QSize(400, 300)
def paintEvent(self, event):
tex = self.Meta3DWorld.qt_output_tex
gsg = base.win.getGsg()
if not gsg:
self.update()
return
if not tex.hasRamImage():
base.graphicsEngine.extractTextureData(tex, gsg)
self.update()
return
data = tex.getRamImage().getData()
tex_width = tex.getXSize()
tex_height = tex.getYSize()
expected_len = tex_width * tex_height * 4
if len(data) != expected_len:
print(f"⚠️ 像素数据长度异常({len(data)} != {expected_len}),跳过绘制")
self.update()
return
img = QImage(data, tex_width, tex_height, QImage.Format_ARGB32).mirrored()
widget_width = self.width()
widget_height = self.height()
painter = QPainter(self)
# 【保持宽高比的缩放】
scaled_img = img.scaled(widget_width, widget_height, Qt.KeepAspectRatio, Qt.SmoothTransformation)
# 居中绘制
x_offset = (widget_width - scaled_img.width()) // 2
y_offset = (widget_height - scaled_img.height()) // 2
painter.drawImage(x_offset, y_offset, scaled_img)
painter.end()
def sync_Meta3d_window_size(self, width, height):
try:
from panda3d.core import WindowProperties, LVecBase2i
# 确保尺寸是4的倍数RenderPipeline 要求)
adjusted_width = width - width % 4
adjusted_height = height - height % 4
# 更新窗口属性
props = WindowProperties()
props.setSize(adjusted_width, adjusted_height)
# 对于 offscreen 渲染,直接更新窗口属性
if self.Meta3DWorld.win:
self.Meta3DWorld.win.request_properties(props)
# 手动触发 RenderPipeline 的尺寸更新逻辑
if hasattr(self.Meta3DWorld, 'render_pipeline'):
# 更新全局分辨率
from RenderPipelineFile.rpcore.globals import Globals
Globals.native_resolution = LVecBase2i(adjusted_width, adjusted_height)
# 重新计算渲染分辨率
self.Meta3DWorld.render_pipeline._compute_render_resolution()
# 通知各个管理器处理尺寸变化
self.Meta3DWorld.render_pipeline.light_mgr.compute_tile_size()
self.Meta3DWorld.render_pipeline.stage_mgr.handle_window_resize()
if hasattr(self.Meta3DWorld.render_pipeline, 'debugger'):
self.Meta3DWorld.render_pipeline.debugger.handle_window_resize()
# 触发插件的窗口尺寸变化钩子
self.Meta3DWorld.render_pipeline.plugin_mgr.trigger_hook("window_resized")
except Exception as e:
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from direct.task.TaskManagerGlobal import taskMgr
from QMeta3D.QMeta3D_Buttons_Translation import QMeta3D_Button_translation
from QMeta3D.QMeta3D_Keys_Translation import QMeta3D_Key_translation
from QMeta3D.QMeta3D_Modifiers_Translation import QMeta3D_Modifier_translation
__all__ = ["QMeta3DWidget"]
class QMeta3DSynchronizer(QTimer):
def __init__(self, qMeta3DWidget, FPS=60):
QTimer.__init__(self)
self.qMeta3DWidget = qMeta3DWidget
dt = 1000 / FPS
self.setInterval(int(dt))
self.timeout.connect(self.tick)
def tick(self):
try:
# 在渲染前清理可能损坏的TransformState对象
from panda3d.core import TransformState
TransformState.clear_cache()
taskMgr.step()
self.qMeta3DWidget.update()
except AssertionError as e:
# 专门处理 TransformState has_mat() 断言错误
if "has_mat" in str(e):
print(f"警告: 检测到TransformState断言错误已静默处理: {e}")
# 尝试恢复渲染状态
try:
# 强制清理缓存并重试
from panda3d.core import TransformState, RenderState
TransformState.clear_cache()
RenderState.clear_cache()
taskMgr.step()
self.qMeta3DWidget.update()
except:
pass
else:
# 重新抛出其他断言错误
raise
except Exception as e:
# 静默处理其他所有异常
print(f"警告: 检测到异常,已静默处理: {e}")
def get_panda_key_modifiers(evt):
panda_mods = []
qt_mods = evt.modifiers()
for qt_mod, panda_mod in QMeta3D_Modifier_translation.items():
if (qt_mods & qt_mod) == qt_mod:
panda_mods.append(panda_mod)
return panda_mods
def get_panda_key_modifiers_prefix(evt):
# join all modifiers (except NoModifier, which is None) with '-'
prefix = "-".join([mod for mod in get_panda_key_modifiers(evt) if mod is not None])
# if the prefix is not empty, append a '-'
if prefix:
prefix += '-'
return prefix
class QMeta3DWidget(QWidget):
def __init__(self, Meta3DWorld, parent=None, FPS=60, debug=False):
QWidget.__init__(self, parent)
self.rp_sync_requested = False
# set fixed geometry
self.Meta3DWorld = Meta3DWorld
self.Meta3DWorld.set_parent(self)
# Setup a timer in Qt that runs taskMgr.step() to simulate Panda's own main loop
# pandaTimer = QTimer(self)
# pandaTimer.timeout.connect()
# pandaTimer.start(0)
self.setFocusPolicy(Qt.StrongFocus)
# Setup another timer that redraws this widget in a specific FPS
# redrawTimer = QTimer(self)
# redrawTimer.timeout.connect(self.update)
# redrawTimer.start(1000/FPS)
self.paintSurface = QPainter()
self.rotate = QTransform()
self.rotate.rotate(180)
self.out_image = QImage()
size = self.Meta3DWorld.cam.node().get_lens().get_film_size()
self.initial_film_size = QSizeF(size.x, size.y)
self.initial_size = self.size()
self.synchronizer = QMeta3DSynchronizer(self, FPS)
self.synchronizer.start()
self.debug = debug
def mousePressEvent(self, evt):
button = evt.button()
try:
b = "{}{}".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseMoveEvent(self, evt:QtGui.QMouseEvent):
button = evt.button()
try:
b = "mouse-move"
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def mouseReleaseEvent(self, evt):
button = evt.button()
try:
b = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Button_translation[button])
if self.debug:
print(b)
messenger.send(b,[{"x":evt.x(),"y":evt.y()}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def wheelEvent(self, evt):
delta = evt.angleDelta().y()
try:
if self.debug:
print(f"wheel {delta}")
messenger.send('wheel',[{"delta":delta}])
except:
print("Unimplemented button. Please send an issue on github to fix this problem")
def keyPressEvent(self, evt):
key = evt.key()
try:
k = "{}{}".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def keyReleaseEvent(self, evt):
key = evt.key()
try:
k = "{}{}-up".format(get_panda_key_modifiers_prefix(evt), QMeta3D_Key_translation[key])
if self.debug:
print(k)
messenger.send(k)
except:
print("Unimplemented key. Please send an issue on github to fix this problem")
def resizeEvent(self, evt):
width = evt.size().width()
height = evt.size().height()
#print(f"width:{width}")
#print(f"height:{height}")
from Meta3DWorld import resize_buffer
lens = self.Meta3DWorld.cam.node().get_lens()
def minimumSizeHint(self):
return QSize(400, 300)
def paintEvent(self, event):
# 正常窗口渲染模式下Panda3D 会直接渲染到窗口
# 不需要从纹理复制数据
# 只需要确保渲染循环继续运行
# 触发一次渲染更新
if hasattr(self.Meta3DWorld, 'win') and self.Meta3DWorld.win:
# 确保窗口大小匹配
width = self.width()
height = self.height()
# 如果窗口大小不匹配,更新窗口属性
if (self.Meta3DWorld.win.get_x_size() != width or
self.Meta3DWorld.win.get_y_size() != height):
from panda3d.core import WindowProperties
props = WindowProperties()
props.setSize(width, height)
self.Meta3DWorld.win.request_properties(props)
# 继续下一次更新
self.update()
def sync_Meta3d_window_size(self, width, height):
try:
from panda3d.core import WindowProperties
# 更新窗口属性
props = WindowProperties()
props.setSize(width, height)
# 对于正常窗口渲染,直接更新窗口属性
if self.Meta3DWorld.win:
self.Meta3DWorld.win.request_properties(props)
# 如果使用 RenderPipeline更新相关设置
if hasattr(self.Meta3DWorld, 'render_pipeline'):
try:
from RenderPipelineFile.rpcore.globals import Globals
from panda3d.core import LVecBase2i
# 更新全局分辨率
Globals.native_resolution = LVecBase2i(width, height)
# 重新计算渲染分辨率
self.Meta3DWorld.render_pipeline._compute_render_resolution()
# 通知各个管理器处理尺寸变化
self.Meta3DWorld.render_pipeline.light_mgr.compute_tile_size()
self.Meta3DWorld.render_pipeline.stage_mgr.handle_window_resize()
if hasattr(self.Meta3DWorld.render_pipeline, 'debugger'):
self.Meta3DWorld.render_pipeline.debugger.handle_window_resize()
# 触发插件的窗口尺寸变化钩子
self.Meta3DWorld.render_pipeline.plugin_mgr.trigger_hook("window_resized")
except Exception as rp_e:
print(f"RenderPipeline 尺寸更新失败: {rp_e}")
except Exception as e:
print(f"同步 Meta3D 窗口尺寸失败: {str(e)}")

1631
main.py

File diff suppressed because it is too large Load Diff

View File

@ -199,11 +199,11 @@ class EmbeddedWebBrowser(QWidget):
def main():
# 设置标准输出编码为 UTF-8避免 Windows GBK 编码问题
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
# 注释掉标准输出重定向,让输出正常显示在终端
# if sys.platform == 'win32':
# import io
# sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
# sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
print("=" * 60)
print("[WebEngine] 启动独立 WebEngine 进程")

File diff suppressed because it is too large Load Diff