From 52470b2cfc7241b438bb90c4b603c9cc07f595df Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 21 Aug 2020 11:27:57 +0200 Subject: [PATCH] feat(fusion): renaming `saver` family to `render` also changing render targeting names --- pype/hosts/fusion/scripts/set_rendermode.py | 10 +- ...eate_tiff_saver.py => create_exr_saver.py} | 10 +- pype/plugins/fusion/load/load_sequence.py | 8 +- .../fusion/publish/collect_instances.py | 11 ++- .../fusion/publish/collect_render_target.py | 12 +-- .../increment_current_file_deadline.py | 4 +- .../fusion/publish/publish_image_sequences.py | 98 ------------------- pype/plugins/fusion/publish/render_local.py | 36 +++++-- pype/plugins/fusion/publish/save_scene.py | 2 +- .../plugins/fusion/publish/submit_deadline.py | 3 +- .../publish/validate_background_depth.py | 2 +- .../fusion/publish/validate_comp_saved.py | 2 +- .../publish/validate_create_folder_checked.py | 2 +- .../validate_filename_has_extension.py | 2 +- .../publish/validate_saver_has_input.py | 2 +- .../publish/validate_saver_passthrough.py | 2 +- .../fusion/publish/validate_unique_subsets.py | 4 +- .../global/publish/collect_avalon_entities.py | 2 + pype/plugins/global/publish/extract_burnin.py | 3 +- pype/plugins/global/publish/extract_review.py | 9 +- pype/scripts/otio_burnin.py | 2 +- 21 files changed, 79 insertions(+), 147 deletions(-) rename pype/plugins/fusion/create/{create_tiff_saver.py => create_exr_saver.py} (88%) delete mode 100644 pype/plugins/fusion/publish/publish_image_sequences.py diff --git a/pype/hosts/fusion/scripts/set_rendermode.py b/pype/hosts/fusion/scripts/set_rendermode.py index 380b1b3b1c..051f05067d 100644 --- a/pype/hosts/fusion/scripts/set_rendermode.py +++ b/pype/hosts/fusion/scripts/set_rendermode.py @@ -3,10 +3,10 @@ from avalon.vendor import qtawesome import avalon.fusion as avalon -_help = {"renderlocal": "Render the comp on your own machine and publish " - "it from that the destination folder", - "deadline": "Submit a Fusion render job to Deadline to use all other " - "computers and add a publish job"} +_help = {"local": "Render the comp on your own machine and publish " + "it from that the destination folder", + "farm": "Submit a Fusion render job to a Render farm to use all other" + " computers and add a publish job"} class SetRenderMode(QtWidgets.QWidget): @@ -96,7 +96,7 @@ class SetRenderMode(QtWidgets.QWidget): return self._comp.GetAttrs("COMPS_Name") def _get_comp_rendermode(self): - return self._comp.GetData("pype.rendermode") or "renderlocal" + return self._comp.GetData("pype.rendermode") or "local" def _set_comp_rendermode(self): rendermode = self.mode_options.currentText() diff --git a/pype/plugins/fusion/create/create_tiff_saver.py b/pype/plugins/fusion/create/create_exr_saver.py similarity index 88% rename from pype/plugins/fusion/create/create_tiff_saver.py rename to pype/plugins/fusion/create/create_exr_saver.py index 92f97366a3..d5092d1d03 100644 --- a/pype/plugins/fusion/create/create_tiff_saver.py +++ b/pype/plugins/fusion/create/create_exr_saver.py @@ -4,16 +4,16 @@ import avalon.api from avalon import fusion -class CreateTiffSaver(avalon.api.Creator): +class CreateOpenEXRSaver(avalon.api.Creator): - name = "tiffDefault" - label = "Create Tiff Saver" + name = "openexrDefault" + label = "Create OpenEXR Saver" hosts = ["fusion"] - family = "saver" + family = "render" def process(self): - file_format = "TiffFormat" + file_format = "OpenEXRFormat" comp = fusion.get_current_comp() diff --git a/pype/plugins/fusion/load/load_sequence.py b/pype/plugins/fusion/load/load_sequence.py index ce6bca6c77..24d48fb9da 100644 --- a/pype/plugins/fusion/load/load_sequence.py +++ b/pype/plugins/fusion/load/load_sequence.py @@ -4,6 +4,10 @@ import contextlib from avalon import api import avalon.io as io +from avalon import fusion + +comp = fusion.get_current_comp() + @contextlib.contextmanager def preserve_inputs(tool, inputs): @@ -113,7 +117,7 @@ def loader_shift(loader, frame, relative=True): class FusionLoadSequence(api.Loader): """Load image sequence into Fusion""" - families = ["imagesequence"] + families = ["imagesequence", "review"] representations = ["*"] label = "Load sequence" @@ -134,7 +138,7 @@ class FusionLoadSequence(api.Loader): namespace = context['asset']['name'] # Use the first file for now - path = self._get_first_image(self.fname) + path = self._get_first_image(os.path.dirname(self.fname)) # Create the Loader with the filename path set comp = get_current_comp() diff --git a/pype/plugins/fusion/publish/collect_instances.py b/pype/plugins/fusion/publish/collect_instances.py index 6dbb1b1a97..3c7224e65c 100644 --- a/pype/plugins/fusion/publish/collect_instances.py +++ b/pype/plugins/fusion/publish/collect_instances.py @@ -43,8 +43,8 @@ class CollectInstances(pyblish.api.ContextPlugin): savers = [tool for tool in tools if tool.ID == "Saver"] start, end = get_comp_render_range(comp) - context.data["frameStart"] = start - context.data["frameEnd"] = end + context.data["frameStart"] = int(start) + context.data["frameEnd"] = int(end) for tool in savers: path = tool["Clip"][comp.TIME_UNDEFINED] @@ -76,8 +76,11 @@ class CollectInstances(pyblish.api.ContextPlugin): "outputDir": os.path.dirname(path), "ext": ext, # todo: should be redundant "label": label, - "families": ["saver"], - "family": "saver", + "frameStart": context.data["frameStart"], + "frameEnd": context.data["frameEnd"], + "fps": context.data["fps"], + "families": ["render", "review", "ftrack"], + "family": "render", "active": active, "publish": active # backwards compatibility }) diff --git a/pype/plugins/fusion/publish/collect_render_target.py b/pype/plugins/fusion/publish/collect_render_target.py index b6217f1ddf..50cc4fd3e9 100644 --- a/pype/plugins/fusion/publish/collect_render_target.py +++ b/pype/plugins/fusion/publish/collect_render_target.py @@ -5,8 +5,8 @@ class CollectFusionRenderMode(pyblish.api.InstancePlugin): """Collect current comp's render Mode Options: - renderlocal - deadline + local + farm Note that this value is set for each comp separately. When you save the comp this information will be stored in that file. If for some reason the @@ -23,22 +23,22 @@ class CollectFusionRenderMode(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.4 label = "Collect Render Mode" hosts = ["fusion"] - families = ["saver"] + families = ["render"] def process(self, instance): """Collect all image sequence tools""" - options = ["renderlocal", "deadline"] + options = ["local", "farm"] comp = instance.context.data.get("currentComp") if not comp: raise RuntimeError("No comp previously collected, unable to " "retrieve Fusion version.") - rendermode = comp.GetData("pype.rendermode") or "renderlocal" + rendermode = comp.GetData("pype.rendermode") or "local" assert rendermode in options, "Must be supported render mode" self.log.info("Render mode: {0}".format(rendermode)) # Append family - family = "saver.{0}".format(rendermode) + family = "render.{0}".format(rendermode) instance.data["families"].append(family) diff --git a/pype/plugins/fusion/publish/increment_current_file_deadline.py b/pype/plugins/fusion/publish/increment_current_file_deadline.py index 6545d84da3..9641ba7ef6 100644 --- a/pype/plugins/fusion/publish/increment_current_file_deadline.py +++ b/pype/plugins/fusion/publish/increment_current_file_deadline.py @@ -11,7 +11,7 @@ class FusionIncrementCurrentFile(pyblish.api.ContextPlugin): label = "Increment current file" order = pyblish.api.IntegratorOrder + 9.0 hosts = ["fusion"] - families = ["saver.deadline"] + families = ["render.farm"] optional = True def process(self, context): @@ -23,7 +23,7 @@ class FusionIncrementCurrentFile(pyblish.api.ContextPlugin): if any(plugin.__name__ == "FusionSubmitDeadline" for plugin in errored_plugins): raise RuntimeError("Skipping incrementing current file because " - "submission to deadline failed.") + "submission to render farm failed.") comp = context.data.get("currentComp") assert comp, "Must have comp" diff --git a/pype/plugins/fusion/publish/publish_image_sequences.py b/pype/plugins/fusion/publish/publish_image_sequences.py deleted file mode 100644 index 9fe9ddc4cb..0000000000 --- a/pype/plugins/fusion/publish/publish_image_sequences.py +++ /dev/null @@ -1,98 +0,0 @@ -import re -import os -import json -import subprocess - -import pyblish.api - -from pype.action import get_errored_plugins_from_data - - -def _get_script(): - """Get path to the image sequence script""" - - # todo: use a more elegant way to get the python script - - try: - from pype.scripts import publish_filesequence - except Exception: - raise RuntimeError("Expected module 'publish_imagesequence'" - "to be available") - - module_path = publish_filesequence.__file__ - if module_path.endswith(".pyc"): - module_path = module_path[:-len(".pyc")] + ".py" - - return module_path - - -class PublishImageSequence(pyblish.api.InstancePlugin): - """Publish the generated local image sequences.""" - - order = pyblish.api.IntegratorOrder - label = "Publish Rendered Image Sequence(s)" - hosts = ["fusion"] - families = ["saver.renderlocal"] - - def process(self, instance): - - # Skip this plug-in if the ExtractImageSequence failed - errored_plugins = get_errored_plugins_from_data(instance.context) - if any(plugin.__name__ == "FusionRenderLocal" for plugin in - errored_plugins): - raise RuntimeError("Fusion local render failed, " - "publishing images skipped.") - - subset = instance.data["subset"] - ext = instance.data["ext"] - - # Regex to match resulting renders - regex = "^{subset}.*[0-9]+{ext}+$".format(subset=re.escape(subset), - ext=re.escape(ext)) - - # The instance has most of the information already stored - metadata = { - "regex": regex, - "frameStart": instance.context.data["frameStart"], - "frameEnd": instance.context.data["frameEnd"], - "families": ["imagesequence"], - } - - # Write metadata and store the path in the instance - output_directory = instance.data["outputDir"] - path = os.path.join(output_directory, - "{}_metadata.json".format(subset)) - with open(path, "w") as f: - json.dump(metadata, f) - - assert os.path.isfile(path), ("Stored path is not a file for %s" - % instance.data["name"]) - - # Suppress any subprocess console - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = subprocess.SW_HIDE - - process = subprocess.Popen(["python", _get_script(), - "--paths", path], - bufsize=1, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - startupinfo=startupinfo) - - while True: - output = process.stdout.readline() - # Break when there is no output or a return code has been given - if output == '' and process.poll() is not None: - process.stdout.close() - break - if output: - line = output.strip() - if line.startswith("ERROR"): - self.log.error(line) - else: - self.log.info(line) - - if process.returncode != 0: - raise RuntimeError("Process quit with non-zero " - "return code: {}".format(process.returncode)) diff --git a/pype/plugins/fusion/publish/render_local.py b/pype/plugins/fusion/publish/render_local.py index c97fe1a13d..c5d1fd9b7a 100644 --- a/pype/plugins/fusion/publish/render_local.py +++ b/pype/plugins/fusion/publish/render_local.py @@ -1,9 +1,11 @@ +import os import pyblish.api import avalon.fusion as fusion +from pprint import pformat -class FusionRenderLocal(pyblish.api.InstancePlugin): +class Fusionlocal(pyblish.api.InstancePlugin): """Render the current Fusion composition locally. Extract the result of savers by starting a comp render @@ -14,12 +16,10 @@ class FusionRenderLocal(pyblish.api.InstancePlugin): order = pyblish.api.ExtractorOrder label = "Render Local" hosts = ["fusion"] - families = ["saver.renderlocal"] + families = ["render.local"] def process(self, instance): - # This should be a ContextPlugin, but this is a workaround - # for a bug in pyblish to run once for a family: issue #250 context = instance.context key = "__hasRun{}".format(self.__class__.__name__) if context.data.get(key, False): @@ -28,15 +28,35 @@ class FusionRenderLocal(pyblish.api.InstancePlugin): context.data[key] = True current_comp = context.data["currentComp"] - start_frame = current_comp.GetAttrs("COMPN_RenderStart") - end_frame = current_comp.GetAttrs("COMPN_RenderEnd") + frame_start = current_comp.GetAttrs("COMPN_RenderStart") + frame_end = current_comp.GetAttrs("COMPN_RenderEnd") + path = instance.data["path"] + output_dir = instance.data["outputDir"] + + ext = os.path.splitext(os.path.basename(path))[-1] self.log.info("Starting render") - self.log.info("Start frame: {}".format(start_frame)) - self.log.info("End frame: {}".format(end_frame)) + self.log.info("Start frame: {}".format(frame_start)) + self.log.info("End frame: {}".format(frame_end)) with fusion.comp_lock_and_undo_chunk(current_comp): result = current_comp.Render() + if "representations" not in instance.data: + instance.data["representations"] = [] + + collected_frames = os.listdir(output_dir) + repre = { + 'name': ext[1:], + 'ext': ext[1:], + 'frameStart': "%0{}d".format(len(str(frame_end))) % frame_start, + 'files': collected_frames, + "stagingDir": output_dir, + "tags": ["review", "ftrackreview"] + } + instance.data["representations"].append(repre) + + self.log.debug(f"_ instance.data: {pformat(instance.data)}") + if not result: raise RuntimeError("Comp render failed") diff --git a/pype/plugins/fusion/publish/save_scene.py b/pype/plugins/fusion/publish/save_scene.py index 850ac5c372..0cdfafa095 100644 --- a/pype/plugins/fusion/publish/save_scene.py +++ b/pype/plugins/fusion/publish/save_scene.py @@ -7,7 +7,7 @@ class FusionSaveComp(pyblish.api.ContextPlugin): label = "Save current file" order = pyblish.api.ExtractorOrder - 0.49 hosts = ["fusion"] - families = ["saver"] + families = ["render"] def process(self, context): diff --git a/pype/plugins/fusion/publish/submit_deadline.py b/pype/plugins/fusion/publish/submit_deadline.py index 0dd34ba713..ed3fb06586 100644 --- a/pype/plugins/fusion/publish/submit_deadline.py +++ b/pype/plugins/fusion/publish/submit_deadline.py @@ -19,10 +19,9 @@ class FusionSubmitDeadline(pyblish.api.InstancePlugin): label = "Submit to Deadline" order = pyblish.api.IntegratorOrder hosts = ["fusion"] - families = ["saver.deadline"] + families = ["render.farm"] def process(self, instance): - instance.data["toBeRenderedOn"] = "deadline" context = instance.context key = "__hasRun{}".format(self.__class__.__name__) diff --git a/pype/plugins/fusion/publish/validate_background_depth.py b/pype/plugins/fusion/publish/validate_background_depth.py index 88a52ad52d..de042ae315 100644 --- a/pype/plugins/fusion/publish/validate_background_depth.py +++ b/pype/plugins/fusion/publish/validate_background_depth.py @@ -10,7 +10,7 @@ class ValidateBackgroundDepth(pyblish.api.InstancePlugin): label = "Validate Background Depth 32 bit" actions = [action.RepairAction] hosts = ["fusion"] - families = ["saver"] + families = ["render"] optional = True @classmethod diff --git a/pype/plugins/fusion/publish/validate_comp_saved.py b/pype/plugins/fusion/publish/validate_comp_saved.py index 425168fbdf..cabe65af6e 100644 --- a/pype/plugins/fusion/publish/validate_comp_saved.py +++ b/pype/plugins/fusion/publish/validate_comp_saved.py @@ -8,7 +8,7 @@ class ValidateFusionCompSaved(pyblish.api.ContextPlugin): order = pyblish.api.ValidatorOrder label = "Validate Comp Saved" - families = ["saver"] + families = ["render"] hosts = ["fusion"] def process(self, context): diff --git a/pype/plugins/fusion/publish/validate_create_folder_checked.py b/pype/plugins/fusion/publish/validate_create_folder_checked.py index 00a8526c6b..cce3695c31 100644 --- a/pype/plugins/fusion/publish/validate_create_folder_checked.py +++ b/pype/plugins/fusion/publish/validate_create_folder_checked.py @@ -13,7 +13,7 @@ class ValidateCreateFolderChecked(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder actions = [action.RepairAction] label = "Validate Create Folder Checked" - families = ["saver"] + families = ["render"] hosts = ["fusion"] @classmethod diff --git a/pype/plugins/fusion/publish/validate_filename_has_extension.py b/pype/plugins/fusion/publish/validate_filename_has_extension.py index d3762ad290..4795a2aa05 100644 --- a/pype/plugins/fusion/publish/validate_filename_has_extension.py +++ b/pype/plugins/fusion/publish/validate_filename_has_extension.py @@ -14,7 +14,7 @@ class ValidateFilenameHasExtension(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder label = "Validate Filename Has Extension" - families = ["saver"] + families = ["render"] hosts = ["fusion"] def process(self, instance): diff --git a/pype/plugins/fusion/publish/validate_saver_has_input.py b/pype/plugins/fusion/publish/validate_saver_has_input.py index 6887a9704c..7243b44a3e 100644 --- a/pype/plugins/fusion/publish/validate_saver_has_input.py +++ b/pype/plugins/fusion/publish/validate_saver_has_input.py @@ -10,7 +10,7 @@ class ValidateSaverHasInput(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder label = "Validate Saver Has Input" - families = ["saver"] + families = ["render"] hosts = ["fusion"] @classmethod diff --git a/pype/plugins/fusion/publish/validate_saver_passthrough.py b/pype/plugins/fusion/publish/validate_saver_passthrough.py index 2da5cf2494..aed3835de3 100644 --- a/pype/plugins/fusion/publish/validate_saver_passthrough.py +++ b/pype/plugins/fusion/publish/validate_saver_passthrough.py @@ -6,7 +6,7 @@ class ValidateSaverPassthrough(pyblish.api.ContextPlugin): order = pyblish.api.ValidatorOrder label = "Validate Saver Passthrough" - families = ["saver"] + families = ["render"] hosts = ["fusion"] def process(self, context): diff --git a/pype/plugins/fusion/publish/validate_unique_subsets.py b/pype/plugins/fusion/publish/validate_unique_subsets.py index 2000e1c05d..b218a311ba 100644 --- a/pype/plugins/fusion/publish/validate_unique_subsets.py +++ b/pype/plugins/fusion/publish/validate_unique_subsets.py @@ -6,7 +6,7 @@ class ValidateUniqueSubsets(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder label = "Validate Unique Subsets" - families = ["saver"] + families = ["render"] hosts = ["fusion"] @classmethod @@ -14,7 +14,7 @@ class ValidateUniqueSubsets(pyblish.api.InstancePlugin): context = instance.context subset = instance.data["subset"] - for other_instance in context[:]: + for other_instance in context: if other_instance == instance: continue diff --git a/pype/plugins/global/publish/collect_avalon_entities.py b/pype/plugins/global/publish/collect_avalon_entities.py index 917172d40c..0b6423818e 100644 --- a/pype/plugins/global/publish/collect_avalon_entities.py +++ b/pype/plugins/global/publish/collect_avalon_entities.py @@ -86,3 +86,5 @@ class CollectAvalonEntities(pyblish.api.ContextPlugin): frame_end_h = frame_end + context.data["handleEnd"] context.data["frameStartHandle"] = frame_start_h context.data["frameEndHandle"] = frame_end_h + + context.data["fps"] = data["fps"] diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index dedfd98979..fd73fd4a04 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -25,7 +25,8 @@ class ExtractBurnin(pype.api.Extractor): "shell", "nukestudio", "premiere", - "standalonepublisher" + "standalonepublisher", + "fusion" ] optional = True diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 3a5bd3464a..0ea82cbbef 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -29,7 +29,8 @@ class ExtractReview(pyblish.api.InstancePlugin): "nukestudio", "premiere", "harmony", - "standalonepublisher" + "standalonepublisher", + "fusion" ] # Supported extensions @@ -50,9 +51,9 @@ class ExtractReview(pyblish.api.InstancePlugin): to_height = 1080 def process(self, instance): - # Skip review when requested. - if not instance.data.get("review"): - return + # # Skip review when requested. + # if not instance.data.get("review"): + # return # ffmpeg doesn't support multipart exrs if instance.data.get("multipartExr") is True: diff --git a/pype/scripts/otio_burnin.py b/pype/scripts/otio_burnin.py index 718943855c..156896a759 100644 --- a/pype/scripts/otio_burnin.py +++ b/pype/scripts/otio_burnin.py @@ -526,7 +526,7 @@ def burnins_from_data( bit_rate = burnin._streams[0].get("bit_rate") if bit_rate: - ffmpeg_args.append("--b:v {}".format(bit_rate)) + ffmpeg_args.append("-b:v {}".format(bit_rate)) pix_fmt = burnin._streams[0].get("pix_fmt") if pix_fmt: