Operations and ToolControllers have labels set automatically.

This will hopefully make things a little clearer
A couple more Sanity checks.
Don't error if no TC in project.
This commit is contained in:
brad 2016-05-18 13:54:51 -05:00 committed by Yorik van Havre
parent 7436a5e397
commit 91978ba1a4
13 changed files with 246 additions and 70 deletions

View File

@ -59,6 +59,7 @@ SET(PathScripts_SRCS
PathScripts/PathEngrave.py PathScripts/PathEngrave.py
PathScripts/PathSurface.py PathScripts/PathSurface.py
PathScripts/PathRemote.py PathScripts/PathRemote.py
PathScripts/PathSanity.py
) )

View File

@ -73,5 +73,6 @@
<file>panels/ProfileEdit.ui</file> <file>panels/ProfileEdit.ui</file>
<file>panels/SurfaceEdit.ui</file> <file>panels/SurfaceEdit.ui</file>
<file>panels/RemoteEdit.ui</file> <file>panels/RemoteEdit.ui</file>
<file>panels/ToolControl.ui</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -263,6 +263,67 @@
<attribute name="label"> <attribute name="label">
<string>Pattern</string> <string>Pattern</string>
</attribute> </attribute>
<layout class="QFormLayout" name="formLayout_5">
<item row="0" column="0">
<widget class="QSpinBox" name="stepOverPercent">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Step Over Percent</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_4">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="useZigZag">
<property name="text">
<string>Use ZigZag</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="zigZagUnidirectional">
<property name="text">
<string>ZigZag Unidirectional</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSpinBox" name="zigZagAngle"/>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_10">
<property name="text">
<string>ZigZag Angle</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget> </widget>
<widget class="QWidget" name="page_3"> <widget class="QWidget" name="page_3">
<property name="geometry"> <property name="geometry">

View File

