| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| 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 |
|
|