diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 3330391c2..e84930e28 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -59,6 +59,7 @@ SET(PathScripts_SRCS PathScripts/PathEngrave.py PathScripts/PathSurface.py PathScripts/PathRemote.py + PathScripts/PathSanity.py ) diff --git a/src/Mod/Path/Gui/Resources/Path.qrc b/src/Mod/Path/Gui/Resources/Path.qrc index 98dff69fb..424b448b0 100644 --- a/src/Mod/Path/Gui/Resources/Path.qrc +++ b/src/Mod/Path/Gui/Resources/Path.qrc @@ -73,5 +73,6 @@ panels/ProfileEdit.ui panels/SurfaceEdit.ui panels/RemoteEdit.ui + panels/ToolControl.ui diff --git a/src/Mod/Path/Gui/Resources/panels/PocketEdit.ui b/src/Mod/Path/Gui/Resources/panels/PocketEdit.ui index 47391e373..edb60bf13 100644 --- a/src/Mod/Path/Gui/Resources/panels/PocketEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PocketEdit.ui @@ -263,6 +263,67 @@ Pattern + + + + + 1 + + + 100 + + + 10 + + + 100 + + + + + + + Step Over Percent + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Use ZigZag + + + + + + + ZigZag Unidirectional + + + + + + + + + + ZigZag Angle + + + + + + + diff --git a/src/Mod/Path/InitGui.py b/src/Mod/Path/InitGui.py index 4cc94a460..8fd3d2a8c 100644 --- a/src/Mod/Path/InitGui.py +++ b/src/Mod/Path/InitGui.py @@ -69,9 +69,9 @@ class PathWorkbench (Workbench): from PathScripts import PathSanity # build commands list - projcmdlist = ["Path_Project", "Path_ToolTableEdit", - "Path_Post", "Path_Inspect", "Path_Sanity"] - prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_LoadTool", "Path_ToolLenOffset", "Path_Comment", + projcmdlist = ["Path_Project", "Path_Post", "Path_Inspect", "Path_Sanity"] + toolcmdlist = ["Path_ToolTableEdit", "Path_LoadTool"] + prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment", "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"] opcmdlist = ["Path_Profile", "Path_Pocket", "Path_Drilling", "Path_Engrave", "Path_Surfacing"] @@ -86,12 +86,15 @@ class PathWorkbench (Workbench): def translate(context, text): return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).encode("utf8") self.appendToolbar(translate("Path", "Project Setup"), projcmdlist) - self.appendToolbar(translate("Path", "Partial Commands"), prepcmdlist) + self.appendToolbar(translate("Path", "Tool Commands"), toolcmdlist) + #self.appendToolbar(translate("Path", "Partial Commands"), prepcmdlist) self.appendToolbar(translate("Path", "New Operations"), opcmdlist) self.appendToolbar(translate("Path", "Path Modification"), modcmdlist) self.appendMenu([translate("Path", "Path"), translate( - "Path", "Project Setup")], projcmdlist) + "Path", "Project Tools")], projcmdlist) + self.appendMenu([translate("Path", "Path"), translate( + "Path", "Tools")], projcmdlist) self.appendMenu([translate("Path", "Path"), translate( "Path", "Partial Commands")], prepcmdlist) self.appendMenu([translate("Path", "Path"), translate( diff --git a/src/Mod/Path/PathScripts/PathDrilling.py b/src/Mod/Path/PathScripts/PathDrilling.py index 861f80007..88aa5881f 100644 --- a/src/Mod/Path/PathScripts/PathDrilling.py +++ b/src/Mod/Path/PathScripts/PathDrilling.py @@ -51,6 +51,7 @@ class ObjectDrilling: obj.addProperty("App::PropertyLinkSubList", "Base","Path", translate("PathProject", "The base geometry of this toolpath")) obj.addProperty("App::PropertyBool", "Active", "Path", translate("PathProject", "Make False, to prevent operation from generating code")) obj.addProperty("App::PropertyString", "Comment", "Path", translate("PathProject", "An optional comment for this profile")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", translate("Path", "User Assigned Label")) obj.addProperty("App::PropertyLength", "PeckDepth", "Depth", translate("PathProject", "Incremental Drill depth before retracting to clear chips")) obj.addProperty("App::PropertyLength", "StartDepth", "Depth", translate("PathProject", "Starting Depth of Tool- first cut depth in Z")) @@ -63,6 +64,9 @@ class ObjectDrilling: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 1) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt + obj.Proxy = self @@ -72,6 +76,10 @@ class ObjectDrilling: def __setstate__(self, state): return None + def onChanged(self, obj, prop): + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + def execute(self, obj): output = "" toolLoad = PathUtils.getLastToolLoad(obj) @@ -80,16 +88,20 @@ class ObjectDrilling: self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" + else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value - obj.ToolNumber = toolLoad.ToolNumber - tool = PathUtils.getTool(obj, toolLoad.ToolNumber) - if tool is None: - self.radius = 0.25 - else: - self.radius = tool.Diameter/2 + self.radius = tool.Diameter/2 + obj.ToolNumber = toolLoad.ToolNumber + obj.ToolDescription = toolLoad.Name + + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" if obj.Base: locations = [] diff --git a/src/Mod/Path/PathScripts/PathEngrave.py b/src/Mod/Path/PathScripts/PathEngrave.py index 88d7552c2..8cddee746 100644 --- a/src/Mod/Path/PathScripts/PathEngrave.py +++ b/src/Mod/Path/PathScripts/PathEngrave.py @@ -49,6 +49,7 @@ class ObjectPathEngrave: obj.addProperty("App::PropertyLinkSubList", "Base", "Path", "The base geometry of this object") obj.addProperty("App::PropertyBool", "Active", "Path", translate("Path", "Make False, to prevent operation from generating code")) obj.addProperty("App::PropertyString", "Comment", "Path", translate("Path", "An optional comment for this profile")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", translate("Path", "User Assigned Label")) obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate("Path", "The library or Algorithm used to generate the path")) obj.Algorithm = ['OCC Native'] @@ -57,6 +58,8 @@ class ObjectPathEngrave: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 1) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt # Depth Properties obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("Path", "The height needed to clear clamps and obstructions")) @@ -76,6 +79,10 @@ class ObjectPathEngrave: def __setstate__(self, state): return None + def onChanged(self, obj, prop): + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + def execute(self, obj): output = "" @@ -85,16 +92,19 @@ class ObjectPathEngrave: self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value - obj.ToolNumber = toolLoad.ToolNumber - tool = PathUtils.getTool(obj, toolLoad.ToolNumber) - if tool is None: - self.radius = 0.25 - else: - self.radius = tool.Diameter/2 + self.radius = tool.Diameter/2 + obj.ToolNumber = toolLoad.ToolNumber + obj.ToolDescription = toolLoad.Name + + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" if obj.Base: for o in obj.Base: diff --git a/src/Mod/Path/PathScripts/PathLoadTool.py b/src/Mod/Path/PathScripts/PathLoadTool.py index 3593dbcda..70a4977b3 100644 --- a/src/Mod/Path/PathScripts/PathLoadTool.py +++ b/src/Mod/Path/PathScripts/PathLoadTool.py @@ -21,7 +21,7 @@ # * USA * # * * # *************************************************************************** -''' Used for CNC machine to load cutting Tool ie M6T3''' +''' Tool Controller defines tool, spindle speed and feed rates for Path Operations ''' import FreeCAD import FreeCADGui @@ -58,6 +58,15 @@ class LoadTool: obj.setEditorMode('Placement', mode) def execute(self, obj): +# if obj.ToolNumber != 0: + + tool = PathUtils.getTool(obj, obj.ToolNumber) + if tool is not None: + obj.Label = obj.Name + ": (" + tool.Name + ")" + else: + obj.Label = obj.Name + ": (UNDEFINED TOOL)" + + commands = "" commands = 'M6T'+str(obj.ToolNumber)+'\n' @@ -68,7 +77,7 @@ class LoadTool: commands += 'M4S' + str(obj.SpindleSpeed) + '\n' obj.Path = Path.Path(commands) - obj.Label = "Tool"+str(obj.ToolNumber) + # obj.Label = "TC: Tool"+str(obj.ToolNumber) def onChanged(self, obj, prop): mode = 2 @@ -135,20 +144,20 @@ class _ViewProviderLoadTool: class CommandPathLoadTool: def GetResources(self): return {'Pixmap': 'Path-LoadTool', - 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Tool Number to Load"), + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Add Tool Controller to the Project"), 'Accel': "P, T", - 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Tool Number to Load")} + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Path_LoadTool", "Add Tool Controller")} def IsActive(self): return FreeCAD.ActiveDocument is not None def Activated(self): - FreeCAD.ActiveDocument.openTransaction(translate("Current Tool", "Tool Number to Load")) + FreeCAD.ActiveDocument.openTransaction(translate("Path_LoadTool", "Create Tool Controller Object")) snippet = ''' import Path, PathScripts from PathScripts import PathUtils, PathLoadTool -obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","Tool") +obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython","TC") PathScripts.PathLoadTool.LoadTool(obj) PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject) @@ -165,7 +174,7 @@ PathUtils.addToProject(obj) import PathScripts import PathUtils - obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Tool") + obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TC") PathScripts.PathLoadTool.LoadTool(obj) PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject) @@ -174,8 +183,8 @@ PathUtils.addToProject(obj) class TaskPanel: def __init__(self): - #self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolControl.ui") - self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolControl.ui") + self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolControl.ui") + #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolControl.ui") self.updating = False def accept(self): @@ -196,25 +205,41 @@ class TaskPanel: if hasattr(self.obj, "VertFeed"): self.obj.Label = self.form.tcoName.text() - if hasattr(self.obj, "VertFeed"): - self.obj.VertFeed = self.form.vertFeed.value() + self.obj.VertFeed = self.form.vertFeed.text() if hasattr(self.obj, "HorizFeed"): - self.obj.HorizFeed = self.form.horizFeed.value() + self.obj.HorizFeed = self.form.horizFeed.text() if hasattr(self.obj, "SpindleSpeed"): self.obj.SpindleSpeed = self.form.spindleSpeed.value() if hasattr(self.obj, "SpindleDir"): self.obj.SpindleDir = str(self.form.cboSpindleDirection.currentText()) - if hasattr(self.obj, "ToolNumber"): - self.obj.ToolNumber = self.form.ToolNumber.value() + #if hasattr(self.obj, "ToolNumber"): + # self.obj.ToolNumber = self.form.ToolNumber.value() self.obj.Proxy.execute(self.obj) - def setFields(self): + def setFields(self): self.form.vertFeed.setText(str(self.obj.VertFeed.Value)) self.form.horizFeed.setText(str(self.obj.HorizFeed.Value)) - self.form.spindleSpeed.setText(str(self.obj.SpindleSpeed.Value)) - self.form.cboSpindleDirection.setText(str(self.obj.SpindleDir.Value)) - self.form.ToolNumber.setValue(self.obj.ToolNumber) + self.form.spindleSpeed.setValue(self.obj.SpindleSpeed) + self.form.tcoName.setText(str(self.obj.Label)) + + index = self.form.cboSpindleDirection.findText(self.obj.SpindleDir, QtCore.Qt.MatchFixedString) + if index >= 0: + self.form.cboSpindleDirection.setCurrentIndex(index) + # Populate the tool list + mach = PathUtils.findMachine() + tool = mach.Tooltable.Tools[self.obj.ToolNumber] + + self.form.txtToolName.setText(tool.Name) + self.form.txtToolType.setText(tool.ToolType) + self.form.txtToolMaterial.setText(tool.Material) + self.form.txtToolDiameter.setText(str(tool.Diameter)) + + # self.form.cboToolSelect.addItem(tool.Name) + + # index = self.form.cboToolSelect.findText(self.obj.SpindleDir, QtCore.Qt.MatchFixedString) + # if index >= 0: + # self.form.cboSpindleDirection.setCurrentIndex(index) def open(self): diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/PathScripts/PathPocket.py index b0ca151e0..3e5d0ede8 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/PathScripts/PathPocket.py @@ -50,6 +50,7 @@ class ObjectPocket: obj.addProperty("App::PropertyLinkSubList", "Base", "Path", translate("PathProject", "The base geometry of this object")) obj.addProperty("App::PropertyBool", "Active", "Path", translate("PathProject", "Make False, to prevent operation from generating code")) obj.addProperty("App::PropertyString", "Comment", "Path", translate("PathProject", "An optional comment for this profile")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", translate("Path", "User Assigned Label")) obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate("PathProject", "The library to use to generate the path")) obj.Algorithm = ['OCC Native', 'libarea'] @@ -58,6 +59,8 @@ class ObjectPocket: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 0) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt # Depth Properties obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("PathProject", "The height needed to clear clamps and obstructions")) @@ -107,6 +110,10 @@ class ObjectPocket: obj.setEditorMode('RampAngle', 2) # make this hidden obj.setEditorMode('RampSize', 2) # make this hidden + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + + def __getstate__(self): return None @@ -354,17 +361,19 @@ class ObjectPocket: self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value tool = PathUtils.getTool(obj, toolLoad.ToolNumber) self.radius = tool.Diameter/2 obj.ToolNumber = toolLoad.ToolNumber + obj.ToolDescription = toolLoad.Name -# if tool is None: -# self.radius = 0.25 -# else: -# self.radius = tool.Diameter/2 + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" if obj.Base: for b in obj.Base: @@ -501,6 +510,7 @@ class CommandPathPocket: FreeCADGui.doCommand('obj.Active = True') FreeCADGui.doCommand('PathScripts.PathPocket.ViewProviderPocket(obj.ViewObject)') FreeCADGui.doCommand('from PathScripts import PathUtils') + FreeCADGui.doCommand('obj.Algorithm = "libarea"') FreeCADGui.doCommand('obj.StepOver = 100') FreeCADGui.doCommand('obj.ClearanceHeight = 10') # + str(bb.ZMax + 2.0)) FreeCADGui.doCommand('obj.StepDown = 1.0') @@ -557,6 +567,15 @@ class TaskPanel: self.obj.Algorithm = str(self.form.algorithmSelect.currentText()) if hasattr(self.obj, "CutMode"): self.obj.CutMode = str(self.form.cutMode.currentText()) + if hasattr(self.obj, "UseZigZag"): + self.obj.UseZigZag = self.form.useZigZag.isChecked() + if hasattr(self.obj, "ZigUnidirectional"): + self.obj.ZigUnidirectional = self.form.zigZagUnidirectional.isChecked() + if hasattr(self.obj, "ZigZagAngle"): + self.obj.ZigZagAngle = self.form.zigZagAngle.value() + if hasattr(self.obj, "StepOver"): + self.obj.StepOver = self.form.stepOverPercent.value() + self.obj.Proxy.execute(self.obj) def setFields(self): @@ -567,6 +586,10 @@ class TaskPanel: self.form.stepDown.setValue(self.obj.StepDown) self.form.extraOffset.setValue(self.obj.MaterialAllowance.Value) self.form.useStartPoint.setChecked(self.obj.UseStartPoint) + self.form.useZigZag.setChecked(self.obj.UseZigZag) + self.form.zigZagUnidirectional.setChecked(self.obj.ZigUnidirectional) + self.form.zigZagAngle.setValue(self.obj.ZigZagAngle) + self.form.stepOverPercent.setValue(self.obj.StepOver) index = self.form.algorithmSelect.findText(self.obj.Algorithm, QtCore.Qt.MatchFixedString) if index >= 0: @@ -586,16 +609,6 @@ class TaskPanel: # check that the selection contains exactly what we want selection = FreeCADGui.Selection.getSelectionEx() - # if not len(selection) >= 1: - # FreeCAD.Console.PrintError(translate("PathProject", "Please select at least one profileable object\n")) - # return - # for s in selection: - # if s.HasSubObjects: - # for i in s.SubElementNames: - # self.obj.Proxy.addpocketbase(self.obj, s.Object, i) - # else: - # self.obj.Proxy.addpocketbase(self.obj, s.Object) - if len(selection) != 1: FreeCAD.Console.PrintError(translate("PathProject", "Please select only faces from one solid\n")) return @@ -685,6 +698,13 @@ class TaskPanel: self.form.useStartPoint.clicked.connect(self.getFields) self.form.extraOffset.editingFinished.connect(self.getFields) + # Pattern + self.form.stepOverPercent.editingFinished.connect(self.getFields) + self.form.useZigZag.clicked.connect(self.getFields) + self.form.zigZagUnidirectional.clicked.connect(self.getFields) + self.form.zigZagAngle.editingFinished.connect(self.getFields) + + self.setFields() sel = FreeCADGui.Selection.getSelectionEx() diff --git a/src/Mod/Path/PathScripts/PathProfile.py b/src/Mod/Path/PathScripts/PathProfile.py index 226c89e07..58656d1e1 100644 --- a/src/Mod/Path/PathScripts/PathProfile.py +++ b/src/Mod/Path/PathScripts/PathProfile.py @@ -66,6 +66,8 @@ class ObjectProfile: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 1) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt # Depth Properties obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("Path", "The height needed to clear clamps and obstructions")) @@ -112,6 +114,7 @@ class ObjectProfile: obj.angles = angles obj.lengths = lengths obj.heights = heights + obj.ToolDescription = "UNDEFINED" obj.Proxy = self @@ -121,9 +124,9 @@ class ObjectProfile: def __setstate__(self, state): return None - # def onChanged(self, obj, prop): - # if prop == "Label": - # print "we're here" + def onChanged(self, obj, prop): + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" def addprofilebase(self, obj, ss, sub=""): baselist = obj.Base @@ -263,13 +266,20 @@ print "y - " + str(point.y) self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value tool = PathUtils.getTool(obj, toolLoad.ToolNumber) self.radius = tool.Diameter/2 obj.ToolNumber = toolLoad.ToolNumber - #obj.Label = obj.Label + "(" + toolLoad.Label + ")" + obj.ToolDescription = toolLoad.Name + + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + if obj.Base: hfaces = [] diff --git a/src/Mod/Path/PathScripts/PathRemote.py b/src/Mod/Path/PathScripts/PathRemote.py index 57e01fde5..6030b2c23 100644 --- a/src/Mod/Path/PathScripts/PathRemote.py +++ b/src/Mod/Path/PathScripts/PathRemote.py @@ -60,6 +60,7 @@ class ObjectRemote: obj.addProperty("App::PropertyLinkSubList", "Base", "Path", translate("Parent Object(s)", "The base geometry of this toolpath")) obj.addProperty("App::PropertyBool", "Active", "Path", translate("Active", "Make False, to prevent operation from generating code")) obj.addProperty("App::PropertyString", "Comment", "Path", translate("PathProject", "An optional comment for this profile")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", translate("Path", "User Assigned Label")) obj.addProperty("App::PropertyString", "URL", "API", translate("RemotePath", "The Base URL of the remote path service")) obj.addProperty("App::PropertyStringList", "proplist", "Path", translate("Path", "list of remote properties")) @@ -69,6 +70,8 @@ class ObjectRemote: obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 0) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt # Depth Properties obj.addProperty("App::PropertyFloat", "ClearanceHeight", "Depth", translate("PathProject", "The height needed to clear clamps and obstructions")) @@ -153,6 +156,9 @@ class ObjectRemote: print "adding: " + str(prop) obj.proplist = pl + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + def execute(self, obj): output = "" @@ -162,12 +168,19 @@ class ObjectRemote: self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value tool = PathUtils.getTool(obj, toolLoad.ToolNumber) self.radius = tool.Diameter/2 obj.ToolNumber = toolLoad.ToolNumber + obj.ToolDescription = toolLoad.Name + + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" output += "(remote gcode goes here)" path = Path.Path(output) diff --git a/src/Mod/Path/PathScripts/PathSanity.py b/src/Mod/Path/PathScripts/PathSanity.py index bf8b84222..7953e2de8 100644 --- a/src/Mod/Path/PathScripts/PathSanity.py +++ b/src/Mod/Path/PathScripts/PathSanity.py @@ -41,21 +41,20 @@ except AttributeError: def review(obj): - + limits = False "checks the selected project for common errors" + toolcontrolcount = 0 for item in obj.Group: print "Checking: " + item.Label - - if item.Name[:4] == "Tool": + if item.Name[:2] == "TC": + toolcontrolcount += 1 if item.ToolNumber == 0: - FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using ID 0 which is the default\n")) + FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using ID 0 which the undefined default. Please set a real tool.\n")) else: tool = PU.getTool(item, item.ToolNumber) if tool is None: FreeCAD.Console.PrintError(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using tool: " + str(item.ToolNumber) + " which is invalid\n")) - continue - - if tool.Diameter == 0: + elif tool.Diameter == 0: FreeCAD.Console.PrintError(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using tool: " + str(item.ToolNumber) + " which has a zero diameter\n")) if item.HorizFeed == 0: FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " has a 0 value for the Horizontal feed rate\n")) @@ -68,6 +67,14 @@ def review(obj): if len(item.Tooltable.Tools) == 0: FreeCAD.Console.PrintWarning(translate("Path_Sanity", "Machine: " + str(item.Label) + " has no tools defined in the tool table\n")) + if item.X_Max == item.X_Min or item.Y_Max == item.Y_Min: + FreeCAD.Console.PrintWarning(translate("Path_Sanity", "It appears the machine limits haven't been set. Not able to check path extents.\n")) + else: + limits = True + + if toolcontrolcount == 0: + FreeCAD.Console.PrintWarning(translate("Path_Sanity", "A Tool Controller was not found. Default values are used which is dangerous. Please add a Tool Controller.\n")) + class CommandPathSanity: diff --git a/src/Mod/Path/PathScripts/PathSurface.py b/src/Mod/Path/PathScripts/PathSurface.py index 624496820..787ef541e 100644 --- a/src/Mod/Path/PathScripts/PathSurface.py +++ b/src/Mod/Path/PathScripts/PathSurface.py @@ -60,6 +60,7 @@ class ObjectSurface: "Active", "Make False, to prevent operation from generating code")) obj.addProperty("App::PropertyString", "Comment", "Path", translate( "PathProject", "An optional comment for this profile")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", translate("Path", "User Assigned Label")) obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate( "PathProject", "The library to use to generate the path")) @@ -70,6 +71,8 @@ class ObjectSurface: "Tool", translate("PathProfile", "The tool number in use")) obj.ToolNumber = (0, 0, 1000, 0) obj.setEditorMode('ToolNumber', 1) # make this read only + obj.addProperty("App::PropertyString", "ToolDescription", "Tool", translate("Path", "The description of the tool ")) + obj.setEditorMode('ToolDescription', 1) # make this read onlyt # Surface Properties obj.addProperty("App::PropertyFloatConstraint", "SampleInterval", "Surface", translate( @@ -128,6 +131,10 @@ class ObjectSurface: def __setstate__(self, state): return None + def onChanged(self, obj, prop): + if prop == "UserLabel": + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" + def _waterline(self, obj, s, bb): import ocl from PathScripts.PathUtils import depth_params, fmt @@ -270,16 +277,19 @@ class ObjectSurface: self.horizFeed = 100 self.radius = 0.25 obj.ToolNumber = 0 + obj.ToolDescription = "UNDEFINED" else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value - obj.ToolNumber = toolLoad.ToolNumber - tool = PathUtils.getTool(obj, toolLoad.ToolNumber) - if tool is None: - self.radius = 0.25 - else: - self.radius = tool.Diameter / 2 + self.radius = tool.Diameter/2 + obj.ToolNumber = toolLoad.ToolNumber + obj.ToolDescription = toolLoad.Name + + if obj.UserLabel == "": + obj.Label = obj.Name + " (" + obj.ToolDescription + ")" + else: + obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")" if obj.Base: for b in obj.Base: diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 937bf7361..200febc44 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -404,10 +404,13 @@ def getLastToolLoad(obj): if tc is None: for g in FreeCAD.ActiveDocument.Objects: # top level object - if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool): - lastfound = g - if g == obj: - tc = lastfound + try: + if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool): + lastfound = g + if g == obj: + tc = lastfound + except: + continue return tc