@ -69,9 +69,9 @@ class PathWorkbench (Workbench):
from PathScripts import PathSanity from PathScripts import PathSanity
# build commands list # build commands list
projcmdlist = ["Path_Project", "Path_ToolTableEdit", projcmdlist = ["Path_Project", "Path_Post", "Path_Inspect", "Path_Sanity"]
"Path_Post", "Path_Inspect", "Path_Sanity"] toolcmdlist = ["Path_ToolTableEdit", "Path_LoadTool"]
prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_LoadTool", "Path_ToolLenOffset", "Path_Comment", prepcmdlist = ["Path_Plane", "Path_Fixture", "Path_ToolLenOffset", "Path_Comment",
"Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"] "Path_Stop", "Path_FaceProfile", "Path_FacePocket", "Path_Custom", "Path_FromShape"]
opcmdlist = ["Path_Profile", "Path_Pocket", opcmdlist = ["Path_Profile", "Path_Pocket",
"Path_Drilling", "Path_Engrave", "Path_Surfacing"] "Path_Drilling", "Path_Engrave", "Path_Surfacing"]
@ -86,12 +86,15 @@ class PathWorkbench (Workbench):
def translate(context, text): def translate(context, text):
return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).encode("utf8") return QtGui.QApplication.translate(context, text, None, QtGui.QApplication.UnicodeUTF8).encode("utf8")
self.appendToolbar(translate("Path", "Project Setup"), projcmdlist) 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", "New Operations"), opcmdlist)
self.appendToolbar(translate("Path", "Path Modification"), modcmdlist) self.appendToolbar(translate("Path", "Path Modification"), modcmdlist)
self.appendMenu([translate("Path", "Path"), translate( 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( self.appendMenu([translate("Path", "Path"), translate(
"Path", "Partial Commands")], prepcmdlist) "Path", "Partial Commands")], prepcmdlist)
self.appendMenu([translate("Path", "Path"), translate( self.appendMenu([translate("Path", "Path"), translate(

View File

@ -51,6 +51,7 @@ class ObjectDrilling:
obj.addProperty("App::PropertyLinkSubList", "Base","Path", translate("PathProject", "The base geometry of this toolpath")) 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::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", "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", "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")) 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.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 1) obj.ToolNumber = (0, 0, 1000, 1)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 obj.Proxy = self
@ -72,6 +76,10 @@ class ObjectDrilling:
def __setstate__(self, state): def __setstate__(self, state):
return None return None
def onChanged(self, obj, prop):
if prop == "UserLabel":
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def execute(self, obj): def execute(self, obj):
output = "" output = ""
toolLoad = PathUtils.getLastToolLoad(obj) toolLoad = PathUtils.getLastToolLoad(obj)
@ -80,16 +88,20 @@ class ObjectDrilling:
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
obj.ToolNumber = toolLoad.ToolNumber
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
if tool is None: self.radius = tool.Diameter/2
self.radius = 0.25 obj.ToolNumber = toolLoad.ToolNumber
else: obj.ToolDescription = toolLoad.Name
self.radius = tool.Diameter/2
if obj.UserLabel == "":
obj.Label = obj.Name + " (" + obj.ToolDescription + ")"
else:
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
if obj.Base: if obj.Base:
locations = [] locations = []

View File

@ -49,6 +49,7 @@ class ObjectPathEngrave:
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", "The base geometry of this object") 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::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", "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.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate("Path", "The library or Algorithm used to generate the path"))
obj.Algorithm = ['OCC Native'] obj.Algorithm = ['OCC Native']
@ -57,6 +58,8 @@ class ObjectPathEngrave:
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use")) obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 1) obj.ToolNumber = (0, 0, 1000, 1)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 # Depth Properties
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("Path", "The height needed to clear clamps and obstructions")) 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): def __setstate__(self, state):
return None return None
def onChanged(self, obj, prop):
if prop == "UserLabel":
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def execute(self, obj): def execute(self, obj):
output = "" output = ""
@ -85,16 +92,19 @@ class ObjectPathEngrave:
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
obj.ToolNumber = toolLoad.ToolNumber
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
if tool is None: self.radius = tool.Diameter/2
self.radius = 0.25 obj.ToolNumber = toolLoad.ToolNumber
else: obj.ToolDescription = toolLoad.Name
self.radius = tool.Diameter/2
if obj.UserLabel == "":
obj.Label = obj.Name + " (" + obj.ToolDescription + ")"
else:
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
if obj.Base: if obj.Base:
for o in obj.Base: for o in obj.Base:

View File

@ -21,7 +21,7 @@
# * USA * # * 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 FreeCAD
import FreeCADGui import FreeCADGui
@ -58,6 +58,15 @@ class LoadTool:
obj.setEditorMode('Placement', mode) obj.setEditorMode('Placement', mode)
def execute(self, obj): 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 = ""
commands = 'M6T'+str(obj.ToolNumber)+'\n' commands = 'M6T'+str(obj.ToolNumber)+'\n'
@ -68,7 +77,7 @@ class LoadTool:
commands += 'M4S' + str(obj.SpindleSpeed) + '\n' commands += 'M4S' + str(obj.SpindleSpeed) + '\n'
obj.Path = Path.Path(commands) obj.Path = Path.Path(commands)
obj.Label = "Tool"+str(obj.ToolNumber) # obj.Label = "TC: Tool"+str(obj.ToolNumber)
def onChanged(self, obj, prop): def onChanged(self, obj, prop):
mode = 2 mode = 2
@ -135,20 +144,20 @@ class _ViewProviderLoadTool:
class CommandPathLoadTool: class CommandPathLoadTool:
def GetResources(self): def GetResources(self):
return {'Pixmap': 'Path-LoadTool', 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", '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): def IsActive(self):
return FreeCAD.ActiveDocument is not None return FreeCAD.ActiveDocument is not None
def Activated(self): def Activated(self):
FreeCAD.ActiveDocument.openTransaction(translate("Current Tool", "Tool Number to Load")) FreeCAD.ActiveDocument.openTransaction(translate("Path_LoadTool", "Create Tool Controller Object"))
snippet = ''' snippet = '''
import Path, PathScripts import Path, PathScripts
from PathScripts import PathUtils, PathLoadTool 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.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject) PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
@ -165,7 +174,7 @@ PathUtils.addToProject(obj)
import PathScripts import PathScripts
import PathUtils import PathUtils
obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "Tool") obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TC")
PathScripts.PathLoadTool.LoadTool(obj) PathScripts.PathLoadTool.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject) PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
@ -174,8 +183,8 @@ PathUtils.addToProject(obj)
class TaskPanel: class TaskPanel:
def __init__(self): def __init__(self):
#self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolControl.ui") self.form = FreeCADGui.PySideUic.loadUi(":/panels/ToolControl.ui")
self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolControl.ui") #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/ToolControl.ui")
self.updating = False self.updating = False
def accept(self): def accept(self):
@ -196,25 +205,41 @@ class TaskPanel:
if hasattr(self.obj, "VertFeed"): if hasattr(self.obj, "VertFeed"):
self.obj.Label = self.form.tcoName.text() self.obj.Label = self.form.tcoName.text()
if hasattr(self.obj, "VertFeed"): if hasattr(self.obj, "VertFeed"):
self.obj.VertFeed = self.form.vertFeed.value() self.obj.VertFeed = self.form.vertFeed.text()
if hasattr(self.obj, "HorizFeed"): if hasattr(self.obj, "HorizFeed"):
self.obj.HorizFeed = self.form.horizFeed.value() self.obj.HorizFeed = self.form.horizFeed.text()
if hasattr(self.obj, "SpindleSpeed"): if hasattr(self.obj, "SpindleSpeed"):
self.obj.SpindleSpeed = self.form.spindleSpeed.value() self.obj.SpindleSpeed = self.form.spindleSpeed.value()
if hasattr(self.obj, "SpindleDir"): if hasattr(self.obj, "SpindleDir"):
self.obj.SpindleDir = str(self.form.cboSpindleDirection.currentText()) self.obj.SpindleDir = str(self.form.cboSpindleDirection.currentText())
if hasattr(self.obj, "ToolNumber"): #if hasattr(self.obj, "ToolNumber"):
self.obj.ToolNumber = self.form.ToolNumber.value() # self.obj.ToolNumber = self.form.ToolNumber.value()
self.obj.Proxy.execute(self.obj) self.obj.Proxy.execute(self.obj)
def setFields(self): def setFields(self):
self.form.vertFeed.setText(str(self.obj.VertFeed.Value)) self.form.vertFeed.setText(str(self.obj.VertFeed.Value))
self.form.horizFeed.setText(str(self.obj.HorizFeed.Value)) self.form.horizFeed.setText(str(self.obj.HorizFeed.Value))
self.form.spindleSpeed.setText(str(self.obj.SpindleSpeed.Value)) self.form.spindleSpeed.setValue(self.obj.SpindleSpeed)
self.form.cboSpindleDirection.setText(str(self.obj.SpindleDir.Value)) self.form.tcoName.setText(str(self.obj.Label))
self.form.ToolNumber.setValue(self.obj.ToolNumber)
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): def open(self):

View File

@ -50,6 +50,7 @@ class ObjectPocket:
obj.addProperty("App::PropertyLinkSubList", "Base", "Path", translate("PathProject", "The base geometry of this object")) 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::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", "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.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate("PathProject", "The library to use to generate the path"))
obj.Algorithm = ['OCC Native', 'libarea'] 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.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 0) obj.ToolNumber = (0, 0, 1000, 0)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 # Depth Properties
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("PathProject", "The height needed to clear clamps and obstructions")) 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('RampAngle', 2) # make this hidden
obj.setEditorMode('RampSize', 2) # make this hidden obj.setEditorMode('RampSize', 2) # make this hidden
if prop == "UserLabel":
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def __getstate__(self): def __getstate__(self):
return None return None
@ -354,17 +361,19 @@ class ObjectPocket:
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2 self.radius = tool.Diameter/2
obj.ToolNumber = toolLoad.ToolNumber obj.ToolNumber = toolLoad.ToolNumber
obj.ToolDescription = toolLoad.Name
# if tool is None: if obj.UserLabel == "":
# self.radius = 0.25 obj.Label = obj.Name + " (" + obj.ToolDescription + ")"
# else: else:
# self.radius = tool.Diameter/2 obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
if obj.Base: if obj.Base:
for b in obj.Base: for b in obj.Base:
@ -501,6 +510,7 @@ class CommandPathPocket:
FreeCADGui.doCommand('obj.Active = True') FreeCADGui.doCommand('obj.Active = True')
FreeCADGui.doCommand('PathScripts.PathPocket.ViewProviderPocket(obj.ViewObject)') FreeCADGui.doCommand('PathScripts.PathPocket.ViewProviderPocket(obj.ViewObject)')
FreeCADGui.doCommand('from PathScripts import PathUtils') FreeCADGui.doCommand('from PathScripts import PathUtils')
FreeCADGui.doCommand('obj.Algorithm = "libarea"')
FreeCADGui.doCommand('obj.StepOver = 100') FreeCADGui.doCommand('obj.StepOver = 100')
FreeCADGui.doCommand('obj.ClearanceHeight = 10') # + str(bb.ZMax + 2.0)) FreeCADGui.doCommand('obj.ClearanceHeight = 10') # + str(bb.ZMax + 2.0))
FreeCADGui.doCommand('obj.StepDown = 1.0') FreeCADGui.doCommand('obj.StepDown = 1.0')
@ -557,6 +567,15 @@ class TaskPanel:
self.obj.Algorithm = str(self.form.algorithmSelect.currentText()) self.obj.Algorithm = str(self.form.algorithmSelect.currentText())
if hasattr(self.obj, "CutMode"): if hasattr(self.obj, "CutMode"):
self.obj.CutMode = str(self.form.cutMode.currentText()) 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) self.obj.Proxy.execute(self.obj)
def setFields(self): def setFields(self):
@ -567,6 +586,10 @@ class TaskPanel:
self.form.stepDown.setValue(self.obj.StepDown) self.form.stepDown.setValue(self.obj.StepDown)
self.form.extraOffset.setValue(self.obj.MaterialAllowance.Value) self.form.extraOffset.setValue(self.obj.MaterialAllowance.Value)
self.form.useStartPoint.setChecked(self.obj.UseStartPoint) 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) index = self.form.algorithmSelect.findText(self.obj.Algorithm, QtCore.Qt.MatchFixedString)
if index >= 0: if index >= 0:
@ -586,16 +609,6 @@ class TaskPanel:
# check that the selection contains exactly what we want # check that the selection contains exactly what we want
selection = FreeCADGui.Selection.getSelectionEx() 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: if len(selection) != 1:
FreeCAD.Console.PrintError(translate("PathProject", "Please select only faces from one solid\n")) FreeCAD.Console.PrintError(translate("PathProject", "Please select only faces from one solid\n"))
return return
@ -685,6 +698,13 @@ class TaskPanel:
self.form.useStartPoint.clicked.connect(self.getFields) self.form.useStartPoint.clicked.connect(self.getFields)
self.form.extraOffset.editingFinished.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() self.setFields()
sel = FreeCADGui.Selection.getSelectionEx() sel = FreeCADGui.Selection.getSelectionEx()

