Merge pull request #22764 from tarman3/postprocess
CAM: Post Process only selected Operations
This commit is contained in:
@@ -277,7 +277,7 @@ class JobPreferencesPage:
|
||||
self.form.stockCreateCylinder.hide()
|
||||
|
||||
def getPostProcessor(self, name):
|
||||
if not name in self.processor:
|
||||
if name not in self.processor:
|
||||
processor = PostProcessorFactory.get_post_processor(None, name)
|
||||
self.processor[name] = processor
|
||||
return processor
|
||||
|
||||
@@ -61,8 +61,7 @@ def _resolve_post_processor_name(job):
|
||||
|
||||
if valid_name and PostProcessor.exists(valid_name):
|
||||
return valid_name
|
||||
else:
|
||||
raise ValueError(f"Post processor not identified.")
|
||||
raise ValueError("Post processor not identified.")
|
||||
|
||||
|
||||
class DlgSelectPostProcessor:
|
||||
@@ -109,16 +108,15 @@ class CommandPathPost:
|
||||
"Pixmap": "CAM_Post",
|
||||
"MenuText": QT_TRANSLATE_NOOP("CAM_Post", "Post Process"),
|
||||
"Accel": "P, P",
|
||||
"ToolTip": QT_TRANSLATE_NOOP("CAM_Post", "Post Processes the selected job"),
|
||||
"ToolTip": QT_TRANSLATE_NOOP("CAM_Post", "Post Processes the selected Job"),
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
selected = FreeCADGui.Selection.getSelectionEx()
|
||||
if len(selected) != 1:
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
if not selection:
|
||||
return False
|
||||
|
||||
selected_object = selected[0].Object
|
||||
self.candidate = PathUtils.findParentJob(selected_object)
|
||||
self.candidate = PathUtils.findParentJob(selection[0])
|
||||
|
||||
return self.candidate is not None
|
||||
|
||||
@@ -212,7 +210,10 @@ class CommandPathPost:
|
||||
return
|
||||
|
||||
# get a postprocessor
|
||||
postprocessor = PostProcessorFactory.get_post_processor(self.candidate, postprocessor_name)
|
||||
postprocessor = PostProcessorFactory.get_post_processor(
|
||||
self.candidate,
|
||||
postprocessor_name,
|
||||
)
|
||||
|
||||
post_data = postprocessor.export()
|
||||
# None is returned if there was an error during argument processing
|
||||
@@ -259,8 +260,105 @@ class CommandPathPost:
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
class CommandPathPostSelected(CommandPathPost):
|
||||
def GetResources(self):
|
||||
return {
|
||||
"Pixmap": "CAM_PostSelected",
|
||||
"MenuText": QT_TRANSLATE_NOOP("CAM_Post", "Post Process Selected"),
|
||||
"Accel": "P, O",
|
||||
"ToolTip": QT_TRANSLATE_NOOP("CAM_Post", "Post Processes the selected operations"),
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
if not selection:
|
||||
return False
|
||||
|
||||
return all(hasattr(op, "Path") and not op.Name.startswith("Job") for op in selection)
|
||||
|
||||
def Activated(self):
|
||||
"""
|
||||
Handles the activation of post processing, initiating the process based
|
||||
on user selection and document context.
|
||||
"""
|
||||
FreeCAD.ActiveDocument.openTransaction("Post Process the Selected operations")
|
||||
|
||||
selection = FreeCADGui.Selection.getSelection()
|
||||
job = PathUtils.findParentJob(selection[0])
|
||||
if (
|
||||
not job
|
||||
and hasattr(selection[0], "Base")
|
||||
and isinstance(selection[0].Base, list)
|
||||
and selection[0].Base
|
||||
):
|
||||
# find 'job' for operation inside 'Array' with multi tool controller
|
||||
baseOp = FreeCAD.ActiveDocument.getObject(selection[0].Base[0])
|
||||
job = PathUtils.findParentJob(baseOp)
|
||||
|
||||
opCandidates = [op for op in selection if hasattr(op, "Path") and "Job" not in op.Name]
|
||||
operations = []
|
||||
if opCandidates and job.Operations.Group != opCandidates:
|
||||
msgBox = QtGui.QMessageBox()
|
||||
msgBox.setWindowTitle("Post Process")
|
||||
msgBox.setText("<p align='center'>What needs to be exported?</p>")
|
||||
msgBox.setInformativeText(
|
||||
"<p align='center'>Check to make sure that you won't break anything by leaving out operations</p>"
|
||||
)
|
||||
msgBox.findChild(QtGui.QGridLayout).setColumnMinimumWidth(1, 250)
|
||||
btn1 = msgBox.addButton("Only selected", QtGui.QMessageBox.ButtonRole.YesRole)
|
||||
btn2 = msgBox.addButton("All", QtGui.QMessageBox.ButtonRole.NoRole)
|
||||
msgBox.setDefaultButton(btn2)
|
||||
msgBox.exec()
|
||||
|
||||
if msgBox.clickedButton() == btn1:
|
||||
print(
|
||||
f"Post process only selected operations: {', '.join([op.Name for op in opCandidates])}"
|
||||
)
|
||||
operations = opCandidates
|
||||
|
||||
postprocessor_name = _resolve_post_processor_name(job)
|
||||
Path.Log.debug(f"Post Processor: {postprocessor_name}")
|
||||
|
||||
if not postprocessor_name:
|
||||
FreeCAD.ActiveDocument.abortTransaction()
|
||||
return
|
||||
|
||||
# get a postprocessor
|
||||
postprocessor = PostProcessorFactory.get_post_processor(
|
||||
{"job": job, "operations": operations}, postprocessor_name
|
||||
)
|
||||
|
||||
post_data = postprocessor.export()
|
||||
# None is returned if there was an error during argument processing
|
||||
# otherwise the "usual" post_data data structure is returned.
|
||||
if not post_data:
|
||||
FreeCAD.ActiveDocument.abortTransaction()
|
||||
return
|
||||
|
||||
policy = Path.Preferences.defaultOutputPolicy()
|
||||
generator = FilenameGenerator(job=job)
|
||||
generated_filename = generator.generate_filenames()
|
||||
|
||||
for item in post_data:
|
||||
subpart, gcode = item
|
||||
|
||||
# get a name for the file
|
||||
subpart = "" if subpart == "allitems" else subpart
|
||||
Path.Log.debug(subpart)
|
||||
generator.set_subpartname(subpart)
|
||||
fname = next(generated_filename)
|
||||
|
||||
if gcode is not None:
|
||||
# write the results to the file
|
||||
self._write_file(fname, gcode, policy)
|
||||
|
||||
FreeCAD.ActiveDocument.commitTransaction()
|
||||
FreeCAD.ActiveDocument.recompute()
|
||||
|
||||
|
||||
if FreeCAD.GuiUp:
|
||||
# register the FreeCAD command
|
||||
FreeCADGui.addCommand("CAM_Post", CommandPathPost())
|
||||
FreeCADGui.addCommand("CAM_PostSelected", CommandPathPostSelected())
|
||||
|
||||
FreeCAD.Console.PrintLog("Loading PathPost… done\n")
|
||||
|
||||
@@ -116,6 +116,8 @@ class PostProcessorFactory:
|
||||
Path.Log.debug(f"Post processor {postname} is a script")
|
||||
return WrapperPost(job, module_path, module_name)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def needsTcOp(oldTc, newTc):
|
||||
return (
|
||||
@@ -133,11 +135,19 @@ class PostProcessor:
|
||||
self._tooltip = tooltip
|
||||
self._tooltipargs = tooltipargs
|
||||
self._units = units
|
||||
self._job = job
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
self.reinitialize()
|
||||
|
||||
if isinstance(job, dict):
|
||||
# process only selected operations
|
||||
self._job = job["job"]
|
||||
self._operations = job["operations"]
|
||||
else:
|
||||
# get all operations from 'Operations' group
|
||||
self._job = job
|
||||
self._operations = getattr(job.Operations, "Group", [])
|
||||
|
||||
@classmethod
|
||||
def exists(cls, processor):
|
||||
return processor in Path.Preferences.allAvailablePostProcessors()
|
||||
@@ -203,7 +213,7 @@ class PostProcessor:
|
||||
sublist = [__fixtureSetup(index, f, self._job)]
|
||||
|
||||
# Now generate the gcode
|
||||
for obj in self._job.Operations.Group:
|
||||
for obj in self._operations:
|
||||
tc = PathUtil.toolControllerForOp(obj)
|
||||
if tc is not None and PathUtil.activeForOp(obj):
|
||||
if needsTcOp(currTc, tc):
|
||||
@@ -240,7 +250,7 @@ class PostProcessor:
|
||||
postlist.append((toolstring, sublist))
|
||||
|
||||
Path.Log.track(self._job.PostProcessorOutputFile)
|
||||
for idx, obj in enumerate(self._job.Operations.Group):
|
||||
for idx, obj in enumerate(self._operations):
|
||||
Path.Log.track(obj.Label)
|
||||
|
||||
# check if the operation is active
|
||||
@@ -286,7 +296,7 @@ class PostProcessor:
|
||||
currTc = None
|
||||
|
||||
# Now generate the gcode
|
||||
for obj in self._job.Operations.Group:
|
||||
for obj in self._operations:
|
||||
|
||||
# check if the operation is active
|
||||
if not PathUtil.activeForOp(obj):
|
||||
|
||||
Reference in New Issue
Block a user