Files
jmwright-CQ-Editor/cq_editor/widgets/occt_widget.py
2023-03-13 13:37:25 -05:00

176 lines
4.7 KiB
Python

from sys import platform
from PyQt5.QtWidgets import QWidget, QApplication
from PyQt5.QtCore import pyqtSlot, 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
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), Quantity_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
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())