| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import FreeCAD |
| | import FreeCADGui |
| | import Path |
| |
|
| | |
| | from lazy_loader.lazy_loader import LazyLoader |
| |
|
| | Draft = LazyLoader("Draft", globals(), "Draft") |
| |
|
| | from PySide import QtCore, QtGui |
| | from pivy import coin |
| |
|
| | __title__ = "CAM GetPoint UI" |
| | __author__ = "sliptonic (Brad Collette)" |
| | __url__ = "https://www.freecad.org" |
| | __doc__ = "Helper class to use FreeCADGUi.Snapper to let the user enter arbitrary points while the task panel is active." |
| |
|
| | Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) |
| | |
| |
|
| |
|
| | class TaskPanel: |
| | """Use an instance of this class in another TaskPanel to invoke the snapper. |
| | Create the instance in the TaskPanel's constructors and invoke getPoint(whenDone, start) whenever a new point is |
| | required or an existing point needs to be edited. The receiver is expected to have the same lifespan as the form |
| | provided in the constructor. |
| | The (only) public API function other than the constructor is getPoint(whenDone, start). |
| | """ |
| |
|
| | def __init__(self, form, onPath=False): |
| | """__init___(form) ... form will be replaced by PointEdit.ui while the Snapper is active.""" |
| | self.formOrig = form |
| | self.formPoint = FreeCADGui.PySideUic.loadUi(":/panels/PointEdit.ui") |
| |
|
| | self.formPoint.setParent(form.parent()) |
| | form.parent().layout().addWidget(self.formPoint) |
| | self.formPoint.hide() |
| |
|
| | self.setupUi() |
| | self.buttonBox = None |
| | self.onPath = onPath |
| | self.obj = None |
| |
|
| | self.pt = None |
| | self.point = None |
| | self.pointCbClick = None |
| | self.pointCbMove = None |
| | self.pointWhenDone = None |
| | self.escape = None |
| | self.view = None |
| |
|
| | def setupUi(self): |
| | """setupUi() ... internal function - do not call.""" |
| | self.formPoint.buttonBox.accepted.connect(self.pointAccept) |
| | self.formPoint.buttonBox.rejected.connect(self.pointReject) |
| |
|
| | self.formPoint.XGlobal.editingFinished.connect(self.updatePoint) |
| | self.formPoint.YGlobal.editingFinished.connect(self.updatePoint) |
| | self.formPoint.ZGlobal.editingFinished.connect(self.updatePoint) |
| |
|
| | self.formPoint.XGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) |
| | self.formPoint.YGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) |
| | self.formPoint.ZGlobal.setProperty("unit", FreeCAD.Units.MilliMetre.getUserPreferred()[2]) |
| |
|
| | def addEscapeShortcut(self): |
| | """addEscapeShortcut() ... internal function - do not call.""" |
| | |
| | |
| | self.escape = QtGui.QAction(self.formPoint) |
| | self.escape.setText("Done") |
| | self.escape.setShortcut(QtGui.QKeySequence.fromString("Esc")) |
| | QtCore.QObject.connect(self.escape, QtCore.SIGNAL("triggered()"), self.pointDone) |
| | self.formPoint.addAction(self.escape) |
| |
|
| | def removeEscapeShortcut(self): |
| | """removeEscapeShortcut() ... internal function - do not call.""" |
| | if self.escape: |
| | self.formPoint.removeAction(self.escape) |
| | self.escape = None |
| |
|
| | def getPoint(self, whenDone, start=None): |
| | """getPoint(whenDone, start=None) ... invoke Snapper and call whenDone when a point is entered or the user cancels the operation. |
| | whenDone(point, obj) is called either with a point and the object on which the point lies if the user set the point, |
| | or None and None if the user cancelled the operation. |
| | start is an optional Vector indicating from where to start Snapper. This is mostly used when editing existing points. Snapper also |
| | creates a dotted line indicating from where the original point started from. |
| | If start is specified the Snapper UI is closed on the first point the user enters. If start remains None, then Snapper is kept open |
| | until the user explicitly closes Snapper. This lets the user enter multiple points in quick succession. |
| | """ |
| |
|
| | |
| | if not hasattr(FreeCADGui, "Snapper"): |
| | import DraftTools |
| |
|
| | def displayPoint(p): |
| | self.point = p |
| | self.formPoint.XGlobal.setProperty("rawValue", p.x) |
| | self.formPoint.YGlobal.setProperty("rawValue", p.y) |
| | self.formPoint.ZGlobal.setProperty("rawValue", p.z) |
| | self.formPoint.XGlobal.setFocus() |
| | self.formPoint.XGlobal.selectAll() |
| |
|
| | def mouseMove(cb): |
| | p = None |
| | event = cb.getEvent() |
| | pos = event.getPosition() |
| | if self.onPath: |
| | |
| | |
| | |
| | screenpos = tuple(pos.getValue()) |
| | snapInfo = Draft.get3DView().getObjectInfo(screenpos) |
| | if snapInfo: |
| | obj = FreeCAD.ActiveDocument.getObject(snapInfo["Object"]) |
| | if hasattr(obj, "Path"): |
| | self.obj = obj |
| | p = FreeCAD.Vector(snapInfo["x"], snapInfo["y"], snapInfo["z"]) |
| | self.pt = p |
| | else: |
| | self.obj = None |
| | else: |
| | |
| | cntrl = event.wasCtrlDown() |
| | shift = event.wasShiftDown() |
| | self.pt = FreeCADGui.Snapper.snap( |
| | pos, lastpoint=start, active=cntrl, constrain=shift |
| | ) |
| | plane = FreeCAD.DraftWorkingPlane |
| | p = plane.getLocalCoords(self.pt) |
| | self.obj = FreeCADGui.Snapper.lastSnappedObject |
| |
|
| | if p: |
| | displayPoint(p) |
| |
|
| | def click(cb): |
| | event = cb.getEvent() |
| | if event.getButton() == 1 and event.getState() == coin.SoMouseButtonEvent.DOWN: |
| | if self.obj: |
| | accept() |
| |
|
| | def accept(): |
| | if start: |
| | self.pointAccept() |
| | else: |
| | self.pointAcceptAndContinue() |
| |
|
| | def cancel(): |
| | self.pointReject() |
| |
|
| | self.pointWhenDone = whenDone |
| | self.formOrig.hide() |
| | self.formPoint.show() |
| | self.addEscapeShortcut() |
| | if start: |
| | displayPoint(start) |
| | else: |
| | displayPoint(FreeCAD.Vector(0, 0, 0)) |
| |
|
| | self.view = Draft.get3DView() |
| | self.pointCbClick = self.view.addEventCallbackPivy( |
| | coin.SoMouseButtonEvent.getClassTypeId(), click |
| | ) |
| | self.pointCbMove = self.view.addEventCallbackPivy( |
| | coin.SoLocation2Event.getClassTypeId(), mouseMove |
| | ) |
| |
|
| | if self.buttonBox: |
| | self.buttonBox.setEnabled(False) |
| |
|
| | FreeCADGui.Snapper.forceGridOff = True |
| |
|
| | def pointFinish(self, ok, cleanup=True): |
| | """pointFinish(ok, cleanup=True) ... internal function - do not call.""" |
| |
|
| | if cleanup: |
| | self.removeGlobalCallbacks() |
| | FreeCADGui.Snapper.off() |
| | if self.buttonBox: |
| | self.buttonBox.setEnabled(True) |
| | self.removeEscapeShortcut() |
| | self.formPoint.hide() |
| | self.formOrig.show() |
| | self.formOrig.setFocus() |
| |
|
| | if ok: |
| | self.updatePoint(False) |
| | self.pointWhenDone(self.pt, self.obj) |
| | else: |
| | self.pointWhenDone(None, None) |
| |
|
| | def pointDone(self): |
| | """pointDone() ... internal function - do not call.""" |
| | self.pointFinish(False) |
| |
|
| | def pointReject(self): |
| | """pointReject() ... internal function - do not call.""" |
| | self.pointFinish(False) |
| |
|
| | def pointAccept(self): |
| | """pointAccept() ... internal function - do not call.""" |
| | self.pointFinish(True) |
| |
|
| | def pointAcceptAndContinue(self): |
| | """pointAcceptAndContinue() ... internal function - do not call.""" |
| | self.pointFinish(True, False) |
| |
|
| | def removeGlobalCallbacks(self): |
| | """removeGlobalCallbacks() ... internal function - do not call.""" |
| | if hasattr(self, "view") and self.view: |
| | if self.pointCbClick: |
| | self.view.removeEventCallbackPivy( |
| | coin.SoMouseButtonEvent.getClassTypeId(), self.pointCbClick |
| | ) |
| | self.pointCbClick = None |
| | if self.pointCbMove: |
| | self.view.removeEventCallbackPivy( |
| | coin.SoLocation2Event.getClassTypeId(), self.pointCbMove |
| | ) |
| | self.pointCbMove = None |
| | self.view = None |
| |
|
| | def updatePoint(self, usePoint=True): |
| | """updatePoint() ... internal function - do not call.""" |
| | if usePoint and self.point: |
| | self.pt = self.point |
| | else: |
| | x = FreeCAD.Units.Quantity(self.formPoint.XGlobal.text()).Value |
| | y = FreeCAD.Units.Quantity(self.formPoint.YGlobal.text()).Value |
| | z = FreeCAD.Units.Quantity(self.formPoint.ZGlobal.text()).Value |
| | self.pt = FreeCAD.Vector(x, y, z) |
| |
|