vr添加调试信息

This commit is contained in:
Rowland 2025-09-16 16:30:36 +08:00
parent 86b38bcfb3
commit ef639ab0b1
3 changed files with 1286 additions and 53 deletions

View File

@ -153,26 +153,38 @@ class VRController(DirectObject):
try:
result, state = vr_system.getControllerState(self.device_index)
if result:
# 更新按钮状态
# 更新按钮状态 - 使用正确的OpenVR属性名
for i in range(openvr.k_EButton_Max):
button_mask = 1 << i
self.button_states[i] = (state.rButtonPressed & button_mask) != 0
# OpenVR Python绑定中使用ulButtonPressed而不是rButtonPressed
self.button_states[i] = (state.ulButtonPressed & button_mask) != 0
# 更新轴状态(扳机、握把、触摸板)
if len(state.rAxis) > 0:
# OpenVR Python绑定中使用vAxis而不是rAxis
if hasattr(state, 'vAxis') and len(state.vAxis) > 0:
# 扳机轴通常在axis[1].x
if len(state.rAxis) > 1:
self.trigger_value = state.rAxis[1].x
if len(state.vAxis) > 1:
self.trigger_value = state.vAxis[1].x
# 触摸板轴通常在axis[0]
if len(state.rAxis) > 0:
self.touchpad_pos = Vec3(state.rAxis[0].x, state.rAxis[0].y, 0)
if len(state.vAxis) > 0:
self.touchpad_pos = Vec3(state.vAxis[0].x, state.vAxis[0].y, 0)
# 触摸板触摸状态
self.touchpad_touched = (state.rButtonTouched & (1 << openvr.k_EButton_SteamVR_Touchpad)) != 0
# 触摸板触摸状态 - 使用正确的OpenVR属性名
self.touchpad_touched = (state.ulButtonTouched & (1 << openvr.k_EButton_SteamVR_Touchpad)) != 0
except Exception as e:
print(f"⚠️ 更新{self.name}手柄输入状态失败: {e}")
# 减少错误输出频率
if not hasattr(self, '_last_input_error_frame'):
self._last_input_error_frame = 0
# 获取当前帧数通过VR管理器
current_frame = getattr(self.vr_manager, 'frame_count', 0)
# 每5秒最多输出一次错误300帧@60fps
if current_frame - self._last_input_error_frame > 300:
print(f"⚠️ 更新{self.name}手柄输入状态失败: {e}")
self._last_input_error_frame = current_frame
def is_button_pressed(self, button_id):
"""检查按钮是否被按下"""

File diff suppressed because it is too large Load Diff

View File

