| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | """Provides GUI tools to create circular arc objects.""" |
| | |
| | |
| | |
| |
|
| | |
| | |
| | import math |
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| |
|
| | import FreeCAD as App |
| | import FreeCADGui as Gui |
| | import Draft |
| | import DraftVecUtils |
| | from FreeCAD import Units as U |
| | from draftguitools import gui_base |
| | from draftguitools import gui_base_original |
| | from draftguitools import gui_tool_utils |
| | from draftguitools import gui_trackers as trackers |
| | from draftutils import gui_utils |
| | from draftutils import params |
| | from draftutils import utils |
| | from draftutils.messages import _err, _toolmsg |
| | from draftutils.translate import translate |
| |
|
| |
|
| | class Arc(gui_base_original.Creator): |
| | """Gui command for the Circular Arc tool.""" |
| |
|
| | def __init__(self): |
| | super().__init__() |
| | self.closedCircle = False |
| | self.featureName = "Arc" |
| |
|
| | def GetResources(self): |
| | """Set icon, menu and tooltip.""" |
| | return { |
| | "Pixmap": "Draft_Arc", |
| | "Accel": "A, R", |
| | "MenuText": QT_TRANSLATE_NOOP("Draft_Arc", "Arc"), |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Draft_Arc", "Creates a circular arc from a center point and a radius" |
| | ), |
| | } |
| |
|
| | def Activated(self): |
| | """Execute when the command is called.""" |
| | super().Activated(name=self.featureName) |
| | if self.ui: |
| | self.step = 0 |
| | self.center = None |
| | self.rad = None |
| | self.angle = 0 |
| | self.tangents = [] |
| | self.tanpoints = [] |
| | if self.featureName == "Arc": |
| | self.ui.arcUi() |
| | else: |
| | self.ui.circleUi() |
| | self.altdown = False |
| | self.ui.sourceCmd = self |
| | self.linetrack = trackers.lineTracker(dotted=True) |
| | self.arctrack = trackers.arcTracker() |
| | self.call = self.view.addEventCallback("SoEvent", self.action) |
| | _toolmsg(translate("draft", "Pick center point")) |
| |
|
| | def finish(self, cont=False): |
| | """Terminate the operation. |
| | |
| | Parameters |
| | ---------- |
| | cont: bool or None, optional |
| | Restart (continue) the command if `True`, or if `None` and |
| | `ui.continueMode` is `True`. |
| | """ |
| | self.end_callbacks(self.call) |
| | if self.ui: |
| | self.linetrack.finalize() |
| | self.arctrack.finalize() |
| | super().finish() |
| | if cont or (cont is None and self.ui and self.ui.continueMode): |
| | self.Activated() |
| |
|
| | def updateAngle(self, angle): |
| | """Update the angle with the new value.""" |
| | |
| | lastangle = self.firstangle + self.angle |
| | if lastangle <= -2 * math.pi: |
| | lastangle += 2 * math.pi |
| | if lastangle >= 2 * math.pi: |
| | lastangle -= 2 * math.pi |
| | |
| | d0 = angle - lastangle |
| | d1 = d0 + 2 * math.pi |
| | d2 = d0 - 2 * math.pi |
| | if abs(d0) < min(abs(d1), abs(d2)): |
| | delta = d0 |
| | elif abs(d1) < abs(d2): |
| | delta = d1 |
| | else: |
| | delta = d2 |
| | newangle = self.angle + delta |
| | |
| | if newangle >= 2 * math.pi: |
| | newangle -= 2 * math.pi |
| | if newangle <= -2 * math.pi: |
| | newangle += 2 * math.pi |
| | self.angle = newangle |
| |
|
| | def action(self, arg): |
| | """Handle the 3D scene events. |
| | |
| | This is installed as an EventCallback in the Inventor view. |
| | |
| | Parameters |
| | ---------- |
| | arg: dict |
| | Dictionary with strings that indicates the type of event received |
| | from the 3D view. |
| | """ |
| | import DraftGeomUtils |
| |
|
| | if arg["Type"] == "SoKeyboardEvent": |
| | if arg["Key"] == "ESCAPE": |
| | self.finish() |
| | elif not self.ui.mouse: |
| | pass |
| | elif arg["Type"] == "SoLocation2Event": |
| | self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) |
| | |
| | if self.center and DraftVecUtils.dist(self.point, self.center) > 0: |
| | viewdelta = DraftVecUtils.project(self.point.sub(self.center), self.wp.axis) |
| | if not DraftVecUtils.isNull(viewdelta): |
| | self.point = self.point.add(viewdelta.negative()) |
| | if self.step == 0: |
| | if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): |
| | if not self.altdown: |
| | self.altdown = True |
| | self.ui.switchUi(True) |
| | else: |
| | if self.altdown: |
| | self.altdown = False |
| | self.ui.switchUi(False) |
| | elif self.step == 1: |
| | if len(self.tangents) == 2: |
| | cir = DraftGeomUtils.circleFrom2tan1pt( |
| | self.tangents[0], self.tangents[1], self.point |
| | ) |
| | _c = DraftGeomUtils.findClosestCircle(self.point, cir) |
| | self.center = _c.Center |
| | self.arctrack.setCenter(self.center) |
| | elif self.tangents and self.tanpoints: |
| | cir = DraftGeomUtils.circleFrom1tan2pt( |
| | self.tangents[0], self.tanpoints[0], self.point |
| | ) |
| | _c = DraftGeomUtils.findClosestCircle(self.point, cir) |
| | self.center = _c.Center |
| | self.arctrack.setCenter(self.center) |
| | if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): |
| | if not self.altdown: |
| | self.altdown = True |
| | if info: |
| | ob = self.doc.getObject(info["Object"]) |
| | num = int(info["Component"].lstrip("Edge")) - 1 |
| | ed = ob.Shape.Edges[num] |
| | if len(self.tangents) == 2: |
| | cir = DraftGeomUtils.circleFrom3tan( |
| | self.tangents[0], self.tangents[1], ed |
| | ) |
| | cl = DraftGeomUtils.findClosestCircle(self.point, cir) |
| | self.center = cl.Center |
| | self.rad = cl.Radius |
| | self.arctrack.setCenter(self.center) |
| | else: |
| | self.rad = self.center.add( |
| | DraftGeomUtils.findDistance(self.center, ed).sub(self.center) |
| | ).Length |
| | else: |
| | self.rad = DraftVecUtils.dist(self.point, self.center) |
| | else: |
| | if self.altdown: |
| | self.altdown = False |
| | self.rad = DraftVecUtils.dist(self.point, self.center) |
| | self.ui.setRadiusValue(self.rad, "Length") |
| | self.arctrack.setRadius(self.rad) |
| | self.linetrack.p1(self.center) |
| | self.linetrack.p2(self.point) |
| | self.linetrack.on() |
| | elif self.step == 2: |
| | currentrad = DraftVecUtils.dist(self.point, self.center) |
| | if currentrad != 0: |
| | angle = DraftVecUtils.angle( |
| | self.wp.u, self.point.sub(self.center), self.wp.axis |
| | ) |
| | else: |
| | angle = 0 |
| | self.linetrack.p2( |
| | DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center) |
| | ) |
| | self.ui.setRadiusValue(math.degrees(angle), unit="Angle") |
| | self.firstangle = angle |
| | else: |
| | |
| | currentrad = DraftVecUtils.dist(self.point, self.center) |
| | if currentrad != 0: |
| | angle = DraftVecUtils.angle( |
| | self.wp.u, self.point.sub(self.center), self.wp.axis |
| | ) |
| | else: |
| | angle = 0 |
| | self.linetrack.p2( |
| | DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center) |
| | ) |
| | self.updateAngle(angle) |
| | self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle") |
| | self.arctrack.setApertureAngle(self.angle) |
| |
|
| | gui_tool_utils.redraw3DView() |
| |
|
| | elif arg["Type"] == "SoMouseButtonEvent": |
| | if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1": |
| | if self.point: |
| | if self.step == 0: |
| | if not self.support: |
| | gui_tool_utils.getSupport(arg) |
| | (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) |
| | if gui_tool_utils.hasMod(arg, gui_tool_utils.get_mod_alt_key()): |
| | snapped = self.view.getObjectInfo( |
| | (arg["Position"][0], arg["Position"][1]) |
| | ) |
| | if snapped: |
| | ob = self.doc.getObject(snapped["Object"]) |
| | num = int(snapped["Component"].lstrip("Edge")) - 1 |
| | ed = ob.Shape.Edges[num] |
| | self.tangents.append(ed) |
| | if len(self.tangents) == 2: |
| | self.arctrack.on() |
| | self.ui.radiusUi() |
| | self.step = 1 |
| | self.ui.setNextFocus() |
| | self.linetrack.on() |
| | _toolmsg(translate("draft", "Pick radius")) |
| | else: |
| | if len(self.tangents) == 1: |
| | self.tanpoints.append(self.point) |
| | else: |
| | self.center = self.point |
| | self.node = [self.point] |
| | self.arctrack.setCenter(self.center) |
| | self.linetrack.p1(self.center) |
| | self.linetrack.p2( |
| | self.view.getPoint(arg["Position"][0], arg["Position"][1]) |
| | ) |
| | self.arctrack.on() |
| | self.ui.radiusUi() |
| | self.step = 1 |
| | self.ui.setNextFocus() |
| | self.linetrack.on() |
| | _toolmsg(translate("draft", "Pick radius")) |
| | if self.planetrack: |
| | self.planetrack.set(self.point) |
| | elif self.step == 1: |
| | if self.closedCircle: |
| | self.drawArc() |
| | else: |
| | self.ui.labelRadius.setText(translate("draft", "Start angle")) |
| | self.ui.radiusValue.setToolTip(translate("draft", "Start angle")) |
| | self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) |
| | self.linetrack.p1(self.center) |
| | self.linetrack.on() |
| | self.step = 2 |
| | _toolmsg(translate("draft", "Pick start angle")) |
| | elif self.step == 2: |
| | self.ui.labelRadius.setText(translate("draft", "Aperture angle")) |
| | self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) |
| | ang_offset = DraftVecUtils.angle( |
| | self.wp.u, self.arctrack.getDeviation(), self.wp.axis |
| | ) |
| | self.arctrack.setStartAngle(self.firstangle - ang_offset) |
| | self.step = 3 |
| | _toolmsg(translate("draft", "Pick aperture")) |
| | else: |
| | self.step = 4 |
| | self.drawArc() |
| | self.update_hints() |
| |
|
| | def drawArc(self): |
| | """Actually draw the arc object.""" |
| | rot, sup, pts, fil = self.getStrings() |
| | if self.closedCircle: |
| | try: |
| | |
| | |
| | Gui.addModule("Draft") |
| | if params.get_param("UsePartPrimitives"): |
| | |
| | _base = DraftVecUtils.toString(self.center) |
| | _cmd = "FreeCAD.ActiveDocument." |
| | _cmd += 'addObject("Part::Circle", "Circle")' |
| | _cmd_list = [ |
| | "circle = " + _cmd, |
| | "circle.Radius = " + str(self.rad), |
| | "pl = FreeCAD.Placement()", |
| | "pl.Rotation.Q = " + rot, |
| | "pl.Base = " + _base, |
| | "circle.Placement = pl", |
| | "Draft.autogroup(circle)", |
| | "Draft.select(circle)", |
| | "FreeCAD.ActiveDocument.recompute()", |
| | ] |
| | self.commit(translate("draft", "Create Circle (Part)"), _cmd_list) |
| | else: |
| | |
| | _base = DraftVecUtils.toString(self.center) |
| | _cmd = "Draft.make_circle" |
| | _cmd += "(" |
| | _cmd += "radius=" + str(self.rad) + ", " |
| | _cmd += "placement=pl, " |
| | _cmd += "face=" + fil + ", " |
| | _cmd += "support=" + sup |
| | _cmd += ")" |
| | _cmd_list = [ |
| | "pl=FreeCAD.Placement()", |
| | "pl.Rotation.Q=" + rot, |
| | "pl.Base=" + _base, |
| | "circle = " + _cmd, |
| | "Draft.autogroup(circle)", |
| | "FreeCAD.ActiveDocument.recompute()", |
| | ] |
| | self.commit(translate("draft", "Create Circle"), _cmd_list) |
| | except Exception: |
| | _err("Draft: error delaying commit") |
| | else: |
| | |
| | sta = math.degrees(self.firstangle) |
| | end = math.degrees(self.firstangle + self.angle) |
| | if end < sta: |
| | sta, end = end, sta |
| | sta %= 360 |
| | end %= 360 |
| |
|
| | try: |
| | Gui.addModule("Draft") |
| | if params.get_param("UsePartPrimitives"): |
| | |
| | _base = DraftVecUtils.toString(self.center) |
| | _cmd = "FreeCAD.ActiveDocument." |
| | _cmd += 'addObject("Part::Circle", "Circle")' |
| | _cmd_list = [ |
| | "circle = " + _cmd, |
| | "circle.Radius = " + str(self.rad), |
| | "circle.Angle1 = " + str(sta), |
| | "circle.Angle2 = " + str(end), |
| | "pl = FreeCAD.Placement()", |
| | "pl.Rotation.Q = " + rot, |
| | "pl.Base = " + _base, |
| | "circle.Placement = pl", |
| | "Draft.autogroup(circle)", |
| | "Draft.select(circle)", |
| | "FreeCAD.ActiveDocument.recompute()", |
| | ] |
| | self.commit(translate("draft", "Create Arc (Part)"), _cmd_list) |
| | else: |
| | |
| | _base = DraftVecUtils.toString(self.center) |
| | _cmd = "Draft.make_circle" |
| | _cmd += "(" |
| | _cmd += "radius=" + str(self.rad) + ", " |
| | _cmd += "placement=pl, " |
| | _cmd += "face=" + fil + ", " |
| | _cmd += "startangle=" + str(sta) + ", " |
| | _cmd += "endangle=" + str(end) + ", " |
| | _cmd += "support=" + sup |
| | _cmd += ")" |
| | _cmd_list = [ |
| | "pl = FreeCAD.Placement()", |
| | "pl.Rotation.Q = " + rot, |
| | "pl.Base = " + _base, |
| | "circle = " + _cmd, |
| | "Draft.autogroup(circle)", |
| | "FreeCAD.ActiveDocument.recompute()", |
| | ] |
| | self.commit(translate("draft", "Create Arc"), _cmd_list) |
| | except Exception: |
| | _err("Draft: error delaying commit") |
| |
|
| | |
| | self.finish(cont=None) |
| |
|
| | def numericInput(self, numx, numy, numz): |
| | """Validate the entry fields in the user interface. |
| | |
| | This function is called by the toolbar or taskpanel interface |
| | when valid x, y, and z have been entered in the input fields. |
| | """ |
| | self.center = App.Vector(numx, numy, numz) |
| | self.node = [self.center] |
| | self.arctrack.setCenter(self.center) |
| | self.arctrack.on() |
| | self.ui.radiusUi() |
| | self.step = 1 |
| | self.ui.setNextFocus() |
| | _toolmsg(translate("draft", "Pick radius")) |
| | self.update_hints() |
| |
|
| | def numericRadius(self, rad): |
| | """Validate the entry radius in the user interface. |
| | |
| | This function is called by the toolbar or taskpanel interface |
| | when a valid radius has been entered in the input field. |
| | """ |
| | import DraftGeomUtils |
| |
|
| | if self.step == 1: |
| | self.rad = rad |
| | if len(self.tangents) == 2: |
| | cir = DraftGeomUtils.circleFrom2tan1rad(self.tangents[0], self.tangents[1], rad) |
| | if self.center: |
| | _c = DraftGeomUtils.findClosestCircle(self.center, cir) |
| | self.center = _c.Center |
| | else: |
| | self.center = cir[-1].Center |
| | elif self.tangents and self.tanpoints: |
| | cir = DraftGeomUtils.circleFrom1tan1pt1rad(self.tangents[0], self.tanpoints[0], rad) |
| | if self.center: |
| | _c = DraftGeomUtils.findClosestCircle(self.center, cir) |
| | self.center = _c.Center |
| | else: |
| | self.center = cir[-1].Center |
| | if self.closedCircle: |
| | self.drawArc() |
| | else: |
| | self.step = 2 |
| | self.arctrack.setCenter(self.center) |
| | self.ui.labelRadius.setText(translate("draft", "Start angle")) |
| | self.ui.radiusValue.setToolTip(translate("draft", "Start angle")) |
| | self.linetrack.p1(self.center) |
| | self.linetrack.on() |
| | self.ui.radiusValue.setText("") |
| | self.ui.radiusValue.setFocus() |
| | _toolmsg(translate("draft", "Pick start angle")) |
| | elif self.step == 2: |
| | self.ui.labelRadius.setText(translate("draft", "Aperture angle")) |
| | self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) |
| | self.firstangle = math.radians(rad) |
| | ang_offset = DraftVecUtils.angle(self.wp.u, self.arctrack.getDeviation(), self.wp.axis) |
| | self.arctrack.setStartAngle(self.firstangle - ang_offset) |
| | self.step = 3 |
| | self.ui.radiusValue.setText("") |
| | self.ui.radiusValue.setFocus() |
| | _toolmsg(translate("draft", "Pick aperture angle")) |
| | else: |
| | self.updateAngle(rad) |
| | self.angle = math.radians(rad) |
| | self.step = 4 |
| | self.drawArc() |
| | self.update_hints() |
| |
|
| | def get_hints(self): |
| | if self.step == 0: |
| | hints = [Gui.InputHint(translate("draft", "%1 pick center"), Gui.UserInput.MouseLeft)] |
| | elif self.step == 1: |
| | hints = [Gui.InputHint(translate("draft", "%1 pick radius"), Gui.UserInput.MouseLeft)] |
| | elif self.step == 2: |
| | hints = [ |
| | Gui.InputHint(translate("draft", "%1 pick start angle"), Gui.UserInput.MouseLeft) |
| | ] |
| | else: |
| | hints = [Gui.InputHint(translate("draft", "%1 pick aperture"), Gui.UserInput.MouseLeft)] |
| | return ( |
| | hints |
| | + gui_tool_utils._get_hint_xyz_constrain() |
| | + gui_tool_utils._get_hint_mod_constrain() |
| | + gui_tool_utils._get_hint_mod_snap() |
| | ) |
| |
|
| |
|
| | Gui.addCommand("Draft_Arc", Arc()) |
| |
|
| |
|
| | class Arc_3Points(gui_base.GuiCommandBase): |
| | """GuiCommand for the Draft_Arc_3Points tool.""" |
| |
|
| | def __init__(self): |
| | super().__init__(name="Arc_3Points") |
| |
|
| | def GetResources(self): |
| | """Set icon, menu and tooltip.""" |
| | return { |
| | "Pixmap": "Draft_Arc_3Points", |
| | "Accel": "A, T", |
| | "MenuText": QT_TRANSLATE_NOOP("Draft_Arc_3Points", "Arc From 3 Points"), |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Draft_Arc_3Points", "Creates a circular arc from 3 points" |
| | ), |
| | } |
| |
|
| | def Activated(self): |
| | """Execute when the command is called.""" |
| | super().Activated() |
| |
|
| | |
| | self.points = [] |
| | self.normal = None |
| | self.tracker = trackers.arcTracker() |
| | self.tracker.autoinvert = False |
| |
|
| | |
| | |
| | |
| | import WorkingPlane |
| |
|
| | WorkingPlane.get_working_plane() |
| |
|
| | Gui.Snapper.getPoint(callback=self.getPoint, movecallback=self.drawArc) |
| | Gui.Snapper.ui.sourceCmd = self |
| | Gui.Snapper.ui.setTitle( |
| | title=translate("draft", "Arc From 3 Points"), icon="Draft_Arc_3Points" |
| | ) |
| | Gui.Snapper.ui.continueCmd.show() |
| | self.update_hints() |
| |
|
| | def getPoint(self, point, info): |
| | """Get the point by clicking on the 3D view. |
| | |
| | Every time the user clicks on the 3D view this method is run. |
| | In this case, a point is appended to the list of points, |
| | and the tracker is updated. |
| | The object is finally created when three points are picked. |
| | |
| | Parameters |
| | ---------- |
| | point: Base::Vector |
| | The point selected in the 3D view. |
| | |
| | info: str |
| | Some information obtained about the point passed by the Snapper. |
| | """ |
| | |
| | |
| | if not point: |
| | return None |
| |
|
| | |
| | if point not in self.points: |
| | self.points.append(point) |
| | if self.planetrack and len(self.points) == 1: |
| | self.planetrack.set(point) |
| |
|
| | if len(self.points) < 3: |
| | |
| | |
| | |
| | |
| | |
| | |
| | if len(self.points) == 2: |
| | self.tracker.on() |
| | Gui.Snapper.getPoint( |
| | last=self.points[-1], callback=self.getPoint, movecallback=self.drawArc |
| | ) |
| | Gui.Snapper.ui.sourceCmd = self |
| | Gui.Snapper.ui.setTitle( |
| | title=translate("draft", "Arc From 3 Points"), icon="Draft_Arc_3Points" |
| | ) |
| | Gui.Snapper.ui.continueCmd.show() |
| | self.update_hints() |
| |
|
| | else: |
| | |
| | |
| | |
| | Gui.addModule("Draft") |
| | Gui.addModule("WorkingPlane") |
| | _cmd = "Draft.make_arc_3points([" |
| | _cmd += "FreeCAD." + str(self.points[0]) |
| | _cmd += ", FreeCAD." + str(self.points[1]) |
| | _cmd += ", FreeCAD." + str(self.points[2]) |
| | _cmd += "]" |
| | _cmd += ", placement=pl" |
| | _cmd += ", primitive=" + str(params.get_param("UsePartPrimitives")) |
| | _cmd += ")" |
| | _cmd_list = [ |
| | "pl = WorkingPlane.get_working_plane().get_placement()", |
| | "circle = " + _cmd, |
| | "Draft.autogroup(circle)", |
| | ] |
| | if params.get_param("UsePartPrimitives"): |
| | _cmd_list.append("Draft.select(circle)") |
| | _cmd_list.append("FreeCAD.ActiveDocument.recompute()") |
| | self.commit(translate("draft", "Create Arc From 3 Points"), _cmd_list) |
| | self.finish(cont=None) |
| |
|
| | def drawArc(self, point, info): |
| | """Draw preview arc when we move the pointer in the 3D view. |
| | |
| | It uses the `gui_trackers.arcTracker.setBy3Points` method. |
| | |
| | Parameters |
| | ---------- |
| | point: Base::Vector |
| | The dynamic point passed by the callback |
| | as we move the pointer in the 3D view. |
| | |
| | info: str |
| | Some information obtained from the point by the Snapper. |
| | """ |
| | if len(self.points) == 2: |
| | if point.sub(self.points[1]).Length > 0.001: |
| | self.tracker.setBy3Points(self.points[0], self.points[1], point) |
| |
|
| | def finish(self, cont=False): |
| | """Terminate the operation. |
| | |
| | Parameters |
| | ---------- |
| | cont: bool or None, optional |
| | Restart (continue) the command if `True`, or if `None` and |
| | `ui.continueMode` is `True`. |
| | """ |
| | self.tracker.finalize() |
| | super().finish() |
| | if cont or (cont is None and Gui.Snapper.ui and Gui.Snapper.ui.continueMode): |
| | self.Activated() |
| |
|
| | def get_hints(self): |
| | if len(self.points) == 0: |
| | hints = [ |
| | Gui.InputHint(translate("draft", "%1 pick first point"), Gui.UserInput.MouseLeft) |
| | ] |
| | elif len(self.points) == 1: |
| | hints = [ |
| | Gui.InputHint(translate("draft", "%1 pick second point"), Gui.UserInput.MouseLeft) |
| | ] |
| | else: |
| | hints = [ |
| | Gui.InputHint(translate("draft", "%1 pick third point"), Gui.UserInput.MouseLeft) |
| | ] |
| | return ( |
| | hints |
| | + gui_tool_utils._get_hint_xyz_constrain() |
| | + gui_tool_utils._get_hint_mod_constrain() |
| | + gui_tool_utils._get_hint_mod_snap() |
| | ) |
| |
|
| |
|
| | Draft_Arc_3Points = Arc_3Points |
| | Gui.addCommand("Draft_Arc_3Points", Arc_3Points()) |
| |
|
| |
|
| | class ArcGroup: |
| | """Gui Command group for the Arc tools.""" |
| |
|
| | def GetResources(self): |
| | """Set icon, menu and tooltip.""" |
| | return { |
| | "MenuText": QT_TRANSLATE_NOOP("Draft_ArcTools", "Arc Tools"), |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "Draft_ArcTools", "Tools to create various types of circular arcs" |
| | ), |
| | } |
| |
|
| | def GetCommands(self): |
| | """Return a tuple of commands in the group.""" |
| | return ("Draft_Arc", "Draft_Arc_3Points") |
| |
|
| | def IsActive(self): |
| | """Return True when this command should be available.""" |
| | return bool(gui_utils.get_3d_view()) |
| |
|
| |
|
| | Gui.addCommand("Draft_ArcTools", ArcGroup()) |
| |
|
| | |
| |
|