| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import FreeCAD |
| | import Part |
| | import Path |
| | import traceback |
| |
|
| | import Path.Dressup.Utils as PathDressup |
| |
|
| | from PathScripts.PathUtils import loopdetect |
| | from PathScripts.PathUtils import wiredetect |
| | from PathScripts.PathUtils import horizontalEdgeLoop |
| | from PathScripts.PathUtils import tangentEdgeLoop |
| | from PathScripts.PathUtils import horizontalFaceLoop |
| | from PathScripts.PathUtils import addToJob |
| | from PathScripts.PathUtils import findParentJob |
| |
|
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| |
|
| | if FreeCAD.GuiUp: |
| | import FreeCADGui |
| |
|
| | translate = FreeCAD.Qt.translate |
| |
|
| | __title__ = "FreeCAD Path Commands" |
| | __author__ = "sliptonic" |
| | __url__ = "https://www.freecad.org" |
| |
|
| |
|
| | class _CommandSelectLoop: |
| | "the Path command to complete loop selection definition" |
| |
|
| | def __init__(self): |
| | self.obj = None |
| | self.sub = [] |
| | self.active = False |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "CAM_SelectLoop", |
| | "MenuText": QT_TRANSLATE_NOOP("CAM_SelectLoop", "Finish Selecting Loop"), |
| | "Accel": "P, L", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "CAM_SelectLoop", |
| | "Completes the selection of edges or faces that form a loop" |
| | "\n\nSelect faces: searching loop faces which form the walls." |
| | "\n\nSelect one edge: searching loop edges in horizontal plane" |
| | "\nor wire which contain selected edge." |
| | "\n\nSelect two edges: searching loop edges in wires of the shape" |
| | "\nor tangent edges.", |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | if bool(FreeCADGui.Selection.getSelection()) is False: |
| | return False |
| | try: |
| | sel = FreeCADGui.Selection.getSelectionEx()[0] |
| | if sel.Object == self.obj and sel.SubElementNames == self.sub: |
| | return self.active |
| | self.obj = sel.Object |
| | self.sub = sel.SubElementNames |
| | if sel.SubObjects: |
| | |
| | self.active = True |
| | else: |
| | self.active = False |
| | return self.active |
| | except Exception as exc: |
| | Path.Log.error(exc) |
| | traceback.print_exc(exc) |
| | return False |
| |
|
| | def Activated(self): |
| | from PathScripts.PathUtils import horizontalEdgeLoop, horizontalFaceLoop |
| |
|
| | if not FreeCADGui.Selection.getSelectionEx(): |
| | return |
| |
|
| | sel = FreeCADGui.Selection.getSelectionEx()[0] |
| | if not sel.SubObjects: |
| | return |
| |
|
| | obj = sel.Object |
| | sub = sel.SubObjects |
| | names = sel.SubElementNames |
| | loop = None |
| |
|
| | |
| | if "Face" in names[0]: |
| | loop = horizontalFaceLoop(obj, sub[0], names) |
| | if loop: |
| | FreeCADGui.Selection.clearSelection() |
| | FreeCADGui.Selection.addSelection(obj, loop) |
| | return |
| |
|
| | elif "Edge" in names[0]: |
| | if len(sub) == 1: |
| | |
| | loop = horizontalEdgeLoop(obj, sub[0], verbose=True) |
| |
|
| | elif len(sub) >= 2: |
| | |
| | loop = loopdetect(obj, sub[0], sub[1]) |
| |
|
| | if not loop: |
| | |
| | loop = tangentEdgeLoop(obj, sub[0]) |
| |
|
| | if not loop: |
| | |
| | loop = wiredetect(obj, names[0]) |
| |
|
| | if isinstance(loop, list) and len(loop) > 0 and isinstance(loop[0], Part.Edge): |
| | |
| | objEdges = obj.Shape.Edges |
| | FreeCADGui.Selection.clearSelection() |
| | for el in loop: |
| | for eo in objEdges: |
| | if eo.hashCode() == el.hashCode(): |
| | FreeCADGui.Selection.addSelection(obj, f"Edge{objEdges.index(eo) + 1}") |
| | return |
| |
|
| | Path.Log.warning(translate("CAM_SelectLoop", "Closed loop detection failed.")) |
| |
|
| | def formsPartOfALoop(self, obj, sub, names): |
| | try: |
| | if names[0][0:4] != "Edge": |
| | if names[0][0:4] == "Face" and horizontalFaceLoop(obj, sub, names): |
| | return True |
| | return False |
| | if len(names) == 1 and horizontalEdgeLoop(obj, sub): |
| | return True |
| | if len(names) == 1 or names[1][0:4] != "Edge": |
| | return False |
| | return True |
| | except Exception: |
| | return False |
| |
|
| |
|
| | if FreeCAD.GuiUp: |
| | FreeCADGui.addCommand("CAM_SelectLoop", _CommandSelectLoop()) |
| |
|
| |
|
| | class _ToggleOperation: |
| | "command definition to toggle Operation Active state" |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "CAM_OpActive", |
| | "MenuText": QT_TRANSLATE_NOOP("CAM_OpActiveToggle", "Toggle Operation"), |
| | "Accel": "P, X", |
| | "ToolTip": QT_TRANSLATE_NOOP( |
| | "CAM_OpActiveToggle", "Toggles the active state of the operation" |
| | ), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | selection = FreeCADGui.Selection.getSelection() |
| | if not selection: |
| | return False |
| |
|
| | if len(selection) == 1: |
| | |
| | sel = selection[0] |
| | if hasattr(sel, "Group") and sel.Name.startswith("Job"): |
| | return True |
| | if hasattr(sel, "Group") and sel.Name.startswith("Operations"): |
| | return True |
| |
|
| | for sel in selection: |
| | baseOp = Path.Dressup.Utils.baseOp(sel) |
| | if not hasattr(baseOp, "Active"): |
| | return False |
| |
|
| | return True |
| |
|
| | def Activated(self): |
| | selection = FreeCADGui.Selection.getSelection() |
| | if (len(selection) == 1 and hasattr(selection[0], "Group")) and ( |
| | selection[0].Name.startswith("Job") or selection[0].Name.startswith("Operations") |
| | ): |
| | sel = selection[0] |
| | |
| | if sel.Name.startswith("Job"): |
| | selection = sel.Operations.Group |
| | elif sel.Name.startswith("Operations"): |
| | selection = sel.Group |
| |
|
| | states = [Path.Dressup.Utils.baseOp(sel).Active for sel in selection] |
| | if all(states) or not any(states): |
| | |
| | for sel in selection: |
| | baseOp = Path.Dressup.Utils.baseOp(sel) |
| | baseOp.Active = not baseOp.Active |
| | else: |
| | |
| | for sel in selection: |
| | baseOp = Path.Dressup.Utils.baseOp(sel) |
| | baseOp.Active = True |
| |
|
| | else: |
| | for sel in selection: |
| | baseOp = Path.Dressup.Utils.baseOp(sel) |
| | baseOp.Active = not baseOp.Active |
| |
|
| | FreeCAD.ActiveDocument.recompute() |
| |
|
| |
|
| | if FreeCAD.GuiUp: |
| | FreeCADGui.addCommand("CAM_OpActiveToggle", _ToggleOperation()) |
| |
|
| |
|
| | class _CopyOperation: |
| | "the Path Copy Operation command definition" |
| |
|
| | def GetResources(self): |
| | return { |
| | "Pixmap": "CAM_OpCopy", |
| | "MenuText": QT_TRANSLATE_NOOP("CAM_OperationCopy", "Copy Operation"), |
| | "ToolTip": QT_TRANSLATE_NOOP("CAM_OperationCopy", "Copies the operation in the job"), |
| | "CmdType": "ForEdit", |
| | } |
| |
|
| | def IsActive(self): |
| | selection = FreeCADGui.Selection.getSelection() |
| | if not selection: |
| | return False |
| | if any([not hasattr(sel, "Path") for sel in selection]): |
| | return False |
| | if any([sel.Name.startswith("Job") for sel in selection]): |
| | return False |
| |
|
| | return True |
| |
|
| | def Activated(self): |
| | selection = FreeCADGui.Selection.getSelection() |
| | for sel in selection: |
| | job = findParentJob(sel) |
| | prevOp = PathDressup.baseOp(sel) |
| | prevOpCopy = FreeCAD.ActiveDocument.copyObject(prevOp, False) |
| | while prevOp != sel: |
| | |
| | op = sel |
| | while op.Base != prevOp: |
| | |
| | op = op.Base |
| | opCopy = FreeCAD.ActiveDocument.copyObject(op, False) |
| | opCopy.Base = prevOpCopy |
| | prevOpCopy = opCopy |
| | prevOp = op |
| |
|
| | |
| | addToJob(prevOpCopy, job.Name) |
| |
|
| |
|
| | if FreeCAD.GuiUp: |
| | FreeCADGui.addCommand("CAM_OperationCopy", _CopyOperation()) |
| |
|
| |
|
| | |
| | |
| | def findShape(shape, subname=None, subtype=None): |
| | """To find a higher order shape containing the subshape with subname. |
| | E.g. to find the wire containing 'Edge1' in shape, |
| | findShape(shape,'Edge1','Wires') |
| | """ |
| | if not subname: |
| | return shape |
| | ret = shape.getElement(subname) |
| | if not subtype or not ret or ret.isNull(): |
| | return ret |
| | if subname.startswith("Face"): |
| | tp = "Faces" |
| | elif subname.startswith("Edge"): |
| | tp = "Edges" |
| | elif subname.startswith("Vertex"): |
| | tp = "Vertex" |
| | else: |
| | return ret |
| | for obj in getattr(shape, subtype): |
| | for sobj in getattr(obj, tp): |
| | if sobj.isEqual(ret): |
| | return obj |
| | return ret |
| |
|