117 lines
4.8 KiB
Python
117 lines
4.8 KiB
Python
# -*- coding: utf-8 -*-
|
||
# gui/components/model_view/_scenario_camera.py
|
||
"""Камерный сценарий — базовый слой, всегда активен.
|
||
|
||
Обрабатывает ПКМ (вращение), СКМ (панорамирование), подавление ЛКМ drag.
|
||
Политика камеры текущего доменного сценария определяет, работает ли этот слой.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from typing import TYPE_CHECKING
|
||
|
||
from PySide6.QtCore import Qt
|
||
from PySide6.QtGui import QGuiApplication
|
||
|
||
from gui.components.model_view._interaction_scenario import (
|
||
CameraPolicy,
|
||
InteractionScenario,
|
||
)
|
||
from error_logger import log_exception
|
||
|
||
if TYPE_CHECKING: # pragma: no cover
|
||
from gui.components.model_view_widget import ModelViewWidget
|
||
|
||
|
||
class CameraScenario(InteractionScenario):
|
||
"""Базовый камерный слой: вращение (ПКМ), панорамирование (СКМ)."""
|
||
|
||
name = "camera"
|
||
camera_policy = CameraPolicy.FREE
|
||
|
||
def on_mouse_press(self, mv: "ModelViewWidget", event) -> bool:
|
||
if event.button() == Qt.MouseButton.RightButton:
|
||
# В режиме контура ПКМ передаётся PyVista (remove point)
|
||
if mv._zone_selection_mode and mv.is_scenario_active("contour_edit"):
|
||
return False
|
||
mv._cam_rotate_active = True
|
||
mv._cam_last_pos = (event.position().x(), event.position().y())
|
||
return True
|
||
|
||
if event.button() == Qt.MouseButton.MiddleButton:
|
||
mv._cam_pan_active = True
|
||
mv._cam_last_pos = (event.position().x(), event.position().y())
|
||
return True
|
||
return False
|
||
|
||
def on_mouse_move(self, mv: "ModelViewWidget", event) -> bool:
|
||
# Safeguard: если release-событие потерялось (после модалок/фокуса),
|
||
# синхронизируем drag-флаги с реальным состоянием кнопок мыши.
|
||
try:
|
||
real_buttons = QGuiApplication.mouseButtons()
|
||
except Exception as _exc:
|
||
real_buttons = Qt.MouseButton.NoButton
|
||
if mv._cam_rotate_active and not (real_buttons & Qt.MouseButton.RightButton):
|
||
mv._cam_rotate_active = False
|
||
mv._cam_last_pos = None
|
||
if mv._cam_pan_active and not (real_buttons & Qt.MouseButton.MiddleButton):
|
||
mv._cam_pan_active = False
|
||
mv._cam_last_pos = None
|
||
|
||
# Подавление ЛКМ drag (не конфликтует с click-сценариями)
|
||
if hasattr(event, "buttons") and (event.buttons() & Qt.MouseButton.LeftButton):
|
||
return True
|
||
|
||
# ПКМ drag → вращение камеры
|
||
if (
|
||
mv._cam_rotate_active
|
||
and hasattr(event, "buttons")
|
||
and (event.buttons() & Qt.MouseButton.RightButton)
|
||
):
|
||
cx, cy = mv._cam_last_pos or (event.position().x(), event.position().y())
|
||
nx, ny = event.position().x(), event.position().y()
|
||
dx, dy = float(nx - cx), float(ny - cy)
|
||
mv._cam_last_pos = (nx, ny)
|
||
try:
|
||
cam = mv._plotter.camera
|
||
cam.Azimuth(-dx * 0.35)
|
||
cam.Elevation(dy * 0.35)
|
||
cam.OrthogonalizeViewUp()
|
||
if hasattr(mv, "_reset_camera_clipping_range"):
|
||
mv._reset_camera_clipping_range()
|
||
mv._safe_render(min_interval_s=1.0 / 75.0)
|
||
except Exception as _exc:
|
||
log_exception(__name__, "on_mouse_move", _exc)
|
||
return True
|
||
|
||
# СКМ drag → панорамирование
|
||
if (
|
||
mv._cam_pan_active
|
||
and hasattr(event, "buttons")
|
||
and (event.buttons() & Qt.MouseButton.MiddleButton)
|
||
):
|
||
cx, cy = mv._cam_last_pos or (event.position().x(), event.position().y())
|
||
nx, ny = event.position().x(), event.position().y()
|
||
dx, dy = float(nx - cx), float(ny - cy)
|
||
mv._cam_last_pos = (nx, ny)
|
||
mv._pan_camera_by_pixels(dx, dy)
|
||
try:
|
||
if hasattr(mv, "_reset_camera_clipping_range"):
|
||
mv._reset_camera_clipping_range()
|
||
mv._safe_render(min_interval_s=1.0 / 75.0)
|
||
except Exception as _exc:
|
||
log_exception(__name__, "on_mouse_move", _exc)
|
||
return True
|
||
return False
|
||
|
||
def on_mouse_release(self, mv: "ModelViewWidget", event) -> bool:
|
||
if event.button() == Qt.MouseButton.RightButton:
|
||
mv._cam_rotate_active = False
|
||
mv._cam_last_pos = None
|
||
return True
|
||
if event.button() == Qt.MouseButton.MiddleButton:
|
||
mv._cam_pan_active = False
|
||
mv._cam_last_pos = None
|
||
return True
|
||
return False
|