Files
2026-04-29 08:18:54 +04:00

117 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- 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