summaryrefslogtreecommitdiff
path: root/plugins/motion_capture/camera_panel.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/motion_capture/camera_panel.py')
-rw-r--r--plugins/motion_capture/camera_panel.py117
1 files changed, 42 insertions, 75 deletions
diff --git a/plugins/motion_capture/camera_panel.py b/plugins/motion_capture/camera_panel.py
index 611c942..5e25f7f 100644
--- a/plugins/motion_capture/camera_panel.py
+++ b/plugins/motion_capture/camera_panel.py
@@ -1,17 +1,25 @@
"""
motion_capture/camera_panel.py
-CameraPanel for AddDeviceDialog — scans for OpenCV cameras and builds
-a CameraDevice when the user clicks "Add Device".
+CameraPanel for AddDeviceDialog.
+Camera discovery and simulation toggle are handled by AddDeviceDialog.
+CameraScanThread is kept here and used by the unified scanner.
"""
from __future__ import annotations
+from typing import Optional, Tuple
-from PyQt6.QtCore import Qt, QThread, pyqtSignal
-from PyQt6.QtWidgets import (
- QCheckBox, QGroupBox, QHBoxLayout, QLabel, QListWidget,
- QListWidgetItem, QPushButton, QVBoxLayout, QWidget,
-)
+from PyQt6.QtCore import QThread, pyqtSignal
+from PyQt6.QtWidgets import QComboBox, QFormLayout, QLabel, QVBoxLayout, QWidget
+
+
+_RESOLUTIONS = {
+ "Default": None,
+ "640 × 480": (640, 480),
+ "1280 × 720": (1280, 720),
+ "1920 × 1080": (1920, 1080),
+ "2560 × 1440": (2560, 1440),
+}
class CameraScanThread(QThread):
@@ -40,44 +48,24 @@ class CameraPanel(QWidget):
def __init__(self):
super().__init__()
- self._cameras: list = []
- self._selected_index: int = 0
- self._scanner = None
+ self._selected_index: int = 0
+ self._simulate: bool = False
lay = QVBoxLayout(self)
lay.setContentsMargins(0, 4, 0, 4)
lay.setSpacing(8)
- self.sim_chk = QCheckBox("Simulation mode (Lissajous pattern, no camera needed)")
- self.sim_chk.setChecked(False)
- lay.addWidget(self.sim_chk)
-
- scan_grp = QGroupBox("Available Cameras")
- sg = QVBoxLayout(scan_grp)
- sg.setSpacing(4)
-
- top = QHBoxLayout()
- self._scan_btn = QPushButton("🔍 Scan Cameras")
- self._scan_btn.setObjectName("addTraceBtn")
- self._scan_btn.clicked.connect(self._scan)
- self._status = QLabel("Click Scan to detect cameras")
- self._status.setObjectName("traceSource")
- top.addWidget(self._scan_btn)
- top.addWidget(self._status, 1)
- sg.addLayout(top)
-
- self._list = QListWidget()
- self._list.setMaximumHeight(120)
- self._list.setObjectName("portList")
- self._list.itemClicked.connect(self._on_select)
- self._list.setToolTip("Click a camera to select it")
- sg.addWidget(self._list)
-
- hint = QLabel("↑ Click a camera above to select it")
- hint.setObjectName("traceSource")
- sg.addWidget(hint)
-
- lay.addWidget(scan_grp)
+ self._selected_lbl = QLabel("No camera selected — scan above and click a camera")
+ self._selected_lbl.setObjectName("traceSource")
+ self._selected_lbl.setWordWrap(True)
+ lay.addWidget(self._selected_lbl)
+
+ form = QFormLayout()
+ form.setContentsMargins(0, 0, 0, 0)
+ self.res_cb = QComboBox()
+ self.res_cb.addItems(list(_RESOLUTIONS.keys()))
+ form.addRow("Resolution:", self.res_cb)
+ lay.addLayout(form)
note = QLabel(
"Requires OpenCV: pip install opencv-python\n"
@@ -88,45 +76,24 @@ class CameraPanel(QWidget):
lay.addWidget(note)
lay.addStretch()
- # ── Scan ─────────────────────────────────────────────────────────────
-
- def _scan(self):
- self._scan_btn.setEnabled(False)
- self._status.setText("Scanning…")
- self._list.clear()
- self._scanner = CameraScanThread()
- self._scanner.cameras_found.connect(self._on_found)
- self._scanner.start()
-
- def _on_found(self, cameras):
- self._scan_btn.setEnabled(True)
- self._cameras = cameras
- self._list.clear()
- if not cameras:
- self._status.setText("No cameras found")
- item = QListWidgetItem(" No cameras detected")
- item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsSelectable)
- self._list.addItem(item)
- else:
- self._status.setText(f"{len(cameras)} camera(s) found")
- for idx, label in cameras:
- item = QListWidgetItem(f" {label}")
- item.setData(Qt.ItemDataRole.UserRole, idx)
- self._list.addItem(item)
- self._list.setCurrentRow(0)
- self._selected_index = cameras[0][0]
-
- def _on_select(self, item: QListWidgetItem):
- idx = item.data(Qt.ItemDataRole.UserRole)
- if idx is not None:
- self._selected_index = idx
-
- # ── Build ─────────────────────────────────────────────────────────────
+ def is_valid(self) -> bool:
+ return True
+
+ def set_simulate(self, simulate: bool):
+ self._simulate = simulate
+
+ def set_camera_index(self, index: int):
+ self._selected_index = index
+ self._selected_lbl.setText(f"Selected: Camera {index}")
def build_device(self, device_id: str):
from device import CameraDevice
+ resolution: Optional[Tuple[int, int]] = _RESOLUTIONS.get(
+ self.res_cb.currentText()
+ )
return CameraDevice(
device_id=device_id,
camera_index=self._selected_index,
- simulate=self.sim_chk.isChecked(),
+ simulate=self._simulate,
+ resolution=resolution,
)