Files
jmwright-CQ-Editor/cq_editor/widgets/occt_widget.py
2023-10-11 12:11:37 -05:00

159 lines
4.3 KiB
Python

from sys import platform
from PySide6.QtWidgets import QWidget, QApplication
from PySide6.QtCore import Slot as pyqtSlot, Signal as pyqtSignal, Qt, QEvent
import OCP
from OCP.Aspect import Aspect_DisplayConnection, Aspect_TypeOfTriedronPosition
from OCP.OpenGl import OpenGl_GraphicDriver
from OCP.V3d import V3d_Viewer
from OCP.AIS import AIS_InteractiveContext, AIS_DisplayMode
from OCP.Quantity import Quantity_Color, Quantity_TOC_RGB as TOC_RGB
ZOOM_STEP = 0.9
class OCCTWidget(QWidget):
sigObjectSelected = pyqtSignal(list)
def __init__(self, parent=None):
super(OCCTWidget, self).__init__(parent)
self.setAttribute(Qt.WA_NativeWindow)
self.setAttribute(Qt.WA_PaintOnScreen)
self.setAttribute(Qt.WA_NoSystemBackground)
self._initialized = False
self._needs_update = False
# OCCT secific things
self.display_connection = Aspect_DisplayConnection()
self.graphics_driver = OpenGl_GraphicDriver(self.display_connection)
self.viewer = V3d_Viewer(self.graphics_driver)
self.view = self.viewer.CreateView()
self.context = AIS_InteractiveContext(self.viewer)
# Trihedorn, lights, etc
self.prepare_display()
def prepare_display(self):
view = self.view
params = view.ChangeRenderingParams()
params.NbMsaaSamples = 8
params.IsAntialiasingEnabled = True
view.TriedronDisplay(
Aspect_TypeOfTriedronPosition.Aspect_TOTP_RIGHT_LOWER, Quantity_Color(), 0.1
)
view.ZBufferTriedronSetup(Quantity_Color(*(0.2, 0.0, 0.0), TOC_RGB))
viewer = self.viewer
viewer.SetDefaultLights()
viewer.SetLightOn()
ctx = self.context
ctx.SetDisplayMode(AIS_DisplayMode.AIS_Shaded, True)
ctx.DefaultDrawer().SetFaceBoundaryDraw(True)
def wheelEvent(self, event):
delta = event.angleDelta().y()
factor = ZOOM_STEP if delta < 0 else 1 / ZOOM_STEP
self.view.SetZoom(factor)
def mousePressEvent(self, event):
pos = event.pos()
if event.button() == Qt.LeftButton:
self.view.StartRotation(pos.x(), pos.y())
elif event.button() == Qt.RightButton:
self.view.StartZoomAtPoint(pos.x(), pos.y())
self.old_pos = pos
def mouseMoveEvent(self, event):
pos = event.pos()
x, y = pos.x(), pos.y()
if event.buttons() == Qt.LeftButton:
self.view.Rotation(x, y)
elif event.buttons() == Qt.MiddleButton:
self.view.Pan(x - self.old_pos.x(), self.old_pos.y() - y, theToStart=True)
elif event.buttons() == Qt.RightButton:
self.view.Pan(x - self.old_pos.x(), self.old_pos.y() - y, theToStart=True)
self.old_pos = pos
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
pos = event.pos()
x, y = pos.x(), pos.y()
self.context.MoveTo(x, y, self.view, True)
self._handle_selection()
def _handle_selection(self):
self.context.Select(True)
self.context.InitSelected()
selected = []
if self.context.HasSelectedShape():
selected.append(self.context.SelectedShape())
self.sigObjectSelected.emit(selected)
def paintEngine(self):
return None
def paintEvent(self, event):
if not self._initialized:
self._initialize()
else:
self.view.Redraw()
def showEvent(self, event):
super(OCCTWidget, self).showEvent(event)
def resizeEvent(self, event):
super(OCCTWidget, self).resizeEvent(event)
self.view.MustBeResized()
def _initialize(self):
wins = {
"darwin": self._get_window_osx,
"linux": self._get_window_linux,
"win32": self._get_window_win,
}
self.view.SetWindow(wins.get(platform, self._get_window_linux)(self.winId()))
self._initialized = True
def _get_window_win(self, wid):
from OCP.WNT import WNT_Window
print(wid)
return WNT_Window(wid.ascapsule())
def _get_window_linux(self, wid):
from OCP.Xw import Xw_Window
return Xw_Window(self.display_connection, int(wid))
def _get_window_osx(self, wid):
from OCP.Cocoa import Cocoa_Window
return Cocoa_Window(wid.ascapsule())