View File

@ -66,6 +66,8 @@ class ObjectProfile:
obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use")) obj.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("Path", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 1) obj.ToolNumber = (0, 0, 1000, 1)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 # Depth Properties
obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", translate("Path", "The height needed to clear clamps and obstructions")) 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.angles = angles
obj.lengths = lengths obj.lengths = lengths
obj.heights = heights obj.heights = heights
obj.ToolDescription = "UNDEFINED"
obj.Proxy = self obj.Proxy = self
@ -121,9 +124,9 @@ class ObjectProfile:
def __setstate__(self, state): def __setstate__(self, state):
return None return None
# def onChanged(self, obj, prop): def onChanged(self, obj, prop):
# if prop == "Label": if prop == "UserLabel":
# print "we're here" obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def addprofilebase(self, obj, ss, sub=""): def addprofilebase(self, obj, ss, sub=""):
baselist = obj.Base baselist = obj.Base
@ -263,13 +266,20 @@ print "y - " + str(point.y)
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2 self.radius = tool.Diameter/2
obj.ToolNumber = toolLoad.ToolNumber 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: if obj.Base:
hfaces = [] hfaces = []

View File

@ -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::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::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", "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::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")) 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.addProperty("App::PropertyIntegerConstraint", "ToolNumber", "Tool", translate("PathProfile", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 0) obj.ToolNumber = (0, 0, 1000, 0)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 # Depth Properties
obj.addProperty("App::PropertyFloat", "ClearanceHeight", "Depth", translate("PathProject", "The height needed to clear clamps and obstructions")) 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) print "adding: " + str(prop)
obj.proplist = pl obj.proplist = pl
if prop == "UserLabel":
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def execute(self, obj): def execute(self, obj):
output = "" output = ""
@ -162,12 +168,19 @@ class ObjectRemote:
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
self.radius = tool.Diameter/2 self.radius = tool.Diameter/2
obj.ToolNumber = toolLoad.ToolNumber 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)" output += "(remote gcode goes here)"
path = Path.Path(output) path = Path.Path(output)

