diff --git a/src/Mod/Path/PathScripts/PathJob.py b/src/Mod/Path/PathScripts/PathJob.py index b873707492..13739292ae 100644 --- a/src/Mod/Path/PathScripts/PathJob.py +++ b/src/Mod/Path/PathScripts/PathJob.py @@ -51,19 +51,16 @@ def translate(context, text, disambig=None): class JobTemplate: '''Attribute and sub element strings for template export/import.''' + Description = 'Desc' + GeometryTolerance = 'Tolerance' Job = 'Job' PostProcessor = 'Post' PostProcessorArgs = 'PostArgs' PostProcessorOutputFile = 'Output' - GeometryTolerance = 'Tolerance' - Description = 'Desc' - ToolController = 'ToolController' + Settings = 'Settings' Stock = 'Stock' + ToolController = 'ToolController' Version = 'Version' - DefaultVertRapid = 'DefaultVertRapid' - DefaultHorizRapid = 'DefaultHorizRapid' - DefaultSafeHeight = 'DefaultSafeHeight' - DefaultClearanceHeight = 'DefaultClearanceHeight' def isArchPanelSheet(obj): return hasattr(obj, 'Proxy') and isinstance(obj.Proxy, ArchPanel.PanelSheet) @@ -209,14 +206,8 @@ class ObjectJob: attrs = json.load(fp) if attrs.get(JobTemplate.Version) and 1 == int(attrs[JobTemplate.Version]): - if attrs.get(JobTemplate.DefaultVertRapid): - self.settings.updateSetting(PathSettings.Default.VertRapid, attrs[JobTemplate.DefaultVertRapid]) - if attrs.get(JobTemplate.DefaultHorizRapid): - self.settings.updateSetting(PathSettings.Default.HorizRapid, attrs[JobTemplate.DefaultHorizRapid]) - if attrs.get(JobTemplate.DefaultSafeHeight): - self.settings.updateSetting(PathSettings.Default.SafeHeight, attrs[JobTemplate.DefaultSafeHeight]) - if attrs.get(JobTemplate.DefaultClearanceHeight): - self.settings.updateSetting(PathSettings.Default.ClearanceHeight, attrs[JobTemplate.DefaultClearanceHeight]) + if attrs.get(JobTemplate.Settings): + self.settings.setFromTemplate(attrs[JobTemplate.Settings]) if attrs.get(JobTemplate.GeometryTolerance): obj.GeometryTolerance = float(attrs.get(JobTemplate.GeometryTolerance)) @@ -236,13 +227,13 @@ class ObjectJob: tcs.append(PathToolController.FromTemplate(tc)) if attrs.get(JobTemplate.Stock): obj.Stock = PathStock.CreateFromTemplate(obj, attrs.get(JobTemplate.Stock)) + + PathLog.debug("setting tool controllers (%d)" % len(tcs)) + obj.ToolController = tcs else: PathLog.error(translate('PathJob', "Unsupported PathJob template version %s") % attrs.get(JobTemplate.Version)) - tcs.append(PathToolController.Create()) if not tcs: - tcs.append(PathToolController.Create()) - PathLog.debug("setting tool controllers (%d)" % len(tcs)) - obj.ToolController = tcs + self.addToolController(PathToolController.Create()) def templateAttrs(self, obj): '''templateAttrs(obj) ... answer a dictionary with all properties of the receiver that should be stored in a template file.''' @@ -256,10 +247,6 @@ class ObjectJob: attrs[JobTemplate.GeometryTolerance] = str(obj.GeometryTolerance.Value) if obj.Description: attrs[JobTemplate.Description] = obj.Description - attrs[JobTemplate.DefaultVertRapid] = obj.Settings.DefaultVertRapid - attrs[JobTemplate.DefaultHorizRapid] = obj.Settings.DefaultHorizRapid - attrs[JobTemplate.DefaultSafeHeight] = obj.Settings.DefaultSafeHeight - attrs[JobTemplate.DefaultClearanceHeight] = obj.Settings.DefaultClearanceHeight return attrs def __getstate__(self): @@ -283,7 +270,7 @@ class ObjectJob: def addToolController(self, tc): group = self.obj.ToolController - PathLog.info("addToolController(%s): %s" % (tc.Label, [t.Label for t in group])) + PathLog.debug("addToolController(%s): %s" % (tc.Label, [t.Label for t in group])) if tc.Name not in [str(t.Name) for t in group]: tc.setExpression('VertRapid', "%s.%s" % (self.obj.Settings.Name, PathSettings.Default.VertRapid)) tc.setExpression('HorizRapid', "%s.%s" % (self.obj.Settings.Name, PathSettings.Default.HorizRapid)) diff --git a/src/Mod/Path/PathScripts/PathJobCmd.py b/src/Mod/Path/PathScripts/PathJobCmd.py index e8ca2ae244..d9be97b97a 100644 --- a/src/Mod/Path/PathScripts/PathJobCmd.py +++ b/src/Mod/Path/PathScripts/PathJobCmd.py @@ -251,13 +251,14 @@ class CommandJobTemplateExport: if stockAttrs: attrs[PathJob.JobTemplate.Stock] = stockAttrs - # defaults settings - if dialog and not (dialog.includeDefaults() and dialog.includeDefaultToolRapid()): - attrs.pop(PathJob.JobTemplate.DefaultVertRapid, None) - attrs.pop(PathJob.JobTemplate.DefaultHorizRapid, None) - if dialog and not (dialog.includeDefaults() and dialog.includeDefaultOperationHeights()): - attrs.pop(PathJob.JobTemplate.DefaultSafeHeight, None) - attrs.pop(PathJob.JobTemplate.DefaultClearanceHeight, None) + # settings + settingsAttrs = None + if dialog: + settingsAttrs = job.Proxy.settings.templateAttributes(dialog.includeDefaultToolRapid(), dialog.includeDefaultOperationHeights()) + else: + settingsAttrs = job.Proxy.settings.templateAttributes(True, True) + if settingsAttrs: + attrs[PathJob.JobTemplate.Settings] = settingsAttrs # write template with open(unicode(path), 'wb') as fp: diff --git a/src/Mod/Path/PathScripts/PathOp.py b/src/Mod/Path/PathScripts/PathOp.py index 1185b539cf..01c6418791 100644 --- a/src/Mod/Path/PathScripts/PathOp.py +++ b/src/Mod/Path/PathScripts/PathOp.py @@ -94,15 +94,25 @@ class ObjectOp(object): ''' def addBaseProperty(self, obj): - obj.addProperty("App::PropertyLinkSubListGlobal", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The base geometry for this operation")) + obj.addProperty("App::PropertyLinkSubListGlobal", "Base", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "The base geometry for this operation")) + def addOpValues(self, obj, values): + if 'start' in values: + obj.addProperty("App::PropertyDistance", "OpStartDepth", "Op Values", QtCore.QT_TRANSLATE_NOOP("PathOp", "Holds the calculated value for the StartDepth")) + obj.setEditorMode('OpStartDepth', 1) # read-only + if 'final' in values: + obj.addProperty("App::PropertyDistance", "OpFinalDepth", "Op Values", QtCore.QT_TRANSLATE_NOOP("PathOp", "Holds the calculated value for the FinalDepth")) + obj.setEditorMode('OpFinalDepth', 1) # read-only + if 'tooldia' in values: + obj.addProperty("App::PropertyDistance", "OpToolDiameter", "Op Values", QtCore.QT_TRANSLATE_NOOP("PathOp", "Holds the diameter of the tool")) + obj.setEditorMode('OpToolDiameter', 1) # read-only def __init__(self, obj): PathLog.track() - obj.addProperty("App::PropertyBool", "Active", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Make False, to prevent operation from generating code")) - obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "An optional comment for this Operation")) - obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "User Assigned Label")) + obj.addProperty("App::PropertyBool", "Active", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "Make False, to prevent operation from generating code")) + obj.addProperty("App::PropertyString", "Comment", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "An optional comment for this Operation")) + obj.addProperty("App::PropertyString", "UserLabel", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "User Assigned Label")) features = self.opFeatures(obj) @@ -110,32 +120,38 @@ class ObjectOp(object): self.addBaseProperty(obj) if FeatureLocations & features: - obj.addProperty("App::PropertyVectorList", "Locations", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "Base locations for this operation")) + obj.addProperty("App::PropertyVectorList", "Locations", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "Base locations for this operation")) if FeatureTool & features: - obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property", "The tool controller that will be used to calculate the path")) + obj.addProperty("App::PropertyLink", "ToolController", "Path", QtCore.QT_TRANSLATE_NOOP("PathOp", "The tool controller that will be used to calculate the path")) if FeatureDepths & features: - obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Starting Depth of Tool- first cut depth in Z")) - obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Final Depth of Tool- lowest value in Z")) - obj.addProperty("App::PropertyBool", "StartDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "If enabled Start Depth will not be automatically updated when geometry changes")) - obj.addProperty("App::PropertyBool", "FinalDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "If enabled Final Depth will not be automatically updated when geometry changes")) + obj.addProperty("App::PropertyDistance", "StartDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "Starting Depth of Tool- first cut depth in Z")) + obj.addProperty("App::PropertyDistance", "FinalDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "Final Depth of Tool- lowest value in Z")) + obj.addProperty("App::PropertyBool", "StartDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "If enabled Start Depth will not be automatically updated when geometry changes")) + obj.addProperty("App::PropertyBool", "FinalDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "If enabled Final Depth will not be automatically updated when geometry changes")) + values = ['start'] if FeatureNoFinalDepth & features: obj.setEditorMode('FinalDepth', 2) # hide + obj.setEditorMode('FinalDepthLock', 2) # hide + else: + values.append('final') + self.addOpValues(obj, values) if FeatureStepDown & features: - obj.addProperty("App::PropertyDistance", "StepDown", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Incremental Step Down of Tool")) + obj.addProperty("App::PropertyDistance", "StepDown", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "Incremental Step Down of Tool")) + self.addOpValues(obj, ['tooldia']) if FeatureFinishDepth & features: - obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Maximum material removed on final pass.")) + obj.addProperty("App::PropertyDistance", "FinishDepth", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "Maximum material removed on final pass.")) if FeatureHeights & features: - obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "The height needed to clear clamps and obstructions")) - obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "Rapid Safety Height between locations.")) + obj.addProperty("App::PropertyDistance", "ClearanceHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "The height needed to clear clamps and obstructions")) + obj.addProperty("App::PropertyDistance", "SafeHeight", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "Rapid Safety Height between locations.")) if FeatureStartPoint & features: - obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path")) - obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point")) + obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("PathOp", "The start point of this path")) + obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("PathOp", "make True, if specifying a Start Point")) self.initOperation(obj) @@ -153,11 +169,23 @@ class ObjectOp(object): obj.Document.recompute() if FeatureDepths & self.opFeatures(obj): if not hasattr(obj, 'StartDepthLock'): - obj.addProperty("App::PropertyBool", "StartDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "If enabled Start Depth will not be automatically updated when geometry changes")) + obj.addProperty("App::PropertyBool", "StartDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "If enabled Start Depth will not be automatically updated when geometry changes")) obj.StartDepthLock = False if not hasattr(obj, 'FinalDepthLock'): - obj.addProperty("App::PropertyBool", "FinalDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("App::Property", "If enabled Final Depth will not be automatically updated when geometry changes")) + obj.addProperty("App::PropertyBool", "FinalDepthLock", "Depth", QtCore.QT_TRANSLATE_NOOP("PathOp", "If enabled Final Depth will not be automatically updated when geometry changes")) obj.FinalDepthLock = False + if not hasattr(obj, 'OpStartDepth'): + self.addOpValues(obj, ['start', 'final']) + if not obj.StartDepthLock: + obj.setExpression('StartDepth', 'OpStartDepth') + if FeatureNoFinalDepth & features: + obj.setEditorMode('OpFinalDepth', 2) + elif not obj.FinalDepthLock: + obj.setExpression('FinalDepth', 'OpFinalDepth') + if PatGeom.isRoughly(obj.StepDown.Value, 1): + obj.setExpression('StepDown', 'OpToolDiameter') + if FeatureStepDown & self.opFeatures(obj) and not hasattr(obj, 'OpToolDiameter'): + self.addOpValues(['tooldia']) def __getstate__(self): '''__getstat__(self) ... called when receiver is saved. @@ -227,13 +255,16 @@ class ObjectOp(object): obj.ToolController = PathUtils.findToolController(obj) if FeatureDepths & features: - obj.StartDepth = 1.0 + obj.setExpression('StartDepth', 'OpStartDepth') + obj.setExpression('FinalDepth', 'OpFinalDepth') + obj.OpStartDepth = 1.0 obj.StartDepthLock = False - obj.FinalDepth = 0.0 + obj.OpFinalDepth = 0.0 obj.FinalDepthLock = False if FeatureStepDown & features: - obj.StepDown = 1.0 + obj.OpToolDiameter = 1.0 + obj.setExpression('StepDown', 'OpToolDiameter') if FeatureHeights & features: obj.setExpression('SafeHeight', "%s.%s+StartDepth" % (job.Settings.Name, PathSettings.Default.SafeHeight)) @@ -268,7 +299,7 @@ class ObjectOp(object): def updateDepths(self, obj, ignoreErrors=False): '''updateDepths(obj) ... base implementation calculating depths depending on base geometry. - Can safely be overwritten.''' + Should not be overwritten.''' def faceZmin(bb, fbb): if fbb.ZMax == fbb.ZMin and fbb.ZMax == bb.ZMax: # top face @@ -303,13 +334,13 @@ class ObjectOp(object): safeDepths = True if FeatureDepths & self.opFeatures(obj): # first set update final depth, it's value is not negotiable - if not PathGeom.isRoughly(obj.FinalDepth.Value, zmin): + if not PathGeom.isRoughly(obj.OpFinalDepth.Value, zmin): if not hasattr(obj, 'FinalDepthLock') or not obj.FinalDepthLock: - obj.FinalDepth = zmin + obj.OpFinalDepth = zmin else: - if obj.FinalDepth.Value < zmin: + if obj.OpFinalDepth.Value < zmin: safeDepths = False - zmin = obj.FinalDepth.Value + zmin = obj.OpFinalDepth.Value def minZmax(z): if hasattr(obj, 'StepDown') and not PathGeom.isRoughly(obj.StepDown.Value, 0): @@ -322,22 +353,15 @@ class ObjectOp(object): zmax = minZmax(zmin) # update start depth if requested and required - if not PathGeom.isRoughly(obj.StartDepth.Value, zmax): + if not PathGeom.isRoughly(obj.OpStartDepth.Value, zmax): if not hasattr(obj, 'StartDepthLock') or not obj.StartDepthLock: - obj.StartDepth = zmax - elif (obj.StartDepth.Value - 0.0001) <= obj.FinalDepth.Value: - obj.StartDepth = minZmax(obj.FinalDepth.Value) + obj.OpStartDepth = zmax + elif (obj.OpStartDepth.Value - 0.0001) <= obj.OpFinalDepth.Value: + obj.OpStartDepth = minZmax(obj.OpFinalDepth.Value) else: - if obj.StartDepth.Value < zmax: + if obj.OpStartDepth.Value < zmax: safeDepths = False - #clearance = obj.StartDepth.Value + self.job.Settings.DefaultClearanceHeight.Value - #safe = obj.StartDepth.Value + self.job.Settings.DefaultSafeHeight.Value - #if hasattr(obj, 'ClearanceHeight') and not PathGeom.isRoughly(clearance, obj.ClearanceHeight.Value): - # obj.ClearanceHeight = clearance - #if hasattr(obj, 'SafeHeight') and not PathGeom.isRoughly(safe, obj.SafeHeight.Value): - # obj.SafeHeight = safe - return safeDepths @waiting_effects @@ -387,11 +411,14 @@ class ObjectOp(object): if not tool or tool.Diameter == 0: FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.") return - else: - self.radius = tool.Diameter/2 - self.tool = tool + self.radius = tool.Diameter/2 + self.tool = tool + obj.OpToolDiameter = tool.Diameter self.updateDepths(obj) + # now that all op values are set make sure the user properties get updated accordingly, + # in case they still have an expression referencing any op values + obj.recompute() self.commandlist = [] self.commandlist.append(Path.Command("(%s)" % obj.Label)) diff --git a/src/Mod/Path/PathScripts/PathSettings.py b/src/Mod/Path/PathScripts/PathSettings.py index 895fdb5cdc..80c60a7c3a 100644 --- a/src/Mod/Path/PathScripts/PathSettings.py +++ b/src/Mod/Path/PathScripts/PathSettings.py @@ -76,3 +76,23 @@ class Settings: self.obj.Settings.setAlias(valueCell, name) self.obj.Settings.set(descCell, desc) + def setFromTemplate(self, attrs): + if attrs.get(Default.VertRapid): + self.updateSetting(Default.VertRapid, attrs[Default.VertRapid]) + if attrs.get(Default.HorizRapid): + self.updateSetting(Default.HorizRapid, attrs[Default.HorizRapid]) + if attrs.get(Default.SafeHeight): + self.updateSetting(Default.SafeHeight, attrs[Default.SafeHeight]) + if attrs.get(Default.ClearanceHeight): + self.updateSetting(Default.ClearanceHeight, attrs[Default.ClearanceHeight]) + + def templateAttributes(self, includeRapids, includeHeights): + attrs = {} + if includeRapids: + attrs[Default.VertRapid] = self.obj.Settings.DefaultVertRapid.UserString + attrs[Default.HorizRapid] = self.obj.Settings.DefaultHorizRapid.UserString + if includeHeights: + attrs[Default.SafeHeight] = self.obj.Settings.DefaultSafeHeight.UserString + attrs[Default.ClearanceHeight] = self.obj.Settings.DefaultClearanceHeight.UserString + return attrs +