From 2a912abbcebccdf16e21e4ac597b17f8b282f932 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:53:44 +0100 Subject: [PATCH 01/29] extract sequence can ignore layer's transparency --- .../plugins/publish/extract_sequence.py | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py index f2856c72a9..1a21715aa2 100644 --- a/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py +++ b/openpype/hosts/tvpaint/plugins/publish/extract_sequence.py @@ -59,6 +59,10 @@ class ExtractSequence(pyblish.api.Extractor): ) ) + ignore_layers_transparency = instance.data.get( + "ignoreLayersTransparency", False + ) + family_lowered = instance.data["family"].lower() mark_in = instance.context.data["sceneMarkIn"] mark_out = instance.context.data["sceneMarkOut"] @@ -114,7 +118,11 @@ class ExtractSequence(pyblish.api.Extractor): else: # Render output result = self.render( - output_dir, mark_in, mark_out, filtered_layers + output_dir, + mark_in, + mark_out, + filtered_layers, + ignore_layers_transparency ) output_filepaths_by_frame_idx, thumbnail_fullpath = result @@ -274,7 +282,9 @@ class ExtractSequence(pyblish.api.Extractor): return output_filepaths_by_frame_idx, thumbnail_filepath - def render(self, output_dir, mark_in, mark_out, layers): + def render( + self, output_dir, mark_in, mark_out, layers, ignore_layer_opacity + ): """ Export images from TVPaint. Args: @@ -282,6 +292,7 @@ class ExtractSequence(pyblish.api.Extractor): mark_in (int): Starting frame index from which export will begin. mark_out (int): On which frame index export will end. layers (list): List of layers to be exported. + ignore_layer_opacity (bool): Layer's opacity will be ignored. Returns: tuple: With 2 items first is list of filenames second is path to @@ -323,7 +334,7 @@ class ExtractSequence(pyblish.api.Extractor): for layer_id, render_data in extraction_data_by_layer_id.items(): layer = layers_by_id[layer_id] filepaths_by_layer_id[layer_id] = self._render_layer( - render_data, layer, output_dir + render_data, layer, output_dir, ignore_layer_opacity ) # Prepare final filepaths where compositing should store result @@ -380,7 +391,9 @@ class ExtractSequence(pyblish.api.Extractor): red, green, blue = self.review_bg return (red, green, blue) - def _render_layer(self, render_data, layer, output_dir): + def _render_layer( + self, render_data, layer, output_dir, ignore_layer_opacity + ): frame_references = render_data["frame_references"] filenames_by_frame_index = render_data["filenames_by_frame_index"] @@ -389,6 +402,12 @@ class ExtractSequence(pyblish.api.Extractor): "tv_layerset {}".format(layer_id), "tv_SaveMode \"PNG\"" ] + # Set density to 100 and store previous opacity + if ignore_layer_opacity: + george_script_lines.extend([ + "tv_layerdensity 100", + "orig_opacity = result", + ]) filepaths_by_frame = {} frames_to_render = [] @@ -409,6 +428,10 @@ class ExtractSequence(pyblish.api.Extractor): # Store image to output george_script_lines.append("tv_saveimage \"{}\"".format(dst_path)) + # Set density back to origin opacity + if ignore_layer_opacity: + george_script_lines.append("tv_layerdensity orig_opacity") + self.log.debug("Rendering Exposure frames {} of layer {} ({})".format( ",".join(frames_to_render), layer_id, layer["name"] )) From fd086776102236e9137a8d6d80d56b5d8def2a3a Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:58:49 +0100 Subject: [PATCH 02/29] collect render instances can set 'ignoreLayersTransparency' --- .../tvpaint/plugins/publish/collect_render_instances.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py b/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py index ba89deac5d..e89fbf7882 100644 --- a/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py +++ b/openpype/hosts/tvpaint/plugins/publish/collect_render_instances.py @@ -9,6 +9,8 @@ class CollectRenderInstances(pyblish.api.InstancePlugin): hosts = ["tvpaint"] families = ["render", "review"] + ignore_render_pass_transparency = False + def process(self, instance): context = instance.context creator_identifier = instance.data["creator_identifier"] @@ -63,6 +65,9 @@ class CollectRenderInstances(pyblish.api.InstancePlugin): for layer in layers_data if layer["name"] in layer_names ] + instance.data["ignoreLayersTransparency"] = ( + self.ignore_render_pass_transparency + ) render_layer_data = None render_layer_id = creator_attributes["render_layer_instance_id"] From 9c8a9412006a2c6a598cbb5d9253ca8dfb837126 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 10:59:03 +0100 Subject: [PATCH 03/29] added settings for Collect Render Instances --- .../defaults/project_settings/tvpaint.json | 3 +++ .../projects_schema/schema_project_tvpaint.json | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 0b6d3d7e81..87d3601ae4 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -49,6 +49,9 @@ } }, "publish": { + "CollectRenderInstances": { + "ignore_render_pass_transparency": true + }, "ExtractSequence": { "review_bg": [ 255, diff --git a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json index 57016a8311..708b688ba5 100644 --- a/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json +++ b/openpype/settings/entities/schemas/projects_schema/schema_project_tvpaint.json @@ -241,6 +241,20 @@ "key": "publish", "label": "Publish plugins", "children": [ + { + "type": "dict", + "collapsible": true, + "key": "CollectRenderInstances", + "label": "Collect Render Instances", + "is_group": true, + "children": [ + { + "type": "boolean", + "key": "ignore_render_pass_transparency", + "label": "Ignore Render Pass opacity" + } + ] + }, { "type": "dict", "collapsible": true, From 0cfc46f4140531e5646df353c81d8ec6895b1b44 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Wed, 22 Feb 2023 11:19:49 +0100 Subject: [PATCH 04/29] disable ignore transparency by default --- openpype/settings/defaults/project_settings/tvpaint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/settings/defaults/project_settings/tvpaint.json b/openpype/settings/defaults/project_settings/tvpaint.json index 87d3601ae4..e06a67a254 100644 --- a/openpype/settings/defaults/project_settings/tvpaint.json +++ b/openpype/settings/defaults/project_settings/tvpaint.json @@ -50,7 +50,7 @@ }, "publish": { "CollectRenderInstances": { - "ignore_render_pass_transparency": true + "ignore_render_pass_transparency": false }, "ExtractSequence": { "review_bg": [ From ddf333fcdb502ecb8ce10a9b2d2152de198c686c Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Thu, 23 Feb 2023 10:39:10 +0100 Subject: [PATCH 05/29] fix access to not existing settings key --- openpype/hosts/tvpaint/plugins/create/create_render.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/tvpaint/plugins/create/create_render.py b/openpype/hosts/tvpaint/plugins/create/create_render.py index 40386efe91..7e85977b11 100644 --- a/openpype/hosts/tvpaint/plugins/create/create_render.py +++ b/openpype/hosts/tvpaint/plugins/create/create_render.py @@ -660,7 +660,6 @@ class TVPaintAutoDetectRenderCreator(TVPaintCreator): ["create"] ["auto_detect_render"] ) - self.enabled = plugin_settings["enabled"] self.allow_group_rename = plugin_settings["allow_group_rename"] self.group_name_template = plugin_settings["group_name_template"] self.group_idx_offset = plugin_settings["group_idx_offset"] From bae2ded2f711d68291d6a6d14e60cb19f856d1c5 Mon Sep 17 00:00:00 2001 From: Petr Kalis Date: Thu, 23 Feb 2023 11:30:15 +0100 Subject: [PATCH 06/29] Fix - check existence only if not None review_path might be None --- openpype/modules/slack/plugins/publish/integrate_slack_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/modules/slack/plugins/publish/integrate_slack_api.py b/openpype/modules/slack/plugins/publish/integrate_slack_api.py index 4e2557ccc7..86c97586d2 100644 --- a/openpype/modules/slack/plugins/publish/integrate_slack_api.py +++ b/openpype/modules/slack/plugins/publish/integrate_slack_api.py @@ -187,7 +187,7 @@ class IntegrateSlackAPI(pyblish.api.InstancePlugin): repre_review_path = get_publish_repre_path( instance, repre, False ) - if os.path.exists(repre_review_path): + if repre_review_path and os.path.exists(repre_review_path): review_path = repre_review_path if "burnin" in tags: # burnin has precedence if exists break From d74e17a0e112c48714a87afeddf7750494fb6fca Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 21 Feb 2023 17:40:29 +0000 Subject: [PATCH 07/29] Implement get_multipart --- openpype/hosts/maya/api/lib_renderproducts.py | 82 ++++++++++++------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 60090e9f6d..e635414029 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -196,12 +196,18 @@ class ARenderProducts: """Constructor.""" self.layer = layer self.render_instance = render_instance - self.multipart = False + self.multipart = self.get_multipart() # Initialize self.layer_data = self._get_layer_data() self.layer_data.products = self.get_render_products() + def get_multipart(self): + raise NotImplementedError( + "The render product implementation does not have a " + "\"get_multipart\" method." + ) + def has_camera_token(self): # type: () -> bool """Check if camera token is in image prefix. @@ -344,7 +350,6 @@ class ARenderProducts: separator = file_prefix[matches[0].end(1):matches[1].start(1)] return separator - def _get_layer_data(self): # type: () -> LayerMetadata # ______________________________________________ @@ -531,16 +536,20 @@ class RenderProductsArnold(ARenderProducts): return prefix - def _get_aov_render_products(self, aov, cameras=None): - """Return all render products for the AOV""" - - products = [] - aov_name = self._get_attr(aov, "name") + def get_multipart(self): multipart = False multilayer = bool(self._get_attr("defaultArnoldDriver.multipart")) merge_AOVs = bool(self._get_attr("defaultArnoldDriver.mergeAOVs")) if multilayer or merge_AOVs: multipart = True + + return multipart + + def _get_aov_render_products(self, aov, cameras=None): + """Return all render products for the AOV""" + + products = [] + aov_name = self._get_attr(aov, "name") ai_drivers = cmds.listConnections("{}.outputs".format(aov), source=True, destination=False, @@ -594,7 +603,7 @@ class RenderProductsArnold(ARenderProducts): ext=ext, aov=aov_name, driver=ai_driver, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -731,6 +740,14 @@ class RenderProductsVray(ARenderProducts): renderer = "vray" + def get_multipart(self): + multipart = False + image_format = self._get_attr("vraySettings.imageFormatStr") + if image_format == "exr (multichannel)": + multipart = True + + return multipart + def get_renderer_prefix(self): # type: () -> str """Get image prefix for V-Ray. @@ -797,11 +814,6 @@ class RenderProductsVray(ARenderProducts): if default_ext in {"exr (multichannel)", "exr (deep)"}: default_ext = "exr" - # Define multipart. - multipart = False - if image_format_str == "exr (multichannel)": - multipart = True - products = [] # add beauty as default when not disabled @@ -813,7 +825,7 @@ class RenderProductsVray(ARenderProducts): productName="", ext=default_ext, camera=camera, - multipart=multipart + multipart=self.multipart ) ) @@ -826,10 +838,10 @@ class RenderProductsVray(ARenderProducts): productName="Alpha", ext=default_ext, camera=camera, - multipart=multipart + multipart=self.multipart ) ) - if multipart: + if self.multipart: # AOVs are merged in m-channel file, only main layer is rendered return products @@ -989,6 +1001,19 @@ class RenderProductsRedshift(ARenderProducts): renderer = "redshift" unmerged_aovs = {"Cryptomatte"} + def get_multipart(self): + # For Redshift we don't directly return upon forcing multilayer + # due to some AOVs still being written into separate files, + # like Cryptomatte. + # AOVs are merged in multi-channel file + multipart = False + force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa + exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) + if exMultipart or force_layer: + multipart = True + + return multipart + def get_renderer_prefix(self): """Get image prefix for Redshift. @@ -1028,16 +1053,6 @@ class RenderProductsRedshift(ARenderProducts): for c in self.get_renderable_cameras() ] - # For Redshift we don't directly return upon forcing multilayer - # due to some AOVs still being written into separate files, - # like Cryptomatte. - # AOVs are merged in multi-channel file - multipart = False - force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa - exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart or force_layer: - multipart = True - # Get Redshift Extension from image format image_format = self._get_attr("redshiftOptions.imageFormat") # integer ext = mel.eval("redshiftGetImageExtension(%i)" % image_format) @@ -1059,7 +1074,7 @@ class RenderProductsRedshift(ARenderProducts): continue aov_type = self._get_attr(aov, "aovType") - if multipart and aov_type not in self.unmerged_aovs: + if self.multipart and aov_type not in self.unmerged_aovs: continue # Any AOVs that still get processed, like Cryptomatte @@ -1094,7 +1109,7 @@ class RenderProductsRedshift(ARenderProducts): productName=aov_light_group_name, aov=aov_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -1108,7 +1123,7 @@ class RenderProductsRedshift(ARenderProducts): product = RenderProduct(productName=aov_name, aov=aov_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera) products.append(product) @@ -1124,7 +1139,7 @@ class RenderProductsRedshift(ARenderProducts): products.insert(0, RenderProduct(productName=beauty_name, ext=ext, - multipart=multipart, + multipart=self.multipart, camera=camera)) return products @@ -1144,6 +1159,10 @@ class RenderProductsRenderman(ARenderProducts): renderer = "renderman" unmerged_aovs = {"PxrCryptomatte"} + def get_multipart(self): + # Implemented as display specific in "get_render_products". + return False + def get_render_products(self): """Get all AOVs. @@ -1283,6 +1302,9 @@ class RenderProductsMayaHardware(ARenderProducts): {"label": "EXR(exr)", "index": 40, "extension": "exr"} ] + def get_multipart(self): + return False + def _get_extension(self, value): result = None if isinstance(value, int): From 069e1eed21a360d8a01effdacd3b3684954ea83c Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Wed, 22 Feb 2023 18:00:11 +0000 Subject: [PATCH 08/29] Fix Redshift expected files. --- openpype/hosts/maya/api/lib_renderproducts.py | 26 +++++++++++++++---- .../maya/plugins/publish/collect_render.py | 7 ++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index e635414029..4e9e13d2a3 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1001,6 +1001,20 @@ class RenderProductsRedshift(ARenderProducts): renderer = "redshift" unmerged_aovs = {"Cryptomatte"} + def get_files(self, product): + # When outputting AOVs we need to replace Redshift specific AOV tokens + # with Maya render tokens for generating file sequences. We validate to + # a specific AOV fileprefix so we only need to accout for one + # replacement. + if not product.multipart and product.driver: + file_prefix = self._get_attr(product.driver + ".filePrefix") + self.layer_data.filePrefix = file_prefix.replace( + "/", + "//" + ) + + return super(RenderProductsRedshift, self).get_files(product) + def get_multipart(self): # For Redshift we don't directly return upon forcing multilayer # due to some AOVs still being written into separate files, @@ -1009,7 +1023,7 @@ class RenderProductsRedshift(ARenderProducts): multipart = False force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart or force_layer: + if exMultipart and force_layer: multipart = True return multipart @@ -1109,8 +1123,9 @@ class RenderProductsRedshift(ARenderProducts): productName=aov_light_group_name, aov=aov_name, ext=ext, - multipart=self.multipart, - camera=camera) + multipart=False, + camera=camera, + driver=aov) products.append(product) if light_groups: @@ -1123,8 +1138,9 @@ class RenderProductsRedshift(ARenderProducts): product = RenderProduct(productName=aov_name, aov=aov_name, ext=ext, - multipart=self.multipart, - camera=camera) + multipart=False, + camera=camera, + driver=aov) products.append(product) # When a Beauty AOV is added manually, it will be rendered as diff --git a/openpype/hosts/maya/plugins/publish/collect_render.py b/openpype/hosts/maya/plugins/publish/collect_render.py index f2b5262187..338f148f85 100644 --- a/openpype/hosts/maya/plugins/publish/collect_render.py +++ b/openpype/hosts/maya/plugins/publish/collect_render.py @@ -42,6 +42,7 @@ Provides: import re import os import platform +import json from maya import cmds import maya.app.renderSetup.model.renderSetup as renderSetup @@ -183,7 +184,11 @@ class CollectMayaRender(pyblish.api.ContextPlugin): self.log.info("multipart: {}".format( multipart)) assert exp_files, "no file names were generated, this is bug" - self.log.info(exp_files) + self.log.info( + "expected files: {}".format( + json.dumps(exp_files, indent=4, sort_keys=True) + ) + ) # 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 From 43020a6c9d6a8366048a294969deb5d6e6a999e8 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Thu, 23 Feb 2023 09:20:25 +0000 Subject: [PATCH 09/29] Only use force options as multipart identifier. --- openpype/hosts/maya/api/lib_renderproducts.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 4e9e13d2a3..02e55601b9 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1021,9 +1021,10 @@ class RenderProductsRedshift(ARenderProducts): # like Cryptomatte. # AOVs are merged in multi-channel file multipart = False - force_layer = bool(self._get_attr("redshiftOptions.exrForceMultilayer")) # noqa - exMultipart = bool(self._get_attr("redshiftOptions.exrMultipart")) - if exMultipart and force_layer: + force_layer = bool( + self._get_attr("redshiftOptions.exrForceMultilayer") + ) + if force_layer: multipart = True return multipart From 9c688309a9883654c0fb66fab992e6f28323670c Mon Sep 17 00:00:00 2001 From: Toke Jepsen Date: Thu, 23 Feb 2023 11:53:55 +0000 Subject: [PATCH 10/29] Update openpype/hosts/maya/api/lib_renderproducts.py --- openpype/hosts/maya/api/lib_renderproducts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/maya/api/lib_renderproducts.py b/openpype/hosts/maya/api/lib_renderproducts.py index 02e55601b9..463324284b 100644 --- a/openpype/hosts/maya/api/lib_renderproducts.py +++ b/openpype/hosts/maya/api/lib_renderproducts.py @@ -1320,6 +1320,7 @@ class RenderProductsMayaHardware(ARenderProducts): ] def get_multipart(self): + # MayaHardware does not support multipart EXRs. return False def _get_extension(self, value): From d760cbab77c39f3a4ae9b72924ad222304a8aa65 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Tue, 31 Jan 2023 06:55:36 +0000 Subject: [PATCH 11/29] Batch script for running Openpype on Deadline. --- tools/openpype_console.bat | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tools/openpype_console.bat diff --git a/tools/openpype_console.bat b/tools/openpype_console.bat new file mode 100644 index 0000000000..414b5fdf66 --- /dev/null +++ b/tools/openpype_console.bat @@ -0,0 +1,3 @@ +cd "%~dp0\.." +echo %OPENPYPE_MONGO% +.poetry\bin\poetry.exe run python start.py %* From 5d9fe60013148054b3cbd70d3701febc7f2fe3a4 Mon Sep 17 00:00:00 2001 From: Toke Stuart Jepsen Date: Fri, 17 Feb 2023 16:25:35 +0000 Subject: [PATCH 12/29] Commenting for documentation --- tools/openpype_console.bat | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tools/openpype_console.bat b/tools/openpype_console.bat index 414b5fdf66..04b28c389f 100644 --- a/tools/openpype_console.bat +++ b/tools/openpype_console.bat @@ -1,3 +1,15 @@ +goto comment +SYNOPSIS + Helper script running scripts through the OpenPype environment. + +DESCRIPTION + This script is usually used as a replacement for building when tested farm integration like Deadline. + +EXAMPLE + +cmd> .\openpype_console.bat path/to/python_script.py +:comment + cd "%~dp0\.." echo %OPENPYPE_MONGO% .poetry\bin\poetry.exe run python start.py %* From 7c73995971a39ef5f77bfe277cd86cddc76b78cd Mon Sep 17 00:00:00 2001 From: Fabia Serra Arrizabalaga Date: Thu, 23 Feb 2023 00:52:40 +0100 Subject: [PATCH 13/29] Move get_workfile_build_placeholder_plugins to NukeHost class as workfile template builder expects --- openpype/hosts/nuke/api/__init__.py | 3 --- openpype/hosts/nuke/api/pipeline.py | 13 ++++++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 3b00ca9f6f..1af5ff365d 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -30,7 +30,6 @@ from .pipeline import ( parse_container, update_container, - get_workfile_build_placeholder_plugins, ) from .lib import ( INSTANCE_DATA_KNOB, @@ -79,8 +78,6 @@ __all__ = ( "parse_container", "update_container", - "get_workfile_build_placeholder_plugins", - "INSTANCE_DATA_KNOB", "ROOT_DATA_KNOB", "maintained_selection", diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 6dec60d81a..d5289010cb 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -101,6 +101,12 @@ class NukeHost( def get_workfile_extensions(self): return file_extensions() + def get_workfile_build_placeholder_plugins(self): + return [ + NukePlaceholderLoadPlugin, + NukePlaceholderCreatePlugin + ] + def get_containers(self): return ls() @@ -200,13 +206,6 @@ def _show_workfiles(): host_tools.show_workfiles(parent=None, on_top=False) -def get_workfile_build_placeholder_plugins(): - return [ - NukePlaceholderLoadPlugin, - NukePlaceholderCreatePlugin - ] - - def _install_menu(): # uninstall original avalon menu main_window = get_main_window() From 6ad3421f7f4c6aa7d3cd21d7e63dca19df3d8e41 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 15:40:55 +0100 Subject: [PATCH 14/29] improving deprecation --- openpype/hosts/nuke/api/lib.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 0325838e78..b13c592fbf 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -214,8 +214,9 @@ def update_node_data(node, knobname, data): knob.setValue(knob_value) +@deprecated class Knobby(object): - """[DEPRICATED] For creating knob which it's type isn't + """[DEPRECATED] For creating knob which it's type isn't mapped in `create_knobs` Args: @@ -248,8 +249,9 @@ class Knobby(object): return " ".join(words) +@deprecated def create_knobs(data, tab=None): - """[DEPRICATED] Create knobs by data + """[DEPRECATED] Create knobs by data Depending on the type of each dict value and creates the correct Knob. @@ -342,8 +344,9 @@ def create_knobs(data, tab=None): return knobs +@deprecated def imprint(node, data, tab=None): - """[DEPRICATED] Store attributes with value on node + """[DEPRECATED] Store attributes with value on node Parse user data into Node knobs. Use `collections.OrderedDict` to ensure knob order. @@ -398,8 +401,9 @@ def imprint(node, data, tab=None): node.addKnob(knob) +@deprecated def add_publish_knob(node): - """[DEPRICATED] Add Publish knob to node + """[DEPRECATED] Add Publish knob to node Arguments: node (nuke.Node): nuke node to be processed @@ -416,8 +420,9 @@ def add_publish_knob(node): return node +@deprecated def set_avalon_knob_data(node, data=None, prefix="avalon:"): - """[DEPRICATED] Sets data into nodes's avalon knob + """[DEPRECATED] Sets data into nodes's avalon knob Arguments: node (nuke.Node): Nuke node to imprint with data, @@ -478,8 +483,9 @@ def set_avalon_knob_data(node, data=None, prefix="avalon:"): return node +@deprecated def get_avalon_knob_data(node, prefix="avalon:", create=True): - """[DEPRICATED] Gets a data from nodes's avalon knob + """[DEPRECATED] Gets a data from nodes's avalon knob Arguments: node (obj): Nuke node to search for data, @@ -521,8 +527,9 @@ def get_avalon_knob_data(node, prefix="avalon:", create=True): return data +@deprecated def fix_data_for_node_create(data): - """[DEPRICATED] Fixing data to be used for nuke knobs + """[DEPRECATED] Fixing data to be used for nuke knobs """ for k, v in data.items(): if isinstance(v, six.text_type): @@ -532,8 +539,9 @@ def fix_data_for_node_create(data): return data +@deprecated def add_write_node_legacy(name, **kwarg): - """[DEPRICATED] Adding nuke write node + """[DEPRECATED] Adding nuke write node Arguments: name (str): nuke node name kwarg (attrs): data for nuke knobs @@ -697,7 +705,7 @@ def get_nuke_imageio_settings(): @deprecated("openpype.hosts.nuke.api.lib.get_nuke_imageio_settings") def get_created_node_imageio_setting_legacy(nodeclass, creator, subset): - '''[DEPRICATED] Get preset data for dataflow (fileType, compression, bitDepth) + '''[DEPRECATED] Get preset data for dataflow (fileType, compression, bitDepth) ''' assert any([creator, nodeclass]), nuke.message( From 2e07aa33fa398148dd51ed103cf4da553c4f2379 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 17:21:17 +0100 Subject: [PATCH 15/29] Nuke: baking with multiple reposition nodes also with settings and defaults --- openpype/hosts/nuke/api/plugin.py | 96 ++++++++++++------- .../defaults/project_settings/nuke.json | 35 +++++++ .../schemas/schema_nuke_publish.json | 47 +++++++++ 3 files changed, 144 insertions(+), 34 deletions(-) diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index d3f8357f7d..5521db99c0 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -558,9 +558,7 @@ class ExporterReview(object): self.path_in = self.instance.data.get("path", None) self.staging_dir = self.instance.data["stagingDir"] self.collection = self.instance.data.get("collection", None) - self.data = dict({ - "representations": list() - }) + self.data = {"representations": []} def get_file_info(self): if self.collection: @@ -626,7 +624,7 @@ class ExporterReview(object): nuke_imageio = opnlib.get_nuke_imageio_settings() # TODO: this is only securing backward compatibility lets remove - # this once all projects's anotomy are updated to newer config + # this once all projects's anatomy are updated to newer config if "baking" in nuke_imageio.keys(): return nuke_imageio["baking"]["viewerProcess"] else: @@ -823,8 +821,41 @@ class ExporterReviewMov(ExporterReview): add_tags = [] self.publish_on_farm = farm read_raw = kwargs["read_raw"] + + # TODO: remove this when `reformat_nodes_config` + # is changed in settings reformat_node_add = kwargs["reformat_node_add"] reformat_node_config = kwargs["reformat_node_config"] + + # TODO: make this required in future + reformat_nodes_config = kwargs.get("reformat_nodes_config", {}) + + # TODO: remove this once deprecated is removed + # make sure only reformat_nodes_config is used in future + if reformat_node_add and reformat_nodes_config.get("enabled"): + self.log.warning( + "`reformat_node_add` is deprecated. " + "Please use only `reformat_nodes_config` instead.") + reformat_nodes_config = None + + # TODO: reformat code when backward compatibility is not needed + # warning if reformat_nodes_config is not set + if not reformat_nodes_config: + self.log.warning( + "Please set `reformat_nodes_config` in settings.") + self.log.warning( + "Using `reformat_node_config` instead.") + reformat_nodes_config = { + "enabled": reformat_node_add, + "reposition_nodes": [ + { + "node_class": "Reformat", + "knobs": reformat_node_config + } + ] + } + + bake_viewer_process = kwargs["bake_viewer_process"] bake_viewer_input_process_node = kwargs[ "bake_viewer_input_process"] @@ -846,7 +877,6 @@ class ExporterReviewMov(ExporterReview): subset = self.instance.data["subset"] self._temp_nodes[subset] = [] - # ---------- start nodes creation # Read node r_node = nuke.createNode("Read") @@ -860,44 +890,39 @@ class ExporterReviewMov(ExporterReview): if read_raw: r_node["raw"].setValue(1) - # connect - self._temp_nodes[subset].append(r_node) - self.previous_node = r_node - self.log.debug("Read... `{}`".format(self._temp_nodes[subset])) + # connect to Read node + self._shift_to_previous_node_and_temp(subset, r_node, "Read... `{}`") # add reformat node - if reformat_node_add: + if reformat_nodes_config["enabled"]: + reposition_nodes = reformat_nodes_config["reposition_nodes"] + for reposition_node in reposition_nodes: + node_class = reposition_node["node_class"] + knobs = reposition_node["knobs"] + node = nuke.createNode(node_class) + set_node_knobs_from_settings(node, knobs) + + # connect in order + self._connect_to_above_nodes( + node, subset, "Reposition node... `{}`" + ) # append reformated tag add_tags.append("reformated") - rf_node = nuke.createNode("Reformat") - set_node_knobs_from_settings(rf_node, reformat_node_config) - - # connect - rf_node.setInput(0, self.previous_node) - self._temp_nodes[subset].append(rf_node) - self.previous_node = rf_node - self.log.debug( - "Reformat... `{}`".format(self._temp_nodes[subset])) - # only create colorspace baking if toggled on if bake_viewer_process: if bake_viewer_input_process_node: # View Process node ipn = get_view_process_node() if ipn is not None: - # connect - ipn.setInput(0, self.previous_node) - self._temp_nodes[subset].append(ipn) - self.previous_node = ipn - self.log.debug( - "ViewProcess... `{}`".format( - self._temp_nodes[subset])) + # connect to ViewProcess node + self._connect_to_above_nodes(ipn, subset, "ViewProcess... `{}`") if not self.viewer_lut_raw: # OCIODisplay dag_node = nuke.createNode("OCIODisplay") + # assign display display, viewer = get_viewer_config_from_string( str(baking_view_profile) ) @@ -907,13 +932,7 @@ class ExporterReviewMov(ExporterReview): # assign viewer dag_node["view"].setValue(viewer) - # connect - dag_node.setInput(0, self.previous_node) - self._temp_nodes[subset].append(dag_node) - self.previous_node = dag_node - self.log.debug("OCIODisplay... `{}`".format( - self._temp_nodes[subset])) - + self._connect_to_above_nodes(dag_node, subset, "OCIODisplay... `{}`") # Write node write_node = nuke.createNode("Write") self.log.debug("Path: {}".format(self.path)) @@ -967,6 +986,15 @@ class ExporterReviewMov(ExporterReview): return self.data + def _shift_to_previous_node_and_temp(self, subset, node, message): + self._temp_nodes[subset].append(node) + self.previous_node = node + self.log.debug(message.format(self._temp_nodes[subset])) + + def _connect_to_above_nodes(self, node, subset, message): + node.setInput(0, self.previous_node) + self._shift_to_previous_node_and_temp(subset, node, message) + @deprecated("openpype.hosts.nuke.api.plugin.NukeWriteCreator") class AbstractWriteRender(OpenPypeCreator): diff --git a/openpype/settings/defaults/project_settings/nuke.json b/openpype/settings/defaults/project_settings/nuke.json index d475c337d9..2545411e0a 100644 --- a/openpype/settings/defaults/project_settings/nuke.json +++ b/openpype/settings/defaults/project_settings/nuke.json @@ -446,6 +446,41 @@ "value": false } ], + "reformat_nodes_config": { + "enabled": false, + "reposition_nodes": [ + { + "node_class": "Reformat", + "knobs": [ + { + "type": "text", + "name": "type", + "value": "to format" + }, + { + "type": "text", + "name": "format", + "value": "HD_1080" + }, + { + "type": "text", + "name": "filter", + "value": "Lanczos6" + }, + { + "type": "bool", + "name": "black_outside", + "value": true + }, + { + "type": "bool", + "name": "pbb", + "value": false + } + ] + } + ] + }, "extension": "mov", "add_custom_tags": [] } 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 5b9145e7d9..1c542279fc 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 @@ -271,6 +271,10 @@ { "type": "separator" }, + { + "type": "label", + "label": "Currently we are supporting also multiple reposition nodes.
Older single reformat node is still supported
and if it is activated then preference will
be on it. If you want to use multiple reformat
nodes then you need to disable single reformat
node and enable multiple Reformat nodes here." + }, { "type": "boolean", "key": "reformat_node_add", @@ -287,6 +291,49 @@ } ] }, + { + "key": "reformat_nodes_config", + "type": "dict", + "label": "Reformat Nodes", + "collapsible": true, + "checkbox_key": "enabled", + "children": [ + { + "type": "boolean", + "key": "enabled", + "label": "Enabled" + }, + { + "type": "label", + "label": "Reposition knobs supported only.
You can add multiple reformat nodes
and set their knobs. Order of reformat
nodes is important. First reformat node
will be applied first and last reformat
node will be applied last." + }, + { + "key": "reposition_nodes", + "type": "list", + "label": "Reposition nodes", + "object_type": { + "type": "dict", + "children": [ + { + "key": "node_class", + "label": "Node class", + "type": "text" + }, + { + "type": "schema_template", + "name": "template_nuke_knob_inputs", + "template_data": [ + { + "label": "Node knobs", + "key": "knobs" + } + ] + } + ] + } + } + ] + }, { "type": "separator" }, From fb3bda7c80c908dc052f50092e6d94a62947a3ad Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 23 Feb 2023 10:57:00 +0100 Subject: [PATCH 16/29] little fixes --- openpype/hosts/nuke/api/lib.py | 9 +++------ openpype/hosts/nuke/api/plugin.py | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index b13c592fbf..73d4986b64 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -214,7 +214,6 @@ def update_node_data(node, knobname, data): knob.setValue(knob_value) -@deprecated class Knobby(object): """[DEPRECATED] For creating knob which it's type isn't mapped in `create_knobs` @@ -249,9 +248,8 @@ class Knobby(object): return " ".join(words) -@deprecated def create_knobs(data, tab=None): - """[DEPRECATED] Create knobs by data + """Create knobs by data Depending on the type of each dict value and creates the correct Knob. @@ -344,9 +342,8 @@ def create_knobs(data, tab=None): return knobs -@deprecated def imprint(node, data, tab=None): - """[DEPRECATED] Store attributes with value on node + """Store attributes with value on node Parse user data into Node knobs. Use `collections.OrderedDict` to ensure knob order. @@ -1249,7 +1246,7 @@ def create_write_node( nodes to be created before write with dependency review (bool)[optional]: adding review knob farm (bool)[optional]: rendering workflow target - kwargs (dict)[optional]: additional key arguments for formating + kwargs (dict)[optional]: additional key arguments for formatting Example: prenodes = { diff --git a/openpype/hosts/nuke/api/plugin.py b/openpype/hosts/nuke/api/plugin.py index 5521db99c0..160ca820a4 100644 --- a/openpype/hosts/nuke/api/plugin.py +++ b/openpype/hosts/nuke/api/plugin.py @@ -842,9 +842,9 @@ class ExporterReviewMov(ExporterReview): # warning if reformat_nodes_config is not set if not reformat_nodes_config: self.log.warning( - "Please set `reformat_nodes_config` in settings.") - self.log.warning( - "Using `reformat_node_config` instead.") + "Please set `reformat_nodes_config` in settings. " + "Using `reformat_node_config` instead." + ) reformat_nodes_config = { "enabled": reformat_node_add, "reposition_nodes": [ From b4541d29fe823416c27b9a07424d431a738d3e8a Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 11:47:32 +0100 Subject: [PATCH 17/29] nuke assist kickoff --- .../system_settings/applications.json | 128 ++++++++++++++++++ .../system_schema/schema_applications.json | 8 ++ 2 files changed, 136 insertions(+) diff --git a/openpype/settings/defaults/system_settings/applications.json b/openpype/settings/defaults/system_settings/applications.json index f84d99e36b..5fd9b926fb 100644 --- a/openpype/settings/defaults/system_settings/applications.json +++ b/openpype/settings/defaults/system_settings/applications.json @@ -337,6 +337,134 @@ } } }, + "nukeassist": { + "enabled": true, + "label": "Nuke Assist", + "icon": "{}/app_icons/nuke.png", + "host_name": "nuke", + "environment": { + "NUKE_PATH": [ + "{NUKE_PATH}", + "{OPENPYPE_STUDIO_PLUGINS}/nuke" + ] + }, + "variants": { + "13-2": { + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke13.2v1\\Nuke13.2.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke13.2v1/Nuke13.2" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "13-0": { + "use_python_2": false, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke13.0v1\\Nuke13.0.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke13.0v1/Nuke13.0" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "12-2": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke12.2v3\\Nuke12.2.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke12.2v3Nuke12.2" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "12-0": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke12.0v1\\Nuke12.0.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke12.0v1/Nuke12.0" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "11-3": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke11.3v1\\Nuke11.3.exe" + ], + "darwin": [], + "linux": [ + "/usr/local/Nuke11.3v5/Nuke11.3" + ] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "11-2": { + "use_python_2": true, + "executables": { + "windows": [ + "C:\\Program Files\\Nuke11.2v2\\Nuke11.2.exe" + ], + "darwin": [], + "linux": [] + }, + "arguments": { + "windows": ["--nukeassist"], + "darwin": ["--nukeassist"], + "linux": ["--nukeassist"] + }, + "environment": {} + }, + "__dynamic_keys_labels__": { + "13-2": "13.2", + "13-0": "13.0", + "12-2": "12.2", + "12-0": "12.0", + "11-3": "11.3", + "11-2": "11.2" + } + } + }, "nukex": { "enabled": true, "label": "Nuke X", diff --git a/openpype/settings/entities/schemas/system_schema/schema_applications.json b/openpype/settings/entities/schemas/system_schema/schema_applications.json index 36c5811496..b17687cf71 100644 --- a/openpype/settings/entities/schemas/system_schema/schema_applications.json +++ b/openpype/settings/entities/schemas/system_schema/schema_applications.json @@ -25,6 +25,14 @@ "nuke_label": "Nuke" } }, + { + "type": "schema_template", + "name": "template_nuke", + "template_data": { + "nuke_type": "nukeassist", + "nuke_label": "Nuke Assist" + } + }, { "type": "schema_template", "name": "template_nuke", From e57c9e8dd6dc9b08d914f43805b3583e5c3bbe1c Mon Sep 17 00:00:00 2001 From: ynput Date: Tue, 21 Feb 2023 14:23:26 +0200 Subject: [PATCH 18/29] adding appgroup to prelaunch hook --- openpype/hooks/pre_foundry_apps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hooks/pre_foundry_apps.py b/openpype/hooks/pre_foundry_apps.py index 85f68c6b60..2092d5025d 100644 --- a/openpype/hooks/pre_foundry_apps.py +++ b/openpype/hooks/pre_foundry_apps.py @@ -13,7 +13,7 @@ class LaunchFoundryAppsWindows(PreLaunchHook): # Should be as last hook because must change launch arguments to string order = 1000 - app_groups = ["nuke", "nukex", "hiero", "nukestudio"] + app_groups = ["nuke", "nukeassist", "nukex", "hiero", "nukestudio"] platforms = ["windows"] def execute(self): From fc6e5ca854fad80a6687befba10422a187724bfd Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 13:39:02 +0100 Subject: [PATCH 19/29] adding nukeassist hook --- openpype/hosts/nuke/hooks/__init__.py | 0 openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 10 ++++++++++ 2 files changed, 10 insertions(+) create mode 100644 openpype/hosts/nuke/hooks/__init__.py create mode 100644 openpype/hosts/nuke/hooks/pre_nukeassist_setup.py diff --git a/openpype/hosts/nuke/hooks/__init__.py b/openpype/hosts/nuke/hooks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py new file mode 100644 index 0000000000..80696c34e5 --- /dev/null +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -0,0 +1,10 @@ +from openpype.lib import PreLaunchHook + +class PrelaunchNukeAssistHook(PreLaunchHook): + """ + Adding flag when nukeassist + """ + app_groups = ["nukeassist"] + + def execute(self): + self.launch_context.env["NUKEASSIST"] = True From a1c9e396640e9d6691af68e21ac1fa3ff78e9bf3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 13:56:17 +0100 Subject: [PATCH 20/29] adding hook to host --- openpype/hosts/nuke/addon.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openpype/hosts/nuke/addon.py b/openpype/hosts/nuke/addon.py index 9d25afe2b6..6a4b91a76d 100644 --- a/openpype/hosts/nuke/addon.py +++ b/openpype/hosts/nuke/addon.py @@ -63,5 +63,12 @@ class NukeAddon(OpenPypeModule, IHostAddon): path_paths.append(quick_time_path) env["PATH"] = os.pathsep.join(path_paths) + def get_launch_hook_paths(self, app): + if app.host_name != self.host_name: + return [] + return [ + os.path.join(NUKE_ROOT_DIR, "hooks") + ] + def get_workfile_extensions(self): return [".nk"] From 71745e185cae75de715a0962fcf34262d4d7df9d Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 14:54:51 +0100 Subject: [PATCH 21/29] adding menu assist variant conditions --- openpype/hosts/nuke/api/pipeline.py | 50 +++++++++++-------- openpype/hosts/nuke/hooks/__init__.py | 0 .../hosts/nuke/hooks/pre_nukeassist_setup.py | 2 +- 3 files changed, 30 insertions(+), 22 deletions(-) delete mode 100644 openpype/hosts/nuke/hooks/__init__.py diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index d5289010cb..306fa50de9 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -71,7 +71,7 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "create") INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") MENU_LABEL = os.environ["AVALON_LABEL"] - +ASSIST = bool(os.getenv("NUKEASSIST")) # registering pyblish gui regarding settings in presets if os.getenv("PYBLISH_GUI", None): @@ -207,6 +207,7 @@ def _show_workfiles(): def _install_menu(): + # uninstall original avalon menu main_window = get_main_window() menubar = nuke.menu("Nuke") @@ -217,7 +218,9 @@ def _install_menu(): ) Context.context_label = label context_action = menu.addCommand(label) - context_action.setEnabled(False) + + if not ASSIST: + context_action.setEnabled(False) menu.addSeparator() menu.addCommand( @@ -226,18 +229,20 @@ def _install_menu(): ) menu.addSeparator() - menu.addCommand( - "Create...", - lambda: host_tools.show_publisher( - tab="create" + if not ASSIST: + menu.addCommand( + "Create...", + lambda: host_tools.show_publisher( + tab="create" + ) ) - ) - menu.addCommand( - "Publish...", - lambda: host_tools.show_publisher( - tab="publish" + menu.addCommand( + "Publish...", + lambda: host_tools.show_publisher( + tab="publish" + ) ) - ) + menu.addCommand( "Load...", lambda: host_tools.show_loader( @@ -285,15 +290,18 @@ def _install_menu(): "Build Workfile from template", lambda: build_workfile_template() ) - menu_template.addSeparator() - menu_template.addCommand( - "Create Place Holder", - lambda: create_placeholder() - ) - menu_template.addCommand( - "Update Place Holder", - lambda: update_placeholder() - ) + + if not ASSIST: + menu_template.addSeparator() + menu_template.addCommand( + "Create Place Holder", + lambda: create_placeholder() + ) + menu_template.addCommand( + "Update Place Holder", + lambda: update_placeholder() + ) + menu.addSeparator() menu.addCommand( "Experimental tools...", diff --git a/openpype/hosts/nuke/hooks/__init__.py b/openpype/hosts/nuke/hooks/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 80696c34e5..054bd677a7 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -7,4 +7,4 @@ class PrelaunchNukeAssistHook(PreLaunchHook): app_groups = ["nukeassist"] def execute(self): - self.launch_context.env["NUKEASSIST"] = True + self.launch_context.env["NUKEASSIST"] = "1" From f3431c62792cea3a65c95366d105bd782fe46376 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 15:26:07 +0100 Subject: [PATCH 22/29] moving Assist switch to api level condition for updating nodes --- openpype/hosts/nuke/api/__init__.py | 7 ++++++- openpype/hosts/nuke/api/lib.py | 21 ++++++++++++--------- openpype/hosts/nuke/api/pipeline.py | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 1af5ff365d..7766a94140 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -1,3 +1,4 @@ +import os from .workio import ( file_extensions, has_unsaved_changes, @@ -50,6 +51,8 @@ from .utils import ( get_colorspace_list ) +ASSIST = bool(os.getenv("NUKEASSIST")) + __all__ = ( "file_extensions", "has_unsaved_changes", @@ -92,5 +95,7 @@ __all__ = ( "create_write_node", "colorspace_exists_on_node", - "get_colorspace_list" + "get_colorspace_list", + + "ASSIST" ) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 73d4986b64..ec5bc58f9f 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -49,7 +49,7 @@ from openpype.pipeline.colorspace import ( ) from openpype.pipeline.workfile import BuildWorkfile -from . import gizmo_menu +from . import gizmo_menu, ASSIST from .workio import ( save_file, @@ -2263,14 +2263,17 @@ class WorkfileSettings(object): node['frame_range'].setValue(range) node['frame_range_lock'].setValue(True) - set_node_data( - self._root_node, - INSTANCE_DATA_KNOB, - { - "handleStart": int(handle_start), - "handleEnd": int(handle_end) - } - ) + if not ASSIST: + set_node_data( + self._root_node, + INSTANCE_DATA_KNOB, + { + "handleStart": int(handle_start), + "handleEnd": int(handle_end) + } + ) + else: + log.warning("NukeAssist mode is not allowing updating custom knobs...") def reset_resolution(self): """Set resolution to project resolution.""" diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 306fa50de9..94c4518664 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,6 +60,7 @@ from .workio import ( work_root, current_file ) +from . import ASSIST log = Logger.get_logger(__name__) @@ -71,7 +72,6 @@ CREATE_PATH = os.path.join(PLUGINS_DIR, "create") INVENTORY_PATH = os.path.join(PLUGINS_DIR, "inventory") MENU_LABEL = os.environ["AVALON_LABEL"] -ASSIST = bool(os.getenv("NUKEASSIST")) # registering pyblish gui regarding settings in presets if os.getenv("PYBLISH_GUI", None): From fe163ab19b43bbde9c9ee297cf02ca2d42d998b5 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 16:06:39 +0100 Subject: [PATCH 23/29] moving ASSIST switch to utils --- openpype/hosts/nuke/api/__init__.py | 7 +------ openpype/hosts/nuke/api/lib.py | 3 ++- openpype/hosts/nuke/api/pipeline.py | 2 +- openpype/hosts/nuke/api/utils.py | 1 + 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/openpype/hosts/nuke/api/__init__.py b/openpype/hosts/nuke/api/__init__.py index 7766a94140..1af5ff365d 100644 --- a/openpype/hosts/nuke/api/__init__.py +++ b/openpype/hosts/nuke/api/__init__.py @@ -1,4 +1,3 @@ -import os from .workio import ( file_extensions, has_unsaved_changes, @@ -51,8 +50,6 @@ from .utils import ( get_colorspace_list ) -ASSIST = bool(os.getenv("NUKEASSIST")) - __all__ = ( "file_extensions", "has_unsaved_changes", @@ -95,7 +92,5 @@ __all__ = ( "create_write_node", "colorspace_exists_on_node", - "get_colorspace_list", - - "ASSIST" + "get_colorspace_list" ) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index ec5bc58f9f..dfc647872b 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -49,7 +49,8 @@ from openpype.pipeline.colorspace import ( ) from openpype.pipeline.workfile import BuildWorkfile -from . import gizmo_menu, ASSIST +from . import gizmo_menu +from .utils import ASSIST from .workio import ( save_file, diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 94c4518664..55cb77bafe 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,7 +60,7 @@ from .workio import ( work_root, current_file ) -from . import ASSIST +from .utils import ASSIST log = Logger.get_logger(__name__) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 6bcb752dd1..261eba8401 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -4,6 +4,7 @@ import nuke from openpype import resources from .lib import maintained_selection +ASSIST = bool(os.getenv("NUKEASSIST")) def set_context_favorites(favorites=None): """ Adding favorite folders to nuke's browser From 360a5b3b68de7e3f735078173c897e21196adec4 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 21 Feb 2023 16:38:54 +0100 Subject: [PATCH 24/29] move ASSIST to constant --- openpype/hosts/nuke/api/constants.py | 4 ++++ openpype/hosts/nuke/api/lib.py | 2 +- openpype/hosts/nuke/api/pipeline.py | 2 +- openpype/hosts/nuke/api/utils.py | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 openpype/hosts/nuke/api/constants.py diff --git a/openpype/hosts/nuke/api/constants.py b/openpype/hosts/nuke/api/constants.py new file mode 100644 index 0000000000..110199720f --- /dev/null +++ b/openpype/hosts/nuke/api/constants.py @@ -0,0 +1,4 @@ +import os + + +ASSIST = bool(os.getenv("NUKEASSIST")) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index dfc647872b..9e36fb147b 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -50,7 +50,7 @@ from openpype.pipeline.colorspace import ( from openpype.pipeline.workfile import BuildWorkfile from . import gizmo_menu -from .utils import ASSIST +from .constants import ASSIST from .workio import ( save_file, diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 55cb77bafe..f07d150ba5 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -60,7 +60,7 @@ from .workio import ( work_root, current_file ) -from .utils import ASSIST +from .constants import ASSIST log = Logger.get_logger(__name__) diff --git a/openpype/hosts/nuke/api/utils.py b/openpype/hosts/nuke/api/utils.py index 261eba8401..6bcb752dd1 100644 --- a/openpype/hosts/nuke/api/utils.py +++ b/openpype/hosts/nuke/api/utils.py @@ -4,7 +4,6 @@ import nuke from openpype import resources from .lib import maintained_selection -ASSIST = bool(os.getenv("NUKEASSIST")) def set_context_favorites(favorites=None): """ Adding favorite folders to nuke's browser From 132b616f1f9b4c802f7c985b5eb73948d3ae22a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Je=C5=BEek?= Date: Wed, 22 Feb 2023 14:41:36 +0100 Subject: [PATCH 25/29] Update openpype/hosts/nuke/hooks/pre_nukeassist_setup.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 054bd677a7..3a0f00413a 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -8,3 +8,4 @@ class PrelaunchNukeAssistHook(PreLaunchHook): def execute(self): self.launch_context.env["NUKEASSIST"] = "1" + From b3b488c2a6235d71d1e15eb2d058d22c439f5303 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:44:22 +0100 Subject: [PATCH 26/29] removing line --- openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 3a0f00413a..054bd677a7 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -8,4 +8,3 @@ class PrelaunchNukeAssistHook(PreLaunchHook): def execute(self): self.launch_context.env["NUKEASSIST"] = "1" - From 363551af73a5703a08af4a5881448e9bc61885d3 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:52:57 +0100 Subject: [PATCH 27/29] context label is not needed in nukeassist --- openpype/hosts/nuke/api/pipeline.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index f07d150ba5..4c0f169ade 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -207,22 +207,25 @@ def _show_workfiles(): def _install_menu(): + """Install Avalon menu into Nuke's main menu bar.""" # uninstall original avalon menu main_window = get_main_window() menubar = nuke.menu("Nuke") menu = menubar.addMenu(MENU_LABEL) - label = "{0}, {1}".format( - os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] - ) - Context.context_label = label - context_action = menu.addCommand(label) if not ASSIST: + label = "{0}, {1}".format( + os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] + ) + Context.context_label = label + context_action = menu.addCommand(label) context_action.setEnabled(False) - menu.addSeparator() + # add separator after context label + menu.addSeparator() + menu.addCommand( "Work Files...", _show_workfiles From cb87097f74af6d6c616486867e89a9c0afada6c0 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:56:27 +0100 Subject: [PATCH 28/29] adding empty lines --- openpype/hosts/nuke/api/pipeline.py | 1 - openpype/hosts/nuke/hooks/pre_nukeassist_setup.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/pipeline.py b/openpype/hosts/nuke/api/pipeline.py index 4c0f169ade..2496d66c1d 100644 --- a/openpype/hosts/nuke/api/pipeline.py +++ b/openpype/hosts/nuke/api/pipeline.py @@ -214,7 +214,6 @@ def _install_menu(): menubar = nuke.menu("Nuke") menu = menubar.addMenu(MENU_LABEL) - if not ASSIST: label = "{0}, {1}".format( os.environ["AVALON_ASSET"], os.environ["AVALON_TASK"] diff --git a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py index 054bd677a7..3948a665c6 100644 --- a/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py +++ b/openpype/hosts/nuke/hooks/pre_nukeassist_setup.py @@ -1,5 +1,6 @@ from openpype.lib import PreLaunchHook + class PrelaunchNukeAssistHook(PreLaunchHook): """ Adding flag when nukeassist From 3218dd021ad1f471215fd9e7b1f2ce1972e42d74 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Wed, 22 Feb 2023 14:59:30 +0100 Subject: [PATCH 29/29] hound comments --- openpype/hosts/nuke/api/lib.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openpype/hosts/nuke/api/lib.py b/openpype/hosts/nuke/api/lib.py index 9e36fb147b..c08db978d3 100644 --- a/openpype/hosts/nuke/api/lib.py +++ b/openpype/hosts/nuke/api/lib.py @@ -2274,7 +2274,10 @@ class WorkfileSettings(object): } ) else: - log.warning("NukeAssist mode is not allowing updating custom knobs...") + log.warning( + "NukeAssist mode is not allowing " + "updating custom knobs..." + ) def reset_resolution(self): """Set resolution to project resolution."""