View File

@ -41,21 +41,20 @@ except AttributeError:
def review(obj): def review(obj):
limits = False
"checks the selected project for common errors" "checks the selected project for common errors"
toolcontrolcount = 0
for item in obj.Group: for item in obj.Group:
print "Checking: " + item.Label print "Checking: " + item.Label
if item.Name[:2] == "TC":
if item.Name[:4] == "Tool": toolcontrolcount += 1
if item.ToolNumber == 0: 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: else:
tool = PU.getTool(item, item.ToolNumber) tool = PU.getTool(item, item.ToolNumber)
if tool is None: 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")) FreeCAD.Console.PrintError(translate("Path_Sanity", "Tool Controller: " + str(item.Label) + " is using tool: " + str(item.ToolNumber) + " which is invalid\n"))
continue elif tool.Diameter == 0:
if 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")) 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: 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")) 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: 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")) 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: class CommandPathSanity:

View File

@ -60,6 +60,7 @@ class ObjectSurface:
"Active", "Make False, to prevent operation from generating code")) "Active", "Make False, to prevent operation from generating code"))
obj.addProperty("App::PropertyString", "Comment", "Path", translate( obj.addProperty("App::PropertyString", "Comment", "Path", translate(
"PathProject", "An optional comment for this profile")) "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( obj.addProperty("App::PropertyEnumeration", "Algorithm", "Algorithm", translate(
"PathProject", "The library to use to generate the path")) "PathProject", "The library to use to generate the path"))
@ -70,6 +71,8 @@ class ObjectSurface:
"Tool", translate("PathProfile", "The tool number in use")) "Tool", translate("PathProfile", "The tool number in use"))
obj.ToolNumber = (0, 0, 1000, 0) obj.ToolNumber = (0, 0, 1000, 0)
obj.setEditorMode('ToolNumber', 1) # make this read only 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 # Surface Properties
obj.addProperty("App::PropertyFloatConstraint", "SampleInterval", "Surface", translate( obj.addProperty("App::PropertyFloatConstraint", "SampleInterval", "Surface", translate(
@ -128,6 +131,10 @@ class ObjectSurface:
def __setstate__(self, state): def __setstate__(self, state):
return None return None
def onChanged(self, obj, prop):
if prop == "UserLabel":
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
def _waterline(self, obj, s, bb): def _waterline(self, obj, s, bb):
import ocl import ocl
from PathScripts.PathUtils import depth_params, fmt from PathScripts.PathUtils import depth_params, fmt
@ -270,16 +277,19 @@ class ObjectSurface:
self.horizFeed = 100 self.horizFeed = 100
self.radius = 0.25 self.radius = 0.25
obj.ToolNumber = 0 obj.ToolNumber = 0
obj.ToolDescription = "UNDEFINED"
else: else:
self.vertFeed = toolLoad.VertFeed.Value self.vertFeed = toolLoad.VertFeed.Value
self.horizFeed = toolLoad.HorizFeed.Value self.horizFeed = toolLoad.HorizFeed.Value
obj.ToolNumber = toolLoad.ToolNumber
tool = PathUtils.getTool(obj, toolLoad.ToolNumber) tool = PathUtils.getTool(obj, toolLoad.ToolNumber)
if tool is None: self.radius = tool.Diameter/2
self.radius = 0.25 obj.ToolNumber = toolLoad.ToolNumber
else: obj.ToolDescription = toolLoad.Name
self.radius = tool.Diameter / 2
if obj.UserLabel == "":
obj.Label = obj.Name + " (" + obj.ToolDescription + ")"
else:
obj.Label = obj.UserLabel + " (" + obj.ToolDescription + ")"
if obj.Base: if obj.Base:
for b in obj.Base: for b in obj.Base:

View File

@ -404,10 +404,13 @@ def getLastToolLoad(obj):
if tc is None: if tc is None:
for g in FreeCAD.ActiveDocument.Objects: # top level object for g in FreeCAD.ActiveDocument.Objects: # top level object
if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool): try:
lastfound = g if isinstance(g.Proxy, PathScripts.PathLoadTool.LoadTool):
if g == obj: lastfound = g
tc = lastfound if g == obj:
tc = lastfound
except:
continue
return tc return tc