diff --git a/meshroom/ui/app.py b/meshroom/ui/app.py index 9ed6559e68..035942edbd 100644 --- a/meshroom/ui/app.py +++ b/meshroom/ui/app.py @@ -183,6 +183,14 @@ def createMeshroomParser(args): action='store_true', help=argparse.SUPPRESS # This hides the option from the help message ) + project_group.add_argument( + '-o', '--output', + metavar='OUTPUT_FOLDER', + type=str, + required=False, + nargs='*', + help='Set the output folder for the CopyFiles nodes.' + ) # Pipeline Options pipeline_group = parser.add_argument_group('Pipeline Options') @@ -320,7 +328,16 @@ def __init__(self, inputArgs): self._activeProject.load(project) self.addRecentProjectFile(project) elif getattr(args, "import", None) or args.importRecursive or args.save or args.pipeline: - self._activeProject.new() + if args.output: + # Initialize the template and keep the "CopyFiles" nodes + self._activeProject.newWithCopyOutputs() + # Use the provided output paths to initialize the "CopyFiles" nodes + copyNodes = self._activeProject.graph.nodesOfType("CopyFiles") + if len(copyNodes) > 0: + for index, node in enumerate(copyNodes): + node.output.value = args.output[index] if index < len(args.output) else args.output[0] + else: + self._activeProject.new() # import is a python keyword, so we have to access the attribute by a string if getattr(args, "import", None): diff --git a/meshroom/ui/graph.py b/meshroom/ui/graph.py index 178097d956..0edb35b4a6 100644 --- a/meshroom/ui/graph.py +++ b/meshroom/ui/graph.py @@ -468,7 +468,8 @@ def loadGraph(self, filepath): os.mkdir(g.cacheDir) self.setGraph(g) - @Slot(str, bool, result=bool) + @Slot(str) + @Slot(str, bool) def initFromTemplate(self, filepath, copyOutputs=False): graph = Graph("") if filepath: diff --git a/meshroom/ui/reconstruction.py b/meshroom/ui/reconstruction.py index 3448e1611c..08192bcd4c 100755 --- a/meshroom/ui/reconstruction.py +++ b/meshroom/ui/reconstruction.py @@ -457,11 +457,11 @@ def _onPluginsReloaded(self, nodeTypes: list): self._graph.reloadNodePlugins(nodeTypes) self.parent().showMessage("Plugins reloaded!", "ok") - @Slot() - @Slot(str) + @Slot(result=bool) + @Slot(str, result=bool) def new(self, pipeline=None): """ Create a new pipeline. """ - p = pipeline if pipeline != None else self._defaultPipeline + p = pipeline if pipeline is not None else self._defaultPipeline # Lower the input and the dictionary keys to make sure that all input types can be found: # - correct pipeline name but the case does not match (e.g. panoramaHDR instead of panoramaHdr) # - lowercase pipeline name given through the "New Pipeline" menu @@ -469,6 +469,19 @@ def new(self, pipeline=None): filepath = loweredPipelineTemplates.get(p.lower(), p) return self._loadWithErrorReport(self.initFromTemplate, filepath) + def _initFromTemplateWithCopyOutputs(self, filepath): + self.initFromTemplate(filepath, copyOutputs=True) + + @Slot(result=bool) + @Slot(str, result=bool) + def newWithCopyOutputs(self, pipeline=None): + """ Create a new pipeline with all the "CopyFiles" nodes included if the provided template has any. """ + p = pipeline if pipeline is not None else self._defaultPipeline + loweredPipelineTemplates = {k.lower(): v for k, v in meshroom.core.pipelineTemplates.items()} + filepath = loweredPipelineTemplates.get(p.lower(), p) + return self._loadWithErrorReport(self._initFromTemplateWithCopyOutputs, filepath) + + @Slot(str, result=bool) @Slot(QUrl, result=bool) def load(self, url):