""" VR控制面板 提供VR系统的GUI控制界面 包括VR启用/禁用、ALVR串流控制、性能监控等功能 """ from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QPushButton, QLabel, QProgressBar, QSlider, QSpinBox, QCheckBox, QComboBox, QTextEdit, QGridLayout, QFrame, QSizePolicy) from PyQt5.QtCore import Qt, QTimer, pyqtSignal from PyQt5.QtGui import QFont, QColor, QPalette class VRControlPanel(QWidget): """VR控制面板""" # 信号定义 vr_enabled = pyqtSignal(bool) alvr_streaming_changed = pyqtSignal(bool) def __init__(self, world, parent=None): super().__init__(parent) self.world = world self.setupUI() self.connectSignals() # 设置更新定时器 self.update_timer = QTimer() self.update_timer.timeout.connect(self.updateStatus) self.update_timer.start(1000) # 每秒更新一次 def setupUI(self): """设置界面""" self.setWindowTitle("VR控制面板") self.setMinimumSize(400, 600) # 主布局 main_layout = QVBoxLayout(self) # VR系统控制组 vr_control_group = self.createVRControlGroup() main_layout.addWidget(vr_control_group) # ALVR串流控制组 alvr_control_group = self.createALVRControlGroup() main_layout.addWidget(alvr_control_group) # 性能监控组 performance_group = self.createPerformanceGroup() main_layout.addWidget(performance_group) # 控制器状态组 controller_group = self.createControllerGroup() main_layout.addWidget(controller_group) # 日志输出组 log_group = self.createLogGroup() main_layout.addWidget(log_group) # 添加弹性空间 main_layout.addStretch() def createVRControlGroup(self): """创建VR系统控制组""" group = QGroupBox("VR系统控制") layout = QVBoxLayout(group) # 状态指示器 self.vr_status_label = QLabel("VR状态: 未启用") self.vr_status_label.setStyleSheet("color: red; font-weight: bold;") layout.addWidget(self.vr_status_label) # 启用/禁用VR按钮 button_layout = QHBoxLayout() self.enable_vr_button = QPushButton("启用VR") self.enable_vr_button.clicked.connect(self.enableVR) button_layout.addWidget(self.enable_vr_button) self.disable_vr_button = QPushButton("禁用VR") self.disable_vr_button.clicked.connect(self.disableVR) self.disable_vr_button.setEnabled(False) button_layout.addWidget(self.disable_vr_button) layout.addLayout(button_layout) # VR设备信息 self.vr_info_label = QLabel("VR设备: 未连接") layout.addWidget(self.vr_info_label) # VR选项 options_layout = QGridLayout() # 控制器射线显示 self.show_rays_checkbox = QCheckBox("显示控制器射线") self.show_rays_checkbox.stateChanged.connect(self.toggleControllerRays) options_layout.addWidget(self.show_rays_checkbox, 0, 0) # 手势识别 self.gesture_checkbox = QCheckBox("启用手势识别") self.gesture_checkbox.stateChanged.connect(self.toggleGestureRecognition) options_layout.addWidget(self.gesture_checkbox, 0, 1) # VR交互 self.interaction_checkbox = QCheckBox("启用VR交互") self.interaction_checkbox.setChecked(True) self.interaction_checkbox.stateChanged.connect(self.toggleVRInteraction) options_layout.addWidget(self.interaction_checkbox, 1, 0) layout.addLayout(options_layout) return group def createALVRControlGroup(self): """创建ALVR串流控制组""" group = QGroupBox("ALVR串流控制") layout = QVBoxLayout(group) # 连接状态 self.alvr_status_label = QLabel("ALVR状态: 未连接") self.alvr_status_label.setStyleSheet("color: red; font-weight: bold;") layout.addWidget(self.alvr_status_label) # 串流控制按钮 button_layout = QHBoxLayout() self.start_streaming_button = QPushButton("开始串流") self.start_streaming_button.clicked.connect(self.startStreaming) self.start_streaming_button.setEnabled(False) button_layout.addWidget(self.start_streaming_button) self.stop_streaming_button = QPushButton("停止串流") self.stop_streaming_button.clicked.connect(self.stopStreaming) self.stop_streaming_button.setEnabled(False) button_layout.addWidget(self.stop_streaming_button) layout.addLayout(button_layout) # 串流质量设置 quality_layout = QGridLayout() # 分辨率 quality_layout.addWidget(QLabel("分辨率宽度:"), 0, 0) self.width_spinbox = QSpinBox() self.width_spinbox.setRange(1920, 4096) self.width_spinbox.setValue(2880) self.width_spinbox.setSuffix(" px") quality_layout.addWidget(self.width_spinbox, 0, 1) quality_layout.addWidget(QLabel("分辨率高度:"), 1, 0) self.height_spinbox = QSpinBox() self.height_spinbox.setRange(1080, 2160) self.height_spinbox.setValue(1700) self.height_spinbox.setSuffix(" px") quality_layout.addWidget(self.height_spinbox, 1, 1) # 帧率 quality_layout.addWidget(QLabel("帧率:"), 2, 0) self.fps_spinbox = QSpinBox() self.fps_spinbox.setRange(60, 120) self.fps_spinbox.setValue(72) self.fps_spinbox.setSuffix(" fps") quality_layout.addWidget(self.fps_spinbox, 2, 1) # 比特率 quality_layout.addWidget(QLabel("比特率:"), 3, 0) self.bitrate_spinbox = QSpinBox() self.bitrate_spinbox.setRange(50, 500) self.bitrate_spinbox.setValue(150) self.bitrate_spinbox.setSuffix(" Mbps") quality_layout.addWidget(self.bitrate_spinbox, 3, 1) layout.addLayout(quality_layout) # 应用设置按钮 self.apply_quality_button = QPushButton("应用质量设置") self.apply_quality_button.clicked.connect(self.applyQualitySettings) layout.addWidget(self.apply_quality_button) return group def createPerformanceGroup(self): """创建性能监控组""" group = QGroupBox("性能监控") layout = QGridLayout(group) # FPS显示 layout.addWidget(QLabel("渲染FPS:"), 0, 0) self.fps_label = QLabel("0") self.fps_label.setStyleSheet("font-weight: bold; color: blue;") layout.addWidget(self.fps_label, 0, 1) # 串流FPS layout.addWidget(QLabel("串流FPS:"), 1, 0) self.stream_fps_label = QLabel("0") self.stream_fps_label.setStyleSheet("font-weight: bold; color: green;") layout.addWidget(self.stream_fps_label, 1, 1) # 延迟 layout.addWidget(QLabel("延迟:"), 2, 0) self.latency_label = QLabel("0 ms") self.latency_label.setStyleSheet("font-weight: bold; color: orange;") layout.addWidget(self.latency_label, 2, 1) # 性能进度条 layout.addWidget(QLabel("CPU使用率:"), 3, 0) self.cpu_progress = QProgressBar() self.cpu_progress.setRange(0, 100) layout.addWidget(self.cpu_progress, 3, 1) layout.addWidget(QLabel("GPU使用率:"), 4, 0) self.gpu_progress = QProgressBar() self.gpu_progress.setRange(0, 100) layout.addWidget(self.gpu_progress, 4, 1) return group def createControllerGroup(self): """创建控制器状态组""" group = QGroupBox("控制器状态") layout = QVBoxLayout(group) # 控制器列表 self.controller_list = QTextEdit() self.controller_list.setMaximumHeight(100) self.controller_list.setReadOnly(True) layout.addWidget(self.controller_list) # 触觉反馈测试 haptic_layout = QHBoxLayout() haptic_layout.addWidget(QLabel("触觉反馈测试:")) self.haptic_button = QPushButton("发送震动") self.haptic_button.clicked.connect(self.sendHapticFeedback) haptic_layout.addWidget(self.haptic_button) layout.addLayout(haptic_layout) return group def createLogGroup(self): """创建日志输出组""" group = QGroupBox("系统日志") layout = QVBoxLayout(group) self.log_text = QTextEdit() self.log_text.setMaximumHeight(150) self.log_text.setReadOnly(True) layout.addWidget(self.log_text) # 清空日志按钮 clear_button = QPushButton("清空日志") clear_button.clicked.connect(self.clearLog) layout.addWidget(clear_button) return group def connectSignals(self): """连接信号""" # 连接值变化信号 self.width_spinbox.valueChanged.connect(self.onQualityChanged) self.height_spinbox.valueChanged.connect(self.onQualityChanged) self.fps_spinbox.valueChanged.connect(self.onQualityChanged) self.bitrate_spinbox.valueChanged.connect(self.onQualityChanged) def enableVR(self): """启用VR""" self.addLog("正在启用VR模式...") if self.world.enableVRMode(): self.addLog("✓ VR模式已启用") self.vr_enabled.emit(True) else: self.addLog("✗ VR模式启用失败") def disableVR(self): """禁用VR""" self.addLog("正在禁用VR模式...") self.world.disableVRMode() self.addLog("✓ VR模式已禁用") self.vr_enabled.emit(False) def startStreaming(self): """开始串流""" self.addLog("正在开始ALVR串流...") if self.world.startALVRStreaming(): self.addLog("✓ ALVR串流已开始") self.alvr_streaming_changed.emit(True) else: self.addLog("✗ ALVR串流开始失败") def stopStreaming(self): """停止串流""" self.addLog("正在停止ALVR串流...") self.world.stopALVRStreaming() self.addLog("✓ ALVR串流已停止") self.alvr_streaming_changed.emit(False) def toggleControllerRays(self, checked): """切换控制器射线显示""" self.world.showControllerRays(checked) self.addLog(f"控制器射线: {'显示' if checked else '隐藏'}") def toggleGestureRecognition(self, checked): """切换手势识别""" self.world.setVRGestureEnabled(checked) self.addLog(f"手势识别: {'启用' if checked else '禁用'}") def toggleVRInteraction(self, checked): """切换VR交互""" self.world.setVRInteractionEnabled(checked) self.addLog(f"VR交互: {'启用' if checked else '禁用'}") def applyQualitySettings(self): """应用质量设置""" width = self.width_spinbox.value() height = self.height_spinbox.value() fps = self.fps_spinbox.value() bitrate = self.bitrate_spinbox.value() self.world.setALVRStreamQuality(width, height, fps, bitrate) self.addLog(f"串流质量已设置: {width}x{height} @ {fps}fps, {bitrate}Mbps") def sendHapticFeedback(self): """发送触觉反馈""" controllers = self.world.getAllControllers() if controllers: controller_id = controllers[0] # 使用第一个控制器 self.world.sendHapticFeedback(controller_id, 0.5, 0.8) self.addLog(f"已发送触觉反馈到控制器 {controller_id}") else: self.addLog("没有可用的控制器") def onQualityChanged(self): """质量设置变化""" # 可以在这里实现实时质量调整 pass def updateStatus(self): """更新状态显示""" # 更新VR状态 vr_status = self.world.getVRStatus() # VR系统状态 if vr_status['vr_enabled']: self.vr_status_label.setText("VR状态: 已启用") self.vr_status_label.setStyleSheet("color: green; font-weight: bold;") self.enable_vr_button.setEnabled(False) self.disable_vr_button.setEnabled(True) # 更新VR设备信息 vr_info = vr_status['vr_info'] if vr_info: device_info = f"VR设备: {vr_info.get('hmd_manufacturer', 'Unknown')} {vr_info.get('hmd_model', 'Unknown')}" self.vr_info_label.setText(device_info) else: self.vr_status_label.setText("VR状态: 未启用") self.vr_status_label.setStyleSheet("color: red; font-weight: bold;") self.enable_vr_button.setEnabled(True) self.disable_vr_button.setEnabled(False) self.vr_info_label.setText("VR设备: 未连接") # ALVR状态 if vr_status['alvr_connected']: self.alvr_status_label.setText("ALVR状态: 已连接") self.alvr_status_label.setStyleSheet("color: green; font-weight: bold;") self.start_streaming_button.setEnabled(not vr_status['alvr_streaming']) self.stop_streaming_button.setEnabled(vr_status['alvr_streaming']) else: self.alvr_status_label.setText("ALVR状态: 未连接") self.alvr_status_label.setStyleSheet("color: red; font-weight: bold;") self.start_streaming_button.setEnabled(False) self.stop_streaming_button.setEnabled(False) # 性能统计 streaming_status = vr_status['streaming_status'] if streaming_status: self.stream_fps_label.setText(str(streaming_status.get('fps', 0))) self.latency_label.setText(f"{streaming_status.get('latency', 0)} ms") # 控制器状态 controllers = vr_status['controllers'] if controllers: controller_text = f"已连接 {len(controllers)} 个控制器:\n" for i, controller_id in enumerate(controllers): controller_text += f"控制器 {i+1}: ID {controller_id}\n" self.controller_list.setText(controller_text) else: self.controller_list.setText("没有连接的控制器") def addLog(self, message): """添加日志""" import datetime timestamp = datetime.datetime.now().strftime("%H:%M:%S") log_message = f"[{timestamp}] {message}" self.log_text.append(log_message) print(log_message) # 同时输出到控制台 def clearLog(self): """清空日志""" self.log_text.clear() def closeEvent(self, event): """关闭事件""" # 停止更新定时器 if hasattr(self, 'update_timer'): self.update_timer.stop() # 如果VR启用,先禁用 if self.world.isVREnabled(): self.disableVR() event.accept()