From fbcd56eb0d2b1c5c4d3032b7737da34cf900b47e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 17:52:21 +0200 Subject: [PATCH 01/30] Support single frame publishes - fix #672 --- .../houdini/client/ayon_houdini/api/plugin.py | 20 +++++++++++++++++++ .../plugins/publish/extract_alembic.py | 11 ++-------- .../plugins/publish/extract_ass.py | 13 ++---------- .../plugins/publish/extract_bgeo.py | 10 ++++------ .../plugins/publish/extract_composite.py | 7 +++---- .../plugins/publish/extract_mantra_ifd.py | 14 ++----------- .../plugins/publish/extract_opengl.py | 4 +--- .../plugins/publish/extract_redshift_proxy.py | 4 +--- .../plugins/publish/extract_vdb_cache.py | 4 +--- 9 files changed, 36 insertions(+), 51 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/plugin.py b/server_addon/houdini/client/ayon_houdini/api/plugin.py index 9c6bba925a..0e2308e948 100644 --- a/server_addon/houdini/client/ayon_houdini/api/plugin.py +++ b/server_addon/houdini/client/ayon_houdini/api/plugin.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- """Houdini specific Avalon/Pyblish plugin definitions.""" +import os import sys from abc import ( ABCMeta @@ -392,3 +393,22 @@ class HoudiniExtractorPlugin(publish.Extractor): hosts = ["houdini"] settings_category = SETTINGS_CATEGORY + + def validate_expected_frames(self, instance, staging_dir): + """ + Validate all expected files in `instance.data["frames"]` exist in + the staging directory. + """ + filenames = instance.data["frames"] + if isinstance(filenames, str): + # Single frame + filenames = [filenames] + + missing_filenames = [] + for filename in filenames: + path = os.path.join(staging_dir, filename) + if not os.path.isfile(path): + missing_filenames.append(filename) + if missing_filenames: + raise RuntimeError(f"Missing frames: {missing_filenames}") + diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py index e82f07284a..07216a491c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py @@ -26,15 +26,8 @@ class ExtractAlembic(plugin.HoudiniExtractorPlugin): staging_dir = os.path.dirname(output) instance.data["stagingDir"] = staging_dir - if instance.data.get("frames"): - # list of files - files = instance.data["frames"] - else: - # single file - files = os.path.basename(output) - # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (files, + self.log.info("Writing alembic '%s' to '%s'" % (output, staging_dir)) render_rop(ropnode) @@ -45,7 +38,7 @@ class ExtractAlembic(plugin.HoudiniExtractorPlugin): representation = { 'name': 'abc', 'ext': 'abc', - 'files': files, + 'files': instance.data["frames"], "stagingDir": staging_dir, } instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py index a796bbf4b3..befa6d0d49 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py @@ -35,16 +35,7 @@ class ExtractAss(plugin.HoudiniExtractorPlugin): # Unfortunately user interrupting the extraction does not raise an # error and thus still continues to the integrator. To capture that # we make sure all files exist - files = instance.data["frames"] - missing = [] - for file_name in files: - full_path = os.path.normpath(os.path.join(staging_dir, file_name)) - if not os.path.exists(full_path): - missing.append(full_path) - - if missing: - raise RuntimeError("Failed to complete Arnold ass extraction. " - "Missing output files: {}".format(missing)) + self.validate_expected_frames(instance, staging_dir) if "representations" not in instance.data: instance.data["representations"] = [] @@ -55,7 +46,7 @@ class ExtractAss(plugin.HoudiniExtractorPlugin): representation = { 'name': 'ass', 'ext': ext, - "files": files, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py index ab8837065d..180812ab87 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py @@ -19,8 +19,8 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): ropnode = hou.node(instance.data["instance_node"]) # Get the filename from the filename parameter - output = ropnode.evalParm("sopoutput") - staging_dir, file_name = os.path.split(output) + sop_output = ropnode.evalParm("sopoutput") + staging_dir, file_name = os.path.split(sop_output) instance.data["stagingDir"] = staging_dir # We run the render @@ -30,10 +30,8 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): # write files lib.render_rop(ropnode) - output = instance.data["frames"] - _, ext = lib.splitext( - output[0], allowed_multidot_extensions=[ + sop_output, allowed_multidot_extensions=[ ".ass.gz", ".bgeo.sc", ".bgeo.gz", ".bgeo.lzma", ".bgeo.bz2"]) @@ -43,7 +41,7 @@ class ExtractBGEO(plugin.HoudiniExtractorPlugin): representation = { "name": "bgeo", "ext": ext.lstrip("."), - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"] diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py index cab462aef6..84f03e5d1c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py @@ -20,17 +20,16 @@ class ExtractComposite(plugin.HoudiniExtractorPlugin, # Get the filename from the copoutput parameter # `.evalParm(parameter)` will make sure all tokens are resolved - output = ropnode.evalParm("copoutput") - staging_dir = os.path.dirname(output) + cop_output = ropnode.evalParm("copoutput") + staging_dir, file_name = os.path.split(cop_output) instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(output) self.log.info("Writing comp '%s' to '%s'" % (file_name, staging_dir)) render_rop(ropnode) output = instance.data["frames"] - _, ext = splitext(output[0], []) + _, ext = splitext(file_name, []) ext = ext.lstrip(".") if "representations" not in instance.data: diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py index b424f2e452..f0f402fa64 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py @@ -23,17 +23,7 @@ class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): staging_dir = os.path.dirname(output) instance.data["stagingDir"] = staging_dir - files = instance.data["frames"] - missing_frames = [ - frame - for frame in instance.data["frames"] - if not os.path.exists( - os.path.normpath(os.path.join(staging_dir, frame))) - ] - if missing_frames: - raise RuntimeError("Failed to complete Mantra ifd extraction. " - "Missing output files: {}".format( - missing_frames)) + self.validate_expected_frames(instance, staging_dir) if "representations" not in instance.data: instance.data["representations"] = [] @@ -41,7 +31,7 @@ class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): representation = { 'name': 'ifd', 'ext': 'ifd', - 'files': files, + 'files': instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStart"], "frameEnd": instance.data["frameEnd"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py index bee1bf871f..934f98a9f3 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py @@ -38,8 +38,6 @@ class ExtractOpenGL(plugin.HoudiniExtractorPlugin, render_rop(ropnode) - output = instance.data["frames"] - tags = ["review"] if not instance.data.get("keepImages"): tags.append("delete") @@ -47,7 +45,7 @@ class ExtractOpenGL(plugin.HoudiniExtractorPlugin, representation = { "name": instance.data["imageFormat"], "ext": instance.data["imageFormat"], - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py index 3e8a79df00..8c3cdd5ef9 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py @@ -32,15 +32,13 @@ class ExtractRedshiftProxy(plugin.HoudiniExtractorPlugin): render_rop(ropnode) - output = instance.data["frames"] - if "representations" not in instance.data: instance.data["representations"] = [] representation = { "name": "rs", "ext": "rs", - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, } diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py index a944d81e9b..8f0c070ff1 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py @@ -30,15 +30,13 @@ class ExtractVDBCache(plugin.HoudiniExtractorPlugin): render_rop(ropnode) - output = instance.data["frames"] - if "representations" not in instance.data: instance.data["representations"] = [] representation = { "name": "vdb", "ext": "vdb", - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], From 0bec3f0d2e2616471102b905785cc739724ee031 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 17:52:38 +0200 Subject: [PATCH 02/30] Simplify setting instance data "frames" --- .../client/ayon_houdini/plugins/publish/collect_frames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py index 3378657bfd..82f986ee13 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py @@ -60,7 +60,7 @@ class CollectFrames(plugin.HoudiniInstancePlugin): # todo: `frames` currently conflicts with "explicit frames" for a # for a custom frame list. So this should be refactored. - instance.data.update({"frames": result}) + instance.data["frames"] = result @staticmethod def create_file_list(match, start_frame, end_frame): From f56f0cc3d761c52330637dd2e2f0f0c10ca58a24 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 18:17:00 +0200 Subject: [PATCH 03/30] Move variable closer to its usage --- .../client/ayon_houdini/plugins/publish/extract_composite.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py index 84f03e5d1c..9830b2ea84 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py @@ -28,7 +28,6 @@ class ExtractComposite(plugin.HoudiniExtractorPlugin, render_rop(ropnode) - output = instance.data["frames"] _, ext = splitext(file_name, []) ext = ext.lstrip(".") @@ -38,7 +37,7 @@ class ExtractComposite(plugin.HoudiniExtractorPlugin, representation = { "name": ext, "ext": ext, - "files": output, + "files": instance.data["frames"], "stagingDir": staging_dir, "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], From 2ce50870377748a9a6e5206542c3d5326c419cd5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:39:16 +0200 Subject: [PATCH 04/30] Implement more generic ExtractROP extractor --- .../plugins/publish/extract_alembic.py | 44 ------ .../plugins/publish/extract_ass.py | 54 ------- .../plugins/publish/extract_bgeo.py | 49 ------- .../plugins/publish/extract_composite.py | 56 -------- .../plugins/publish/extract_fbx.py | 51 ------- .../plugins/publish/extract_mantra_ifd.py | 39 ----- .../plugins/publish/extract_opengl.py | 67 --------- .../plugins/publish/extract_redshift_proxy.py | 50 ------- .../plugins/publish/extract_rop.py | 134 ++++++++++++++++++ .../plugins/publish/extract_vdb_cache.py | 44 ------ 10 files changed, 134 insertions(+), 454 deletions(-) delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_fbx.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py create mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py deleted file mode 100644 index 07216a491c..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_alembic.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractAlembic(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder - label = "Extract Alembic" - families = ["abc", "camera"] - targets = ["local", "remote"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the filename parameter - output = ropnode.evalParm("filename") - staging_dir = os.path.dirname(output) - instance.data["stagingDir"] = staging_dir - - # We run the render - self.log.info("Writing alembic '%s' to '%s'" % (output, - staging_dir)) - - render_rop(ropnode) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - 'name': 'abc', - 'ext': 'abc', - 'files': instance.data["frames"], - "stagingDir": staging_dir, - } - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py deleted file mode 100644 index befa6d0d49..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_ass.py +++ /dev/null @@ -1,54 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractAss(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder + 0.1 - label = "Extract Ass" - families = ["ass"] - targets = ["local", "remote"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the filename parameter - # `.evalParm(parameter)` will make sure all tokens are resolved - output = ropnode.evalParm("ar_ass_file") - staging_dir = os.path.dirname(output) - instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(output) - - # We run the render - self.log.info("Writing ASS '%s' to '%s'" % (file_name, staging_dir)) - - render_rop(ropnode) - - # Unfortunately user interrupting the extraction does not raise an - # error and thus still continues to the integrator. To capture that - # we make sure all files exist - self.validate_expected_frames(instance, staging_dir) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - # Allow ass.gz extension as well - ext = "ass.gz" if file_name.endswith(".ass.gz") else "ass" - - representation = { - 'name': 'ass', - 'ext': ext, - "files": instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStartHandle"], - "frameEnd": instance.data["frameEndHandle"], - } - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py deleted file mode 100644 index 180812ab87..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_bgeo.py +++ /dev/null @@ -1,49 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import lib, plugin - - -class ExtractBGEO(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder - label = "Extract BGEO" - families = ["bgeo"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the filename parameter - sop_output = ropnode.evalParm("sopoutput") - staging_dir, file_name = os.path.split(sop_output) - instance.data["stagingDir"] = staging_dir - - # We run the render - self.log.info("Writing bgeo files '{}' to '{}'.".format( - file_name, staging_dir)) - - # write files - lib.render_rop(ropnode) - - _, ext = lib.splitext( - sop_output, allowed_multidot_extensions=[ - ".ass.gz", ".bgeo.sc", ".bgeo.gz", - ".bgeo.lzma", ".bgeo.bz2"]) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - "name": "bgeo", - "ext": ext.lstrip("."), - "files": instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStartHandle"], - "frameEnd": instance.data["frameEndHandle"] - } - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py deleted file mode 100644 index 9830b2ea84..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_composite.py +++ /dev/null @@ -1,56 +0,0 @@ -import os -import hou -import pyblish.api - -from ayon_core.pipeline import publish -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop, splitext - - -class ExtractComposite(plugin.HoudiniExtractorPlugin, - publish.ColormanagedPyblishPluginMixin): - - order = pyblish.api.ExtractorOrder - label = "Extract Composite (Image Sequence)" - families = ["imagesequence"] - - def process(self, instance): - - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the copoutput parameter - # `.evalParm(parameter)` will make sure all tokens are resolved - cop_output = ropnode.evalParm("copoutput") - staging_dir, file_name = os.path.split(cop_output) - instance.data["stagingDir"] = staging_dir - - self.log.info("Writing comp '%s' to '%s'" % (file_name, staging_dir)) - - render_rop(ropnode) - - _, ext = splitext(file_name, []) - ext = ext.lstrip(".") - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - "name": ext, - "ext": ext, - "files": instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStartHandle"], - "frameEnd": instance.data["frameEndHandle"], - } - - if ext.lower() == "exr": - # Inject colorspace with 'scene_linear' as that's the - # default Houdini working colorspace and all extracted - # OpenEXR images should be in that colorspace. - # https://www.sidefx.com/docs/houdini/render/linear.html#image-formats - self.set_representation_colorspace( - representation, instance.context, - colorspace="scene_linear" - ) - - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_fbx.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_fbx.py deleted file mode 100644 index 49b3fa07ca..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_fbx.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -"""Fbx Extractor for houdini. """ - -import os -import hou -import pyblish.api -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractFBX(plugin.HoudiniExtractorPlugin): - - label = "Extract FBX" - families = ["fbx"] - - order = pyblish.api.ExtractorOrder + 0.1 - - def process(self, instance): - - # get rop node - ropnode = hou.node(instance.data.get("instance_node")) - output_file = ropnode.evalParm("sopoutput") - - # get staging_dir and file_name - staging_dir = os.path.normpath(os.path.dirname(output_file)) - file_name = os.path.basename(output_file) - - # render rop - self.log.debug("Writing FBX '%s' to '%s'", file_name, staging_dir) - render_rop(ropnode) - - # prepare representation - representation = { - "name": "fbx", - "ext": "fbx", - "files": file_name, - "stagingDir": staging_dir - } - - # A single frame may also be rendered without start/end frame. - if "frameStartHandle" in instance.data and "frameEndHandle" in instance.data: # noqa - representation["frameStart"] = instance.data["frameStartHandle"] - representation["frameEnd"] = instance.data["frameEndHandle"] - - # set value type for 'representations' key to list - if "representations" not in instance.data: - instance.data["representations"] = [] - - # update instance data - instance.data["stagingDir"] = staging_dir - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py deleted file mode 100644 index f0f402fa64..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py +++ /dev/null @@ -1,39 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin - - -class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder - label = "Extract Mantra ifd" - families = ["mantraifd"] - targets = ["local", "remote"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - - ropnode = hou.node(instance.data.get("instance_node")) - output = ropnode.evalParm("soho_diskfile") - staging_dir = os.path.dirname(output) - instance.data["stagingDir"] = staging_dir - - self.validate_expected_frames(instance, staging_dir) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - 'name': 'ifd', - 'ext': 'ifd', - 'files': instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStart"], - "frameEnd": instance.data["frameEnd"], - } - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py deleted file mode 100644 index 934f98a9f3..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_opengl.py +++ /dev/null @@ -1,67 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_core.pipeline import publish -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractOpenGL(plugin.HoudiniExtractorPlugin, - publish.ColormanagedPyblishPluginMixin): - - order = pyblish.api.ExtractorOrder - 0.01 - label = "Extract OpenGL" - families = ["review"] - - def process(self, instance): - ropnode = hou.node(instance.data.get("instance_node")) - - # This plugin is triggered when marking render as reviewable. - # Therefore, this plugin will run on over wrong instances. - # TODO: Don't run this plugin on wrong instances. - # This plugin should run only on review product type - # with instance node of opengl type. - if ropnode.type().name() != "opengl": - self.log.debug("Skipping OpenGl extraction. Rop node {} " - "is not an OpenGl node.".format(ropnode.path())) - return - - output = ropnode.evalParm("picture") - staging_dir = os.path.normpath(os.path.dirname(output)) - instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(output) - - self.log.info("Extracting '%s' to '%s'" % (file_name, - staging_dir)) - - render_rop(ropnode) - - tags = ["review"] - if not instance.data.get("keepImages"): - tags.append("delete") - - representation = { - "name": instance.data["imageFormat"], - "ext": instance.data["imageFormat"], - "files": instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStartHandle"], - "frameEnd": instance.data["frameEndHandle"], - "tags": tags, - "preview": True, - "camera_name": instance.data.get("review_camera") - } - - if ropnode.evalParm("colorcorrect") == 2: # OpenColorIO enabled - colorspace = ropnode.evalParm("ociocolorspace") - # inject colorspace data - self.set_representation_colorspace( - representation, instance.context, - colorspace=colorspace - ) - - if "representations" not in instance.data: - instance.data["representations"] = [] - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py deleted file mode 100644 index 8c3cdd5ef9..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_redshift_proxy.py +++ /dev/null @@ -1,50 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractRedshiftProxy(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder + 0.1 - label = "Extract Redshift Proxy" - families = ["redshiftproxy"] - targets = ["local", "remote"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - ropnode = hou.node(instance.data.get("instance_node")) - - # Get the filename from the filename parameter - # `.evalParm(parameter)` will make sure all tokens are resolved - output = ropnode.evalParm("RS_archive_file") - staging_dir = os.path.normpath(os.path.dirname(output)) - instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(output) - - self.log.info("Writing Redshift Proxy '%s' to '%s'" % (file_name, - staging_dir)) - - render_rop(ropnode) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - "name": "rs", - "ext": "rs", - "files": instance.data["frames"], - "stagingDir": staging_dir, - } - - # A single frame may also be rendered without start/end frame. - if "frameStartHandle" in instance.data and "frameEndHandle" in instance.data: # noqa - representation["frameStart"] = instance.data["frameStartHandle"] - representation["frameEnd"] = instance.data["frameEndHandle"] - - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py new file mode 100644 index 0000000000..7b9e389f79 --- /dev/null +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -0,0 +1,134 @@ +import os +import hou + +import pyblish.api + +from ayon_core.pipeline import publish +from ayon_houdini.api import plugin +from ayon_houdini.api.lib import render_rop, get_output_parameter, splitext + + +class ExtractROP(plugin.HoudiniExtractorPlugin): + """Generic Extractor for any ROP node.""" + label = "Extract ROP" + order = pyblish.api.ExtractorOrder + + families = ["abc", "camera", "bgeo", "pointcache", "fbx", "imagesequence", + "vdbcache", "ass", "redshiftproxy", "mantraifd"] + targets = ["local", "remote"] + + def process(self, instance: pyblish.api.Instance): + if instance.data.get("farm"): + self.log.debug("Should be processed on farm, skipping.") + return + + rop_node = hou.node(instance.data["instance_node"]) + + parm = get_output_parameter(rop_node) + filepath = parm.eval() + staging_dir = os.path.dirname(filepath) + _, ext = splitext( + filepath, allowed_multidot_extensions=[ + ".ass.gz", ".bgeo.sc", ".bgeo.gz", + ".bgeo.lzma", ".bgeo.bz2"] + ) + + render_rop(rop_node) + self.validate_expected_frames(instance, staging_dir) + + # In some cases representation name is not the the extension + # TODO: Preferably we remove this very specific naming + product_type = instance.data["productType"] + name = { + "bgeo": "bgeo", + "rs": "rs", + "ass": "ass", + }.get(product_type, ext) + + representation = { + "name": name, + "ext": ext, + "files": instance.data["frames"], + "stagingDir": staging_dir, + "frameStart": instance.data["frameStartHandle"], + "frameEnd": instance.data["frameEndHandle"], + } + representation = self.update_representation_data(instance, + representation) + instance.data.setdefault("representations", []).append(representation) + instance.data["stagingDir"] = staging_dir + + def update_representation_data(self, + instance: pyblish.api.Instance, + representation: dict): + """Allow subclass to override the representation data in-place""" + pass + + +class ExtractOpenGL(ExtractROP, + publish.ColormanagedPyblishPluginMixin): + + order = pyblish.api.ExtractorOrder - 0.01 + label = "Extract OpenGL" + families = ["review"] + + def process(self, instance): + # This plugin is triggered when marking render as reviewable. + # Therefore, this plugin will run over wrong instances. + # TODO: Don't run this plugin on wrong instances. + # This plugin should run only on review product type + # with instance node of opengl type. + instance_node = instance.data.get("instance_node") + if not instance_node: + self.log.debug("Skipping instance without instance node.") + return + + rop_node = hou.node(instance_node) + if rop_node.type().name() != "opengl": + self.log.debug("Skipping OpenGl extraction. Rop node {} " + "is not an OpenGl node.".format(rop_node.path())) + return + + super(ExtractOpenGL, self).process(instance) + + def update_representation_data(self, + instance: pyblish.api.Instance, + representation: dict): + + tags = ["review"] + if not instance.data.get("keepImages"): + tags.append("delete") + + representation.update({ + # TODO: Avoid this override? + "name": instance.data["imageFormat"], + "ext": instance.data["imageFormat"], + + "tags": tags, + "preview": True, + "camera_name": instance.data.get("review_camera") + }) + return representation + + +class ExtractComposite(ExtractROP, + publish.ColormanagedPyblishPluginMixin): + + label = "Extract Composite (Image Sequence)" + families = ["imagesequence"] + + def update_representation_data(self, + instance: pyblish.api.Instance, + representation: dict): + + if representation["ext"].lower() != "exr": + return + + # Inject colorspace with 'scene_linear' as that's the + # default Houdini working colorspace and all extracted + # OpenEXR images should be in that colorspace. + # https://www.sidefx.com/docs/houdini/render/linear.html#image-formats + self.set_representation_colorspace( + representation, instance.context, + colorspace="scene_linear" + ) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py deleted file mode 100644 index 8f0c070ff1..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_vdb_cache.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop - - -class ExtractVDBCache(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder + 0.1 - label = "Extract VDB Cache" - families = ["vdbcache"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - ropnode = hou.node(instance.data["instance_node"]) - - # Get the filename from the filename parameter - # `.evalParm(parameter)` will make sure all tokens are resolved - sop_output = ropnode.evalParm("sopoutput") - staging_dir = os.path.normpath(os.path.dirname(sop_output)) - instance.data["stagingDir"] = staging_dir - file_name = os.path.basename(sop_output) - - self.log.info("Writing VDB '%s' to '%s'" % (file_name, staging_dir)) - - render_rop(ropnode) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - "name": "vdb", - "ext": "vdb", - "files": instance.data["frames"], - "stagingDir": staging_dir, - "frameStart": instance.data["frameStartHandle"], - "frameEnd": instance.data["frameEndHandle"], - } - instance.data["representations"].append(representation) From 640a409729f808a40bcec549a545fda060ed14b3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:44:29 +0200 Subject: [PATCH 05/30] Move method to where it's used --- .../houdini/client/ayon_houdini/api/plugin.py | 20 ------------------- .../plugins/publish/extract_rop.py | 18 +++++++++++++++++ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/plugin.py b/server_addon/houdini/client/ayon_houdini/api/plugin.py index 0e2308e948..9c6bba925a 100644 --- a/server_addon/houdini/client/ayon_houdini/api/plugin.py +++ b/server_addon/houdini/client/ayon_houdini/api/plugin.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- """Houdini specific Avalon/Pyblish plugin definitions.""" -import os import sys from abc import ( ABCMeta @@ -393,22 +392,3 @@ class HoudiniExtractorPlugin(publish.Extractor): hosts = ["houdini"] settings_category = SETTINGS_CATEGORY - - def validate_expected_frames(self, instance, staging_dir): - """ - Validate all expected files in `instance.data["frames"]` exist in - the staging directory. - """ - filenames = instance.data["frames"] - if isinstance(filenames, str): - # Single frame - filenames = [filenames] - - missing_filenames = [] - for filename in filenames: - path = os.path.join(staging_dir, filename) - if not os.path.isfile(path): - missing_filenames.append(filename) - if missing_filenames: - raise RuntimeError(f"Missing frames: {missing_filenames}") - diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 7b9e389f79..ed0c3f9855 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -58,6 +58,24 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): instance.data.setdefault("representations", []).append(representation) instance.data["stagingDir"] = staging_dir + def validate_expected_frames(self, instance, staging_dir): + """ + Validate all expected files in `instance.data["frames"]` exist in + the staging directory. + """ + filenames = instance.data["frames"] + if isinstance(filenames, str): + # Single frame + filenames = [filenames] + + missing_filenames = [] + for filename in filenames: + path = os.path.join(staging_dir, filename) + if not os.path.isfile(path): + missing_filenames.append(filename) + if missing_filenames: + raise RuntimeError(f"Missing frames: {missing_filenames}") + def update_representation_data(self, instance: pyblish.api.Instance, representation: dict): From c45144a1cf7631137187ed0d5a2b98f620b741d3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:46:02 +0200 Subject: [PATCH 06/30] Avoid redundant `return` --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index ed0c3f9855..fdabe4c713 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -112,7 +112,6 @@ class ExtractOpenGL(ExtractROP, def update_representation_data(self, instance: pyblish.api.Instance, representation: dict): - tags = ["review"] if not instance.data.get("keepImages"): tags.append("delete") @@ -126,7 +125,6 @@ class ExtractOpenGL(ExtractROP, "preview": True, "camera_name": instance.data.get("review_camera") }) - return representation class ExtractComposite(ExtractROP, From cde63892a8efa184b908b551dc3924902a845773 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:46:50 +0200 Subject: [PATCH 07/30] Do not use extension to base `usd` representation name on --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index fdabe4c713..6b05b468d5 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -43,6 +43,7 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): "bgeo": "bgeo", "rs": "rs", "ass": "ass", + "usd": "usd" }.get(product_type, ext) representation = { From 3de37d0507429a1b5a7d6b3544cd91cabefa349c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:47:34 +0200 Subject: [PATCH 08/30] Revert: Do not use extension to base `usd` representation name on --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 6b05b468d5..265f4c1538 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -42,8 +42,7 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): name = { "bgeo": "bgeo", "rs": "rs", - "ass": "ass", - "usd": "usd" + "ass": "ass" }.get(product_type, ext) representation = { From 020abb84c678f068e5f57fd86fdffe3c63cd690f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 19:57:15 +0200 Subject: [PATCH 09/30] Mimic generic ExtractROP logic more from #542 --- .../plugins/publish/collect_frames.py | 5 +++- .../plugins/publish/extract_rop.py | 24 +++++++++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py index 82f986ee13..94feb7532c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py @@ -60,7 +60,10 @@ class CollectFrames(plugin.HoudiniInstancePlugin): # todo: `frames` currently conflicts with "explicit frames" for a # for a custom frame list. So this should be refactored. - instance.data["frames"] = result + instance.data.update({ + "frames": result, + "stagingDir": os.path.dirname(output) + }) @staticmethod def create_file_list(match, start_frame, end_frame): diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 265f4c1538..4075db3a2c 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -24,17 +24,16 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): rop_node = hou.node(instance.data["instance_node"]) - parm = get_output_parameter(rop_node) - filepath = parm.eval() - staging_dir = os.path.dirname(filepath) + files = instance.data["frames"] + first_file = files[0] if isinstance(files, (list, tuple)) else files _, ext = splitext( - filepath, allowed_multidot_extensions=[ + first_file, allowed_multidot_extensions=[ ".ass.gz", ".bgeo.sc", ".bgeo.gz", ".bgeo.lzma", ".bgeo.bz2"] ) render_rop(rop_node) - self.validate_expected_frames(instance, staging_dir) + self.validate_expected_frames(instance) # In some cases representation name is not the the extension # TODO: Preferably we remove this very specific naming @@ -49,30 +48,29 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): "name": name, "ext": ext, "files": instance.data["frames"], - "stagingDir": staging_dir, + "stagingDir": instance.data["stagingDir"], "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], } representation = self.update_representation_data(instance, representation) instance.data.setdefault("representations", []).append(representation) - instance.data["stagingDir"] = staging_dir - def validate_expected_frames(self, instance, staging_dir): + def validate_expected_frames(self, instance: pyblish.api.Instance): """ Validate all expected files in `instance.data["frames"]` exist in the staging directory. """ filenames = instance.data["frames"] + staging_dir = instance.data["stagingDir"] if isinstance(filenames, str): # Single frame filenames = [filenames] - missing_filenames = [] - for filename in filenames: - path = os.path.join(staging_dir, filename) - if not os.path.isfile(path): - missing_filenames.append(filename) + missing_filenames = [ + filename for filename in filenames + if not os.path.isfile(os.path.join(staging_dir, filename)) + ] if missing_filenames: raise RuntimeError(f"Missing frames: {missing_filenames}") From a45b68f20fdf13bd64d3641abeddf989de646c9f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 20:28:57 +0200 Subject: [PATCH 10/30] Expect update in-place --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 4075db3a2c..37e45e68d5 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -52,8 +52,7 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): "frameStart": instance.data["frameStartHandle"], "frameEnd": instance.data["frameEndHandle"], } - representation = self.update_representation_data(instance, - representation) + self.update_representation_data(instance, representation) instance.data.setdefault("representations", []).append(representation) def validate_expected_frames(self, instance: pyblish.api.Instance): From a6de293bb6ece60983c9f4277bd356e3e8a8cbb7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 20:29:28 +0200 Subject: [PATCH 11/30] Remove dot from `ext` --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 1 + 1 file changed, 1 insertion(+) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 37e45e68d5..784a4f161d 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -31,6 +31,7 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): ".ass.gz", ".bgeo.sc", ".bgeo.gz", ".bgeo.lzma", ".bgeo.bz2"] ) + ext = ext.lstrip(".") render_rop(rop_node) self.validate_expected_frames(instance) From d0d45abfbad76a7dd24307441761cc5cfce1ddbe Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 20:33:16 +0200 Subject: [PATCH 12/30] Add some debug logs --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 784a4f161d..215d4bf213 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -33,6 +33,8 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): ) ext = ext.lstrip(".") + self.log.debug(f"Rendering {rop_node.path()} to {first_file}..") + render_rop(rop_node) self.validate_expected_frames(instance) From 836554d6f6b0d61b53f3dc543023613ba3877870 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Wed, 19 Jun 2024 22:11:24 +0200 Subject: [PATCH 13/30] Remove `imagesequence` because it has its own dedicated plug-in lower down in the file --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 215d4bf213..23657b66c9 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -13,7 +13,7 @@ class ExtractROP(plugin.HoudiniExtractorPlugin): label = "Extract ROP" order = pyblish.api.ExtractorOrder - families = ["abc", "camera", "bgeo", "pointcache", "fbx", "imagesequence", + families = ["abc", "camera", "bgeo", "pointcache", "fbx", "vdbcache", "ass", "redshiftproxy", "mantraifd"] targets = ["local", "remote"] From 64c57d4f6a07394dd7f4871ec731bd94abe29131 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 21 Jun 2024 00:56:26 +0200 Subject: [PATCH 14/30] Remove Houdini `Mantra IDF` product, fix #673 --- .../plugins/create/create_mantra_ifd.py | 55 ------------------- .../plugins/publish/collect_cache_farm.py | 4 +- .../plugins/publish/collect_chunk_size.py | 4 +- .../plugins/publish/collect_frames.py | 3 +- .../plugins/publish/extract_mantra_ifd.py | 49 ----------------- .../houdini/server/settings/create.py | 7 --- 6 files changed, 3 insertions(+), 119 deletions(-) delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/create/create_mantra_ifd.py delete mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py diff --git a/server_addon/houdini/client/ayon_houdini/plugins/create/create_mantra_ifd.py b/server_addon/houdini/client/ayon_houdini/plugins/create/create_mantra_ifd.py deleted file mode 100644 index fc5c4819d0..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/create/create_mantra_ifd.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -"""Creator plugin for creating pointcache alembics.""" -from ayon_houdini.api import plugin -from ayon_core.lib import BoolDef - - -class CreateMantraIFD(plugin.HoudiniCreator): - """Mantra .ifd Archive""" - identifier = "io.openpype.creators.houdini.mantraifd" - label = "Mantra IFD" - product_type = "mantraifd" - icon = "gears" - - def create(self, product_name, instance_data, pre_create_data): - import hou - instance_data.pop("active", None) - instance_data.update({"node_type": "ifd"}) - creator_attributes = instance_data.setdefault( - "creator_attributes", dict()) - creator_attributes["farm"] = pre_create_data["farm"] - instance = super(CreateMantraIFD, self).create( - product_name, - instance_data, - pre_create_data) - - instance_node = hou.node(instance.get("instance_node")) - - filepath = "{}{}".format( - hou.text.expandString("$HIP/pyblish/"), - "{}.$F4.ifd".format(product_name)) - parms = { - # Render frame range - "trange": 1, - # Arnold ROP settings - "soho_diskfile": filepath, - "soho_outputmode": 1 - } - - instance_node.setParms(parms) - - # Lock any parameters in this list - to_lock = ["soho_outputmode", "productType", "id"] - self.lock_parameters(instance_node, to_lock) - - def get_instance_attr_defs(self): - return [ - BoolDef("farm", - label="Submitting to Farm", - default=False) - ] - - def get_pre_create_attr_defs(self): - attrs = super().get_pre_create_attr_defs() - # Use same attributes as for instance attributes - return attrs + self.get_instance_attr_defs() diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_cache_farm.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_cache_farm.py index ecfebccfef..c558f35208 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_cache_farm.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_cache_farm.py @@ -12,9 +12,7 @@ class CollectDataforCache(plugin.HoudiniInstancePlugin): # Run after Collect Frames order = pyblish.api.CollectorOrder + 0.11 - families = ["ass", "pointcache", - "mantraifd", "redshiftproxy", - "vdbcache", "model"] + families = ["ass", "pointcache", "redshiftproxy", "vdbcache", "model"] targets = ["local", "remote"] label = "Collect Data for Cache" diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_chunk_size.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_chunk_size.py index 6ff53b7695..cd94827ba7 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_chunk_size.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_chunk_size.py @@ -9,9 +9,7 @@ class CollectChunkSize(plugin.HoudiniInstancePlugin, """Collect chunk size for cache submission to Deadline.""" order = pyblish.api.CollectorOrder + 0.05 - families = ["ass", "pointcache", - "vdbcache", "mantraifd", - "redshiftproxy", "model"] + families = ["ass", "pointcache", "vdbcache", "redshiftproxy", "model"] targets = ["local", "remote"] label = "Collect Chunk Size" chunk_size = 999999 diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py index 3378657bfd..5b85023123 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py @@ -16,8 +16,7 @@ class CollectFrames(plugin.HoudiniInstancePlugin): order = pyblish.api.CollectorOrder + 0.1 label = "Collect Frames" families = ["vdbcache", "imagesequence", "ass", - "mantraifd", "redshiftproxy", "review", - "pointcache"] + "redshiftproxy", "review", "pointcache"] def process(self, instance): diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py deleted file mode 100644 index b424f2e452..0000000000 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_mantra_ifd.py +++ /dev/null @@ -1,49 +0,0 @@ -import os -import hou - -import pyblish.api - -from ayon_houdini.api import plugin - - -class ExtractMantraIFD(plugin.HoudiniExtractorPlugin): - - order = pyblish.api.ExtractorOrder - label = "Extract Mantra ifd" - families = ["mantraifd"] - targets = ["local", "remote"] - - def process(self, instance): - if instance.data.get("farm"): - self.log.debug("Should be processed on farm, skipping.") - return - - ropnode = hou.node(instance.data.get("instance_node")) - output = ropnode.evalParm("soho_diskfile") - staging_dir = os.path.dirname(output) - instance.data["stagingDir"] = staging_dir - - files = instance.data["frames"] - missing_frames = [ - frame - for frame in instance.data["frames"] - if not os.path.exists( - os.path.normpath(os.path.join(staging_dir, frame))) - ] - if missing_frames: - raise RuntimeError("Failed to complete Mantra ifd extraction. " - "Missing output files: {}".format( - missing_frames)) - - if "representations" not in instance.data: - instance.data["representations"] = [] - - representation = { - 'name': 'ifd', - 'ext': 'ifd', - 'files': files, - "stagingDir": staging_dir, - "frameStart": instance.data["frameStart"], - "frameEnd": instance.data["frameEnd"], - } - instance.data["representations"].append(representation) diff --git a/server_addon/houdini/server/settings/create.py b/server_addon/houdini/server/settings/create.py index cd1e110c23..02fb052a36 100644 --- a/server_addon/houdini/server/settings/create.py +++ b/server_addon/houdini/server/settings/create.py @@ -51,9 +51,6 @@ class CreatePluginsModel(BaseSettingsModel): CreateKarmaROP: CreatorModel = SettingsField( default_factory=CreatorModel, title="Create Karma ROP") - CreateMantraIFD: CreatorModel = SettingsField( - default_factory=CreatorModel, - title="Create Mantra IFD") CreateMantraROP: CreatorModel = SettingsField( default_factory=CreatorModel, title="Create Mantra ROP") @@ -119,10 +116,6 @@ DEFAULT_HOUDINI_CREATE_SETTINGS = { "enabled": True, "default_variants": ["Main"] }, - "CreateMantraIFD": { - "enabled": True, - "default_variants": ["Main"] - }, "CreateMantraROP": { "enabled": True, "default_variants": ["Main"] From 2a847b1e55750b64eea69da6eb11e07a743ad1d7 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 21 Jun 2024 15:37:11 +0200 Subject: [PATCH 15/30] Bump houdini addon version --- server_addon/houdini/client/ayon_houdini/version.py | 2 +- server_addon/houdini/package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/version.py b/server_addon/houdini/client/ayon_houdini/version.py index 10d1478249..af2c4557db 100644 --- a/server_addon/houdini/client/ayon_houdini/version.py +++ b/server_addon/houdini/client/ayon_houdini/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'houdini' version.""" -__version__ = "0.3.2" +__version__ = "0.3.3" diff --git a/server_addon/houdini/package.py b/server_addon/houdini/package.py index 1f7879483e..da13bee9c7 100644 --- a/server_addon/houdini/package.py +++ b/server_addon/houdini/package.py @@ -1,6 +1,6 @@ name = "houdini" title = "Houdini" -version = "0.3.2" +version = "0.3.3" client_dir = "ayon_houdini" From 187b2e98c53e49819c807eab9829f436b16af676 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 21 Jun 2024 16:23:50 +0200 Subject: [PATCH 16/30] Fix FBX export --- .../client/ayon_houdini/plugins/publish/collect_frames.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py index 94feb7532c..64bf0c8f46 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py @@ -17,7 +17,7 @@ class CollectFrames(plugin.HoudiniInstancePlugin): label = "Collect Frames" families = ["vdbcache", "imagesequence", "ass", "mantraifd", "redshiftproxy", "review", - "pointcache"] + "pointcache", "fbx"] def process(self, instance): From 32ebf9c34f91e8f4cc88ed6f98d97c2d6d600fd5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 21 Jun 2024 17:08:05 +0200 Subject: [PATCH 17/30] Fix `camera` product type export --- .../client/ayon_houdini/plugins/publish/collect_frames.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py index 64bf0c8f46..9aceb5a1d0 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_frames.py @@ -15,9 +15,8 @@ class CollectFrames(plugin.HoudiniInstancePlugin): # this plugin runs after CollectRopFrameRange order = pyblish.api.CollectorOrder + 0.1 label = "Collect Frames" - families = ["vdbcache", "imagesequence", "ass", - "mantraifd", "redshiftproxy", "review", - "pointcache", "fbx"] + families = ["camera", "vdbcache", "imagesequence", "ass", "mantraifd", + "redshiftproxy", "review", "pointcache", "fbx"] def process(self, instance): From b61bb2dfc8aaf0452e0548ba8559ef6378d0c93b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 21 Jun 2024 18:00:08 +0200 Subject: [PATCH 18/30] Bump houdini addon version --- server_addon/houdini/client/ayon_houdini/version.py | 2 +- server_addon/houdini/package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/version.py b/server_addon/houdini/client/ayon_houdini/version.py index 10d1478249..af2c4557db 100644 --- a/server_addon/houdini/client/ayon_houdini/version.py +++ b/server_addon/houdini/client/ayon_houdini/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'houdini' version.""" -__version__ = "0.3.2" +__version__ = "0.3.3" diff --git a/server_addon/houdini/package.py b/server_addon/houdini/package.py index 1f7879483e..da13bee9c7 100644 --- a/server_addon/houdini/package.py +++ b/server_addon/houdini/package.py @@ -1,6 +1,6 @@ name = "houdini" title = "Houdini" -version = "0.3.2" +version = "0.3.3" client_dir = "ayon_houdini" From 24a508a7040af06c7ded60d0dfae76e6482ffda8 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Sat, 22 Jun 2024 00:23:28 +0800 Subject: [PATCH 19/30] remove unused function in extract rop --- .../houdini/client/ayon_houdini/plugins/publish/extract_rop.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py index 23657b66c9..62a38c0b93 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_rop.py @@ -5,7 +5,7 @@ import pyblish.api from ayon_core.pipeline import publish from ayon_houdini.api import plugin -from ayon_houdini.api.lib import render_rop, get_output_parameter, splitext +from ayon_houdini.api.lib import render_rop, splitext class ExtractROP(plugin.HoudiniExtractorPlugin): From 7e6af882bd42a24cd8b438f7d091a4e2c2c080fe Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 21 Jun 2024 22:13:06 +0300 Subject: [PATCH 20/30] support_opening_workfile_on_launching_houdini --- .../houdini/client/ayon_houdini/api/lib.py | 50 ++++++++++++++++++- .../client/ayon_houdini/api/pipeline.py | 5 +- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/lib.py b/server_addon/houdini/client/ayon_houdini/api/lib.py index 671265fae9..eefe895b8f 100644 --- a/server_addon/houdini/client/ayon_houdini/api/lib.py +++ b/server_addon/houdini/client/ayon_houdini/api/lib.py @@ -8,6 +8,7 @@ import json from contextlib import contextmanager import six +from qtpy import QtCore, QtWidgets import ayon_api from ayon_core.lib import StringTemplate @@ -23,7 +24,11 @@ from ayon_core.pipeline import ( from ayon_core.pipeline.create import CreateContext from ayon_core.pipeline.template_data import get_template_data from ayon_core.pipeline.context_tools import get_current_folder_entity -from ayon_core.tools.utils import PopupUpdateKeys, SimplePopup +from ayon_core.tools.utils import ( + PopupUpdateKeys, + SimplePopup, + host_tools +) from ayon_core.tools.utils.host_tools import get_tool_by_name import hou @@ -1193,3 +1198,46 @@ def prompt_reset_context(): update_content_on_context_change() dialog.deleteLater() + + +def wait_startup_launch_workfiles_app(): + """Show workfiles tool on Houdini launch. + + Trigger to show workfiles tool on application launch. Can be executed only + once all other calls are ignored. + + Workfiles tool show is deferred after application initialization using + QTimer. + + Basically, it should wait till the app finish starting up. + """ + + # Show workfiles tool using timer + # - this will be probably triggered during initialization in that case + # the application is not be able to show uis so it must be + # deferred using timer + # - timer should be processed when initialization ends + # When applications starts to process events. + timer = QtCore.QTimer() + timer.timeout.connect(lambda: _launch_workfile_app(timer)) + timer.setInterval(100) + timer.start() + + +def _launch_workfile_app(timer): + # Safeguard to not show window when application is still starting up + # or is already closing down. + closing_down = QtWidgets.QApplication.closingDown() + starting_up = QtWidgets.QApplication.startingUp() + + # Stop the timer if application finished start up of is closing down + if closing_down or not starting_up: + timer.stop() + + # Skip if application is starting up or closing down + if starting_up or closing_down: + return + + # Make sure on top is enabled on first show so the window is not hidden + # under main nuke window + host_tools.show_workfiles(parent=hou.qt.mainWindow(), on_top=True) diff --git a/server_addon/houdini/client/ayon_houdini/api/pipeline.py b/server_addon/houdini/client/ayon_houdini/api/pipeline.py index 6af4993d25..9d420a92d3 100644 --- a/server_addon/houdini/client/ayon_houdini/api/pipeline.py +++ b/server_addon/houdini/client/ayon_houdini/api/pipeline.py @@ -85,10 +85,9 @@ class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost): # initialization during start up delays Houdini UI by minutes # making it extremely slow to launch. hdefereval.executeDeferred(shelves.generate_shelves) - - if not IS_HEADLESS: - import hdefereval # noqa, hdefereval is only available in ui mode hdefereval.executeDeferred(creator_node_shelves.install) + if os.environ.get("AYON_WORKFILE_TOOL_ON_START"): + hdefereval.executeDeferred(lib.wait_startup_launch_workfiles_app) def workfile_has_unsaved_changes(self): return hou.hipFile.hasUnsavedChanges() From e6bb56b088ba001859ff02b61d577638f8d61ce1 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 21 Jun 2024 22:56:53 +0300 Subject: [PATCH 21/30] refactor launching the workfile - remove redundant code --- .../houdini/client/ayon_houdini/api/lib.py | 50 +------------------ .../client/ayon_houdini/api/pipeline.py | 11 +++- 2 files changed, 10 insertions(+), 51 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/lib.py b/server_addon/houdini/client/ayon_houdini/api/lib.py index eefe895b8f..671265fae9 100644 --- a/server_addon/houdini/client/ayon_houdini/api/lib.py +++ b/server_addon/houdini/client/ayon_houdini/api/lib.py @@ -8,7 +8,6 @@ import json from contextlib import contextmanager import six -from qtpy import QtCore, QtWidgets import ayon_api from ayon_core.lib import StringTemplate @@ -24,11 +23,7 @@ from ayon_core.pipeline import ( from ayon_core.pipeline.create import CreateContext from ayon_core.pipeline.template_data import get_template_data from ayon_core.pipeline.context_tools import get_current_folder_entity -from ayon_core.tools.utils import ( - PopupUpdateKeys, - SimplePopup, - host_tools -) +from ayon_core.tools.utils import PopupUpdateKeys, SimplePopup from ayon_core.tools.utils.host_tools import get_tool_by_name import hou @@ -1198,46 +1193,3 @@ def prompt_reset_context(): update_content_on_context_change() dialog.deleteLater() - - -def wait_startup_launch_workfiles_app(): - """Show workfiles tool on Houdini launch. - - Trigger to show workfiles tool on application launch. Can be executed only - once all other calls are ignored. - - Workfiles tool show is deferred after application initialization using - QTimer. - - Basically, it should wait till the app finish starting up. - """ - - # Show workfiles tool using timer - # - this will be probably triggered during initialization in that case - # the application is not be able to show uis so it must be - # deferred using timer - # - timer should be processed when initialization ends - # When applications starts to process events. - timer = QtCore.QTimer() - timer.timeout.connect(lambda: _launch_workfile_app(timer)) - timer.setInterval(100) - timer.start() - - -def _launch_workfile_app(timer): - # Safeguard to not show window when application is still starting up - # or is already closing down. - closing_down = QtWidgets.QApplication.closingDown() - starting_up = QtWidgets.QApplication.startingUp() - - # Stop the timer if application finished start up of is closing down - if closing_down or not starting_up: - timer.stop() - - # Skip if application is starting up or closing down - if starting_up or closing_down: - return - - # Make sure on top is enabled on first show so the window is not hidden - # under main nuke window - host_tools.show_workfiles(parent=hou.qt.mainWindow(), on_top=True) diff --git a/server_addon/houdini/client/ayon_houdini/api/pipeline.py b/server_addon/houdini/client/ayon_houdini/api/pipeline.py index 9d420a92d3..2c28e33929 100644 --- a/server_addon/houdini/client/ayon_houdini/api/pipeline.py +++ b/server_addon/houdini/client/ayon_houdini/api/pipeline.py @@ -6,7 +6,7 @@ import logging import hou # noqa from ayon_core.host import HostBase, IWorkfileHost, ILoadHost, IPublishHost - +from ayon_core.tools.utils import host_tools import pyblish.api from ayon_core.pipeline import ( @@ -25,6 +25,13 @@ from ayon_core.lib import ( emit_event, ) +def show_workfiles_tool(): + # Make sure on top is enabled on first show so the + # window is not hidden under main nuke window + print("showing workfiles tool..") + from ayon_core.tools.utils import host_tools + host_tools.show_workfiles(parent=hou.qt.mainWindow(), + on_top=True) log = logging.getLogger("ayon_houdini") @@ -87,7 +94,7 @@ class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost): hdefereval.executeDeferred(shelves.generate_shelves) hdefereval.executeDeferred(creator_node_shelves.install) if os.environ.get("AYON_WORKFILE_TOOL_ON_START"): - hdefereval.executeDeferred(lib.wait_startup_launch_workfiles_app) + hdefereval.executeDeferred(lambda: host_tools.show_workfiles(parent=hou.qt.mainWindow())) def workfile_has_unsaved_changes(self): return hou.hipFile.hasUnsavedChanges() From d88c36b01ec50a706bb544f09574dadc963e762e Mon Sep 17 00:00:00 2001 From: Mustafa Taher Date: Fri, 21 Jun 2024 23:05:34 +0300 Subject: [PATCH 22/30] remove redundant code Co-authored-by: Roy Nieterau --- server_addon/houdini/client/ayon_houdini/api/pipeline.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/pipeline.py b/server_addon/houdini/client/ayon_houdini/api/pipeline.py index 2c28e33929..463191f787 100644 --- a/server_addon/houdini/client/ayon_houdini/api/pipeline.py +++ b/server_addon/houdini/client/ayon_houdini/api/pipeline.py @@ -25,13 +25,6 @@ from ayon_core.lib import ( emit_event, ) -def show_workfiles_tool(): - # Make sure on top is enabled on first show so the - # window is not hidden under main nuke window - print("showing workfiles tool..") - from ayon_core.tools.utils import host_tools - host_tools.show_workfiles(parent=hou.qt.mainWindow(), - on_top=True) log = logging.getLogger("ayon_houdini") From 583bc8f86b596ed0e6fc27b97e46b20d5b9929b5 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 21 Jun 2024 23:07:52 +0300 Subject: [PATCH 23/30] use env_value_to_bool instead of os.environ.get --- server_addon/houdini/client/ayon_houdini/api/pipeline.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server_addon/houdini/client/ayon_houdini/api/pipeline.py b/server_addon/houdini/client/ayon_houdini/api/pipeline.py index 463191f787..22a15605c7 100644 --- a/server_addon/houdini/client/ayon_houdini/api/pipeline.py +++ b/server_addon/houdini/client/ayon_houdini/api/pipeline.py @@ -23,6 +23,7 @@ from ayon_houdini.api import lib, shelves, creator_node_shelves from ayon_core.lib import ( register_event_callback, emit_event, + env_value_to_bool, ) @@ -86,7 +87,7 @@ class HoudiniHost(HostBase, IWorkfileHost, ILoadHost, IPublishHost): # making it extremely slow to launch. hdefereval.executeDeferred(shelves.generate_shelves) hdefereval.executeDeferred(creator_node_shelves.install) - if os.environ.get("AYON_WORKFILE_TOOL_ON_START"): + if env_value_to_bool("AYON_WORKFILE_TOOL_ON_START"): hdefereval.executeDeferred(lambda: host_tools.show_workfiles(parent=hou.qt.mainWindow())) def workfile_has_unsaved_changes(self): From fc4df957e6351d120b8ac7cc6e566d762729a3e8 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 24 Jun 2024 09:59:35 +0200 Subject: [PATCH 24/30] Maya: Remove the legacy creator from before new publisher UI --- .../maya/client/ayon_maya/api/__init__.py | 2 -- .../maya/client/ayon_maya/api/plugin.py | 26 +++++-------------- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/server_addon/maya/client/ayon_maya/api/__init__.py b/server_addon/maya/client/ayon_maya/api/__init__.py index 0948282f57..8783fbeeb7 100644 --- a/server_addon/maya/client/ayon_maya/api/__init__.py +++ b/server_addon/maya/client/ayon_maya/api/__init__.py @@ -12,7 +12,6 @@ from .pipeline import ( MayaHost, ) from .plugin import ( - Creator, Loader ) @@ -45,7 +44,6 @@ __all__ = [ "containerise", "MayaHost", - "Creator", "Loader", # Workfiles API diff --git a/server_addon/maya/client/ayon_maya/api/plugin.py b/server_addon/maya/client/ayon_maya/api/plugin.py index b8d9748ef1..6ff428567e 100644 --- a/server_addon/maya/client/ayon_maya/api/plugin.py +++ b/server_addon/maya/client/ayon_maya/api/plugin.py @@ -15,10 +15,9 @@ from ayon_core.pipeline import ( Anatomy, AutoCreator, CreatedInstance, - Creator as NewCreator, + Creator, CreatorError, HiddenCreator, - LegacyCreator, LoaderPlugin, get_current_project_name, get_representation_path, @@ -35,6 +34,9 @@ from . import lib from .lib import imprint, read from .pipeline import containerise +# Backwards compatibility +NewCreator = Creator + log = Logger.get_logger() SETTINGS_CATEGORY = "maya" @@ -70,22 +72,6 @@ def get_reference_node_parents(*args, **kwargs): return lib.get_reference_node_parents(*args, **kwargs) -class Creator(LegacyCreator): - defaults = ['Main'] - - def process(self): - nodes = list() - - with lib.undo_chunk(): - if (self.options or {}).get("useSelection"): - nodes = cmds.ls(selection=True) - - instance = cmds.sets(nodes, name=self.name) - lib.imprint(instance, self.data) - - return instance - - @six.add_metaclass(ABCMeta) class MayaCreatorBase(object): @@ -274,7 +260,7 @@ class MayaCreatorBase(object): @six.add_metaclass(ABCMeta) -class MayaCreator(NewCreator, MayaCreatorBase): +class MayaCreator(Creator, MayaCreatorBase): settings_category = "maya" @@ -381,7 +367,7 @@ def ensure_namespace(namespace): return cmds.namespace(add=namespace) -class RenderlayerCreator(NewCreator, MayaCreatorBase): +class RenderlayerCreator(Creator, MayaCreatorBase): """Creator which creates an instance per renderlayer in the workfile. Create and manages renderlayer product per renderLayer in workfile. From a01f047e2a6761ffb2cef86c499dbb8779cc584e Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 24 Jun 2024 10:42:11 +0200 Subject: [PATCH 25/30] convert version string to integer --- server_addon/maya/client/ayon_maya/api/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_addon/maya/client/ayon_maya/api/lib.py b/server_addon/maya/client/ayon_maya/api/lib.py index 3b351ec1f0..0242dafc0b 100644 --- a/server_addon/maya/client/ayon_maya/api/lib.py +++ b/server_addon/maya/client/ayon_maya/api/lib.py @@ -1733,7 +1733,7 @@ def is_valid_reference_node(reference_node): """ # maya 2022 is missing `isValidReference` so the check needs to be # done in different way. - if cmds.about(version=True) < 2023: + if int(cmds.about(version=True)) < 2023: try: cmds.referenceQuery(reference_node, filename=True) return True From 0fdb63bc6779e3956c5b2f240a0d6fceb664b641 Mon Sep 17 00:00:00 2001 From: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:01:15 +0200 Subject: [PATCH 26/30] bump version to '0.2.5' --- server_addon/maya/client/ayon_maya/version.py | 2 +- server_addon/maya/package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/maya/client/ayon_maya/version.py b/server_addon/maya/client/ayon_maya/version.py index 37f9026945..df66e3f399 100644 --- a/server_addon/maya/client/ayon_maya/version.py +++ b/server_addon/maya/client/ayon_maya/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'maya' version.""" -__version__ = "0.2.4" +__version__ = "0.2.5" diff --git a/server_addon/maya/package.py b/server_addon/maya/package.py index 17614ed9c1..3dd863a1b3 100644 --- a/server_addon/maya/package.py +++ b/server_addon/maya/package.py @@ -1,6 +1,6 @@ name = "maya" title = "Maya" -version = "0.2.4" +version = "0.2.5" client_dir = "ayon_maya" ayon_required_addons = { From 2e8d578d8f4999fb3e58ec473470c77ba62a2d3f Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 24 Jun 2024 11:22:29 +0200 Subject: [PATCH 27/30] Update server_addon/maya/client/ayon_maya/api/plugin.py Co-authored-by: Jakub Trllo <43494761+iLLiCiTiT@users.noreply.github.com> --- server_addon/maya/client/ayon_maya/api/plugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/server_addon/maya/client/ayon_maya/api/plugin.py b/server_addon/maya/client/ayon_maya/api/plugin.py index 6ff428567e..45b2151e26 100644 --- a/server_addon/maya/client/ayon_maya/api/plugin.py +++ b/server_addon/maya/client/ayon_maya/api/plugin.py @@ -34,8 +34,6 @@ from . import lib from .lib import imprint, read from .pipeline import containerise -# Backwards compatibility -NewCreator = Creator log = Logger.get_logger() SETTINGS_CATEGORY = "maya" From 48a9077acb7c3ef5d5c4bc8912e2f5023823833d Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 24 Jun 2024 11:24:39 +0200 Subject: [PATCH 28/30] Bump Maya addon version --- server_addon/maya/client/ayon_maya/version.py | 2 +- server_addon/maya/package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/maya/client/ayon_maya/version.py b/server_addon/maya/client/ayon_maya/version.py index df66e3f399..c5fbef58fe 100644 --- a/server_addon/maya/client/ayon_maya/version.py +++ b/server_addon/maya/client/ayon_maya/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'maya' version.""" -__version__ = "0.2.5" +__version__ = "0.2.6" diff --git a/server_addon/maya/package.py b/server_addon/maya/package.py index 3dd863a1b3..2f70b630d5 100644 --- a/server_addon/maya/package.py +++ b/server_addon/maya/package.py @@ -1,6 +1,6 @@ name = "maya" title = "Maya" -version = "0.2.5" +version = "0.2.6" client_dir = "ayon_maya" ayon_required_addons = { From 79ccd665944bc7546f40a8695b06671760d3b895 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 24 Jun 2024 11:25:39 +0200 Subject: [PATCH 29/30] Cosmetics --- server_addon/maya/client/ayon_maya/api/plugin.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server_addon/maya/client/ayon_maya/api/plugin.py b/server_addon/maya/client/ayon_maya/api/plugin.py index 45b2151e26..d2678e2100 100644 --- a/server_addon/maya/client/ayon_maya/api/plugin.py +++ b/server_addon/maya/client/ayon_maya/api/plugin.py @@ -34,7 +34,6 @@ from . import lib from .lib import imprint, read from .pipeline import containerise - log = Logger.get_logger() SETTINGS_CATEGORY = "maya" From 7daf688533e3db83cf32d1c138808d49fc45f58b Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 24 Jun 2024 11:28:20 +0200 Subject: [PATCH 30/30] Bump houdini addon version --- server_addon/houdini/client/ayon_houdini/version.py | 2 +- server_addon/houdini/package.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server_addon/houdini/client/ayon_houdini/version.py b/server_addon/houdini/client/ayon_houdini/version.py index af2c4557db..66f3ac59e7 100644 --- a/server_addon/houdini/client/ayon_houdini/version.py +++ b/server_addon/houdini/client/ayon_houdini/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'houdini' version.""" -__version__ = "0.3.3" +__version__ = "0.3.4" diff --git a/server_addon/houdini/package.py b/server_addon/houdini/package.py index da13bee9c7..0c1b1fcf9b 100644 --- a/server_addon/houdini/package.py +++ b/server_addon/houdini/package.py @@ -1,6 +1,6 @@ name = "houdini" title = "Houdini" -version = "0.3.3" +version = "0.3.4" client_dir = "ayon_houdini"