From 397ecb529e2a0524435055cfaedb5f465fa1a103 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 17:46:35 +0200 Subject: [PATCH 01/32] nuke validate backdrop with help --- .../publish/help/validate_backdrop.xml | 36 +++++++++++++++++++ .../nuke/plugins/publish/validate_backdrop.py | 19 ++++++++-- 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_backdrop.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_backdrop.xml b/openpype/hosts/nuke/plugins/publish/help/validate_backdrop.xml new file mode 100644 index 0000000000..ab1b650773 --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_backdrop.xml @@ -0,0 +1,36 @@ + + + + Found multiple outputs + +## Invalid output amount + +Backdrop is having more than one outgoing connections. + +### How to repair? + +1. Use button `Center node in node graph` and navigate to the backdrop. +2. Reorganize nodes the way only one outgoing connection is present. +3. Hit reload button on the publisher. + + +### How could this happen? + +More than one node, which are found above the backdrop, are linked downstream or more output connections from a node also linked downstream. + + + + Empty backdrop + +## Invalid empty backdrop + +Backdrop is empty and no nodes are found above it. + +### How to repair? + +1. Use button `Center node in node graph` and navigate to the backdrop. +2. Add any node above it or delete it. +3. Hit reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py index e2843d146e..2a0d3309a0 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py @@ -1,6 +1,7 @@ import nuke import pyblish from openpype.hosts.nuke.api.lib import maintained_selection +from openpype.pipeline import PublishXmlValidationError class SelectCenterInNodeGraph(pyblish.api.Action): @@ -63,8 +64,20 @@ class ValidateBackdrop(pyblish.api.InstancePlugin): msg_multiple_outputs = ( "Only one outcoming connection from " "\"{}\" is allowed").format(instance.data["name"]) - assert len(connections_out.keys()) <= 1, msg_multiple_outputs - msg_no_content = "No content on backdrop node: \"{}\"".format( + if len(connections_out.keys()) > 1: + raise PublishXmlValidationError( + self, + msg_multiple_outputs, + "multiple_outputs" + ) + + msg_no_nodes = "No content on backdrop node: \"{}\"".format( instance.data["name"]) - assert len(instance) > 1, msg_no_content + + if len(instance) == 0: + raise PublishXmlValidationError( + self, + msg_no_nodes, + "no_nodes" + ) From d097503f4de4828d4a30071769a26328a71f90f9 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 17:54:22 +0200 Subject: [PATCH 02/32] nuke validate write nodes with help --- .../publish/help/validate_write_nodes.xml | 17 ++++++++++++++ .../plugins/publish/validate_write_nodes.py | 22 +++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml new file mode 100644 index 0000000000..d209329434 --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml @@ -0,0 +1,17 @@ + + + + Knobs values + +## Invalid node's knobs values + +Following write node knobs needs to be repaired: +{xml_msg} + +### How to repair? + +1. Use Repair button. +3. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index c0d5c8f402..94dabecc97 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -1,10 +1,10 @@ -import os import pyblish.api -import openpype.utils +from openpype.api import get_errored_instances_from_context from openpype.hosts.nuke.api.lib import ( get_write_node_template_attr, get_node_path ) +from openpype.pipeline import PublishXmlValidationError @pyblish.api.log @@ -14,7 +14,7 @@ class RepairNukeWriteNodeAction(pyblish.api.Action): icon = "wrench" def process(self, context, plugin): - instances = openpype.utils.filter_instances(context, plugin) + instances = get_errored_instances_from_context(context) for instance in instances: node = instance[1] @@ -60,13 +60,17 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): self.log.info(check) - msg = "Node's attribute `{0}` is not correct!\n" \ - "\nCorrect: `{1}` \n\nWrong: `{2}` \n\n" + msg = "Write node's knobs values are not correct!\n" + msg_add = "Knob `{0}` Correct: `{1}` Wrong: `{2}` \n" + xml_msg = "" if check: - print_msg = "" + dbg_msg = msg for item in check: - print_msg += msg.format(item[0], item[1], item[2]) - print_msg += "`RMB` click to the validator and `A` to fix!" + _msg_add = msg_add.format(item[0], item[1], item[2]) + dbg_msg += _msg_add + xml_msg += _msg_add - assert not check, print_msg + raise PublishXmlValidationError( + self, dbg_msg, {"xml_msg": xml_msg} + ) From bdf8c158e5877b1f2bfa08eb8e766e339b52867a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Dec 2021 14:42:25 +0100 Subject: [PATCH 03/32] nuke adding better docstring --- openpype/hosts/nuke/plugins/publish/validate_write_nodes.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index 94dabecc97..069c6f4d8c 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -25,7 +25,11 @@ class RepairNukeWriteNodeAction(pyblish.api.Action): class ValidateNukeWriteNode(pyblish.api.InstancePlugin): - """ Validates file output. """ + """ Validate Write node's knobs. + + Compare knobs on write node inside the render group + with settings. At the moment supporting only `file` knob. + """ order = pyblish.api.ValidatorOrder optional = True From 1a86a2e2655e81e2633841bf26935d31f42a888a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 17:56:07 +0200 Subject: [PATCH 04/32] nuke validate gizmo with help --- .../plugins/publish/help/validate_gizmo.xml | 36 +++++++++++++++++++ .../nuke/plugins/publish/validate_gizmo.py | 31 +++++++++++----- 2 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_gizmo.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_gizmo.xml b/openpype/hosts/nuke/plugins/publish/help/validate_gizmo.xml new file mode 100644 index 0000000000..f39a41a4f9 --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_gizmo.xml @@ -0,0 +1,36 @@ + + + + Found multiple outputs + +## Invalid amount of Output nodes + +Group node `{node_name}` is having more than one Output node. + +### How to repair? + +1. Use button `Open Group`. +2. Remove redundant Output node. +3. Hit reload button on the publisher. + + +### How could this happen? + +Perhaps you had created exciently more than one Output node. + + + + Missing Input nodes + +## Missing Input nodes + +Make sure there is at least one connected Input node inside the group node with name `{node_name}` + +### How to repair? + +1. Use button `Open Group`. +2. Add at least one Input node and connect to other nodes. +3. Hit reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_gizmo.py b/openpype/hosts/nuke/plugins/publish/validate_gizmo.py index d0d930f50c..2321bd1fd4 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_gizmo.py +++ b/openpype/hosts/nuke/plugins/publish/validate_gizmo.py @@ -1,6 +1,7 @@ -import nuke import pyblish -from openpype.hosts.nuke.api.lib import maintained_selection +from openpype.pipeline import PublishXmlValidationError +from openpype.hosts.nuke.api import maintained_selection +import nuke class OpenFailedGroupNode(pyblish.api.Action): @@ -8,7 +9,7 @@ class OpenFailedGroupNode(pyblish.api.Action): Centering failed instance node in node grap """ - label = "Open Gizmo in Node Graph" + label = "Open Group" icon = "wrench" on = "failed" @@ -48,11 +49,23 @@ class ValidateGizmo(pyblish.api.InstancePlugin): with grpn: connections_out = nuke.allNodes('Output') - msg_multiple_outputs = "Only one outcoming connection from " - "\"{}\" is allowed".format(instance.data["name"]) - assert len(connections_out) <= 1, msg_multiple_outputs + msg_multiple_outputs = ( + "Only one outcoming connection from " + "\"{}\" is allowed").format(instance.data["name"]) + + if len(connections_out) > 1: + raise PublishXmlValidationError( + self, msg_multiple_outputs, "multiple_outputs", + {"node_name": grpn["name"].value()} + ) connections_in = nuke.allNodes('Input') - msg_missing_inputs = "At least one Input node has to be used in: " - "\"{}\"".format(instance.data["name"]) - assert len(connections_in) >= 1, msg_missing_inputs + msg_missing_inputs = ( + "At least one Input node has to be inside Group: " + "\"{}\"").format(instance.data["name"]) + + if len(connections_in) == 0: + raise PublishXmlValidationError( + self, msg_missing_inputs, "no_inputs", + {"node_name": grpn["name"].value()} + ) From 0666bce2be03be03e9a4ff73ff48ee0d36343735 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 17:58:33 +0200 Subject: [PATCH 05/32] nuke validate asset name with help rename plugin, fix order on how to fix in validate write nodes xml --- .../publish/help/validate_asset_name.xml | 18 ++++++++ .../publish/help/validate_write_nodes.xml | 2 +- ...e_in_context.py => validate_asset_name.py} | 43 ++++++++++++------- 3 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml rename openpype/hosts/nuke/plugins/publish/{validate_instance_in_context.py => validate_asset_name.py} (75%) diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml b/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml new file mode 100644 index 0000000000..7ea552597a --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml @@ -0,0 +1,18 @@ + + + + Shot/Asset mame + +## Invalid Shot/Asset name in subset + +Following Node with name `{node_name}`: +Is in context of `{context_asset}` but Node _asset_ knob is set as `{asset}`. + +### How to repair? + +1. Either use Repair or Select button. +2. If you chose Select then rename asset knob to correct name. +3. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml index d209329434..c1f59a94f8 100644 --- a/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml +++ b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml @@ -11,7 +11,7 @@ Following write node knobs needs to be repaired: ### How to repair? 1. Use Repair button. -3. Hit Reload button on the publisher. +2. Hit Reload button on the publisher. \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_instance_in_context.py b/openpype/hosts/nuke/plugins/publish/validate_asset_name.py similarity index 75% rename from openpype/hosts/nuke/plugins/publish/validate_instance_in_context.py rename to openpype/hosts/nuke/plugins/publish/validate_asset_name.py index 842f74b6f6..f9adac81f8 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_instance_in_context.py +++ b/openpype/hosts/nuke/plugins/publish/validate_asset_name.py @@ -3,20 +3,17 @@ from __future__ import absolute_import import nuke - import pyblish.api import openpype.api -from openpype.hosts.nuke.api.lib import ( - recreate_instance, - reset_selection, - select_nodes -) +import openpype.hosts.nuke.api.lib as nlib +import openpype.hosts.nuke.api as nuke_api +from openpype.pipeline import PublishXmlValidationError class SelectInvalidInstances(pyblish.api.Action): """Select invalid instances in Outliner.""" - label = "Select Instances" + label = "Select" icon = "briefcase" on = "failed" @@ -50,12 +47,12 @@ class SelectInvalidInstances(pyblish.api.Action): self.deselect() def select(self, instances): - select_nodes( + nlib.select_nodes( [nuke.toNode(str(x)) for x in instances] ) def deselect(self): - reset_selection() + nlib.reset_selection() class RepairSelectInvalidInstances(pyblish.api.Action): @@ -85,12 +82,12 @@ class RepairSelectInvalidInstances(pyblish.api.Action): context_asset = context.data["assetEntity"]["name"] for instance in instances: origin_node = instance[0] - recreate_instance( + nuke_api.lib.recreate_instance( origin_node, avalon_data={"asset": context_asset} ) -class ValidateInstanceInContext(pyblish.api.InstancePlugin): +class ValidateCorrectAssetName(pyblish.api.InstancePlugin): """Validator to check if instance asset match context asset. When working in per-shot style you always publish data in context of @@ -99,15 +96,29 @@ class ValidateInstanceInContext(pyblish.api.InstancePlugin): Action on this validator will select invalid instances in Outliner. """ - order = openpype.api.ValidateContentsOrder - label = "Instance in same Context" + label = "Validate correct asset name" hosts = ["nuke"] - actions = [SelectInvalidInstances, RepairSelectInvalidInstances] + actions = [ + SelectInvalidInstances, + RepairSelectInvalidInstances + ] optional = True def process(self, instance): asset = instance.data.get("asset") context_asset = instance.context.data["assetEntity"]["name"] - msg = "{} has asset {}".format(instance.name, asset) - assert asset == context_asset, msg + + msg = ( + "Instance `{}` has wrong shot/asset name:\n" + "Correct: `{}` | Wrong: `{}`").format( + instance.name, asset, context_asset) + + if asset != context_asset: + PublishXmlValidationError( + self, msg, formatting_data={ + "node_name": instance[0]["name"].value(), + "wrong_name": asset, + "correct_name": context_asset + } + ) From af3623c4dc3626ee474dd7606ac01a757323787a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 18:00:36 +0200 Subject: [PATCH 06/32] nuke fixes on validation and precollect --- .../plugins/publish/help/validate_asset_name.xml | 2 +- .../nuke/plugins/publish/validate_asset_name.py | 5 ++++- .../hosts/nuke/plugins/publish/validate_backdrop.py | 12 +++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml b/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml index 7ea552597a..1097909a5f 100644 --- a/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml +++ b/openpype/hosts/nuke/plugins/publish/help/validate_asset_name.xml @@ -6,7 +6,7 @@ ## Invalid Shot/Asset name in subset Following Node with name `{node_name}`: -Is in context of `{context_asset}` but Node _asset_ knob is set as `{asset}`. +Is in context of `{correct_name}` but Node _asset_ knob is set as `{wrong_name}`. ### How to repair? diff --git a/openpype/hosts/nuke/plugins/publish/validate_asset_name.py b/openpype/hosts/nuke/plugins/publish/validate_asset_name.py index f9adac81f8..7647471f8a 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_asset_name.py +++ b/openpype/hosts/nuke/plugins/publish/validate_asset_name.py @@ -36,6 +36,7 @@ class SelectInvalidInstances(pyblish.api.Action): instances = pyblish.api.instances_by_plugin(failed, plugin) if instances: + self.deselect() self.log.info( "Selecting invalid nodes: %s" % ", ".join( [str(x) for x in instances] @@ -114,8 +115,10 @@ class ValidateCorrectAssetName(pyblish.api.InstancePlugin): "Correct: `{}` | Wrong: `{}`").format( instance.name, asset, context_asset) + self.log.debug(msg) + if asset != context_asset: - PublishXmlValidationError( + raise PublishXmlValidationError( self, msg, formatting_data={ "node_name": instance[0]["name"].value(), "wrong_name": asset, diff --git a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py index 2a0d3309a0..17dc79dc56 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_backdrop.py +++ b/openpype/hosts/nuke/plugins/publish/validate_backdrop.py @@ -48,8 +48,9 @@ class SelectCenterInNodeGraph(pyblish.api.Action): @pyblish.api.log class ValidateBackdrop(pyblish.api.InstancePlugin): - """Validate amount of nodes on backdrop node in case user - forgotten to add nodes above the publishing backdrop node""" + """ Validate amount of nodes on backdrop node in case user + forgoten to add nodes above the publishing backdrop node. + """ order = pyblish.api.ValidatorOrder optional = True @@ -75,7 +76,12 @@ class ValidateBackdrop(pyblish.api.InstancePlugin): msg_no_nodes = "No content on backdrop node: \"{}\"".format( instance.data["name"]) - if len(instance) == 0: + self.log.debug( + "Amount of nodes on instance: {}".format( + len(instance)) + ) + + if len(instance) == 1: raise PublishXmlValidationError( self, msg_no_nodes, From 44bd543d131e3b60be44fc79004e8487882ca61c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Dec 2021 18:28:30 +0100 Subject: [PATCH 07/32] nuke: fixing name for validate asset name --- openpype/settings/defaults/project_settings/nuke.json | 2 +- .../schemas/projects_schema/schemas/schema_nuke_publish.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index 33ddc2f251..fb1e475e9f 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -91,7 +91,7 @@ "write" ] }, - "ValidateInstanceInContext": { + "ValidateCorrectAssetName": { "enabled": true, "optional": true, "active": true diff --git a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json index 04df957d67..5635f871d5 100644 --- a/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json +++ b/openpype/settings/entities/schemas/projects_schema/schemas/schema_nuke_publish.json @@ -61,8 +61,8 @@ "name": "template_publish_plugin", "template_data": [ { - "key": "ValidateInstanceInContext", - "label": "Validate Instance In Context" + "key": "ValidateCorrectAssetName", + "label": "Validate Correct Asset name" } ] }, From e2b2bdc15d5f919793848e15b3b2fb2f00c2aec5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Dec 2021 15:29:49 +0100 Subject: [PATCH 08/32] nuke validate knobs with help --- .../nuke/plugins/publish/help/validate_knobs.xml | 16 ++++++++++++++++ .../hosts/nuke/plugins/publish/validate_knobs.py | 8 +++++--- .../nuke/plugins/publish/validate_write_nodes.py | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml b/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml new file mode 100644 index 0000000000..cb5494729b --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml @@ -0,0 +1,16 @@ + + + + Knobs value + +## Invalid node's knobs values + +Following node knobs needs to be repaired: + +### How to repair? + +1. Use Repair button. +2. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_knobs.py b/openpype/hosts/nuke/plugins/publish/validate_knobs.py index d290ff4541..d20051a9d5 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_knobs.py +++ b/openpype/hosts/nuke/plugins/publish/validate_knobs.py @@ -2,6 +2,7 @@ import nuke import pyblish.api import openpype.api +from openpype.pipeline import PublishXmlValidationError class ValidateKnobs(pyblish.api.ContextPlugin): @@ -27,11 +28,12 @@ class ValidateKnobs(pyblish.api.ContextPlugin): optional = True def process(self, context): - invalid = self.get_invalid(context, compute=True) if invalid: - raise RuntimeError( - "Found knobs with invalid values:\n{}".format(invalid) + raise PublishXmlValidationError( + self, + "Found knobs with invalid values:\n{}".format(invalid), + formatting_data={} ) @classmethod diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index 069c6f4d8c..f8d8393730 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -76,5 +76,5 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): xml_msg += _msg_add raise PublishXmlValidationError( - self, dbg_msg, {"xml_msg": xml_msg} + self, dbg_msg, formatting_data={"xml_msg": xml_msg} ) From 447742506dcf05301c3818d3ac154c0dd4e25d8d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 21:04:45 +0200 Subject: [PATCH 09/32] Nuke: improving knob validator with p3 compatibility --- openpype/hosts/nuke/plugins/publish/validate_knobs.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_knobs.py b/openpype/hosts/nuke/plugins/publish/validate_knobs.py index d20051a9d5..24723edc7a 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_knobs.py +++ b/openpype/hosts/nuke/plugins/publish/validate_knobs.py @@ -1,5 +1,5 @@ import nuke - +import six import pyblish.api import openpype.api from openpype.pipeline import PublishXmlValidationError @@ -64,7 +64,7 @@ class ValidateKnobs(pyblish.api.ContextPlugin): knobs = {} for family in families: for preset in cls.knobs[family]: - knobs.update({preset: cls.knobs[family][preset]}) + knobs[preset] = cls.knobs[family][preset] # Get invalid knobs. nodes = [] @@ -73,8 +73,7 @@ class ValidateKnobs(pyblish.api.ContextPlugin): nodes.append(node) if node.Class() == "Group": node.begin() - for i in nuke.allNodes(): - nodes.append(i) + nodes.extend(iter(nuke.allNodes())) node.end() for node in nodes: @@ -101,7 +100,9 @@ class ValidateKnobs(pyblish.api.ContextPlugin): def repair(cls, instance): invalid = cls.get_invalid(instance) for data in invalid: - if isinstance(data["expected"], unicode): + # TODO: will need to improve type definitions + # with the new settings for knob types + if isinstance(data["expected"], six.text_type): data["knob"].setValue(str(data["expected"])) continue From 568ce1858163a79ad8b63db78c72a5f28bd77a63 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Dec 2021 20:36:49 +0100 Subject: [PATCH 10/32] fixing validate knobs plugin --- .../hosts/nuke/plugins/publish/help/validate_knobs.xml | 2 ++ openpype/hosts/nuke/plugins/publish/validate_knobs.py | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml b/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml index cb5494729b..76c184f653 100644 --- a/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml +++ b/openpype/hosts/nuke/plugins/publish/help/validate_knobs.xml @@ -7,6 +7,8 @@ Following node knobs needs to be repaired: +{invalid_items} + ### How to repair? 1. Use Repair button. diff --git a/openpype/hosts/nuke/plugins/publish/validate_knobs.py b/openpype/hosts/nuke/plugins/publish/validate_knobs.py index 24723edc7a..6df0afd5ba 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_knobs.py +++ b/openpype/hosts/nuke/plugins/publish/validate_knobs.py @@ -30,10 +30,16 @@ class ValidateKnobs(pyblish.api.ContextPlugin): def process(self, context): invalid = self.get_invalid(context, compute=True) if invalid: + invalid_items = [ + ("Node __{node_name}__ with knob _{label}_ " + "expecting _{expected}_, " + "but is set to _{current}_").format(**i) + for i in invalid] raise PublishXmlValidationError( self, "Found knobs with invalid values:\n{}".format(invalid), - formatting_data={} + formatting_data={ + "invalid_items": "\n".join(invalid_items)} ) @classmethod @@ -85,6 +91,7 @@ class ValidateKnobs(pyblish.api.ContextPlugin): if node[knob].value() != expected: invalid_knobs.append( { + "node_name": node.name(), "knob": node[knob], "name": node[knob].name(), "label": node[knob].label(), From d5f5ba5bbfe361349503b0b24c4b0bc06450f796 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 3 Jan 2022 17:40:46 +0100 Subject: [PATCH 11/32] nuke validate output resolution with help --- .../help/validate_output_resolution.xml | 16 +++ .../publish/validate_output_resolution.py | 123 ++++++++++-------- 2 files changed, 85 insertions(+), 54 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_output_resolution.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_output_resolution.xml b/openpype/hosts/nuke/plugins/publish/help/validate_output_resolution.xml new file mode 100644 index 0000000000..08a88a993e --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_output_resolution.xml @@ -0,0 +1,16 @@ + + + + Output format + +## Invalid format setting + +Either the Reformat node inside of the render group is missing or the Reformat node output format knob is not set to `root.format`. + +### How to repair? + +1. Use Repair button. +2. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py index 27094b8d74..dbd388c2e6 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py +++ b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py @@ -1,43 +1,9 @@ -import nuke import pyblish.api - - -class RepairWriteResolutionDifference(pyblish.api.Action): - - label = "Repair" - icon = "wrench" - on = "failed" - - def process(self, context, plugin): - - # Get the errored instances - failed = [] - for result in context.data["results"]: - if (result["error"] is not None and result["instance"] is not None - and result["instance"] not in failed): - failed.append(result["instance"]) - - # Apply pyblish.logic to get the instances for the plug-in - instances = pyblish.api.instances_by_plugin(failed, plugin) - - for instance in instances: - reformat = instance[0].dependencies()[0] - if reformat.Class() != "Reformat": - reformat = nuke.nodes.Reformat(inputs=[instance[0].input(0)]) - - xpos = instance[0].xpos() - ypos = instance[0].ypos() - 26 - - dependent_ypos = instance[0].dependencies()[0].ypos() - if (instance[0].ypos() - dependent_ypos) <= 51: - xpos += 110 - - reformat.setXYpos(xpos, ypos) - - instance[0].setInput(0, reformat) - - reformat["resize"].setValue("none") +import openpype.api +import avalon.nuke.lib as anlib +from openpype.pipeline import PublishXmlValidationError +import nuke class ValidateOutputResolution(pyblish.api.InstancePlugin): @@ -52,27 +18,76 @@ class ValidateOutputResolution(pyblish.api.InstancePlugin): families = ["render", "render.local", "render.farm"] label = "Write Resolution" hosts = ["nuke"] - actions = [RepairWriteResolutionDifference] + actions = [openpype.api.RepairAction] + + missing_msg = "Missing Reformat node in render group node" + resolution_msg = "Reformat is set to wrong format" def process(self, instance): + invalid = self.get_invalid(instance) + if invalid: + raise PublishXmlValidationError(self, invalid) - # Skip bounding box check if a reformat node exists. - if instance[0].dependencies()[0].Class() == "Reformat": - return + @classmethod + def get_reformat(cls, instance): + reformat = None + for inode in instance: + if inode.Class() != "Reformat": + continue + reformat = inode - msg = "Bounding box is outside the format." - assert self.check_resolution(instance), msg + return reformat - def check_resolution(self, instance): - node = instance[0] + @classmethod + def get_invalid(cls, instance): + def _check_resolution(instance, reformat): + root_width = instance.data["resolutionWidth"] + root_height = instance.data["resolutionHeight"] - root_width = instance.data["resolutionWidth"] - root_height = instance.data["resolutionHeight"] + write_width = reformat.format().width() + write_height = reformat.format().height() - write_width = node.format().width() - write_height = node.format().height() + if (root_width != write_width) or (root_height != write_height): + return None + else: + return True - if (root_width != write_width) or (root_height != write_height): - return None - else: - return True + # check if reformat is in render node + reformat = cls.get_reformat(instance) + if not reformat: + return cls.missing_msg + + # check if reformat is set to correct root format + correct_format = _check_resolution(instance, reformat) + if not correct_format: + return cls.resolution_msg + + + @classmethod + def repair(cls, instance): + invalid = cls.get_invalid(instance) + grp_node = instance[0] + + if cls.missing_msg == invalid: + # make sure we are inside of the group node + with grp_node: + # find input node and select it + input = None + for inode in instance: + if inode.Class() != "Input": + continue + input = inode + + # add reformat node under it + with anlib.maintained_selection(): + input['selected'].setValue(True) + _rfn = nuke.createNode("Reformat", "name Reformat01") + _rfn["resize"].setValue(0) + _rfn["black_outside"].setValue(1) + + cls.log.info("I am adding reformat node") + + if cls.resolution_msg == invalid: + reformat = cls.get_reformat(instance) + reformat["format"].setValue(nuke.root()["format"].value()) + cls.log.info("I am fixing reformat to root.format") \ No newline at end of file From 01ba3d1c8a21b7ae2dd13daff67b30969997b8b5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 25 May 2022 21:10:41 +0200 Subject: [PATCH 12/32] Nuke: validator ditch avalon dependency --- .../plugins/publish/validate_output_resolution.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py index dbd388c2e6..710adde069 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py +++ b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py @@ -1,7 +1,7 @@ import pyblish.api import openpype.api -import avalon.nuke.lib as anlib +from openpype.hosts.nuke.api import maintained_selection from openpype.pipeline import PublishXmlValidationError import nuke @@ -62,7 +62,6 @@ class ValidateOutputResolution(pyblish.api.InstancePlugin): if not correct_format: return cls.resolution_msg - @classmethod def repair(cls, instance): invalid = cls.get_invalid(instance) @@ -72,15 +71,15 @@ class ValidateOutputResolution(pyblish.api.InstancePlugin): # make sure we are inside of the group node with grp_node: # find input node and select it - input = None + _input = None for inode in instance: if inode.Class() != "Input": continue - input = inode + _input = inode # add reformat node under it - with anlib.maintained_selection(): - input['selected'].setValue(True) + with maintained_selection(): + _input['selected'].setValue(True) _rfn = nuke.createNode("Reformat", "name Reformat01") _rfn["resize"].setValue(0) _rfn["black_outside"].setValue(1) From b9e16e87f9d2b26861b5a33e1bba502ffdfafeba Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 13:07:39 +0200 Subject: [PATCH 13/32] Nuke: proxy mode validator refactory to new publisher --- .../plugins/publish/help/validate_proxy_mode.xml | 16 ++++++++++++++++ .../nuke/plugins/publish/validate_proxy_mode.py | 8 ++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_proxy_mode.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_proxy_mode.xml b/openpype/hosts/nuke/plugins/publish/help/validate_proxy_mode.xml new file mode 100644 index 0000000000..6fe5d5d43e --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_proxy_mode.xml @@ -0,0 +1,16 @@ + + + + Proxy mode + +## Invalid proxy mode value + +Nuke is set to use Proxy. This is not supported by publisher. + +### How to repair? + +1. Use Repair button. +2. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py b/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py index 9c6ca03ffd..e5f3ae9800 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py +++ b/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py @@ -1,5 +1,6 @@ import pyblish import nuke +from openpype.pipeline import PublishXmlValidationError class FixProxyMode(pyblish.api.Action): @@ -7,7 +8,7 @@ class FixProxyMode(pyblish.api.Action): Togger off proxy switch OFF """ - label = "Proxy toggle to OFF" + label = "Repair" icon = "wrench" on = "failed" @@ -30,4 +31,7 @@ class ValidateProxyMode(pyblish.api.ContextPlugin): rootNode = nuke.root() isProxy = rootNode["proxy"].value() - assert not isProxy, "Proxy mode should be toggled OFF" + if not isProxy: + raise PublishXmlValidationError( + self, "Proxy mode should be toggled OFF" + ) From 44655d25156b1d8a1587ca898cc5aaf2a17e898e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 13:08:18 +0200 Subject: [PATCH 14/32] Nuke: improving code readability --- .../nuke/plugins/publish/validate_knobs.py | 11 ++-- .../plugins/publish/validate_write_nodes.py | 62 ++++++++++--------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_knobs.py b/openpype/hosts/nuke/plugins/publish/validate_knobs.py index 6df0afd5ba..573c25f3fe 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_knobs.py +++ b/openpype/hosts/nuke/plugins/publish/validate_knobs.py @@ -31,10 +31,13 @@ class ValidateKnobs(pyblish.api.ContextPlugin): invalid = self.get_invalid(context, compute=True) if invalid: invalid_items = [ - ("Node __{node_name}__ with knob _{label}_ " - "expecting _{expected}_, " - "but is set to _{current}_").format(**i) - for i in invalid] + ( + "Node __{node_name}__ with knob _{label}_ " + "expecting _{expected}_, " + "but is set to _{current}_" + ).format(**i) + for i in invalid + ] raise PublishXmlValidationError( self, "Found knobs with invalid values:\n{}".format(invalid), diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index f8d8393730..320307d09f 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -19,8 +19,8 @@ class RepairNukeWriteNodeAction(pyblish.api.Action): for instance in instances: node = instance[1] correct_data = get_write_node_template_attr(node) - for k, v in correct_data.items(): - node[k].setValue(v) + for key, value in correct_data.items(): + node[key].setValue(value) self.log.info("Node attributes were fixed") @@ -41,40 +41,44 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): def process(self, instance): node = instance[1] - correct_data = get_write_node_template_attr(node) + write_group_node = instance[0] + correct_data = get_write_node_template_attr(write_group_node) check = [] - for k, v in correct_data.items(): - if k is 'file': - padding = len(v.split('#')) - ref_path = get_node_path(v, padding) - n_path = get_node_path(node[k].value(), padding) - isnt = False - for i, p in enumerate(ref_path): - if str(n_path[i]) not in str(p): - if not isnt: - isnt = True - else: - continue - if isnt: - check.append([k, v, node[k].value()]) - else: - if str(node[k].value()) not in str(v): - check.append([k, v, node[k].value()]) + for key, value in correct_data.items(): + if key == 'file': + padding = len(value.split('#')) + ref_path = get_node_path(value, padding) + n_path = get_node_path(node[key].value(), padding) + is_not = False + for i, path in enumerate(ref_path): + if ( + str(n_path[i]) != str(path) + and not is_not + ): + is_not = True + if is_not: + check.append([key, value, node[key].value()]) + + elif str(node[key].value()) != str(value): + check.append([key, value, node[key].value()]) self.log.info(check) + if check: + self._make_error(check) + + def _make_error(self, check): msg = "Write node's knobs values are not correct!\n" + dbg_msg = msg msg_add = "Knob `{0}` Correct: `{1}` Wrong: `{2}` \n" xml_msg = "" - if check: - dbg_msg = msg - for item in check: - _msg_add = msg_add.format(item[0], item[1], item[2]) - dbg_msg += _msg_add - xml_msg += _msg_add + for item in check: + _msg_add = msg_add.format(item[0], item[1], item[2]) + dbg_msg += _msg_add + xml_msg += _msg_add - raise PublishXmlValidationError( - self, dbg_msg, formatting_data={"xml_msg": xml_msg} - ) + raise PublishXmlValidationError( + self, dbg_msg, formatting_data={"xml_msg": xml_msg} + ) From e33c06f95e58db53eb27edbfb85909e6643679dd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 17:26:30 +0200 Subject: [PATCH 15/32] Nuke: abstracting function for correct knob type value --- openpype/hosts/nuke/api/__init__.py | 4 ++- openpype/hosts/nuke/api/lib.py | 43 +++++++++++++++++------------ 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index b571c4098c..f7288bb287 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -26,7 +26,8 @@ from .pipeline import ( update_container, ) from .lib import ( - maintained_selection + maintained_selection, + convert_knob_value_to_correct_type ) from .utils import ( @@ -58,6 +59,7 @@ __all__ = ( "update_container", "maintained_selection", + "convert_knob_value_to_correct_type", "colorspace_exists_on_node", "get_colorspace_list" diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index ba8aa7a8db..457e5d851f 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -1528,28 +1528,35 @@ def set_node_knobs_from_settings(node, knob_settings, **kwargs): if not knob_value: continue - # first convert string types to string - # just to ditch unicode - if isinstance(knob_value, six.text_type): - knob_value = str(knob_value) - - # set correctly knob types - if knob_type == "bool": - knob_value = bool(knob_value) - elif knob_type == "decimal_number": - knob_value = float(knob_value) - elif knob_type == "number": - knob_value = int(knob_value) - elif knob_type == "text": - knob_value = knob_value - elif knob_type == "color_gui": - knob_value = color_gui_to_int(knob_value) - elif knob_type in ["2d_vector", "3d_vector", "color"]: - knob_value = [float(v) for v in knob_value] + knob_value = convert_knob_value_to_correct_type( + knob_type, knob_value) node[knob_name].setValue(knob_value) +def convert_knob_value_to_correct_type(knob_type, knob_value): + # first convert string types to string + # just to ditch unicode + if isinstance(knob_value, six.text_type): + knob_value = str(knob_value) + + # set correctly knob types + if knob_type == "bool": + knob_value = bool(knob_value) + elif knob_type == "decimal_number": + knob_value = float(knob_value) + elif knob_type == "number": + knob_value = int(knob_value) + elif knob_type == "text": + knob_value = knob_value + elif knob_type == "color_gui": + knob_value = color_gui_to_int(knob_value) + elif knob_type in ["2d_vector", "3d_vector", "color"]: + knob_value = [float(v) for v in knob_value] + + return knob_value + + def color_gui_to_int(color_gui): hex_value = ( "0x{0:0>2x}{1:0>2x}{2:0>2x}{3:0>2x}").format(*color_gui) From f8b45e078c74c64a9fc549e35429649db42b667a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 17:28:04 +0200 Subject: [PATCH 16/32] Nuke: removing obsolete code fixing family to families as Write is stored there in avalon data on node --- openpype/hosts/nuke/api/lib.py | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 457e5d851f..5d66cb2b89 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -836,29 +836,6 @@ def check_subsetname_exists(nodes, subset_name): if subset_name in read_avalon_data(n).get("subset", "")), False) - -def get_render_path(node): - ''' Generate Render path from presets regarding avalon knob data - ''' - avalon_knob_data = read_avalon_data(node) - data = {'avalon': avalon_knob_data} - - nuke_imageio_writes = get_imageio_node_setting( - node_class=avalon_knob_data["family"], - plugin_name=avalon_knob_data["creator"], - subset=avalon_knob_data["subset"] - ) - host_name = os.environ.get("AVALON_APP") - - data.update({ - "app": host_name, - "nuke_imageio_writes": nuke_imageio_writes - }) - - anatomy_filled = format_anatomy(data) - return anatomy_filled["render"]["path"].replace("\\", "/") - - def format_anatomy(data): ''' Helping function for formatting of anatomy paths @@ -2185,15 +2162,14 @@ def get_write_node_template_attr(node): avalon_knob_data = read_avalon_data(node) # get template data nuke_imageio_writes = get_imageio_node_setting( - node_class=avalon_knob_data["family"], + node_class=avalon_knob_data["families"], plugin_name=avalon_knob_data["creator"], subset=avalon_knob_data["subset"] ) + # collecting correct data - correct_data = OrderedDict({ - "file": get_render_path(node) - }) + correct_data = OrderedDict() # adding imageio knob presets for k, v in nuke_imageio_writes.items(): From 1686eaeadad906ddc8e4f20574f4af6c9e697674 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 17:29:07 +0200 Subject: [PATCH 17/32] Nuke: refactory write node validator --- .../publish/help/validate_write_nodes.xml | 1 + .../plugins/publish/validate_write_nodes.py | 86 ++++++++++++------- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml index c1f59a94f8..cdf85102bc 100644 --- a/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml +++ b/openpype/hosts/nuke/plugins/publish/help/validate_write_nodes.xml @@ -6,6 +6,7 @@ ## Invalid node's knobs values Following write node knobs needs to be repaired: + {xml_msg} ### How to repair? diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index 320307d09f..f0a7f01dfb 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -1,8 +1,10 @@ import pyblish.api from openpype.api import get_errored_instances_from_context +import openpype.hosts.nuke.api.lib as nlib from openpype.hosts.nuke.api.lib import ( get_write_node_template_attr, - get_node_path + set_node_knobs_from_settings + ) from openpype.pipeline import PublishXmlValidationError @@ -17,10 +19,17 @@ class RepairNukeWriteNodeAction(pyblish.api.Action): instances = get_errored_instances_from_context(context) for instance in instances: - node = instance[1] - correct_data = get_write_node_template_attr(node) - for key, value in correct_data.items(): - node[key].setValue(value) + write_group_node = instance[0] + # get write node from inside of group + write_node = None + for x in instance: + if x.Class() == "Write": + write_node = x + + correct_data = get_write_node_template_attr(write_group_node) + + set_node_knobs_from_settings(write_node, correct_data["knobs"]) + self.log.info("Node attributes were fixed") @@ -39,29 +48,41 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): hosts = ["nuke"] def process(self, instance): - - node = instance[1] write_group_node = instance[0] + + # get write node from inside of group + write_node = None + for x in instance: + if x.Class() == "Write": + write_node = x + + if write_node is None: + return + correct_data = get_write_node_template_attr(write_group_node) - check = [] - for key, value in correct_data.items(): - if key == 'file': - padding = len(value.split('#')) - ref_path = get_node_path(value, padding) - n_path = get_node_path(node[key].value(), padding) - is_not = False - for i, path in enumerate(ref_path): - if ( - str(n_path[i]) != str(path) - and not is_not - ): - is_not = True - if is_not: - check.append([key, value, node[key].value()]) + if correct_data: + check_knobs = correct_data["knobs"] + else: + return - elif str(node[key].value()) != str(value): - check.append([key, value, node[key].value()]) + check = [] + self.log.debug("__ write_node: {}".format( + write_node + )) + + for knob_data in check_knobs: + key = knob_data["name"] + value = knob_data["value"] + self.log.debug("__ key: {} | value: {}".format( + key, value + )) + if ( + str(write_node[key].value()) != str(value) + and key != "file" + and key != "tile_color" + ): + check.append([key, value, write_node[key].value()]) self.log.info(check) @@ -69,15 +90,16 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): self._make_error(check) def _make_error(self, check): - msg = "Write node's knobs values are not correct!\n" - dbg_msg = msg - msg_add = "Knob `{0}` Correct: `{1}` Wrong: `{2}` \n" - xml_msg = "" + # sourcery skip: merge-assign-and-aug-assign, move-assign-in-block + dbg_msg = "Write node's knobs values are not correct!\n" + msg_add = "Knob '{0}' > Correct: `{1}` > Wrong: `{2}`" - for item in check: - _msg_add = msg_add.format(item[0], item[1], item[2]) - dbg_msg += _msg_add - xml_msg += _msg_add + details = [ + msg_add.format(item[0], item[1], item[2]) + for item in check + ] + xml_msg = "
".join(details) + dbg_msg += "\n\t".join(details) raise PublishXmlValidationError( self, dbg_msg, formatting_data={"xml_msg": xml_msg} From e71653fb1672a579dfb96b2843ac55eca4de7985 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Fri, 27 May 2022 17:29:21 +0200 Subject: [PATCH 18/32] Nuke: fixing proxy mode validator --- openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py b/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py index e5f3ae9800..dac240ad19 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py +++ b/openpype/hosts/nuke/plugins/publish/validate_proxy_mode.py @@ -31,7 +31,7 @@ class ValidateProxyMode(pyblish.api.ContextPlugin): rootNode = nuke.root() isProxy = rootNode["proxy"].value() - if not isProxy: + if isProxy: raise PublishXmlValidationError( self, "Proxy mode should be toggled OFF" ) From c5258fb295df6c65d81a77a13063034a3b733db0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 12:28:43 +0200 Subject: [PATCH 19/32] nuke: refactory Missing frames validator --- .../publish/help/validate_rendered_frames.xml | 17 +++++++ .../publish/validate_rendered_frames.py | 48 ++++++++++++------- 2 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_rendered_frames.xml diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_rendered_frames.xml b/openpype/hosts/nuke/plugins/publish/help/validate_rendered_frames.xml new file mode 100644 index 0000000000..434081c269 --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_rendered_frames.xml @@ -0,0 +1,17 @@ + + + + Rendered Frames + +## Missing Rendered Frames + +Render node "{node_name}" is set to "Use existing frames", but frames are missing. + +### How to repair? + +1. Use Repair button. +2. Set different target. +2. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py index af5e8e9d27..f8e128cd26 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py +++ b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py @@ -1,7 +1,7 @@ import os import pyblish.api -from openpype.api import ValidationException import clique +from openpype.pipeline import PublishXmlValidationError @pyblish.api.log @@ -36,7 +36,7 @@ class RepairActionBase(pyblish.api.Action): class RepairCollectionActionToLocal(RepairActionBase): - label = "Repair > rerender with `Local` machine" + label = "Repair - rerender with \"Local\"" def process(self, context, plugin): instances = self.get_instance(context, plugin) @@ -44,7 +44,7 @@ class RepairCollectionActionToLocal(RepairActionBase): class RepairCollectionActionToFarm(RepairActionBase): - label = "Repair > rerender `On farm` with remote machines" + label = "Repair - rerender with \"On farm\"" def process(self, context, plugin): instances = self.get_instance(context, plugin) @@ -63,6 +63,10 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): def process(self, instance): + f_data = { + "node_name": instance[0]["name"].value() + } + for repre in instance.data["representations"]: if not repre.get("files"): @@ -71,7 +75,8 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): "Check properties of write node (group) and" "select 'Local' option in 'Publish' dropdown.") self.log.error(msg) - raise ValidationException(msg) + raise PublishXmlValidationError( + self, msg, formatting_data=f_data) if isinstance(repre["files"], str): return @@ -82,30 +87,33 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): collection = collections[0] - fstartH = instance.data["frameStartHandle"] - fendH = instance.data["frameEndHandle"] + f_start_h = instance.data["frameStartHandle"] + f_end_h = instance.data["frameEndHandle"] - frame_length = int(fendH - fstartH + 1) + frame_length = int(f_end_h - f_start_h + 1) if frame_length != 1: if len(collections) != 1: msg = "There are multiple collections in the folder" self.log.error(msg) - raise ValidationException(msg) + raise PublishXmlValidationError( + self, msg, formatting_data=f_data) if not collection.is_contiguous(): msg = "Some frames appear to be missing" self.log.error(msg) - raise ValidationException(msg) + raise PublishXmlValidationError( + self, msg, formatting_data=f_data) - collected_frames_len = int(len(collection.indexes)) + collected_frames_len = len(collection.indexes) coll_start = min(collection.indexes) coll_end = max(collection.indexes) self.log.info("frame_length: {}".format(frame_length)) self.log.info("collected_frames_len: {}".format( collected_frames_len)) - self.log.info("fstartH-fendH: {}-{}".format(fstartH, fendH)) + self.log.info("f_start_h-f_end_h: {}-{}".format( + f_start_h, f_end_h)) self.log.info( "coll_start-coll_end: {}-{}".format(coll_start, coll_end)) @@ -116,13 +124,19 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): if ("slate" in instance.data["families"]) \ and (frame_length != collected_frames_len): collected_frames_len -= 1 - fstartH += 1 + f_start_h += 1 - assert ((collected_frames_len >= frame_length) - and (coll_start <= fstartH) - and (coll_end >= fendH)), ( - "{} missing frames. Use repair to render all frames" - ).format(__name__) + if ( + collected_frames_len >= frame_length + and coll_start <= f_start_h + and coll_end >= f_end_h + ): + raise PublishXmlValidationError( + self, ( + "{} missing frames. Use repair to " + "render all frames" + ).format(__name__), formatting_data=f_data + ) instance.data["collection"] = collection From d3e982ebcf757a07d731760734ac51315454449b Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 16:49:11 +0200 Subject: [PATCH 20/32] nuke: [wip] validate script attributes --- .../help/validate_script_attributes.xml | 18 ++ .../nuke/plugins/publish/validate_script.py | 156 ------------------ .../publish/validate_script_attributes.py | 129 +++++++++++++++ .../plugins/publish/validate_write_nodes.py | 2 - 4 files changed, 147 insertions(+), 158 deletions(-) create mode 100644 openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml delete mode 100644 openpype/hosts/nuke/plugins/publish/validate_script.py create mode 100644 openpype/hosts/nuke/plugins/publish/validate_script_attributes.py diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml b/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml new file mode 100644 index 0000000000..96f8ab5d38 --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml @@ -0,0 +1,18 @@ + + + + Script attributes + +## Invalid Script attributes + +Following script root attributes need to be fixed: +{missing_attributes} + +### How to repair? + +1. Either use Repair or Select button. +2. If you chose Select then rename asset knob to correct name. +3. Hit Reload button on the publisher. + + + \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_script.py b/openpype/hosts/nuke/plugins/publish/validate_script.py deleted file mode 100644 index b8d7494b9d..0000000000 --- a/openpype/hosts/nuke/plugins/publish/validate_script.py +++ /dev/null @@ -1,156 +0,0 @@ -import pyblish.api - -from openpype.client import get_project, get_asset_by_id, get_asset_by_name -from openpype.pipeline import legacy_io - - -@pyblish.api.log -class ValidateScript(pyblish.api.InstancePlugin): - """ Validates file output. """ - - order = pyblish.api.ValidatorOrder + 0.1 - families = ["workfile"] - label = "Check script settings" - hosts = ["nuke"] - optional = True - - def process(self, instance): - ctx_data = instance.context.data - project_name = legacy_io.active_project() - asset_name = ctx_data["asset"] - # TODO repace query with using 'instance.data["assetEntity"]' - asset = get_asset_by_name(project_name, asset_name) - asset_data = asset["data"] - - # These attributes will be checked - attributes = [ - "fps", - "frameStart", - "frameEnd", - "resolutionWidth", - "resolutionHeight", - "handleStart", - "handleEnd" - ] - - # Value of these attributes can be found on parents - hierarchical_attributes = [ - "fps", - "resolutionWidth", - "resolutionHeight", - "pixelAspect", - "handleStart", - "handleEnd" - ] - - missing_attributes = [] - asset_attributes = {} - for attr in attributes: - if attr in asset_data: - asset_attributes[attr] = asset_data[attr] - - elif attr in hierarchical_attributes: - # TODO this should be probably removed - # Hierarchical attributes is not a thing since Pype 2? - - # Try to find attribute on parent - parent_id = asset['parent'] - parent_type = "project" - if asset_data['visualParent'] is not None: - parent_type = "asset" - parent_id = asset_data['visualParent'] - - value = self.check_parent_hierarchical( - project_name, parent_type, parent_id, attr - ) - if value is None: - missing_attributes.append(attr) - else: - asset_attributes[attr] = value - else: - missing_attributes.append(attr) - - # Raise error if attributes weren't found on asset in database - if len(missing_attributes) > 0: - atr = ", ".join(missing_attributes) - msg = 'Missing attributes "{}" in asset "{}"' - message = msg.format(atr, asset_name) - raise ValueError(message) - - # Get handles from database, Default is 0 (if not found) - handle_start = 0 - handle_end = 0 - if "handleStart" in asset_attributes: - handle_start = asset_attributes["handleStart"] - if "handleEnd" in asset_attributes: - handle_end = asset_attributes["handleEnd"] - - asset_attributes["fps"] = float("{0:.4f}".format( - asset_attributes["fps"])) - - # Get values from nukescript - script_attributes = { - "handleStart": ctx_data["handleStart"], - "handleEnd": ctx_data["handleEnd"], - "fps": float("{0:.4f}".format(ctx_data["fps"])), - "frameStart": ctx_data["frameStart"], - "frameEnd": ctx_data["frameEnd"], - "resolutionWidth": ctx_data["resolutionWidth"], - "resolutionHeight": ctx_data["resolutionHeight"], - "pixelAspect": ctx_data["pixelAspect"] - } - - # Compare asset's values Nukescript X Database - not_matching = [] - for attr in attributes: - self.log.debug("asset vs script attribute \"{}\": {}, {}".format( - attr, asset_attributes[attr], script_attributes[attr]) - ) - if asset_attributes[attr] != script_attributes[attr]: - not_matching.append(attr) - - # Raise error if not matching - if len(not_matching) > 0: - msg = "Attributes '{}' are not set correctly" - # Alert user that handles are set if Frame start/end not match - if ( - (("frameStart" in not_matching) or ("frameEnd" in not_matching)) and - ((handle_start > 0) or (handle_end > 0)) - ): - msg += " (`handle_start` are set to {})".format(handle_start) - msg += " (`handle_end` are set to {})".format(handle_end) - message = msg.format(", ".join(not_matching)) - raise ValueError(message) - - def check_parent_hierarchical( - self, project_name, parent_type, parent_id, attr - ): - if parent_id is None: - return None - - doc = None - if parent_type == "project": - doc = get_project(project_name) - elif parent_type == "asset": - doc = get_asset_by_id(project_name, parent_id) - - if not doc: - return None - - doc_data = doc["data"] - if attr in doc_data: - self.log.info(attr) - return doc_data[attr] - - if parent_type == "project": - return None - - parent_id = doc_data.get("visualParent") - new_parent_type = "asset" - if parent_id is None: - parent_id = doc["parent"] - new_parent_type = "project" - - return self.check_parent_hierarchical( - project_name, new_parent_type, parent_id, attr - ) diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py new file mode 100644 index 0000000000..2411c7fe4e --- /dev/null +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -0,0 +1,129 @@ +from pprint import pformat +import pyblish.api + +from openpype.client import get_project, get_asset_by_id, get_asset_by_name +from openpype.pipeline import legacy_io +from openpype.pipeline import PublishXmlValidationError +import nuke + + +@pyblish.api.log +class ValidateScriptAttributes(pyblish.api.InstancePlugin): + """ Validates file output. """ + + order = pyblish.api.ValidatorOrder + 0.1 + families = ["workfile"] + label = "Validatte script attributes" + hosts = ["nuke"] + optional = True + + def process(self, instance): + ctx_data = instance.context.data + project_name = legacy_io.active_project() + asset_name = ctx_data["asset"] + asset = get_asset_by_name(project_name, asset_name) + asset_data = asset["data"] + + # These attributes will be checked + attributes = [ + "fps", + "frameStart", + "frameEnd", + "resolutionWidth", + "resolutionHeight", + "handleStart", + "handleEnd" + ] + + asset_attributes = { + attr: asset_data[attr] + for attr in attributes + if attr in asset_data + } + + self.log.debug(pformat( + asset_attributes + )) + + handle_start = asset_attributes["handleStart"] + handle_end = asset_attributes["handleEnd"] + asset_attributes["fps"] = float("{0:.4f}".format( + asset_attributes["fps"])) + + root = nuke.root() + # Get values from nukescript + script_attributes = { + "handleStart": ctx_data["handleStart"], + "handleEnd": ctx_data["handleEnd"], + "fps": float("{0:.4f}".format(ctx_data["fps"])), + "frameStart": int(root["first_frame"].getValue()), + "frameEnd": int(root["last_frame"].getValue()), + "resolutionWidth": ctx_data["resolutionWidth"], + "resolutionHeight": ctx_data["resolutionHeight"], + "pixelAspect": ctx_data["pixelAspect"] + } + self.log.debug(pformat( + script_attributes + )) + # Compare asset's values Nukescript X Database + not_matching = [] + for attr in attributes: + self.log.debug( + "Asset vs Script attribute \"{}\": {}, {}".format( + attr, + asset_attributes[attr], + script_attributes[attr] + ) + ) + if asset_attributes[attr] != script_attributes[attr]: + not_matching.append({ + "name": attr, + "expected": asset_attributes[attr], + "actual": script_attributes[attr] + }) + + # Raise error if not matching + if not_matching: + msg = "Attributes '{}' are not set correctly" + # Alert user that handles are set if Frame start/end not match + message = msg.format(", ".join( + [at["name"] for at in not_matching])) + raise PublishXmlValidationError( + self, message, + formatting_data={ + "missing_attributes": not_matching + } + ) + + def check_parent_hierarchical( + self, project_name, parent_type, parent_id, attr + ): + if parent_id is None: + return None + + doc = None + if parent_type == "project": + doc = get_project(project_name) + elif parent_type == "asset": + doc = get_asset_by_id(project_name, parent_id) + + if not doc: + return None + + doc_data = doc["data"] + if attr in doc_data: + self.log.info(attr) + return doc_data[attr] + + if parent_type == "project": + return None + + parent_id = doc_data.get("visualParent") + new_parent_type = "asset" + if parent_id is None: + parent_id = doc["parent"] + new_parent_type = "project" + + return self.check_parent_hierarchical( + project_name, new_parent_type, parent_id, attr + ) diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index f0a7f01dfb..48dce623a9 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -1,10 +1,8 @@ import pyblish.api from openpype.api import get_errored_instances_from_context -import openpype.hosts.nuke.api.lib as nlib from openpype.hosts.nuke.api.lib import ( get_write_node_template_attr, set_node_knobs_from_settings - ) from openpype.pipeline import PublishXmlValidationError From b4b4725b5790b5ffee3b258375ef1bbfe7d17d45 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 17:57:13 +0200 Subject: [PATCH 21/32] nuke: getting testing values from script dirrectly --- .../publish/validate_script_attributes.py | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index 2411c7fe4e..d9b9a35ece 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -4,6 +4,9 @@ import pyblish.api from openpype.client import get_project, get_asset_by_id, get_asset_by_name from openpype.pipeline import legacy_io from openpype.pipeline import PublishXmlValidationError +from openpype.hosts.nuke.api.lib import ( + get_avalon_knob_data +) import nuke @@ -45,22 +48,32 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): asset_attributes )) - handle_start = asset_attributes["handleStart"] - handle_end = asset_attributes["handleEnd"] asset_attributes["fps"] = float("{0:.4f}".format( asset_attributes["fps"])) root = nuke.root() + knob_data = get_avalon_knob_data(root) + + # Get frame range + first_frame = int(root["first_frame"].getValue()) + last_frame = int(root["last_frame"].getValue()) + + handle_start = int(knob_data["handleStart"]) + handle_end = int(knob_data["handleEnd"]) + + # Get format + _format = root["format"].value() + # Get values from nukescript script_attributes = { - "handleStart": ctx_data["handleStart"], - "handleEnd": ctx_data["handleEnd"], - "fps": float("{0:.4f}".format(ctx_data["fps"])), - "frameStart": int(root["first_frame"].getValue()), - "frameEnd": int(root["last_frame"].getValue()), - "resolutionWidth": ctx_data["resolutionWidth"], - "resolutionHeight": ctx_data["resolutionHeight"], - "pixelAspect": ctx_data["pixelAspect"] + "handleStart": handle_start, + "handleEnd": handle_end, + "fps": float("{0:.4f}".format(root['fps'].value())), + "frameStart": first_frame + handle_start, + "frameEnd": last_frame - handle_end, + "resolutionWidth": _format.width(), + "resolutionHeight": _format.height(), + "pixelAspect": _format.pixelAspect() } self.log.debug(pformat( script_attributes From 62a7b1f713e636d9ffbf66de6d33d9ea0c6c32a0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 18:04:01 +0200 Subject: [PATCH 22/32] nuke: adding repair action to script attribute validator --- .../publish/validate_script_attributes.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index d9b9a35ece..605145149d 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -4,12 +4,27 @@ import pyblish.api from openpype.client import get_project, get_asset_by_id, get_asset_by_name from openpype.pipeline import legacy_io from openpype.pipeline import PublishXmlValidationError +from openpype.api import get_errored_instances_from_context from openpype.hosts.nuke.api.lib import ( - get_avalon_knob_data + get_avalon_knob_data, + WorkfileSettings ) import nuke +@pyblish.api.log +class RepairScriptAttributes(pyblish.api.Action): + label = "Repair" + on = "failed" + icon = "wrench" + + def process(self, context, plugin): + instances = get_errored_instances_from_context(context) + + self.log.debug(instances) + WorkfileSettings().set_context_settings() + + @pyblish.api.log class ValidateScriptAttributes(pyblish.api.InstancePlugin): """ Validates file output. """ @@ -19,6 +34,7 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): label = "Validatte script attributes" hosts = ["nuke"] optional = True + actions = [RepairScriptAttributes] def process(self, instance): ctx_data = instance.context.data From 907500c9e9354c47d945a1abd785f5520be26bc2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 21:26:13 +0200 Subject: [PATCH 23/32] nuke: validate script attributes finish --- .../help/validate_script_attributes.xml | 8 +- .../publish/validate_script_attributes.py | 107 ++++++++---------- 2 files changed, 49 insertions(+), 66 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml b/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml index 96f8ab5d38..871fc629ce 100644 --- a/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml +++ b/openpype/hosts/nuke/plugins/publish/help/validate_script_attributes.xml @@ -6,13 +6,13 @@ ## Invalid Script attributes Following script root attributes need to be fixed: -{missing_attributes} + +{failed_attributes} ### How to repair? -1. Either use Repair or Select button. -2. If you chose Select then rename asset knob to correct name. -3. Hit Reload button on the publisher. +1. Use Repair. +2. Hit Reload button on the publisher. \ No newline at end of file diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index 605145149d..ef89d71c5b 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -37,11 +37,18 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): actions = [RepairScriptAttributes] def process(self, instance): - ctx_data = instance.context.data + root = nuke.root() + knob_data = get_avalon_knob_data(root) project_name = legacy_io.active_project() - asset_name = ctx_data["asset"] - asset = get_asset_by_name(project_name, asset_name) - asset_data = asset["data"] + asset = get_asset_by_name( + project_name, + instance.context.data["asset"] + ) + # get asset data frame values + frame_start = asset["data"]["frameStart"] + frame_end = asset["data"]["frameEnd"] + handle_start = asset["data"]["handleStart"] + handle_end = asset["data"]["handleEnd"] # These attributes will be checked attributes = [ @@ -54,39 +61,36 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): "handleEnd" ] + # get only defined attributes from asset data asset_attributes = { - attr: asset_data[attr] + attr: asset["data"][attr] for attr in attributes - if attr in asset_data + if attr in asset["data"] } + # fix float to max 4 digints (only for evaluating) + fps_data = float("{0:.4f}".format( + asset_attributes["fps"])) + # fix frame values to include handles + asset_attributes.update({ + "frameStart": frame_start - handle_start, + "frameEnd": frame_end + handle_end, + "fps": fps_data + }) self.log.debug(pformat( asset_attributes )) - asset_attributes["fps"] = float("{0:.4f}".format( - asset_attributes["fps"])) - - root = nuke.root() - knob_data = get_avalon_knob_data(root) - - # Get frame range - first_frame = int(root["first_frame"].getValue()) - last_frame = int(root["last_frame"].getValue()) - - handle_start = int(knob_data["handleStart"]) - handle_end = int(knob_data["handleEnd"]) - # Get format _format = root["format"].value() # Get values from nukescript script_attributes = { - "handleStart": handle_start, - "handleEnd": handle_end, + "handleStart": int(knob_data["handleStart"]), + "handleEnd": int(knob_data["handleEnd"]), "fps": float("{0:.4f}".format(root['fps'].value())), - "frameStart": first_frame + handle_start, - "frameEnd": last_frame - handle_end, + "frameStart": int(root["first_frame"].getValue()), + "frameEnd": int(root["last_frame"].getValue()), "resolutionWidth": _format.width(), "resolutionHeight": _format.height(), "pixelAspect": _format.pixelAspect() @@ -94,6 +98,7 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): self.log.debug(pformat( script_attributes )) + # Compare asset's values Nukescript X Database not_matching = [] for attr in attributes: @@ -113,46 +118,24 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): # Raise error if not matching if not_matching: - msg = "Attributes '{}' are not set correctly" - # Alert user that handles are set if Frame start/end not match - message = msg.format(", ".join( - [at["name"] for at in not_matching])) + msg = "Following attributes are not set correctly: \n{}" + attrs_wrong_str = "\n".join([ + ( + "`{0}` is set to `{1}`, " + "but should be set to `{2}`" + ).format(at["name"], at["actual"], at["expected"]) + for at in not_matching + ]) + attrs_wrong_html = "
".join([ + ( + "-- __{0}__ is set to __{1}__, " + "but should be set to __{2}__" + ).format(at["name"], at["actual"], at["expected"]) + for at in not_matching + ]) raise PublishXmlValidationError( - self, message, + self, msg.format(attrs_wrong_str), formatting_data={ - "missing_attributes": not_matching + "failed_attributes": attrs_wrong_html } ) - - def check_parent_hierarchical( - self, project_name, parent_type, parent_id, attr - ): - if parent_id is None: - return None - - doc = None - if parent_type == "project": - doc = get_project(project_name) - elif parent_type == "asset": - doc = get_asset_by_id(project_name, parent_id) - - if not doc: - return None - - doc_data = doc["data"] - if attr in doc_data: - self.log.info(attr) - return doc_data[attr] - - if parent_type == "project": - return None - - parent_id = doc_data.get("visualParent") - new_parent_type = "asset" - if parent_id is None: - parent_id = doc["parent"] - new_parent_type = "project" - - return self.check_parent_hierarchical( - project_name, new_parent_type, parent_id, attr - ) From 06f338a95bf33644d84e365d01a3c4f6a68ac344 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 25 Jul 2022 21:47:47 +0200 Subject: [PATCH 24/32] nuke: making validator code nicer --- .../publish/validate_script_attributes.py | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index ef89d71c5b..d16660f272 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -1,10 +1,10 @@ from pprint import pformat import pyblish.api -from openpype.client import get_project, get_asset_by_id, get_asset_by_name +import openpype.api +from openpype.client import get_asset_by_name from openpype.pipeline import legacy_io from openpype.pipeline import PublishXmlValidationError -from openpype.api import get_errored_instances_from_context from openpype.hosts.nuke.api.lib import ( get_avalon_knob_data, WorkfileSettings @@ -12,19 +12,6 @@ from openpype.hosts.nuke.api.lib import ( import nuke -@pyblish.api.log -class RepairScriptAttributes(pyblish.api.Action): - label = "Repair" - on = "failed" - icon = "wrench" - - def process(self, context, plugin): - instances = get_errored_instances_from_context(context) - - self.log.debug(instances) - WorkfileSettings().set_context_settings() - - @pyblish.api.log class ValidateScriptAttributes(pyblish.api.InstancePlugin): """ Validates file output. """ @@ -34,7 +21,7 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): label = "Validatte script attributes" hosts = ["nuke"] optional = True - actions = [RepairScriptAttributes] + actions = [openpype.api.RepairAction] def process(self, instance): root = nuke.root() @@ -139,3 +126,8 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): "failed_attributes": attrs_wrong_html } ) + + @classmethod + def repair(cls, instance): + cls.log.debug("__ repairing instance: {}".format(instance)) + WorkfileSettings().set_context_settings() From 4a18e50352cda46e3b8de09bd7a40df15ea1384d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Thu, 28 Jul 2022 17:42:52 +0200 Subject: [PATCH 25/32] Update openpype/hosts/nuke/plugins/publish/validate_script_attributes.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- .../nuke/plugins/publish/validate_script_attributes.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index d16660f272..3907f40991 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -26,11 +26,7 @@ class ValidateScriptAttributes(pyblish.api.InstancePlugin): def process(self, instance): root = nuke.root() knob_data = get_avalon_knob_data(root) - project_name = legacy_io.active_project() - asset = get_asset_by_name( - project_name, - instance.context.data["asset"] - ) + asset = instance.data["assetEntity"] # get asset data frame values frame_start = asset["data"]["frameStart"] frame_end = asset["data"]["frameEnd"] From 6a51b4e7891829761b2c49353d17a7fc3423edcc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 28 Jul 2022 17:49:29 +0200 Subject: [PATCH 26/32] hound suggestions --- .../hosts/nuke/plugins/publish/validate_output_resolution.py | 2 +- .../hosts/nuke/plugins/publish/validate_script_attributes.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py index 710adde069..fc07e9b83b 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py +++ b/openpype/hosts/nuke/plugins/publish/validate_output_resolution.py @@ -89,4 +89,4 @@ class ValidateOutputResolution(pyblish.api.InstancePlugin): if cls.resolution_msg == invalid: reformat = cls.get_reformat(instance) reformat["format"].setValue(nuke.root()["format"].value()) - cls.log.info("I am fixing reformat to root.format") \ No newline at end of file + cls.log.info("I am fixing reformat to root.format") diff --git a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py index 3907f40991..106d7a2524 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_script_attributes.py @@ -2,8 +2,6 @@ from pprint import pformat import pyblish.api import openpype.api -from openpype.client import get_asset_by_name -from openpype.pipeline import legacy_io from openpype.pipeline import PublishXmlValidationError from openpype.hosts.nuke.api.lib import ( get_avalon_knob_data, From dd2becdb7964bf43d71368c89f7a9fdae48ce4a0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 15 Aug 2022 11:55:16 +0200 Subject: [PATCH 27/32] nuke: collect workfile adding KnownPublishErrorl when untitled --- openpype/hosts/nuke/plugins/publish/precollect_workfile.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/hosts/nuke/plugins/publish/precollect_workfile.py b/openpype/hosts/nuke/plugins/publish/precollect_workfile.py index 7349a8f424..822f405a6f 100644 --- a/openpype/hosts/nuke/plugins/publish/precollect_workfile.py +++ b/openpype/hosts/nuke/plugins/publish/precollect_workfile.py @@ -8,6 +8,7 @@ from openpype.hosts.nuke.api.lib import ( add_publish_knob, get_avalon_knob_data ) +from openpype.pipeline import KnownPublishError class CollectWorkfile(pyblish.api.ContextPlugin): @@ -22,6 +23,12 @@ class CollectWorkfile(pyblish.api.ContextPlugin): current_file = os.path.normpath(nuke.root().name()) + if current_file.lower() == "root": + raise KnownPublishError( + "Workfile is not correct file name. \n" + "Use workfile tool to manage the name correctly." + ) + knob_data = get_avalon_knob_data(root) add_publish_knob(root) From 4bd375409e11822978d352cae20fd1081615aa55 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 15 Aug 2022 11:55:37 +0200 Subject: [PATCH 28/32] nuke: fixing validate rendered frames --- openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py index f8e128cd26..237ff423e5 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py +++ b/openpype/hosts/nuke/plugins/publish/validate_rendered_frames.py @@ -127,7 +127,7 @@ class ValidateRenderedFrames(pyblish.api.InstancePlugin): f_start_h += 1 if ( - collected_frames_len >= frame_length + collected_frames_len != frame_length and coll_start <= f_start_h and coll_end >= f_end_h ): From bcb15c2fc5b28ff38ea3d5a9beca41186dec1615 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Mon, 15 Aug 2022 21:01:30 +0200 Subject: [PATCH 29/32] nuke: validation type mishmash wip --- .../nuke/plugins/publish/validate_write_nodes.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index 48dce623a9..9c9b8babaa 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -1,3 +1,4 @@ +import six import pyblish.api from openpype.api import get_errored_instances_from_context from openpype.hosts.nuke.api.lib import ( @@ -72,11 +73,21 @@ class ValidateNukeWriteNode(pyblish.api.InstancePlugin): for knob_data in check_knobs: key = knob_data["name"] value = knob_data["value"] + node_value = write_node[key].value() + + # fix type differences + if type(node_value) in (int, float): + value = float(value) + node_value = float(node_value) + else: + value = str(value) + node_value = str(node_value) + self.log.debug("__ key: {} | value: {}".format( key, value )) if ( - str(write_node[key].value()) != str(value) + node_value != value and key != "file" and key != "tile_color" ): From 309a272a1833ad73badeab5235ece8707c904c33 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 23 Aug 2022 17:27:47 +0200 Subject: [PATCH 30/32] nuke: fixing validate knobs --- openpype/hosts/nuke/plugins/publish/validate_knobs.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_knobs.py b/openpype/hosts/nuke/plugins/publish/validate_knobs.py index 573c25f3fe..e2b11892e5 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_knobs.py +++ b/openpype/hosts/nuke/plugins/publish/validate_knobs.py @@ -65,13 +65,22 @@ class ValidateKnobs(pyblish.api.ContextPlugin): # Filter families. families = [instance.data["family"]] families += instance.data.get("families", []) - families = list(set(families) & set(cls.knobs.keys())) + if not families: continue # Get all knobs to validate. knobs = {} for family in families: + # check if dot in family + if "." in family: + family = family.split(".")[0] + + # avoid families not in settings + if family not in cls.knobs: + continue + + # get presets of knobs for preset in cls.knobs[family]: knobs[preset] = cls.knobs[family][preset] From eb897ac579e0993103cc2d12c82d574181e55754 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 23 Aug 2022 17:28:03 +0200 Subject: [PATCH 31/32] remove unused import --- openpype/hosts/nuke/plugins/publish/validate_write_nodes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py index 9c9b8babaa..362ff31174 100644 --- a/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py +++ b/openpype/hosts/nuke/plugins/publish/validate_write_nodes.py @@ -1,4 +1,3 @@ -import six import pyblish.api from openpype.api import get_errored_instances_from_context from openpype.hosts.nuke.api.lib import ( From 3ab974f98c96c823953e349fe499b48c5e4a0a7c Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 24 Aug 2022 13:46:19 +0200 Subject: [PATCH 32/32] Removed submodule vendor/configs/OpenColorIO-Configs --- vendor/configs/OpenColorIO-Configs | 1 - 1 file changed, 1 deletion(-) delete mode 160000 vendor/configs/OpenColorIO-Configs diff --git a/vendor/configs/OpenColorIO-Configs b/vendor/configs/OpenColorIO-Configs deleted file mode 160000 index 0bb079c08b..0000000000 --- a/vendor/configs/OpenColorIO-Configs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0bb079c08be410030669cbf5f19ff869b88af953