@ -445,6 +445,60 @@ class MainWindow(QMainWindow):
self.vrMenu.addSeparator()
self.vrStatusAction = self.vrMenu.addAction('VR状态')
self.vrSettingsAction = self.vrMenu.addAction('VR设置')
self.vrMenu.addSeparator()
# VR调试子菜单
self.vrDebugMenu = self.vrMenu.addMenu('VR调试')
self.vrDebugToggleAction = self.vrDebugMenu.addAction('启用调试输出')
self.vrDebugToggleAction.setCheckable(True)
self.vrDebugToggleAction.setChecked(True) # 默认启用
self.vrShowPerformanceAction = self.vrDebugMenu.addAction('立即显示性能报告')
self.vrDebugMenu.addSeparator()
# 调试模式切换
self.vrDebugModeMenu = self.vrDebugMenu.addMenu('输出模式')
self.vrDebugBriefAction = self.vrDebugModeMenu.addAction('简短模式')
self.vrDebugDetailedAction = self.vrDebugModeMenu.addAction('详细模式')
self.vrDebugBriefAction.setCheckable(True)
self.vrDebugDetailedAction.setCheckable(True)
self.vrDebugDetailedAction.setChecked(True) # 默认详细模式
# 创建调试模式动作组(单选)
from PyQt5.QtWidgets import QActionGroup
self.vrDebugModeGroup = QActionGroup(self)
self.vrDebugModeGroup.addAction(self.vrDebugBriefAction)
self.vrDebugModeGroup.addAction(self.vrDebugDetailedAction)
self.vrDebugMenu.addSeparator()
# 管线监控选项
self.vrPipelineMonitorAction = self.vrDebugMenu.addAction('启用管线监控')
self.vrPipelineMonitorAction.setCheckable(True)
self.vrPipelineMonitorAction.setChecked(True) # 默认启用
self.vrDebugMenu.addSeparator()
# 姿态策略选项
self.vrPoseStrategyMenu = self.vrDebugMenu.addMenu('姿态策略')
self.vrPoseRenderCallbackAction = self.vrPoseStrategyMenu.addAction('渲染回调策略')
self.vrPoseUpdateTaskAction = self.vrPoseStrategyMenu.addAction('更新任务策略')
self.vrPoseRenderCallbackAction.setCheckable(True)
self.vrPoseUpdateTaskAction.setCheckable(True)
self.vrPoseRenderCallbackAction.setChecked(True) # 默认策略
# 创建姿态策略动作组(单选)
self.vrPoseStrategyGroup = QActionGroup(self)
self.vrPoseStrategyGroup.addAction(self.vrPoseRenderCallbackAction)
self.vrPoseStrategyGroup.addAction(self.vrPoseUpdateTaskAction)
self.vrDebugMenu.addSeparator()
# 测试功能
self.vrTestPipelineAction = self.vrDebugMenu.addAction('测试管线监控')
self.vrDebugSettingsAction = self.vrDebugMenu.addAction('调试设置...')
# 初始状态下禁用退出VR选项
self.exitVRAction.setEnabled(False)
@ -915,6 +969,17 @@ class MainWindow(QMainWindow):
self.vrStatusAction.triggered.connect(self.onShowVRStatus)
self.vrSettingsAction.triggered.connect(self.onShowVRSettings)
# 连接VR调试菜单事件
self.vrDebugToggleAction.triggered.connect(self.onToggleVRDebug)
self.vrShowPerformanceAction.triggered.connect(self.onShowVRPerformance)
self.vrDebugBriefAction.triggered.connect(lambda: self.onSetVRDebugMode('brief'))
self.vrDebugDetailedAction.triggered.connect(lambda: self.onSetVRDebugMode('detailed'))
self.vrPipelineMonitorAction.triggered.connect(self.onToggleVRPipelineMonitor)
self.vrPoseRenderCallbackAction.triggered.connect(lambda: self.onSetVRPoseStrategy('render_callback'))
self.vrPoseUpdateTaskAction.triggered.connect(lambda: self.onSetVRPoseStrategy('update_task'))
self.vrTestPipelineAction.triggered.connect(self.onTestVRPipeline)
self.vrDebugSettingsAction.triggered.connect(self.onShowVRDebugSettings)
def onCreateCesiumView(self):
if hasattr(self.world,'gui_manager') and self.world.gui_manager:
@ -2190,6 +2255,268 @@ class MainWindow(QMainWindow):
except Exception as e:
QMessageBox.critical(dialog, "错误", f"应用VR设置时发生错误\n{str(e)}")
# ==================== VR调试事件处理 ====================
def onToggleVRDebug(self):
"""切换VR调试输出"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
enabled = self.world.vr_manager.toggle_debug_output()
self.vrDebugToggleAction.setChecked(enabled)
status = "启用" if enabled else "禁用"
QMessageBox.information(self, "VR调试", f"VR调试输出已{status}")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"切换VR调试时发生错误\n{str(e)}")
def onShowVRPerformance(self):
"""立即显示VR性能报告"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
if self.world.vr_manager.vr_enabled:
self.world.vr_manager.force_performance_report()
QMessageBox.information(self, "VR性能", "性能报告已输出到控制台")
else:
QMessageBox.warning(self, "提示", "请先启用VR模式")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"显示VR性能报告时发生错误\n{str(e)}")
def onSetVRDebugMode(self, mode):
"""设置VR调试模式"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
self.world.vr_manager.set_debug_mode(mode)
# 更新菜单状态
if mode == 'brief':
self.vrDebugBriefAction.setChecked(True)
self.vrDebugDetailedAction.setChecked(False)
else:
self.vrDebugBriefAction.setChecked(False)
self.vrDebugDetailedAction.setChecked(True)
mode_name = "简短" if mode == 'brief' else "详细"
QMessageBox.information(self, "VR调试", f"调试模式已设置为:{mode_name}")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"设置VR调试模式时发生错误\n{str(e)}")
def onToggleVRPipelineMonitor(self):
"""切换VR管线监控"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
enabled = self.vrPipelineMonitorAction.isChecked()
self.world.vr_manager.enable_pipeline_monitoring = enabled
status = "启用" if enabled else "禁用"
print(f"✓ VR管线监控已{status}")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
self.vrPipelineMonitorAction.setChecked(False)
except Exception as e:
QMessageBox.critical(self, "错误", f"切换VR管线监控时发生错误\n{str(e)}")
def onSetVRPoseStrategy(self, strategy):
"""设置VR姿态策略"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
success = self.world.vr_manager.set_pose_strategy(strategy)
if success:
strategy_names = {
'render_callback': '渲染回调策略',
'update_task': '更新任务策略'
}
QMessageBox.information(self, "VR姿态策略",
f"姿态策略已切换为:{strategy_names.get(strategy, strategy)}")
else:
QMessageBox.warning(self, "错误", f"无效的姿态策略:{strategy}")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"设置VR姿态策略时发生错误\n{str(e)}")
def onTestVRPipeline(self):
"""测试VR管线监控功能"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
self.world.vr_manager.test_pipeline_monitoring()
QMessageBox.information(self, "VR管线测试", "管线监控测试已完成,请查看控制台输出。")
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"测试VR管线监控时发生错误\n{str(e)}")
def onShowVRDebugSettings(self):
"""显示VR调试设置对话框"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
dialog = self.createVRDebugSettingsDialog()
dialog.exec_()
else:
QMessageBox.warning(self, "错误", "VR管理器不可用")
except Exception as e:
QMessageBox.critical(self, "错误", f"打开VR调试设置时发生错误\n{str(e)}")
def createVRDebugSettingsDialog(self):
"""创建VR调试设置对话框"""
from PyQt5.QtWidgets import QCheckBox, QSlider
from PyQt5.QtCore import Qt
dialog = QDialog(self)
dialog.setWindowTitle("VR调试设置")
dialog.setModal(True)
dialog.resize(450, 400)
layout = QVBoxLayout(dialog)
# 获取当前设置
vr_manager = self.world.vr_manager
debug_status = vr_manager.get_debug_status()
perf_config = vr_manager.get_performance_monitoring_config()
# 调试状态显示
status_group = QGroupBox("调试状态")
status_layout = QVBoxLayout()
debug_enabled_label = QLabel(f"调试输出: {'启用' if debug_status['debug_enabled'] else '禁用'}")
debug_enabled_label.setStyleSheet(f"color: {'green' if debug_status['debug_enabled'] else 'red'};")
status_layout.addWidget(debug_enabled_label)
debug_mode_label = QLabel(f"调试模式: {debug_status['debug_mode']}")
status_layout.addWidget(debug_mode_label)
performance_label = QLabel(f"性能监控: {'启用' if debug_status['performance_monitoring'] else '禁用'}")
performance_label.setStyleSheet(f"color: {'green' if debug_status['performance_monitoring'] else 'red'};")
status_layout.addWidget(performance_label)
status_group.setLayout(status_layout)
layout.addWidget(status_group)
# 报告设置
report_group = QGroupBox("报告设置")
report_layout = QFormLayout()
# 报告间隔滑块 (5-120秒)
interval_slider = QSlider(Qt.Horizontal)
interval_slider.setMinimum(5)
interval_slider.setMaximum(120)
interval_slider.setValue(int(debug_status['report_interval_seconds']))
interval_slider.setTickPosition(QSlider.TicksBelow)
interval_slider.setTickInterval(15)
interval_label = QLabel(f"{int(debug_status['report_interval_seconds'])}")
interval_slider.valueChanged.connect(lambda v: interval_label.setText(f"{v}"))
interval_layout = QHBoxLayout()
interval_layout.addWidget(interval_slider)
interval_layout.addWidget(interval_label)
report_layout.addRow("报告间隔:", interval_layout)
# 性能检查间隔
check_interval_combo = QComboBox()
check_interval_combo.addItems(["0.1秒", "0.5秒", "1.0秒", "2.0秒"])
current_check_interval = perf_config['check_interval']
if current_check_interval == 0.1:
check_interval_combo.setCurrentIndex(0)
elif current_check_interval == 0.5:
check_interval_combo.setCurrentIndex(1)
elif current_check_interval == 1.0:
check_interval_combo.setCurrentIndex(2)
else:
check_interval_combo.setCurrentIndex(3)
report_layout.addRow("性能检查间隔:", check_interval_combo)
# 帧历史大小
frame_history_spin = QSpinBox()
frame_history_spin.setMinimum(10)
frame_history_spin.setMaximum(1000)
frame_history_spin.setValue(perf_config['frame_history_size'])
frame_history_spin.setSuffix("")
report_layout.addRow("帧时间历史:", frame_history_spin)
report_group.setLayout(report_layout)
layout.addWidget(report_group)
# 监控项目
monitor_group = QGroupBox("监控项目")
monitor_layout = QVBoxLayout()
cpu_check = QCheckBox("CPU使用率")
cpu_check.setChecked(perf_config['psutil_available'])
cpu_check.setEnabled(perf_config['psutil_available'])
monitor_layout.addWidget(cpu_check)
memory_check = QCheckBox("内存使用率")
memory_check.setChecked(perf_config['psutil_available'])
memory_check.setEnabled(perf_config['psutil_available'])
monitor_layout.addWidget(memory_check)
gpu_check = QCheckBox("GPU使用率")
gpu_check.setChecked(perf_config['gputil_available'] or perf_config['nvidia_ml_available'])
gpu_check.setEnabled(perf_config['gputil_available'] or perf_config['nvidia_ml_available'])
monitor_layout.addWidget(gpu_check)
frame_time_check = QCheckBox("帧时间统计")
frame_time_check.setChecked(True)
monitor_layout.addWidget(frame_time_check)
monitor_group.setLayout(monitor_layout)
layout.addWidget(monitor_group)
# 按钮
button_layout = QHBoxLayout()
apply_button = QPushButton("应用")
reset_button = QPushButton("重置计数器")
ok_button = QPushButton("确定")
cancel_button = QPushButton("取消")
button_layout.addWidget(apply_button)
button_layout.addWidget(reset_button)
button_layout.addStretch()
button_layout.addWidget(ok_button)
button_layout.addWidget(cancel_button)
layout.addLayout(button_layout)
# 连接信号
def apply_settings():
try:
# 应用报告间隔
new_interval_seconds = interval_slider.value()
new_interval_frames = int(new_interval_seconds * 60) # 假设60fps
vr_manager.set_performance_report_interval(new_interval_frames)
# 应用性能检查间隔
check_intervals = [0.1, 0.5, 1.0, 2.0]
new_check_interval = check_intervals[check_interval_combo.currentIndex()]
vr_manager.set_performance_check_interval(new_check_interval)
# 应用帧历史大小
vr_manager.set_frame_time_history_size(frame_history_spin.value())
QMessageBox.information(dialog, "成功", "VR调试设置已应用")
except Exception as e:
QMessageBox.critical(dialog, "错误", f"应用设置时发生错误:\n{str(e)}")
def reset_counters():
try:
vr_manager.reset_performance_counters()
QMessageBox.information(dialog, "成功", "性能计数器已重置!")
except Exception as e:
QMessageBox.critical(dialog, "错误", f"重置计数器时发生错误:\n{str(e)}")
apply_button.clicked.connect(apply_settings)
reset_button.clicked.connect(reset_counters)
ok_button.clicked.connect(lambda: (apply_settings(), dialog.accept()))
cancel_button.clicked.connect(dialog.reject)
return dialog
def setup_main_window(world,path = None):
"""设置主窗口的便利函数"""
app = QApplication.instance()