From 6ae5e2d8a54c76240169d1cb3d5513738448a48d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 15:13:57 +0100 Subject: [PATCH 01/42] fix(nuke): separate write render and prerender create plugins --- ...ate_write.py => create_write_prerender.py} | 107 ++---------------- .../nuke/create/create_write_render.py | 101 +++++++++++++++++ 2 files changed, 108 insertions(+), 100 deletions(-) rename pype/plugins/nuke/create/{create_write.py => create_write_prerender.py} (54%) create mode 100644 pype/plugins/nuke/create/create_write_render.py diff --git a/pype/plugins/nuke/create/create_write.py b/pype/plugins/nuke/create/create_write_prerender.py similarity index 54% rename from pype/plugins/nuke/create/create_write.py rename to pype/plugins/nuke/create/create_write_prerender.py index 74e450f267..f8210db9db 100644 --- a/pype/plugins/nuke/create/create_write.py +++ b/pype/plugins/nuke/create/create_write_prerender.py @@ -1,103 +1,11 @@ from collections import OrderedDict -from pype.nuke import plugin +from pype.nuke import ( + plugin, + lib as pnlib + ) import nuke -class CreateWriteRender(plugin.PypeCreator): - # change this to template preset - name = "WriteRender" - label = "Create Write Render" - hosts = ["nuke"] - n_class = "write" - family = "render" - icon = "sign-out" - defaults = ["Main", "Mask"] - - def __init__(self, *args, **kwargs): - super(CreateWriteRender, self).__init__(*args, **kwargs) - - data = OrderedDict() - - data["family"] = self.family - data["families"] = self.n_class - - for k, v in self.data.items(): - if k not in data.keys(): - data.update({k: v}) - - self.data = data - self.nodes = nuke.selectedNodes() - self.log.debug("_ self.data: '{}'".format(self.data)) - - def process(self): - from pype.nuke import lib as pnlib - - inputs = [] - outputs = [] - instance = nuke.toNode(self.data["subset"]) - selected_node = None - - # use selection - if (self.options or {}).get("useSelection"): - nodes = self.nodes - - if not (len(nodes) < 2): - msg = ("Select only one node. The node you want to connect to, " - "or tick off `Use selection`") - log.error(msg) - nuke.message(msg) - - selected_node = nodes[0] - inputs = [selected_node] - outputs = selected_node.dependent() - - if instance: - if (instance.name() in selected_node.name()): - selected_node = instance.dependencies()[0] - - # if node already exist - if instance: - # collect input / outputs - inputs = instance.dependencies() - outputs = instance.dependent() - selected_node = inputs[0] - # remove old one - nuke.delete(instance) - - # recreate new - write_data = { - "class": self.n_class, - "families": [self.family], - "avalon": self.data - } - - if self.presets.get('fpath_template'): - self.log.info("Adding template path from preset") - write_data.update( - {"fpath_template": self.presets["fpath_template"]} - ) - else: - self.log.info("Adding template path from plugin") - write_data.update({ - "fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"}) - - write_node = pnlib.create_write_node( - self.data["subset"], - write_data, - input=selected_node) - - # relinking to collected connections - for i, input in enumerate(inputs): - write_node.setInput(i, input) - - write_node.autoplace() - - for output in outputs: - output.setInput(0, write_node) - - return write_node - - class CreateWritePrerender(plugin.PypeCreator): # change this to template preset name = "WritePrerender" @@ -125,8 +33,6 @@ class CreateWritePrerender(plugin.PypeCreator): self.log.debug("_ self.data: '{}'".format(self.data)) def process(self): - from pype.nuke import lib as pnlib - inputs = [] outputs = [] instance = nuke.toNode(self.data["subset"]) @@ -137,8 +43,9 @@ class CreateWritePrerender(plugin.PypeCreator): nodes = self.nodes if not (len(nodes) < 2): - msg = ("Select only one node. The node you want to connect to, " - "or tick off `Use selection`") + msg = ("Select only one node. The node " + "you want to connect to, " + "or tick off `Use selection`") self.log.error(msg) nuke.message(msg) diff --git a/pype/plugins/nuke/create/create_write_render.py b/pype/plugins/nuke/create/create_write_render.py new file mode 100644 index 0000000000..c3b60ba2b0 --- /dev/null +++ b/pype/plugins/nuke/create/create_write_render.py @@ -0,0 +1,101 @@ +from collections import OrderedDict +from pype.nuke import ( + plugin, + lib as pnlib + ) +import nuke + + +class CreateWriteRender(plugin.PypeCreator): + # change this to template preset + name = "WriteRender" + label = "Create Write Render" + hosts = ["nuke"] + n_class = "write" + family = "render" + icon = "sign-out" + defaults = ["Main", "Mask"] + + def __init__(self, *args, **kwargs): + super(CreateWriteRender, self).__init__(*args, **kwargs) + + data = OrderedDict() + + data["family"] = self.family + data["families"] = self.n_class + + for k, v in self.data.items(): + if k not in data.keys(): + data.update({k: v}) + + self.data = data + self.nodes = nuke.selectedNodes() + self.log.debug("_ self.data: '{}'".format(self.data)) + + def process(self): + + inputs = [] + outputs = [] + instance = nuke.toNode(self.data["subset"]) + selected_node = None + + # use selection + if (self.options or {}).get("useSelection"): + nodes = self.nodes + + if not (len(nodes) < 2): + msg = ("Select only one node. " + "The node you want to connect to, " + "or tick off `Use selection`") + self.log.error(msg) + nuke.message(msg) + + selected_node = nodes[0] + inputs = [selected_node] + outputs = selected_node.dependent() + + if instance: + if (instance.name() in selected_node.name()): + selected_node = instance.dependencies()[0] + + # if node already exist + if instance: + # collect input / outputs + inputs = instance.dependencies() + outputs = instance.dependent() + selected_node = inputs[0] + # remove old one + nuke.delete(instance) + + # recreate new + write_data = { + "class": self.n_class, + "families": [self.family], + "avalon": self.data + } + + if self.presets.get('fpath_template'): + self.log.info("Adding template path from preset") + write_data.update( + {"fpath_template": self.presets["fpath_template"]} + ) + else: + self.log.info("Adding template path from plugin") + write_data.update({ + "fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"}) + + write_node = pnlib.create_write_node( + self.data["subset"], + write_data, + input=selected_node) + + # relinking to collected connections + for i, input in enumerate(inputs): + write_node.setInput(i, input) + + write_node.autoplace() + + for output in outputs: + output.setInput(0, write_node) + + return write_node From 5dfbe54df1b33b6391dc1b7bf718495982da234d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:01:09 +0100 Subject: [PATCH 02/42] clean(nuke): old code --- pype/plugins/nuke/publish/collect_instances.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index cbbef70e4a..57b4208ce4 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -89,8 +89,6 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): instance.append(i) node.end() - family = avalon_knob_data["family"] - families = list() families_ak = avalon_knob_data.get("families") if families_ak: From a4938110c2c7025f74fe4686a1c4de51706359e1 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:01:47 +0100 Subject: [PATCH 03/42] feat(nuke): accepting `prerender` family on instance --- pype/plugins/nuke/publish/collect_instances.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 57b4208ce4..893c6db7e5 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -80,6 +80,8 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): add_family = "render.farm" instance.data["transfer"] = False families.append(add_family) + if "prerender" in family: + families.append("prerender") else: # add family into families families.insert(0, family) From 7bbc0e5677169091c34611cf9b657ce871de402e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:02:24 +0100 Subject: [PATCH 04/42] clean(nuke): write family is more direct and lest anatomical --- pype/plugins/nuke/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py index c95c94541d..f02f22e053 100644 --- a/pype/plugins/nuke/publish/collect_review.py +++ b/pype/plugins/nuke/publish/collect_review.py @@ -9,7 +9,7 @@ class CollectReview(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.3 label = "Collect Review" hosts = ["nuke"] - families = ["render", "render.local", "render.farm"] + families = ["write", "prerender"] def process(self, instance): From d9a2c7dad5dac122fe1194dc3bf0e02cd9ebac0c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:02:46 +0100 Subject: [PATCH 05/42] clean(nuke): not used import --- pype/plugins/nuke/publish/collect_writes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index 0dc7c81fae..a6fbdbab8b 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -1,7 +1,6 @@ import os import nuke import pyblish.api -import pype.api as pype @pyblish.api.log From 3d32068c10b8e51f1e05d90fdb75485cde312ed2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:06:13 +0100 Subject: [PATCH 06/42] feat(nuke): accepting prerender in img collection --- pype/plugins/nuke/publish/collect_writes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index a6fbdbab8b..b1213199f5 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -67,6 +67,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): ) if 'render' in instance.data['families']: + if [fm for fm in instance.data['families'] + if fm in ["render", "prerender"]]: if "representations" not in instance.data: instance.data["representations"] = list() From e2f51960452f29bb8e717324415c45aa638ba5bf Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:06:41 +0100 Subject: [PATCH 07/42] clean(nuke): removing wrong family definition --- pype/plugins/nuke/publish/validate_write_bounding_box.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/validate_write_bounding_box.py b/pype/plugins/nuke/publish/validate_write_bounding_box.py index e4b7c77a25..cedeea6d9f 100644 --- a/pype/plugins/nuke/publish/validate_write_bounding_box.py +++ b/pype/plugins/nuke/publish/validate_write_bounding_box.py @@ -57,7 +57,7 @@ class ValidateNukeWriteBoundingBox(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder optional = True - families = ["render", "render.local", "render.farm"] + families = ["write"] label = "Write Bounding Box" hosts = ["nuke"] actions = [RepairNukeBoundingBoxAction] From 8c8a4e11ab9a17c2319569d64673f20cc15c9773 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:09:05 +0100 Subject: [PATCH 08/42] feat(nuke): prerender family clarifying --- pype/plugins/nuke/publish/collect_writes.py | 22 ++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index b1213199f5..aa5f825a98 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -66,7 +66,6 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): int(last_frame) ) - if 'render' in instance.data['families']: if [fm for fm in instance.data['families'] if fm in ["render", "prerender"]]: if "representations" not in instance.data: @@ -96,7 +95,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): # this will only run if slate frame is not already # rendered from previews publishes if "slate" in instance.data["families"] \ - and (frame_length == collected_frames_len): + and (frame_length == collected_frames_len) \ + and ("prerender" not in instance.data["families"]): frame_slate_str = "%0{}d".format( len(str(last_frame))) % (first_frame - 1) slate_frame = collected_frames[0].replace( @@ -105,6 +105,8 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): representation['files'] = collected_frames instance.data["representations"].append(representation) + if "render" not in instance.data["families"]: + instance.data["families"].append("render") except Exception: instance.data["representations"].append(representation) self.log.debug("couldn't collect frames: {}".format(label)) @@ -144,5 +146,19 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "deadlineChunkSize": deadlineChunkSize, "deadlinePriority": deadlinePriority }) - + self.log.debug("families: {}".format(families)) + if "prerender" in families: + _families = list() + for fm in families: + if fm in _families: + continue + if "render" in fm: + if "prerender" in fm: + continue + _families.append(fm) + instance.data.update({ + "family": "prerender", + "families": _families + }) + self.log.debug("_families: {}".format(_families)) self.log.debug("instance.data: {}".format(instance.data)) From 9248e4b8cf95c467560259f02126ef0d531ab3ac Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 18 Mar 2020 19:15:04 +0100 Subject: [PATCH 09/42] clear(nuke): cleaning wrong families --- pype/plugins/nuke/publish/extract_review_data_mov.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/nuke/publish/extract_review_data_mov.py b/pype/plugins/nuke/publish/extract_review_data_mov.py index 8b204680a7..683da24fc8 100644 --- a/pype/plugins/nuke/publish/extract_review_data_mov.py +++ b/pype/plugins/nuke/publish/extract_review_data_mov.py @@ -15,7 +15,7 @@ class ExtractReviewDataMov(pype.api.Extractor): order = pyblish.api.ExtractorOrder + 0.01 label = "Extract Review Data Mov" - families = ["review", "render", "render.local"] + families = ["review"] hosts = ["nuke"] def process(self, instance): From 31f0ab63788037a11c1fecb7817bb621651159ad Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:35:23 +0100 Subject: [PATCH 10/42] feat(nuke): prerender node dont need `review` knob --- pype/nuke/lib.py | 38 +++++++++++++------ .../nuke/create/create_write_prerender.py | 4 +- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/pype/nuke/lib.py b/pype/nuke/lib.py index 8e241dad16..989cbf569f 100644 --- a/pype/nuke/lib.py +++ b/pype/nuke/lib.py @@ -215,14 +215,14 @@ def script_name(): def add_button_write_to_read(node): name = "createReadNode" - label = "Create Read" + label = "[ Create Read ]" value = "import write_to_read;write_to_read.write_to_read(nuke.thisNode())" k = nuke.PyScript_Knob(name, label, value) k.setFlag(0x1000) node.addKnob(k) -def create_write_node(name, data, input=None, prenodes=None): +def create_write_node(name, data, input=None, prenodes=None, review=True): ''' Creating write node which is group node Arguments: @@ -231,6 +231,7 @@ def create_write_node(name, data, input=None, prenodes=None): input (node): selected node to connect to prenodes (list, optional): list of lists, definitions for nodes to be created before write + review (bool): adding review knob Example: prenodes = [( @@ -380,15 +381,8 @@ def create_write_node(name, data, input=None, prenodes=None): add_rendering_knobs(GN) - # adding write to read button - add_button_write_to_read(GN) - - divider = nuke.Text_Knob('') - GN.addKnob(divider) - - # set tile color - tile_color = _data.get("tile_color", "0xff0000ff") - GN["tile_color"].setValue(tile_color) + if review: + add_review_knob(GN) # add render button lnk = nuke.Link_Knob("Render") @@ -396,9 +390,20 @@ def create_write_node(name, data, input=None, prenodes=None): lnk.setName("Render") GN.addKnob(lnk) + divider = nuke.Text_Knob('') + GN.addKnob(divider) + + # adding write to read button + add_button_write_to_read(GN) + # Deadline tab. add_deadline_tab(GN) + + # set tile color + tile_color = _data.get("tile_color", "0xff0000ff") + GN["tile_color"].setValue(tile_color) + return GN @@ -420,6 +425,17 @@ def add_rendering_knobs(node): knob = nuke.Boolean_Knob("render_farm", "Render on Farm") knob.setValue(False) node.addKnob(knob) + return node + +def add_review_knob(node): + ''' Adds additional review knob to given node + + Arguments: + node (obj): nuke node object to be fixed + + Return: + node (obj): with added knob + ''' if "review" not in node.knobs(): knob = nuke.Boolean_Knob("review", "Review") knob.setValue(True) diff --git a/pype/plugins/nuke/create/create_write_prerender.py b/pype/plugins/nuke/create/create_write_prerender.py index f8210db9db..6e242f886c 100644 --- a/pype/plugins/nuke/create/create_write_prerender.py +++ b/pype/plugins/nuke/create/create_write_prerender.py @@ -87,7 +87,9 @@ class CreateWritePrerender(plugin.PypeCreator): self.data["subset"], write_data, input=selected_node, - prenodes=[]) + prenodes=[], + review=False + ) # relinking to collected connections for i, input in enumerate(inputs): From 5c7bba0c0676a95a35b1de2e03c523989d7197b2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:36:13 +0100 Subject: [PATCH 11/42] feat(nuke): setting up properly families --- pype/plugins/nuke/publish/collect_review.py | 2 +- pype/plugins/nuke/publish/collect_slate_node.py | 2 +- pype/plugins/nuke/publish/extract_render_local.py | 2 +- pype/plugins/nuke/publish/submit_nuke_deadline.py | 2 +- pype/plugins/nuke/publish/validate_write_bounding_box.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_review.py b/pype/plugins/nuke/publish/collect_review.py index f02f22e053..c95c94541d 100644 --- a/pype/plugins/nuke/publish/collect_review.py +++ b/pype/plugins/nuke/publish/collect_review.py @@ -9,7 +9,7 @@ class CollectReview(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.3 label = "Collect Review" hosts = ["nuke"] - families = ["write", "prerender"] + families = ["render", "render.local", "render.farm"] def process(self, instance): diff --git a/pype/plugins/nuke/publish/collect_slate_node.py b/pype/plugins/nuke/publish/collect_slate_node.py index d8d6b50f05..9c7f1b5e95 100644 --- a/pype/plugins/nuke/publish/collect_slate_node.py +++ b/pype/plugins/nuke/publish/collect_slate_node.py @@ -8,7 +8,7 @@ class CollectSlate(pyblish.api.InstancePlugin): order = pyblish.api.CollectorOrder + 0.09 label = "Collect Slate Node" hosts = ["nuke"] - families = ["write"] + families = ["render", "render.local", "render.farm"] def process(self, instance): node = instance[0] diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index 5467d239c2..1dad413ee5 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -17,7 +17,7 @@ class NukeRenderLocal(pype.api.Extractor): order = pyblish.api.ExtractorOrder label = "Render Local" hosts = ["nuke"] - families = ["render.local"] + families = ["render.local", "prerender.local"] def process(self, instance): node = None diff --git a/pype/plugins/nuke/publish/submit_nuke_deadline.py b/pype/plugins/nuke/publish/submit_nuke_deadline.py index 0a9ef33398..3da2e58e4d 100644 --- a/pype/plugins/nuke/publish/submit_nuke_deadline.py +++ b/pype/plugins/nuke/publish/submit_nuke_deadline.py @@ -19,7 +19,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): label = "Submit to Deadline" order = pyblish.api.IntegratorOrder + 0.1 hosts = ["nuke", "nukestudio"] - families = ["render.farm"] + families = ["render.farm", "prerender.farm"] optional = True deadline_priority = 50 diff --git a/pype/plugins/nuke/publish/validate_write_bounding_box.py b/pype/plugins/nuke/publish/validate_write_bounding_box.py index cedeea6d9f..e4b7c77a25 100644 --- a/pype/plugins/nuke/publish/validate_write_bounding_box.py +++ b/pype/plugins/nuke/publish/validate_write_bounding_box.py @@ -57,7 +57,7 @@ class ValidateNukeWriteBoundingBox(pyblish.api.InstancePlugin): order = pyblish.api.ValidatorOrder optional = True - families = ["write"] + families = ["render", "render.local", "render.farm"] label = "Write Bounding Box" hosts = ["nuke"] actions = [RepairNukeBoundingBoxAction] From 63eac17649a7c42b4ba4f8d93c06f0dfad1af346 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:36:46 +0100 Subject: [PATCH 12/42] clean(nuke): old code and better definition of families --- pype/plugins/nuke/publish/collect_writes.py | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index aa5f825a98..f3f33b7a6d 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -105,8 +105,6 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): representation['files'] = collected_frames instance.data["representations"].append(representation) - if "render" not in instance.data["families"]: - instance.data["families"].append("render") except Exception: instance.data["representations"].append(representation) self.log.debug("couldn't collect frames: {}".format(label)) @@ -127,6 +125,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): deadlinePriority = group_node["deadlinePriority"].value() families = [f for f in instance.data["families"] if "write" not in f] + instance.data.update({ "versionData": version_data, "path": path, @@ -147,18 +146,5 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "deadlinePriority": deadlinePriority }) self.log.debug("families: {}".format(families)) - if "prerender" in families: - _families = list() - for fm in families: - if fm in _families: - continue - if "render" in fm: - if "prerender" in fm: - continue - _families.append(fm) - instance.data.update({ - "family": "prerender", - "families": _families - }) - self.log.debug("_families: {}".format(_families)) + self.log.debug("instance.data: {}".format(instance.data)) From 7fbb72b8a6eecdaf0d3799b59a248aa6cded0aa3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:37:10 +0100 Subject: [PATCH 13/42] clean(nuke): improving code --- .../plugins/nuke/publish/collect_instances.py | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_instances.py b/pype/plugins/nuke/publish/collect_instances.py index 893c6db7e5..54891d189c 100644 --- a/pype/plugins/nuke/publish/collect_instances.py +++ b/pype/plugins/nuke/publish/collect_instances.py @@ -52,6 +52,7 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): # establish families family = avalon_knob_data["family"] + families_ak = avalon_knob_data.get("families") families = list() # except disabled nodes but exclude backdrops in test @@ -68,20 +69,16 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): # Add all nodes in group instances. if node.Class() == "Group": # only alter families for render family - if ("render" in family): - # check if node is not disabled - families.append(avalon_knob_data["families"]) + if "write" in families_ak: if node["render"].value(): self.log.info("flagged for render") - add_family = "render.local" + add_family = "{}.local".format(family) # dealing with local/farm rendering if node["render_farm"].value(): self.log.info("adding render farm family") - add_family = "render.farm" + add_family = "{}.farm".format(family) instance.data["transfer"] = False families.append(add_family) - if "prerender" in family: - families.append("prerender") else: # add family into families families.insert(0, family) @@ -91,7 +88,7 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): instance.append(i) node.end() - families_ak = avalon_knob_data.get("families") + self.log.debug("__ families: `{}`".format(families)) if families_ak: families.append(families_ak) @@ -104,22 +101,6 @@ class CollectNukeInstances(pyblish.api.ContextPlugin): resolution_height = format.height() pixel_aspect = format.pixelAspect() - if node.Class() not in "Read": - if "render" not in node.knobs().keys(): - pass - elif node["render"].value(): - self.log.info("flagged for render") - add_family = "render.local" - # dealing with local/farm rendering - if node["render_farm"].value(): - self.log.info("adding render farm family") - add_family = "render.farm" - instance.data["transfer"] = False - families.append(add_family) - else: - # add family into families - families.insert(0, family) - instance.data.update({ "subset": subset, "asset": os.environ["AVALON_ASSET"], From b3702c49df14b2351cfc9c99e8987fb4e5685896 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:37:37 +0100 Subject: [PATCH 14/42] feat(global): explicit families for integrate new --- pype/plugins/global/publish/integrate_new.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index aa214f36cb..ddb40e321a 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -64,6 +64,9 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "scene", "vrayproxy", "render", + "render.local", + "prerender", + "prerender.local", "imagesequence", "review", "rendersetup", From 9a1167c26d784a43bb6643b4fcd6514d2aebe7b0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 20 Mar 2020 21:38:11 +0100 Subject: [PATCH 15/42] feat(nuke): dealing with `prerender` family when submitting to deadline --- pype/plugins/global/publish/submit_publish_job.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index dcf19ae32c..0b7a8473d4 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -141,7 +141,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): hosts = ["fusion", "maya", "nuke"] - families = ["render.farm", "renderlayer", "imagesequence"] + families = ["render.farm", "prerender.farm", "renderlayer", "imagesequence"] aov_filter = {"maya": ["beauty"]} @@ -583,6 +583,12 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "resolutionHeight": data.get("resolutionHeight", 1080), } + if "prerender.farm" in instance.data["families"]: + instance_skeleton_data.update({ + "family": "prerender", + "families": ["prerender"] + }) + # transfer specific families from original instance to new render for item in self.families_transfer: if item in instance.data.get("families", []): From 570d336f05ad5fb3b2fb8249e06bf1e3cee6ec1b Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 25 Mar 2020 15:29:50 +0100 Subject: [PATCH 16/42] fix invalid iterations in integrate master version --- pype/plugins/global/publish/integrate_master_version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/integrate_master_version.py b/pype/plugins/global/publish/integrate_master_version.py index 3c7838b708..af6e7707e4 100644 --- a/pype/plugins/global/publish/integrate_master_version.py +++ b/pype/plugins/global/publish/integrate_master_version.py @@ -111,13 +111,13 @@ class IntegrateMasterVersion(pyblish.api.InstancePlugin): all_copied_files = [] transfers = instance.data.get("transfers", list()) - for dst in transfers.values(): + for _src, dst in transfers: dst = os.path.normpath(dst) if dst not in all_copied_files: all_copied_files.append(dst) hardlinks = instance.data.get("hardlinks", list()) - for dst in hardlinks.values(): + for _src, dst in hardlinks: dst = os.path.normpath(dst) if dst not in all_copied_files: all_copied_files.append(dst) From c15437f04a0bf215871a2df205ba61e52227521e Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 25 Mar 2020 16:32:06 +0100 Subject: [PATCH 17/42] template_data stores frame used for anatomy filling --- pype/plugins/global/publish/integrate_new.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index ae946f0696..32504a64b3 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -326,6 +326,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): test_dest_files.append( os.path.normpath(template_filled) ) + # Store used frame value to template data + template_data["frame"] = repre_context["frame"] self.log.debug( "test_dest_files: {}".format(str(test_dest_files))) From ac47874d3c7a1f9c6a527236fd29a6344c48e3de Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 25 Mar 2020 16:32:34 +0100 Subject: [PATCH 18/42] template_name could not be overriden during representation loop --- pype/plugins/global/publish/integrate_new.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 32504a64b3..d4e4ae0b87 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -89,6 +89,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "project", "asset", "task", "subset", "version", "representation", "family", "hierarchy", "task", "username" ] + default_template_name = "publish" def process(self, instance): @@ -261,7 +262,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): # Each should be a single representation (as such, a single extension) representations = [] destination_list = [] - template_name = 'publish' + if 'transfers' not in instance.data: instance.data['transfers'] = [] @@ -288,8 +289,10 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): files = repre['files'] if repre.get('stagingDir'): stagingdir = repre['stagingDir'] - if repre.get('anatomy_template'): - template_name = repre['anatomy_template'] + + template_name = ( + repre.get('anatomy_template') or self.default_template_name + ) if repre.get("outputName"): template_data["output"] = repre['outputName'] From 0cb481706ca0d88e0e5fbb2aa7938b904440707d Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Wed, 25 Mar 2020 16:37:55 +0100 Subject: [PATCH 19/42] Now is used corrent frame --- pype/plugins/global/publish/integrate_new.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index d4e4ae0b87..768970ccdc 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -329,8 +329,6 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): test_dest_files.append( os.path.normpath(template_filled) ) - # Store used frame value to template data - template_data["frame"] = repre_context["frame"] self.log.debug( "test_dest_files: {}".format(str(test_dest_files))) @@ -387,6 +385,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): if not dst_start_frame: dst_start_frame = dst_padding + # Store used frame value to template data + template_data["frame"] = dst_start_frame dst = "{0}{1}{2}".format( dst_head, dst_start_frame, From 9577c236243d7caa42a4bdd1409e469d2f1cd0d2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 18:07:12 +0100 Subject: [PATCH 20/42] fix(global): slate was on even if render on farm --- pype/plugins/global/publish/extract_review_slate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pype/plugins/global/publish/extract_review_slate.py b/pype/plugins/global/publish/extract_review_slate.py index 8c33a0d853..da94c7714a 100644 --- a/pype/plugins/global/publish/extract_review_slate.py +++ b/pype/plugins/global/publish/extract_review_slate.py @@ -11,7 +11,9 @@ class ExtractReviewSlate(pype.api.Extractor): label = "Review with Slate frame" order = pyblish.api.ExtractorOrder + 0.031 - families = ["slate"] + families = ["slate", "review"] + match = pyblish.api.Subset + hosts = ["nuke", "maya", "shell"] optional = True From 570269f0247331460ad66baee0a76728bba0242b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 18:56:17 +0100 Subject: [PATCH 21/42] fix(global, nuke): setting families filter --- .../publish/integrate_ftrack_instances.py | 1 + pype/plugins/global/publish/integrate_new.py | 2 -- pype/plugins/nuke/load/load_mov.py | 1 + pype/plugins/nuke/load/load_sequence.py | 4 ++-- .../nuke/publish/increment_script_version.py | 21 +++++-------------- .../nuke/publish/validate_rendered_frames.py | 2 +- 6 files changed, 10 insertions(+), 21 deletions(-) diff --git a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py index db257e901a..59fb507788 100644 --- a/pype/plugins/ftrack/publish/integrate_ftrack_instances.py +++ b/pype/plugins/ftrack/publish/integrate_ftrack_instances.py @@ -22,6 +22,7 @@ class IntegrateFtrackInstance(pyblish.api.InstancePlugin): 'setdress': 'setdress', 'pointcache': 'cache', 'render': 'render', + 'render2d': 'render', 'nukescript': 'comp', 'write': 'render', 'review': 'mov', diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 127bff90f0..0ceac1f4a7 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -64,9 +64,7 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): "scene", "vrayproxy", "render", - "render.local", "prerender", - "prerender.local", "imagesequence", "review", "rendersetup", diff --git a/pype/plugins/nuke/load/load_mov.py b/pype/plugins/nuke/load/load_mov.py index 88e65156cb..5d15efcd3a 100644 --- a/pype/plugins/nuke/load/load_mov.py +++ b/pype/plugins/nuke/load/load_mov.py @@ -92,6 +92,7 @@ class LoadMov(api.Loader): "source", "plate", "render", + "prerender", "review"] + presets["families"] representations = [ diff --git a/pype/plugins/nuke/load/load_sequence.py b/pype/plugins/nuke/load/load_sequence.py index 690f074c3f..083cc86474 100644 --- a/pype/plugins/nuke/load/load_sequence.py +++ b/pype/plugins/nuke/load/load_sequence.py @@ -70,7 +70,7 @@ def loader_shift(node, frame, relative=True): class LoadSequence(api.Loader): """Load image sequence into Nuke""" - families = ["render2d", "source", "plate", "render"] + families = ["render2d", "source", "plate", "render", "prerender"] representations = ["exr", "dpx", "jpg", "jpeg", "png"] label = "Load sequence" @@ -87,7 +87,7 @@ class LoadSequence(api.Loader): version = context['version'] version_data = version.get("data", {}) repr_id = context["representation"]["_id"] - + self.log.info("version_data: {}\n".format(version_data)) self.log.debug( "Representation id `{}` ".format(repr_id)) diff --git a/pype/plugins/nuke/publish/increment_script_version.py b/pype/plugins/nuke/publish/increment_script_version.py index 6e3ce08276..c76083eb1e 100644 --- a/pype/plugins/nuke/publish/increment_script_version.py +++ b/pype/plugins/nuke/publish/increment_script_version.py @@ -9,6 +9,7 @@ class IncrementScriptVersion(pyblish.api.ContextPlugin): order = pyblish.api.IntegratorOrder + 0.9 label = "Increment Script Version" optional = True + families = ["workfile", "render", "render.local", "render.farm"] hosts = ['nuke'] def process(self, context): @@ -16,19 +17,7 @@ class IncrementScriptVersion(pyblish.api.ContextPlugin): assert all(result["success"] for result in context.data["results"]), ( "Publishing not succesfull so version is not increased.") - instances = context[:] - - prerender_check = list() - families_check = list() - for instance in instances: - if ("prerender" in str(instance)) and instance.data.get("families", None): - prerender_check.append(instance) - if instance.data.get("families", None): - families_check.append(True) - - - if len(prerender_check) != len(families_check): - from pype.lib import version_up - path = context.data["currentFile"] - nuke.scriptSaveAs(version_up(path)) - self.log.info('Incrementing script version') + from pype.lib import version_up + path = context.data["currentFile"] + nuke.scriptSaveAs(version_up(path)) + self.log.info('Incrementing script version') diff --git a/pype/plugins/nuke/publish/validate_rendered_frames.py b/pype/plugins/nuke/publish/validate_rendered_frames.py index 6e9b91dd72..425789f18a 100644 --- a/pype/plugins/nuke/publish/validate_rendered_frames.py +++ b/pype/plugins/nuke/publish/validate_rendered_frames.py @@ -28,7 +28,7 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): """ Validates file output. """ order = pyblish.api.ValidatorOrder + 0.1 - families = ["render"] + families = ["render", "prerender"] label = "Validate rendered frame" hosts = ["nuke", "nukestudio"] From f25dea58a808e80876acf5115c41a7fd2c2b3272 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 18:57:20 +0100 Subject: [PATCH 22/42] fix(nuke, global): shuffling families after plugins finish processing --- pype/plugins/nuke/publish/collect_writes.py | 24 ++++++++++++++----- .../nuke/publish/extract_render_local.py | 18 ++++++++++---- .../nuke/publish/submit_nuke_deadline.py | 10 ++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/pype/plugins/nuke/publish/collect_writes.py b/pype/plugins/nuke/publish/collect_writes.py index f3f33b7a6d..6379a1db87 100644 --- a/pype/plugins/nuke/publish/collect_writes.py +++ b/pype/plugins/nuke/publish/collect_writes.py @@ -12,9 +12,11 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): hosts = ["nuke", "nukeassist"] families = ["write"] + # preset attributes + sync_workfile_version = True + def process(self, instance): - # adding 2d focused rendering - instance.data["families"].append("render2d") + families = instance.data["families"] node = None for x in instance: @@ -52,10 +54,13 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): output_dir = os.path.dirname(path) self.log.debug('output dir: {}'.format(output_dir)) - # get version to instance for integration - instance.data['version'] = instance.context.data["version"] + if not next((f for f in families + if "prerender" in f), + None) and self.sync_workfile_version: + # get version to instance for integration + instance.data['version'] = instance.context.data["version"] - self.log.debug('Write Version: %s' % instance.data('version')) + self.log.debug('Write Version: %s' % instance.data('version')) # create label name = node.name() @@ -66,7 +71,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): int(last_frame) ) - if [fm for fm in instance.data['families'] + if [fm for fm in families if fm in ["render", "prerender"]]: if "representations" not in instance.data: instance.data["representations"] = list() @@ -145,6 +150,13 @@ class CollectNukeWrites(pyblish.api.InstancePlugin): "deadlineChunkSize": deadlineChunkSize, "deadlinePriority": deadlinePriority }) + + if "prerender" in families: + instance.data.update({ + "family": "prerender", + "families": [] + }) + self.log.debug("families: {}".format(families)) self.log.debug("instance.data: {}".format(instance.data)) diff --git a/pype/plugins/nuke/publish/extract_render_local.py b/pype/plugins/nuke/publish/extract_render_local.py index 1dad413ee5..b7aa59a457 100644 --- a/pype/plugins/nuke/publish/extract_render_local.py +++ b/pype/plugins/nuke/publish/extract_render_local.py @@ -20,6 +20,8 @@ class NukeRenderLocal(pype.api.Extractor): families = ["render.local", "prerender.local"] def process(self, instance): + families = instance.data["families"] + node = None for x in instance: if x.Class() == "Write": @@ -30,7 +32,7 @@ class NukeRenderLocal(pype.api.Extractor): first_frame = instance.data.get("frameStartHandle", None) # exception for slate workflow - if "slate" in instance.data["families"]: + if "slate" in families: first_frame -= 1 last_frame = instance.data.get("frameEndHandle", None) @@ -53,7 +55,7 @@ class NukeRenderLocal(pype.api.Extractor): ) # exception for slate workflow - if "slate" in instance.data["families"]: + if "slate" in families: first_frame += 1 path = node['file'].value() @@ -79,8 +81,16 @@ class NukeRenderLocal(pype.api.Extractor): out_dir )) - instance.data['family'] = 'render' - instance.data['families'].append('render') + # redefinition of families + if "render.local" in families: + instance.data['family'] = 'render2d' + families.remove('render.local') + families.insert(0, "render") + elif "prerender.local" in families: + instance.data['family'] = 'prerender' + families.remove('prerender.local') + families.insert(0, "prerender") + instance.data["families"] = families collections, remainder = clique.assemble(collected_frames) self.log.info('collections: {}'.format(str(collections))) diff --git a/pype/plugins/nuke/publish/submit_nuke_deadline.py b/pype/plugins/nuke/publish/submit_nuke_deadline.py index 3da2e58e4d..7990c20112 100644 --- a/pype/plugins/nuke/publish/submit_nuke_deadline.py +++ b/pype/plugins/nuke/publish/submit_nuke_deadline.py @@ -28,6 +28,7 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): deadline_chunk_size = 1 def process(self, instance): + families = instance.data["families"] node = instance[0] context = instance.context @@ -82,6 +83,15 @@ class NukeSubmitDeadline(pyblish.api.InstancePlugin): instance.data["deadlineSubmissionJob"] = resp.json() instance.data["publishJobState"] = "Suspended" + # redefinition of families + if "render.farm" in families: + instance.data['family'] = 'write' + families.insert(0, "render2d") + elif "prerender.farm" in families: + instance.data['family'] = 'write' + families.insert(0, "prerender") + instance.data["families"] = families + def payload_submit(self, instance, script_path, From 93761e3010743d139f272022a578af3d90e4acfc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 18:57:52 +0100 Subject: [PATCH 23/42] fix(global): add correct frame number to repre.data --- pype/plugins/global/publish/integrate_new.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pype/plugins/global/publish/integrate_new.py b/pype/plugins/global/publish/integrate_new.py index 0ceac1f4a7..44f91a343c 100644 --- a/pype/plugins/global/publish/integrate_new.py +++ b/pype/plugins/global/publish/integrate_new.py @@ -383,6 +383,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin): if not dst_start_frame: dst_start_frame = dst_padding + template_data["frame"] = dst_start_frame + dst = "{0}{1}{2}".format( dst_head, dst_start_frame, From 5f616f14f1a97db551b713a1ab73415d9ab6ecd4 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 18:58:18 +0100 Subject: [PATCH 24/42] fix(nuke): submitting with correct family --- .../global/publish/submit_publish_job.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index 144a0822a2..134f8e9098 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -141,7 +141,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): hosts = ["fusion", "maya", "nuke"] - families = ["render.farm", "prerender.farm", "renderlayer", "imagesequence"] + families = ["render.farm", "prerener", "renderlayer", "imagesequence"] aov_filter = {"maya": ["beauty"]} @@ -168,9 +168,9 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): instance_transfer = { "slate": ["slateFrame"], "review": ["lutPath"], - "render.farm": ["bakeScriptPath", "bakeRenderPath", - "bakeWriteNodeName", "version"] - } + "render2d": ["bakeScriptPath", "bakeRenderPath", + "bakeWriteNodeName", "version"] + } # list of family names to transfer to new family if present families_transfer = ["render3d", "render2d", "ftrack", "slate"] @@ -586,17 +586,24 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "resolutionHeight": data.get("resolutionHeight", 1080), } - if "prerender.farm" in instance.data["families"]: + if "prerender" in instance.data["families"]: instance_skeleton_data.update({ "family": "prerender", - "families": ["prerender"] - }) + "families": [] + }) # transfer specific families from original instance to new render for item in self.families_transfer: if item in instance.data.get("families", []): instance_skeleton_data["families"] += [item] + if "render.farm" in instance.data["families"]: + instance_skeleton_data.update({ + "family": "render2d", + "families": ["render"] + [f for f in instance.data["families"] + if "render.farm" not in f] + }) + # transfer specific properties from original instance based on # mapping dictionary `instance_transfer` for key, values in self.instance_transfer.items(): From 129eb5db6931832c8a3592295e352dbdd4700ea9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 19:04:03 +0100 Subject: [PATCH 25/42] fix(nuke): hound pep8 --- pype/plugins/nuke/create/create_write_prerender.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pype/plugins/nuke/create/create_write_prerender.py b/pype/plugins/nuke/create/create_write_prerender.py index 6e242f886c..210c84e0cd 100644 --- a/pype/plugins/nuke/create/create_write_prerender.py +++ b/pype/plugins/nuke/create/create_write_prerender.py @@ -1,8 +1,7 @@ from collections import OrderedDict from pype.nuke import ( plugin, - lib as pnlib - ) + lib as pnlib) import nuke @@ -81,15 +80,15 @@ class CreateWritePrerender(plugin.PypeCreator): else: self.log.info("Adding template path from plugin") write_data.update({ - "fpath_template": "{work}/prerenders/nuke/{subset}/{subset}.{frame}.{ext}"}) + "fpath_template": ("{work}/prerenders/nuke/{subset}" + "/{subset}.{frame}.{ext}")}) write_node = pnlib.create_write_node( self.data["subset"], write_data, input=selected_node, prenodes=[], - review=False - ) + review=False) # relinking to collected connections for i, input in enumerate(inputs): From 8d9d965d6d4f8b6fa8a217e45415f3eee611f866 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 19:06:19 +0100 Subject: [PATCH 26/42] fix(nuke): hound pep8 --- pype/plugins/nuke/create/create_write_render.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/nuke/create/create_write_render.py b/pype/plugins/nuke/create/create_write_render.py index c3b60ba2b0..06ef237305 100644 --- a/pype/plugins/nuke/create/create_write_render.py +++ b/pype/plugins/nuke/create/create_write_render.py @@ -1,8 +1,7 @@ from collections import OrderedDict from pype.nuke import ( plugin, - lib as pnlib - ) + lib as pnlib) import nuke @@ -82,7 +81,8 @@ class CreateWriteRender(plugin.PypeCreator): else: self.log.info("Adding template path from plugin") write_data.update({ - "fpath_template": "{work}/renders/nuke/{subset}/{subset}.{frame}.{ext}"}) + "fpath_template": ("{work}/renders/nuke/{subset}" + "/{subset}.{frame}.{ext}")}) write_node = pnlib.create_write_node( self.data["subset"], From 48d7489621f36fe6743207747f093df43f8512f9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 Mar 2020 19:12:34 +0100 Subject: [PATCH 27/42] fix(global): hound pep8 --- .../global/publish/extract_review_slate.py | 15 +++++++++------ pype/plugins/global/publish/submit_publish_job.py | 5 ++--- .../nuke/publish/extract_review_data_mov.py | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/pype/plugins/global/publish/extract_review_slate.py b/pype/plugins/global/publish/extract_review_slate.py index da94c7714a..aaa67bde68 100644 --- a/pype/plugins/global/publish/extract_review_slate.py +++ b/pype/plugins/global/publish/extract_review_slate.py @@ -36,7 +36,8 @@ class ExtractReviewSlate(pype.api.Extractor): fps = inst_data.get("fps") # defining image ratios - resolution_ratio = (float(resolution_width) * pixel_aspect) / resolution_height + resolution_ratio = ((float(resolution_width) * pixel_aspect) / + resolution_height) delivery_ratio = float(to_width) / float(to_height) self.log.debug("__ resolution_ratio: `{}`".format(resolution_ratio)) self.log.debug("__ delivery_ratio: `{}`".format(delivery_ratio)) @@ -91,7 +92,7 @@ class ExtractReviewSlate(pype.api.Extractor): input_args.extend([ "-r {}".format(fps), "-t 0.04"] - ) + ) # output args codec_args = repre["_profile"].get('codec', []) @@ -113,7 +114,7 @@ class ExtractReviewSlate(pype.api.Extractor): self.log.debug("lower then delivery") width_scale = int(to_width * scale_factor) width_half_pad = int(( - to_width - width_scale)/2) + to_width - width_scale) / 2) height_scale = to_height height_half_pad = 0 else: @@ -126,7 +127,7 @@ class ExtractReviewSlate(pype.api.Extractor): height_scale = int( resolution_height * scale_factor) height_half_pad = int( - (to_height - height_scale)/2) + (to_height - height_scale) / 2) self.log.debug( "__ width_scale: `{}`".format(width_scale)) @@ -137,8 +138,10 @@ class ExtractReviewSlate(pype.api.Extractor): self.log.debug( "__ height_half_pad: `{}`".format(height_half_pad)) - scaling_arg = "scale={0}x{1}:flags=lanczos,pad={2}:{3}:{4}:{5}:black,setsar=1".format( - width_scale, height_scale, to_width, to_height, width_half_pad, height_half_pad + scaling_arg = ("scale={0}x{1}:flags=lanczos," + "pad={2}:{3}:{4}:{5}:black,setsar=1").format( + width_scale, height_scale, to_width, to_height, + width_half_pad, height_half_pad ) vf_back = self.add_video_filter_args( diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index 134f8e9098..af16b11db6 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -170,7 +170,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "review": ["lutPath"], "render2d": ["bakeScriptPath", "bakeRenderPath", "bakeWriteNodeName", "version"] - } + } # list of family names to transfer to new family if present families_transfer = ["render3d", "render2d", "ftrack", "slate"] @@ -589,8 +589,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): if "prerender" in instance.data["families"]: instance_skeleton_data.update({ "family": "prerender", - "families": [] - }) + "families": []}) # transfer specific families from original instance to new render for item in self.families_transfer: diff --git a/pype/plugins/nuke/publish/extract_review_data_mov.py b/pype/plugins/nuke/publish/extract_review_data_mov.py index 0bd5394548..7c56dc8b92 100644 --- a/pype/plugins/nuke/publish/extract_review_data_mov.py +++ b/pype/plugins/nuke/publish/extract_review_data_mov.py @@ -3,7 +3,7 @@ import pyblish.api from avalon.nuke import lib as anlib from pype.nuke import lib as pnlib import pype -reload(pnlib) + class ExtractReviewDataMov(pype.api.Extractor): """Extracts movie and thumbnail with baked in luts From 46cc7b2b00657f8fd10fcc503ff03f144ce7843f Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Fri, 27 Mar 2020 17:08:04 +0100 Subject: [PATCH 28/42] disable ffmpeg for multipart EXRs --- pype/plugins/global/publish/extract_burnin.py | 4 + pype/plugins/global/publish/extract_jpeg.py | 4 + pype/plugins/global/publish/extract_review.py | 4 + .../global/publish/submit_publish_job.py | 4 +- pype/plugins/maya/publish/collect_render.py | 409 ++++++++++-------- 5 files changed, 239 insertions(+), 186 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 086a1fdfb2..9ef97e19d0 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -65,6 +65,10 @@ class ExtractBurnin(pype.api.Extractor): for i, repre in enumerate(instance.data["representations"]): self.log.debug("__ i: `{}`, repre: `{}`".format(i, repre)) + if repre.get("multipartExr", False) is True: + # ffmpeg doesn't support multipart exrs + continue + if "burnin" not in repre.get("tags", []): continue diff --git a/pype/plugins/global/publish/extract_jpeg.py b/pype/plugins/global/publish/extract_jpeg.py index 9ad6a15dfe..c856007d31 100644 --- a/pype/plugins/global/publish/extract_jpeg.py +++ b/pype/plugins/global/publish/extract_jpeg.py @@ -36,6 +36,10 @@ class ExtractJpegEXR(pyblish.api.InstancePlugin): if not isinstance(repre['files'], list): continue + if repre.get("multipartExr", False) is True: + # ffmpeg doesn't support multipart exrs + continue + stagingdir = os.path.normpath(repre.get("stagingDir")) input_file = repre['files'][0] diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index c8a8510fb2..02504edd14 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -57,6 +57,10 @@ class ExtractReview(pyblish.api.InstancePlugin): # filter out mov and img sequences representations_new = representations[:] for repre in representations: + if repre.get("multipartExr", False) is True: + # ffmpeg doesn't support multipart exrs + continue + if repre['ext'] not in self.ext_filter: continue diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index dcf19ae32c..6c88b5d2aa 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -443,6 +443,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "stagingDir": os.path.dirname(list(c)[0]), "anatomy_template": "render", "fps": instance.get("fps"), + "multipartExr": instance.get("multipartExr"), "tags": ["review", "preview"] if preview else [], } @@ -458,7 +459,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "ext": ext, "files": os.path.basename(r), "stagingDir": os.path.dirname(r), - "anatomy_template": "publish", + "anatomy_template": "publish" } if r in bake_render_path: rep.update({ @@ -581,6 +582,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "pixelAspect": data.get("pixelAspect", 1), "resolutionWidth": data.get("resolutionWidth", 1920), "resolutionHeight": data.get("resolutionHeight", 1080), + "multipartExr": data.get("multipartExr", False) } # transfer specific families from original instance to new render diff --git a/pype/plugins/maya/publish/collect_render.py b/pype/plugins/maya/publish/collect_render.py index be3878e6bd..ac21d9ad03 100644 --- a/pype/plugins/maya/publish/collect_render.py +++ b/pype/plugins/maya/publish/collect_render.py @@ -52,38 +52,40 @@ from avalon import maya, api import pype.maya.lib as lib -R_SINGLE_FRAME = re.compile(r'^(-?)\d+$') -R_FRAME_RANGE = re.compile(r'^(?P(-?)\d+)-(?P(-?)\d+)$') -R_FRAME_NUMBER = re.compile(r'.+\.(?P[0-9]+)\..+') +R_SINGLE_FRAME = re.compile(r"^(-?)\d+$") +R_FRAME_RANGE = re.compile(r"^(?P(-?)\d+)-(?P(-?)\d+)$") +R_FRAME_NUMBER = re.compile(r".+\.(?P[0-9]+)\..+") R_LAYER_TOKEN = re.compile( - r'.*%l.*|.*.*|.*.*', re.IGNORECASE) -R_AOV_TOKEN = re.compile(r'.*%a.*|.*.*|.*.*', re.IGNORECASE) -R_SUBSTITUTE_AOV_TOKEN = re.compile(r'%a||', re.IGNORECASE) -R_REMOVE_AOV_TOKEN = re.compile(r'_%a|_|_', re.IGNORECASE) + r".*%l.*|.*.*|.*.*", re.IGNORECASE +) +R_AOV_TOKEN = re.compile(r".*%a.*|.*.*|.*.*", re.IGNORECASE) +R_SUBSTITUTE_AOV_TOKEN = re.compile(r"%a||", re.IGNORECASE) +R_REMOVE_AOV_TOKEN = re.compile(r"_%a|_|_", re.IGNORECASE) # to remove unused renderman tokens -R_CLEAN_FRAME_TOKEN = re.compile(r'\.?\.?', re.IGNORECASE) -R_CLEAN_EXT_TOKEN = re.compile(r'\.?\.?', re.IGNORECASE) +R_CLEAN_FRAME_TOKEN = re.compile(r"\.?\.?", re.IGNORECASE) +R_CLEAN_EXT_TOKEN = re.compile(r"\.?\.?", re.IGNORECASE) R_SUBSTITUTE_LAYER_TOKEN = re.compile( - r'%l||', re.IGNORECASE) -R_SUBSTITUTE_CAMERA_TOKEN = re.compile(r'%c|', re.IGNORECASE) -R_SUBSTITUTE_SCENE_TOKEN = re.compile(r'%s|', re.IGNORECASE) + r"%l||", re.IGNORECASE +) +R_SUBSTITUTE_CAMERA_TOKEN = re.compile(r"%c|", re.IGNORECASE) +R_SUBSTITUTE_SCENE_TOKEN = re.compile(r"%s|", re.IGNORECASE) RENDERER_NAMES = { - 'mentalray': 'MentalRay', - 'vray': 'V-Ray', - 'arnold': 'Arnold', - 'renderman': 'Renderman', - 'redshift': 'Redshift' + "mentalray": "MentalRay", + "vray": "V-Ray", + "arnold": "Arnold", + "renderman": "Renderman", + "redshift": "Redshift", } # not sure about the renderman image prefix ImagePrefixes = { - 'mentalray': 'defaultRenderGlobals.imageFilePrefix', - 'vray': 'vraySettings.fileNamePrefix', - 'arnold': 'defaultRenderGlobals.imageFilePrefix', - 'renderman': 'rmanGlobals.imageFileFormat', - 'redshift': 'defaultRenderGlobals.imageFilePrefix' + "mentalray": "defaultRenderGlobals.imageFilePrefix", + "vray": "vraySettings.fileNamePrefix", + "arnold": "defaultRenderGlobals.imageFilePrefix", + "renderman": "rmanGlobals.imageFileFormat", + "redshift": "defaultRenderGlobals.imageFilePrefix", } @@ -97,21 +99,23 @@ class CollectMayaRender(pyblish.api.ContextPlugin): def process(self, context): render_instance = None for instance in context: - if 'rendering' in instance.data['families']: + if "rendering" in instance.data["families"]: render_instance = instance render_instance.data["remove"] = True # make sure workfile instance publishing is enabled - if 'workfile' in instance.data['families']: + if "workfile" in instance.data["families"]: instance.data["publish"] = True if not render_instance: - self.log.info("No render instance found, skipping render " - "layer collection.") + self.log.info( + "No render instance found, skipping render " + "layer collection." + ) return render_globals = render_instance - collected_render_layers = render_instance.data['setMembers'] + collected_render_layers = render_instance.data["setMembers"] filepath = context.data["currentFile"].replace("\\", "/") asset = api.Session["AVALON_ASSET"] workspace = context.data["workspaceDir"] @@ -126,22 +130,24 @@ class CollectMayaRender(pyblish.api.ContextPlugin): try: expected_layer_name = re.search(r"^LAYER_(.*)", layer).group(1) except IndexError: - msg = ("Invalid layer name in set [ {} ]".format(layer)) + msg = "Invalid layer name in set [ {} ]".format(layer) self.log.warnig(msg) continue self.log.info("processing %s" % layer) # check if layer is part of renderSetup if expected_layer_name not in maya_render_layers: - msg = ("Render layer [ {} ] is not in " - "Render Setup".format(expected_layer_name)) + msg = "Render layer [ {} ] is not in " "Render Setup".format( + expected_layer_name + ) self.log.warning(msg) continue # check if layer is renderable if not maya_render_layers[expected_layer_name].isRenderable(): - msg = ("Render layer [ {} ] is not " - "renderable".format(expected_layer_name)) + msg = "Render layer [ {} ] is not " "renderable".format( + expected_layer_name + ) self.log.warning(msg) continue @@ -150,26 +156,31 @@ class CollectMayaRender(pyblish.api.ContextPlugin): attachTo = [] if sets: for s in sets: - attachTo.append({ - "version": None, # we need integrator to get version - "subset": s, - "family": cmds.getAttr("{}.family".format(s)) - }) + attachTo.append( + { + "version": None, # we need integrator for that + "subset": s, + "family": cmds.getAttr("{}.family".format(s)), + } + ) self.log.info(" -> attach render to: {}".format(s)) layer_name = "rs_{}".format(expected_layer_name) # collect all frames we are expecting to be rendered renderer = cmds.getAttr( - 'defaultRenderGlobals.currentRenderer').lower() + "defaultRenderGlobals.currentRenderer" + ).lower() # handle various renderman names - if renderer.startswith('renderman'): - renderer = 'renderman' + if renderer.startswith("renderman"): + renderer = "renderman" # return all expected files for all cameras and aovs in given # frame range - exp_files = ExpectedFiles().get(renderer, layer_name) - assert exp_files, ("no file names were generated, this is bug") + exf = ExpectedFiles() + exp_files = exf.get(renderer, layer_name) + self.log.info("multipart: {}".format(exf.multipart)) + assert exp_files, "no file names were generated, this is bug" # if we want to attach render to subset, check if we have AOV's # in expectedFiles. If so, raise error as we cannot attach AOV @@ -177,7 +188,8 @@ class CollectMayaRender(pyblish.api.ContextPlugin): if attachTo: assert len(exp_files[0].keys()) == 1, ( "attaching multiple AOVs or renderable cameras to " - "subset is not supported") + "subset is not supported" + ) # append full path full_exp_files = [] @@ -210,35 +222,45 @@ class CollectMayaRender(pyblish.api.ContextPlugin): "subset": expected_layer_name, "attachTo": attachTo, "setMembers": layer_name, + "multipartExr": exf.multipart, "publish": True, - "frameStart": int(context.data["assetEntity"]['data']['frameStart']), - "frameEnd": int(context.data["assetEntity"]['data']['frameEnd']), - "frameStartHandle": int(self.get_render_attribute("startFrame", - layer=layer_name)), - "frameEndHandle": int(self.get_render_attribute("endFrame", - layer=layer_name)), + "frameStart": int( + context.data["assetEntity"]["data"]["frameStart"] + ), + "frameEnd": int( + context.data["assetEntity"]["data"]["frameEnd"] + ), + "frameStartHandle": int( + self.get_render_attribute("startFrame", layer=layer_name) + ), + "frameEndHandle": int( + self.get_render_attribute("endFrame", layer=layer_name) + ), "byFrameStep": int( - self.get_render_attribute("byFrameStep", - layer=layer_name)), - "renderer": self.get_render_attribute("currentRenderer", - layer=layer_name), - "handleStart": int(context.data["assetEntity"]['data']['handleStart']), - "handleEnd": int(context.data["assetEntity"]['data']['handleEnd']), - + self.get_render_attribute("byFrameStep", layer=layer_name) + ), + "renderer": self.get_render_attribute( + "currentRenderer", layer=layer_name + ), + "handleStart": int( + context.data["assetEntity"]["data"]["handleStart"] + ), + "handleEnd": int( + context.data["assetEntity"]["data"]["handleEnd"] + ), # instance subset "family": "renderlayer", "families": ["renderlayer"], "asset": asset, "time": api.time(), "author": context.data["user"], - # Add source to allow tracing back to the scene from # which was submitted originally "source": filepath, "expectedFiles": full_exp_files, "resolutionWidth": cmds.getAttr("defaultResolution.width"), "resolutionHeight": cmds.getAttr("defaultResolution.height"), - "pixelAspect": cmds.getAttr("defaultResolution.pixelAspect") + "pixelAspect": cmds.getAttr("defaultResolution.pixelAspect"), } # Apply each user defined attribute as data @@ -261,8 +283,9 @@ class CollectMayaRender(pyblish.api.ContextPlugin): # Define nice label label = "{0} ({1})".format(expected_layer_name, data["asset"]) - label += " [{0}-{1}]".format(int(data["frameStartHandle"]), - int(data["frameEndHandle"])) + label += " [{0}-{1}]".format( + int(data["frameStartHandle"]), int(data["frameEndHandle"]) + ) instance = context.create_instance(expected_layer_name) instance.data["label"] = label @@ -298,7 +321,7 @@ class CollectMayaRender(pyblish.api.ContextPlugin): machine_list = attributes["machineList"] if machine_list: key = "Whitelist" if attributes["whitelist"] else "Blacklist" - options['renderGlobals'][key] = machine_list + options["renderGlobals"][key] = machine_list # Suspend publish job state = "Suspended" if attributes["suspendPublishJob"] else "Active" @@ -354,32 +377,41 @@ class CollectMayaRender(pyblish.api.ContextPlugin): return rset.getOverrides() def get_render_attribute(self, attr, layer): - return lib.get_attr_in_layer("defaultRenderGlobals.{}".format(attr), - layer=layer) + return lib.get_attr_in_layer( + "defaultRenderGlobals.{}".format(attr), layer=layer + ) class ExpectedFiles: + multipart = False def get(self, renderer, layer): - if renderer.lower() == 'arnold': - return ExpectedFilesArnold(layer).get_files() - elif renderer.lower() == 'vray': - return ExpectedFilesVray(layer).get_files() - elif renderer.lower() == 'redshift': - return ExpectedFilesRedshift(layer).get_files() - elif renderer.lower() == 'mentalray': - return ExpectedFilesMentalray(layer).get_files() - elif renderer.lower() == 'renderman': - return ExpectedFilesRenderman(layer).get_files() + if renderer.lower() == "arnold": + return self._get_files(ExpectedFilesArnold(layer)) + elif renderer.lower() == "vray": + return self._get_files(ExpectedFilesVray(layer)) + elif renderer.lower() == "redshift": + return self._get_files(ExpectedFilesRedshift(layer)) + elif renderer.lower() == "mentalray": + return self._get_files(ExpectedFilesMentalray(layer)) + elif renderer.lower() == "renderman": + return self._get_files(ExpectedFilesRenderman(layer)) else: raise UnsupportedRendererException( - "unsupported {}".format(renderer)) + "unsupported {}".format(renderer) + ) + + def _get_files(self, renderer): + files = renderer.get_files() + self.multipart = renderer.multipart + return files @six.add_metaclass(ABCMeta) class AExpectedFiles: renderer = None layer = None + multipart = False def __init__(self, layer): self.layer = layer @@ -393,7 +425,8 @@ class AExpectedFiles: file_prefix = cmds.getAttr(ImagePrefixes[self.renderer]) except KeyError: raise UnsupportedRendererException( - "Unsupported renderer {}".format(self.renderer)) + "Unsupported renderer {}".format(self.renderer) + ) return file_prefix def _get_layer_data(self): @@ -419,7 +452,7 @@ class AExpectedFiles: if not file_prefix: raise RuntimeError("Image prefix not set") - default_ext = cmds.getAttr('defaultRenderGlobals.imfPluginKey') + default_ext = cmds.getAttr("defaultRenderGlobals.imfPluginKey") # ________________________________________________ # __________________/ ______________________________________________/ @@ -440,10 +473,10 @@ class AExpectedFiles: layer_name = self.layer if self.layer.startswith("rs_"): layer_name = self.layer[3:] - start_frame = int(self.get_render_attribute('startFrame')) - end_frame = int(self.get_render_attribute('endFrame')) - frame_step = int(self.get_render_attribute('byFrameStep')) - padding = int(self.get_render_attribute('extensionPadding')) + start_frame = int(self.get_render_attribute("startFrame")) + end_frame = int(self.get_render_attribute("endFrame")) + frame_step = int(self.get_render_attribute("byFrameStep")) + padding = int(self.get_render_attribute("extensionPadding")) scene_data = { "frameStart": start_frame, @@ -456,7 +489,7 @@ class AExpectedFiles: "renderer": renderer, "defaultExt": default_ext, "filePrefix": file_prefix, - "enabledAOVs": enabled_aovs + "enabledAOVs": enabled_aovs, } return scene_data @@ -472,21 +505,24 @@ class AExpectedFiles: # in Redshift (R_REMOVE_AOV_TOKEN, ""), (R_CLEAN_FRAME_TOKEN, ""), - (R_CLEAN_EXT_TOKEN, "") + (R_CLEAN_EXT_TOKEN, ""), ) for regex, value in mappings: file_prefix = re.sub(regex, value, file_prefix) for frame in range( - int(layer_data["frameStart"]), - int(layer_data["frameEnd"]) + 1, - int(layer_data["frameStep"])): + int(layer_data["frameStart"]), + int(layer_data["frameEnd"]) + 1, + int(layer_data["frameStep"]), + ): expected_files.append( - '{}.{}.{}'.format(file_prefix, - str(frame).rjust( - layer_data["padding"], "0"), - layer_data["defaultExt"])) + "{}.{}.{}".format( + file_prefix, + str(frame).rjust(layer_data["padding"], "0"), + layer_data["defaultExt"], + ) + ) return expected_files def _generate_aov_file_sequences(self, layer_data): @@ -502,7 +538,7 @@ class AExpectedFiles: (R_SUBSTITUTE_CAMERA_TOKEN, cam), (R_SUBSTITUTE_AOV_TOKEN, aov[0]), (R_CLEAN_FRAME_TOKEN, ""), - (R_CLEAN_EXT_TOKEN, "") + (R_CLEAN_EXT_TOKEN, ""), ) for regex, value in mappings: @@ -510,14 +546,17 @@ class AExpectedFiles: aov_files = [] for frame in range( - int(layer_data["frameStart"]), - int(layer_data["frameEnd"]) + 1, - int(layer_data["frameStep"])): + int(layer_data["frameStart"]), + int(layer_data["frameEnd"]) + 1, + int(layer_data["frameStep"]), + ): aov_files.append( - '{}.{}.{}'.format( + "{}.{}.{}".format( file_prefix, str(frame).rjust(layer_data["padding"], "0"), - aov[1])) + aov[1], + ) + ) # if we have more then one renderable camera, append # camera name to AOV to allow per camera AOVs. @@ -551,17 +590,19 @@ class AExpectedFiles: return expected_files def get_renderable_cameras(self): - cam_parents = [cmds.listRelatives(x, ap=True)[-1] - for x in cmds.ls(cameras=True)] + cam_parents = [ + cmds.listRelatives(x, ap=True)[-1] for x in cmds.ls(cameras=True) + ] renderable_cameras = [] for cam in cam_parents: renderable = False - if self.maya_is_true(cmds.getAttr('{}.renderable'.format(cam))): + if self.maya_is_true(cmds.getAttr("{}.renderable".format(cam))): renderable = True for override in self.get_layer_overrides( - '{}.renderable'.format(cam), self.layer): + "{}.renderable".format(cam), self.layer + ): renderable = self.maya_is_true(override) if renderable: @@ -587,16 +628,18 @@ class AExpectedFiles: if connections: for connection in connections: if connection: - node_name = connection.split('.')[0] - if cmds.nodeType(node_name) == 'renderLayer': - attr_name = '%s.value' % '.'.join( - connection.split('.')[:-1]) + node_name = connection.split(".")[0] + if cmds.nodeType(node_name) == "renderLayer": + attr_name = "%s.value" % ".".join( + connection.split(".")[:-1] + ) if node_name == layer: yield cmds.getAttr(attr_name) def get_render_attribute(self, attr): - return lib.get_attr_in_layer("defaultRenderGlobals.{}".format(attr), - layer=self.layer) + return lib.get_attr_in_layer( + "defaultRenderGlobals.{}".format(attr), layer=self.layer + ) class ExpectedFilesArnold(AExpectedFiles): @@ -604,25 +647,28 @@ class ExpectedFilesArnold(AExpectedFiles): # Arnold AOV driver extension mapping # Is there a better way? aiDriverExtension = { - 'jpeg': 'jpg', - 'exr': 'exr', - 'deepexr': 'exr', - 'png': 'png', - 'tiff': 'tif', - 'mtoa_shaders': 'ass', # TODO: research what those last two should be - 'maya': '' + "jpeg": "jpg", + "exr": "exr", + "deepexr": "exr", + "png": "png", + "tiff": "tif", + "mtoa_shaders": "ass", # TODO: research what those last two should be + "maya": "", } def __init__(self, layer): super(ExpectedFilesArnold, self).__init__(layer) - self.renderer = 'arnold' + self.renderer = "arnold" def get_aovs(self): enabled_aovs = [] try: - if not (cmds.getAttr('defaultArnoldRenderOptions.aovMode') - and not cmds.getAttr('defaultArnoldDriver.mergeAOVs')): + if not ( + cmds.getAttr("defaultArnoldRenderOptions.aovMode") + and not cmds.getAttr("defaultArnoldDriver.mergeAOVs") + ): # AOVs are merged in mutli-channel file + self.multipart = True return enabled_aovs except ValueError: # this occurs when Render Setting windows was not opened yet. In @@ -635,46 +681,35 @@ class ExpectedFilesArnold(AExpectedFiles): # AOVs are set to be rendered separately. We should expect # token in path. - ai_aovs = [n for n in cmds.ls(type='aiAOV')] + ai_aovs = [n for n in cmds.ls(type="aiAOV")] for aov in ai_aovs: - enabled = self.maya_is_true( - cmds.getAttr('{}.enabled'.format(aov))) - ai_driver = cmds.listConnections( - '{}.outputs'.format(aov))[0] - ai_translator = cmds.getAttr( - '{}.aiTranslator'.format(ai_driver)) + enabled = self.maya_is_true(cmds.getAttr("{}.enabled".format(aov))) + ai_driver = cmds.listConnections("{}.outputs".format(aov))[0] + ai_translator = cmds.getAttr("{}.aiTranslator".format(ai_driver)) try: aov_ext = self.aiDriverExtension[ai_translator] except KeyError: - msg = ('Unrecognized arnold ' - 'driver format for AOV - {}').format( - cmds.getAttr('{}.name'.format(aov)) - ) + msg = ( + "Unrecognized arnold " "driver format for AOV - {}" + ).format(cmds.getAttr("{}.name".format(aov))) raise AOVError(msg) for override in self.get_layer_overrides( - '{}.enabled'.format(aov), self.layer): + "{}.enabled".format(aov), self.layer + ): enabled = self.maya_is_true(override) if enabled: # If aov RGBA is selected, arnold will translate it to `beauty` - aov_name = cmds.getAttr('%s.name' % aov) - if aov_name == 'RGBA': - aov_name = 'beauty' - enabled_aovs.append( - ( - aov_name, - aov_ext - ) - ) + aov_name = cmds.getAttr("%s.name" % aov) + if aov_name == "RGBA": + aov_name = "beauty" + enabled_aovs.append((aov_name, aov_ext)) # Append 'beauty' as this is arnolds # default. If token is specified and no AOVs are # defined, this will be used. enabled_aovs.append( - ( - u'beauty', - cmds.getAttr('defaultRenderGlobals.imfPluginKey') - ) + (u"beauty", cmds.getAttr("defaultRenderGlobals.imfPluginKey")) ) return enabled_aovs @@ -688,7 +723,7 @@ class ExpectedFilesVray(AExpectedFiles): def __init__(self, layer): super(ExpectedFilesVray, self).__init__(layer) - self.renderer = 'vray' + self.renderer = "vray" def get_renderer_prefix(self): prefix = super(ExpectedFilesVray, self).get_renderer_prefix() @@ -703,7 +738,9 @@ class ExpectedFilesVray(AExpectedFiles): layer_data = self._get_layer_data() if layer_data.get("enabledAOVs"): - expected_files[0][u"beauty"] = self._generate_single_file_sequence(layer_data) # noqa: E501 + expected_files[0][u"beauty"] = self._generate_single_file_sequence( + layer_data + ) # noqa: E501 return expected_files @@ -712,9 +749,12 @@ class ExpectedFilesVray(AExpectedFiles): try: # really? do we set it in vray just by selecting multichannel exr? - if cmds.getAttr( - "vraySettings.imageFormatStr") == "exr (multichannel)": + if ( + cmds.getAttr("vraySettings.imageFormatStr") + == "exr (multichannel)" + ): # AOVs are merged in mutli-channel file + self.multipart = True return enabled_aovs except ValueError: # this occurs when Render Setting windows was not opened yet. In @@ -724,35 +764,40 @@ class ExpectedFilesVray(AExpectedFiles): # anyway. return enabled_aovs - default_ext = cmds.getAttr('vraySettings.imageFormatStr') + default_ext = cmds.getAttr("vraySettings.imageFormatStr") if default_ext == "exr (multichannel)" or default_ext == "exr (deep)": default_ext = "exr" - vr_aovs = [n for n in cmds.ls( - type=["VRayRenderElement", "VRayRenderElementSet"])] + vr_aovs = [ + n + for n in cmds.ls( + type=["VRayRenderElement", "VRayRenderElementSet"] + ) + ] # todo: find out how to detect multichannel exr for vray for aov in vr_aovs: - enabled = self.maya_is_true( - cmds.getAttr('{}.enabled'.format(aov))) + enabled = self.maya_is_true(cmds.getAttr("{}.enabled".format(aov))) for override in self.get_layer_overrides( - '{}.enabled'.format(aov), 'rs_{}'.format(self.layer)): + "{}.enabled".format(aov), "rs_{}".format(self.layer) + ): enabled = self.maya_is_true(override) if enabled: # todo: find how vray set format for AOVs enabled_aovs.append( - ( - self._get_vray_aov_name(aov), - default_ext) - ) + (self._get_vray_aov_name(aov), default_ext) + ) return enabled_aovs def _get_vray_aov_name(self, node): # Get render element pass type - vray_node_attr = next(attr for attr in cmds.listAttr(node) - if attr.startswith("vray_name")) + vray_node_attr = next( + attr + for attr in cmds.listAttr(node) + if attr.startswith("vray_name") + ) pass_type = vray_node_attr.rsplit("_", 1)[-1] # Support V-Ray extratex explicit name (if set by user) @@ -770,11 +815,11 @@ class ExpectedFilesVray(AExpectedFiles): class ExpectedFilesRedshift(AExpectedFiles): # mapping redshift extension dropdown values to strings - ext_mapping = ['iff', 'exr', 'tif', 'png', 'tga', 'jpg'] + ext_mapping = ["iff", "exr", "tif", "png", "tga", "jpg"] def __init__(self, layer): super(ExpectedFilesRedshift, self).__init__(layer) - self.renderer = 'redshift' + self.renderer = "redshift" def get_renderer_prefix(self): prefix = super(ExpectedFilesRedshift, self).get_renderer_prefix() @@ -789,7 +834,9 @@ class ExpectedFilesRedshift(AExpectedFiles): layer_data = self._get_layer_data() if layer_data.get("enabledAOVs"): - expected_files[0][u"beauty"] = self._generate_single_file_sequence(layer_data) # noqa: E501 + expected_files[0][u"beauty"] = self._generate_single_file_sequence( + layer_data + ) # noqa: E501 return expected_files @@ -798,8 +845,10 @@ class ExpectedFilesRedshift(AExpectedFiles): try: if self.maya_is_true( - cmds.getAttr("redshiftOptions.exrForceMultilayer")): + cmds.getAttr("redshiftOptions.exrForceMultilayer") + ): # AOVs are merged in mutli-channel file + self.multipart = True return enabled_aovs except ValueError: # this occurs when Render Setting windows was not opened yet. In @@ -810,34 +859,30 @@ class ExpectedFilesRedshift(AExpectedFiles): return enabled_aovs default_ext = self.ext_mapping[ - cmds.getAttr('redshiftOptions.imageFormat') + cmds.getAttr("redshiftOptions.imageFormat") ] - rs_aovs = [n for n in cmds.ls(type='RedshiftAOV')] + rs_aovs = [n for n in cmds.ls(type="RedshiftAOV")] # todo: find out how to detect multichannel exr for redshift for aov in rs_aovs: - enabled = self.maya_is_true( - cmds.getAttr('{}.enabled'.format(aov))) + enabled = self.maya_is_true(cmds.getAttr("{}.enabled".format(aov))) for override in self.get_layer_overrides( - '{}.enabled'.format(aov), self.layer): + "{}.enabled".format(aov), self.layer + ): enabled = self.maya_is_true(override) if enabled: enabled_aovs.append( - ( - cmds.getAttr('%s.name' % aov), - default_ext - ) + (cmds.getAttr("%s.name" % aov), default_ext) ) return enabled_aovs class ExpectedFilesRenderman(AExpectedFiles): - def __init__(self, layer): super(ExpectedFilesRenderman, self).__init__(layer) - self.renderer = 'renderman' + self.renderer = "renderman" def get_aovs(self): enabled_aovs = [] @@ -849,19 +894,14 @@ class ExpectedFilesRenderman(AExpectedFiles): if aov_name == "rmanDefaultDisplay": aov_name = "beauty" - enabled = self.maya_is_true( - cmds.getAttr("{}.enable".format(aov))) + enabled = self.maya_is_true(cmds.getAttr("{}.enable".format(aov))) for override in self.get_layer_overrides( - '{}.enable'.format(aov), self.layer): + "{}.enable".format(aov), self.layer + ): enabled = self.maya_is_true(override) if enabled: - enabled_aovs.append( - ( - aov_name, - default_ext - ) - ) + enabled_aovs.append((aov_name, default_ext)) return enabled_aovs @@ -881,9 +921,9 @@ class ExpectedFilesRenderman(AExpectedFiles): for aov, files in expected_files[0].items(): new_files = [] for file in files: - new_file = "{}/{}/{}".format(layer_data["sceneName"], - layer_data["layerName"], - file) + new_file = "{}/{}/{}".format( + layer_data["sceneName"], layer_data["layerName"], file + ) new_files.append(new_file) new_aovs[aov] = new_files @@ -891,9 +931,8 @@ class ExpectedFilesRenderman(AExpectedFiles): class ExpectedFilesMentalray(AExpectedFiles): - def __init__(self, layer): - raise UnimplementedRendererException('Mentalray not implemented') + raise UnimplementedRendererException("Mentalray not implemented") def get_aovs(self): return [] From 08a861d2a51eb26722971596ec508e956d9e81de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Mon, 30 Mar 2020 15:09:37 +0200 Subject: [PATCH 29/42] move multipart flag to tags on representation --- pype/plugins/global/publish/extract_burnin.py | 2 +- pype/plugins/global/publish/extract_jpeg.py | 2 +- pype/plugins/global/publish/extract_review.py | 7 ++++--- pype/plugins/global/publish/submit_publish_job.py | 4 +++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pype/plugins/global/publish/extract_burnin.py b/pype/plugins/global/publish/extract_burnin.py index 9ef97e19d0..a36ba802df 100644 --- a/pype/plugins/global/publish/extract_burnin.py +++ b/pype/plugins/global/publish/extract_burnin.py @@ -65,7 +65,7 @@ class ExtractBurnin(pype.api.Extractor): for i, repre in enumerate(instance.data["representations"]): self.log.debug("__ i: `{}`, repre: `{}`".format(i, repre)) - if repre.get("multipartExr", False) is True: + if "multipartExr" in repre.get("tags", []): # ffmpeg doesn't support multipart exrs continue diff --git a/pype/plugins/global/publish/extract_jpeg.py b/pype/plugins/global/publish/extract_jpeg.py index c856007d31..40e086db99 100644 --- a/pype/plugins/global/publish/extract_jpeg.py +++ b/pype/plugins/global/publish/extract_jpeg.py @@ -36,7 +36,7 @@ class ExtractJpegEXR(pyblish.api.InstancePlugin): if not isinstance(repre['files'], list): continue - if repre.get("multipartExr", False) is True: + if "multipartExr" in tags: # ffmpeg doesn't support multipart exrs continue diff --git a/pype/plugins/global/publish/extract_review.py b/pype/plugins/global/publish/extract_review.py index 02504edd14..625c96566d 100644 --- a/pype/plugins/global/publish/extract_review.py +++ b/pype/plugins/global/publish/extract_review.py @@ -57,15 +57,16 @@ class ExtractReview(pyblish.api.InstancePlugin): # filter out mov and img sequences representations_new = representations[:] for repre in representations: - if repre.get("multipartExr", False) is True: - # ffmpeg doesn't support multipart exrs - continue if repre['ext'] not in self.ext_filter: continue tags = repre.get("tags", []) + if "multipartExr" in tags: + # ffmpeg doesn't support multipart exrs + continue + if "thumbnail" in tags: continue diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index 6c88b5d2aa..bc9d9ba1ae 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -443,10 +443,12 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): "stagingDir": os.path.dirname(list(c)[0]), "anatomy_template": "render", "fps": instance.get("fps"), - "multipartExr": instance.get("multipartExr"), "tags": ["review", "preview"] if preview else [], } + if instance.get("multipartExr", False): + rep["tags"].append["multipartExr"] + representations.append(rep) self._solve_families(instance, preview) From d9ea84777c4484e2bcb774f904b173ae08f3e532 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Mon, 30 Mar 2020 15:50:36 +0200 Subject: [PATCH 30/42] environment AVALON_PROJECT is sent to publish job an metadata json stars with {root} --- pype/plugins/global/publish/collect_rendered_files.py | 3 +++ pype/plugins/global/publish/submit_publish_job.py | 3 ++- pype/scripts/publish_filesequence.py | 6 ------ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/pype/plugins/global/publish/collect_rendered_files.py b/pype/plugins/global/publish/collect_rendered_files.py index 552fd49f6d..7ae68f8e44 100644 --- a/pype/plugins/global/publish/collect_rendered_files.py +++ b/pype/plugins/global/publish/collect_rendered_files.py @@ -84,6 +84,9 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): session_set = False for path in paths: + path = path.format(**{ + "root": os.environ["PYPE_STUDIO_PROJECTS_PATH"] + }) data = self._load_json(path) if not session_set: self.log.info("Setting session using data from file") diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index dcf19ae32c..c7124d73a5 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -195,7 +195,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): mount_root = os.path.normpath(os.environ["PYPE_STUDIO_PROJECTS_MOUNT"]) network_root = os.environ["PYPE_STUDIO_PROJECTS_PATH"] metadata_path = metadata_path.replace(mount_root, network_root) - metadata_path = os.path.normpath(metadata_path) + metadata_path = metadata_path.replace(network_root, "{root}") # Generate the payload for Deadline submission payload = { @@ -225,6 +225,7 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): environment = job["Props"].get("Env", {}) environment["PYPE_METADATA_FILE"] = metadata_path + environment["AVALON_PROJECT"] = io.Session["AVALON_PROJECT"] i = 0 for index, key in enumerate(environment): if key.upper() in self.enviro_filter: diff --git a/pype/scripts/publish_filesequence.py b/pype/scripts/publish_filesequence.py index fe795564a5..168011391a 100644 --- a/pype/scripts/publish_filesequence.py +++ b/pype/scripts/publish_filesequence.py @@ -90,12 +90,6 @@ def __main__(): paths = kwargs.paths or [os.environ.get("PYPE_METADATA_FILE")] or [os.getcwd()] # noqa - for path in paths: - data = _load_json(path) - log.info("Setting session using data from file") - os.environ["AVALON_PROJECT"] = data["session"]["AVALON_PROJECT"] - break - args = [ os.path.join(pype_root, pype_command), "publish", From 66f7367524dbb3d749cf6564fbd48fbe00b74a34 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Mon, 30 Mar 2020 17:35:16 +0200 Subject: [PATCH 31/42] minor refactor --- ...ract_quicktime.py => extract_playblast.py} | 39 +++++++------------ 1 file changed, 14 insertions(+), 25 deletions(-) rename pype/plugins/maya/publish/{extract_quicktime.py => extract_playblast.py} (87%) diff --git a/pype/plugins/maya/publish/extract_quicktime.py b/pype/plugins/maya/publish/extract_playblast.py similarity index 87% rename from pype/plugins/maya/publish/extract_quicktime.py rename to pype/plugins/maya/publish/extract_playblast.py index 29d6b78051..cc307d6afc 100644 --- a/pype/plugins/maya/publish/extract_quicktime.py +++ b/pype/plugins/maya/publish/extract_playblast.py @@ -3,24 +3,23 @@ import glob import contextlib import clique import capture -# + import pype.maya.lib as lib import pype.api -# -from maya import cmds, mel + +from maya import cmds import pymel.core as pm -# TODO: move codec settings to presets -class ExtractQuicktime(pype.api.Extractor): - """Extract Quicktime from viewport capture. +class ExtractPlayblast(pype.api.Extractor): + """Extract viewport playblast. Takes review camera and creates review Quicktime video based on viewport capture. """ - label = "Quicktime" + label = "Extract Playblast" hosts = ["maya"] families = ["review"] optional = True @@ -29,7 +28,7 @@ class ExtractQuicktime(pype.api.Extractor): self.log.info("Extracting capture..") # get scene fps - fps = mel.eval('currentTimeUnitToFPS()') + fps = instance.data.get("fps") or instance.context.data.get("fps") # if start and end frames cannot be determined, get them # from Maya timeline @@ -39,6 +38,7 @@ class ExtractQuicktime(pype.api.Extractor): start = cmds.playbackOptions(query=True, animationStartTime=True) if end is None: end = cmds.playbackOptions(query=True, animationEndTime=True) + self.log.info("start: {}, end: {}".format(start, end)) # get cameras @@ -47,7 +47,7 @@ class ExtractQuicktime(pype.api.Extractor): try: preset = lib.load_capture_preset(data=capture_preset) - except: + except Exception: preset = {} self.log.info('using viewport preset: {}'.format(preset)) @@ -55,19 +55,10 @@ class ExtractQuicktime(pype.api.Extractor): preset['format'] = "image" # preset['compression'] = "qt" preset['quality'] = 95 - preset['compression'] = "jpg" + preset['compression'] = "png" preset['start_frame'] = start preset['end_frame'] = end preset['camera_options'] = { - "displayGateMask": False, - "displayResolution": False, - "displayFilmGate": False, - "displayFieldChart": False, - "displaySafeAction": False, - "displaySafeTitle": False, - "displayFilmPivot": False, - "displayFilmOrigin": False, - "overscan": 1.0, "depthOfField": cmds.getAttr("{0}.depthOfField".format(camera)), } @@ -90,8 +81,8 @@ class ExtractQuicktime(pype.api.Extractor): filename = preset.get("filename", "%TEMP%") # Force viewer to False in call to capture because we have our own - # viewer opening call to allow a signal to trigger between playblast - # and viewer + # viewer opening call to allow a signal to trigger between + # playblast and viewer preset['viewer'] = False # Remove panel key since it's internal value to capture_gui @@ -112,8 +103,8 @@ class ExtractQuicktime(pype.api.Extractor): instance.data["representations"] = [] representation = { - 'name': 'mov', - 'ext': 'mov', + 'name': 'png', + 'ext': 'png', 'files': collected_frames, "stagingDir": stagingdir, "frameStart": start, @@ -133,7 +124,6 @@ class ExtractQuicktime(pype.api.Extractor): To workaround this we just glob.glob() for any file extensions and assume the latest modified file is the correct file and return it. - """ # Catch cancelled playblast if filepath is None: @@ -164,7 +154,6 @@ class ExtractQuicktime(pype.api.Extractor): return filepath - @contextlib.contextmanager def maintained_time(): ct = cmds.currentTime(query=True) From 3c70a91c3357ae95a169783474568099fe836f17 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Mon, 30 Mar 2020 23:25:55 +0200 Subject: [PATCH 32/42] bump version --- pype/__init__.py | 1 - pype/version.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 pype/version.py diff --git a/pype/__init__.py b/pype/__init__.py index 5cd9832558..803d3fa60e 100644 --- a/pype/__init__.py +++ b/pype/__init__.py @@ -9,7 +9,6 @@ from pypeapp import config import logging log = logging.getLogger(__name__) -__version__ = "2.6.0" PROJECT_PLUGINS_PATH = os.environ.get("PYPE_PROJECT_PLUGINS") PACKAGE_DIR = os.path.dirname(__file__) diff --git a/pype/version.py b/pype/version.py new file mode 100644 index 0000000000..2614ce9d96 --- /dev/null +++ b/pype/version.py @@ -0,0 +1 @@ +__version__ = "2.7.0" From 12bea639ebd5a0a9dbaed87bad255faeed83ed89 Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Wed, 1 Apr 2020 17:25:43 +0200 Subject: [PATCH 33/42] preserve mb file type during publish --- pype/plugins/maya/publish/collect_scene.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pype/plugins/maya/publish/collect_scene.py b/pype/plugins/maya/publish/collect_scene.py index 089019f2d3..3f5760fd7b 100644 --- a/pype/plugins/maya/publish/collect_scene.py +++ b/pype/plugins/maya/publish/collect_scene.py @@ -1,5 +1,3 @@ -from maya import cmds - import pyblish.api import avalon.api import os @@ -42,8 +40,8 @@ class CollectMayaScene(pyblish.api.ContextPlugin): }) data['representations'] = [{ - 'name': 'ma', - 'ext': 'ma', + 'name': ext.lstrip("."), + 'ext': ext.lstrip("."), 'files': file, "stagingDir": folder, }] From 17622b046d3e4fd814ad45d4f2e4cdd554d6a39a Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Wed, 1 Apr 2020 19:16:54 +0200 Subject: [PATCH 34/42] fixed camera options --- pype/plugins/maya/publish/extract_playblast.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pype/plugins/maya/publish/extract_playblast.py b/pype/plugins/maya/publish/extract_playblast.py index cc307d6afc..579712018c 100644 --- a/pype/plugins/maya/publish/extract_playblast.py +++ b/pype/plugins/maya/publish/extract_playblast.py @@ -58,9 +58,9 @@ class ExtractPlayblast(pype.api.Extractor): preset['compression'] = "png" preset['start_frame'] = start preset['end_frame'] = end - preset['camera_options'] = { - "depthOfField": cmds.getAttr("{0}.depthOfField".format(camera)), - } + camera_option = preset.get("camera_option", {}) + camera_option["depthOfField"] = cmds.getAttr( + "{0}.depthOfField".format(camera)) stagingdir = self.staging_dir(instance) filename = "{0}".format(instance.name) From 7763b339927784fdb101daad5386347ae29428e1 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Thu, 2 Apr 2020 16:27:25 +0200 Subject: [PATCH 35/42] make sure we don't error on missing handles in instance --- pype/plugins/maya/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/collect_review.py b/pype/plugins/maya/publish/collect_review.py index 9b6027b98d..063a854bd1 100644 --- a/pype/plugins/maya/publish/collect_review.py +++ b/pype/plugins/maya/publish/collect_review.py @@ -60,7 +60,7 @@ class CollectReview(pyblish.api.InstancePlugin): data['frameEndHandle'] = instance.data["frameEndHandle"] data["frameStart"] = instance.data["frameStart"] data["frameEnd"] = instance.data["frameEnd"] - data['handles'] = instance.data['handles'] + data['handles'] = instance.data.get('handles', None) data['step'] = instance.data['step'] data['fps'] = instance.data['fps'] cmds.setAttr(str(instance) + '.active', 1) From f81e2e9ca3c5ff119a60e09b51f3027f40f9265f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Thu, 2 Apr 2020 18:10:40 +0200 Subject: [PATCH 36/42] Update validate_rig_output_ids.py --- pype/plugins/maya/publish/validate_rig_output_ids.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/validate_rig_output_ids.py b/pype/plugins/maya/publish/validate_rig_output_ids.py index aefe883149..b6b3735196 100644 --- a/pype/plugins/maya/publish/validate_rig_output_ids.py +++ b/pype/plugins/maya/publish/validate_rig_output_ids.py @@ -38,7 +38,7 @@ class ValidateRigOutputIds(pyblish.api.InstancePlugin): if compute: out_set = next(x for x in instance if x.endswith("out_SET")) instance_nodes = pc.sets(out_set, query=True) - instance_nodes.extend([x.getShape() for x in instance_nodes]) + instance_nodes.extend([x.getShape() for x in instance_nodes if x.getShape()]) scene_nodes = pc.ls(type="transform") + pc.ls(type="mesh") scene_nodes = set(scene_nodes) - set(instance_nodes) From 305ba756ba7ad52e0db200ff3718d4df4eb773b8 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Fri, 3 Apr 2020 11:32:13 +0200 Subject: [PATCH 37/42] Subprocess in app launch is again stored to variable. Now it is `_popen` and added comment why it is there. --- pype/ftrack/lib/ftrack_app_handler.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pype/ftrack/lib/ftrack_app_handler.py b/pype/ftrack/lib/ftrack_app_handler.py index b5576ae046..56196d15f9 100644 --- a/pype/ftrack/lib/ftrack_app_handler.py +++ b/pype/ftrack/lib/ftrack_app_handler.py @@ -290,7 +290,10 @@ class AppAction(BaseHandler): # Run SW if was found executable if execfile is not None: - avalonlib.launch( + # Store subprocess to varaible. This is due to Blender launch + # bug. Please make sure Blender >=2.81 can be launched before + # remove `_popen` variable. + _popen = avalonlib.launch( executable=execfile, args=[], environment=env ) else: @@ -323,7 +326,7 @@ class AppAction(BaseHandler): 'message': "No executable permission - {}".format( execfile) } - pass + else: self.log.error('Launcher doesn\'t exist - {}'.format( execfile)) @@ -331,10 +334,13 @@ class AppAction(BaseHandler): 'success': False, 'message': "Launcher doesn't exist - {}".format(execfile) } - pass + # Run SW if was found executable if execfile is not None: - avalonlib.launch( + # Store subprocess to varaible. This is due to Blender launch + # bug. Please make sure Blender >=2.81 can be launched before + # remove `_popen` variable. + _popen = avalonlib.launch( '/usr/bin/env', args=['bash', execfile], environment=env ) else: @@ -343,7 +349,6 @@ class AppAction(BaseHandler): 'message': "We didn't found launcher for {0}" .format(self.label) } - pass # Change status of task to In progress presets = config.get_presets()["ftrack"]["ftrack_config"] From 5109ea9a9047db412c2cf199dca9790910d395ac Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Fri, 3 Apr 2020 15:32:13 +0200 Subject: [PATCH 38/42] fixed missing import --- pype/plugins/maya/publish/collect_scene.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/collect_scene.py b/pype/plugins/maya/publish/collect_scene.py index bbaaa95b18..b94707fc7f 100644 --- a/pype/plugins/maya/publish/collect_scene.py +++ b/pype/plugins/maya/publish/collect_scene.py @@ -1,7 +1,7 @@ import pyblish.api import avalon.api import os -from pype.maya import lib +from pype.maya import cmds class CollectMayaScene(pyblish.api.ContextPlugin): From f9655b0e2156b8d151436a9c575f56a3c5221aaf Mon Sep 17 00:00:00 2001 From: Ondrej Samohel Date: Fri, 3 Apr 2020 19:47:12 +0200 Subject: [PATCH 39/42] fixed handling of fursettings and representation paths --- pype/plugins/maya/load/load_yeti_cache.py | 35 +++++++++++++++---- .../maya/publish/collect_yeti_cache.py | 4 +++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/pype/plugins/maya/load/load_yeti_cache.py b/pype/plugins/maya/load/load_yeti_cache.py index a1793cd67d..286b154ca2 100644 --- a/pype/plugins/maya/load/load_yeti_cache.py +++ b/pype/plugins/maya/load/load_yeti_cache.py @@ -6,10 +6,11 @@ from collections import defaultdict from maya import cmds -from avalon import api +from avalon import api, io from avalon.maya import lib as avalon_lib, pipeline from pype.maya import lib from pypeapp import config +from pprint import pprint class YetiCacheLoader(api.Loader): @@ -101,12 +102,26 @@ class YetiCacheLoader(api.Loader): def update(self, container, representation): + io.install() namespace = container["namespace"] container_node = container["objectName"] + # import web_pdb; web_pdb.set_trace() + + fur_settings = io.find_one( + {"parent": representation["parent"], "name": "fursettings"} + ) + + pprint({"parent": representation["parent"], "name": "fursettings"}) + pprint(fur_settings) + assert fur_settings is not None, ( + "cannot find fursettings representation" + ) + + settings_fname = api.get_representation_path(fur_settings) path = api.get_representation_path(representation) # Get all node data - fname, ext = os.path.splitext(path) - settings_fname = "{}.fursettings".format(fname) + # fname, ext = os.path.splitext(path) + # settings_fname = "{}.fursettings".format(fname) with open(settings_fname, "r") as fp: settings = json.load(fp) @@ -147,13 +162,14 @@ class YetiCacheLoader(api.Loader): cmds.delete(to_remove) + # replace frame in filename with %04d + RE_frame = re.compile(r"(\d+)(\.fur)$") + file_name = re.sub(RE_frame, r"%04d\g<2>", os.path.basename(path)) for cb_id, data in meta_data_lookup.items(): # Update cache file name - file_name = data["name"].replace(":", "_") - cache_file_path = "{}.%04d.fur".format(file_name) data["attrs"]["cacheFileName"] = os.path.join( - path, cache_file_path) + os.path.dirname(path), file_name) if cb_id not in scene_lookup: @@ -197,6 +213,13 @@ class YetiCacheLoader(api.Loader): yeti_node = yeti_nodes[0] for attr, value in data["attrs"].items(): + # import web_pdb; web_pdb.set_trace() + # handle empty attribute strings. Those are reported + # as None, so their type is NoneType and this is not + # supported on attributes in Maya. We change it to + # empty string. + if value is None: + value = "" lib.set_attribute(attr, value, yeti_node) cmds.setAttr("{}.representation".format(container_node), diff --git a/pype/plugins/maya/publish/collect_yeti_cache.py b/pype/plugins/maya/publish/collect_yeti_cache.py index 2365162c05..c5300ff0ee 100644 --- a/pype/plugins/maya/publish/collect_yeti_cache.py +++ b/pype/plugins/maya/publish/collect_yeti_cache.py @@ -49,6 +49,10 @@ class CollectYetiCache(pyblish.api.InstancePlugin): attr_data = {} for attr in SETTINGS: current = cmds.getAttr("%s.%s" % (shape, attr)) + # change None to empty string as Maya doesn't support + # NoneType in attributes + if current is None: + current = "" attr_data[attr] = current # Get transform data From 4bd3d0652e9b56ccbdf1c929d0e05c891b3ac666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= <33513211+antirotor@users.noreply.github.com> Date: Fri, 3 Apr 2020 19:54:14 +0200 Subject: [PATCH 40/42] shutting up hound --- pype/plugins/maya/publish/validate_rig_output_ids.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pype/plugins/maya/publish/validate_rig_output_ids.py b/pype/plugins/maya/publish/validate_rig_output_ids.py index b6b3735196..89cd37fe64 100644 --- a/pype/plugins/maya/publish/validate_rig_output_ids.py +++ b/pype/plugins/maya/publish/validate_rig_output_ids.py @@ -38,7 +38,8 @@ class ValidateRigOutputIds(pyblish.api.InstancePlugin): if compute: out_set = next(x for x in instance if x.endswith("out_SET")) instance_nodes = pc.sets(out_set, query=True) - instance_nodes.extend([x.getShape() for x in instance_nodes if x.getShape()]) + instance_nodes.extend( + [x.getShape() for x in instance_nodes if x.getShape()]) scene_nodes = pc.ls(type="transform") + pc.ls(type="mesh") scene_nodes = set(scene_nodes) - set(instance_nodes) From 3555a008ee8a38461ffb77fcbce04387cb8d8616 Mon Sep 17 00:00:00 2001 From: Milan Kolar Date: Mon, 6 Apr 2020 13:18:13 +0200 Subject: [PATCH 41/42] revert metadata root replacement --- pype/plugins/global/publish/collect_rendered_files.py | 3 --- pype/plugins/global/publish/submit_publish_job.py | 1 - 2 files changed, 4 deletions(-) diff --git a/pype/plugins/global/publish/collect_rendered_files.py b/pype/plugins/global/publish/collect_rendered_files.py index 9f4c84ec07..8ecf7ba156 100644 --- a/pype/plugins/global/publish/collect_rendered_files.py +++ b/pype/plugins/global/publish/collect_rendered_files.py @@ -84,9 +84,6 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin): session_set = False for path in paths: - path = path.format(**{ - "root": os.environ["PYPE_STUDIO_PROJECTS_PATH"] - }) data = self._load_json(path) if not session_set: self.log.info("Setting session using data from file") diff --git a/pype/plugins/global/publish/submit_publish_job.py b/pype/plugins/global/publish/submit_publish_job.py index cac808b0b0..a6f2d5d79b 100644 --- a/pype/plugins/global/publish/submit_publish_job.py +++ b/pype/plugins/global/publish/submit_publish_job.py @@ -195,7 +195,6 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin): mount_root = os.path.normpath(os.environ["PYPE_STUDIO_PROJECTS_MOUNT"]) network_root = os.environ["PYPE_STUDIO_PROJECTS_PATH"] metadata_path = metadata_path.replace(mount_root, network_root) - metadata_path = metadata_path.replace(network_root, "{root}") # Generate the payload for Deadline submission payload = { From 05b33a20ce2e9cd905a92665f0f9f2339d1aedc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Samohel?= Date: Wed, 8 Apr 2020 11:45:51 +0200 Subject: [PATCH 42/42] code cleanup --- pype/plugins/maya/load/load_yeti_cache.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pype/plugins/maya/load/load_yeti_cache.py b/pype/plugins/maya/load/load_yeti_cache.py index 286b154ca2..412c2bd558 100644 --- a/pype/plugins/maya/load/load_yeti_cache.py +++ b/pype/plugins/maya/load/load_yeti_cache.py @@ -105,7 +105,6 @@ class YetiCacheLoader(api.Loader): io.install() namespace = container["namespace"] container_node = container["objectName"] - # import web_pdb; web_pdb.set_trace() fur_settings = io.find_one( {"parent": representation["parent"], "name": "fursettings"} @@ -120,8 +119,6 @@ class YetiCacheLoader(api.Loader): settings_fname = api.get_representation_path(fur_settings) path = api.get_representation_path(representation) # Get all node data - # fname, ext = os.path.splitext(path) - # settings_fname = "{}.fursettings".format(fname) with open(settings_fname, "r") as fp: settings = json.load(fp) @@ -213,7 +210,6 @@ class YetiCacheLoader(api.Loader): yeti_node = yeti_nodes[0] for attr, value in data["attrs"].items(): - # import web_pdb; web_pdb.set_trace() # handle empty attribute strings. Those are reported # as None, so their type is NoneType and this is not # supported on attributes in Maya. We change it to