From b3bdf12fffffd65507e9a66c83e7382cb66dba9c Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Fri, 28 Jan 2022 17:39:09 +0100 Subject: [PATCH] Implement Arnold .ass standin extraction from Houdini (also support .ass.gz) --- openpype/hosts/houdini/api/lib.py | 7 ++- .../plugins/create/create_arnold_ass.py | 51 +++++++++++++++++++ .../houdini/plugins/publish/collect_frames.py | 14 ++++- .../houdini/plugins/publish/extract_ass.py | 47 +++++++++++++++++ 4 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 openpype/hosts/houdini/plugins/create/create_arnold_ass.py create mode 100644 openpype/hosts/houdini/plugins/publish/extract_ass.py diff --git a/openpype/hosts/houdini/api/lib.py b/openpype/hosts/houdini/api/lib.py index 53f0e59ea9..cfb276628a 100644 --- a/openpype/hosts/houdini/api/lib.py +++ b/openpype/hosts/houdini/api/lib.py @@ -180,8 +180,11 @@ def get_output_parameter(node): return node.parm("filename") elif node_type == "comp": return node.parm("copoutput") - else: - raise TypeError("Node type '%s' not supported" % node_type) + elif node_type == "arnold": + if node.evalParm("ar_ass_export_enable"): + return node.parm("ar_ass_file") + + raise TypeError("Node type '%s' not supported" % node_type) @contextmanager diff --git a/openpype/hosts/houdini/plugins/create/create_arnold_ass.py b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py new file mode 100644 index 0000000000..4c87212a98 --- /dev/null +++ b/openpype/hosts/houdini/plugins/create/create_arnold_ass.py @@ -0,0 +1,51 @@ +import hou + +from avalon import houdini + + +class CreateArnoldAss(houdini.Creator): + """Arnold .ass Archive""" + + label = "Arnold ASS" + family = "ass" + icon = "magic" + defaults = ["Main"] + + def __init__(self, *args, **kwargs): + super(CreateArnoldAss, self).__init__(*args, **kwargs) + + # Remove the active, we are checking the bypass flag of the nodes + self.data.pop("active", None) + + self.data.update({"node_type": "arnold"}) + + def process(self): + node = super(CreateArnoldAss, self).process() + + basename = node.name() + node.setName(basename + "_ASS", unique_name=True) + + # Hide Properties Tab on Arnold ROP since that's used + # for rendering instead of .ass Archive Export + parm_template_group = node.parmTemplateGroup() + parm_template_group.hideFolder("Properties", True) + node.setParmTemplateGroup(parm_template_group) + + parms = { + # Render frame range + "trange": 1, + + # Arnold ROP settings + "ar_ass_file": '$HIP/pyblish/`chs("subset")`.$F4.ass.gz', + "ar_ass_export_enable": 1 + } + node.setParms(parms) + + # Lock the ASS export attribute + node.parm("ar_ass_export_enable").lock(True) + + # Lock some Avalon attributes + to_lock = ["family", "id"] + for name in to_lock: + parm = node.parm(name) + parm.lock(True) diff --git a/openpype/hosts/houdini/plugins/publish/collect_frames.py b/openpype/hosts/houdini/plugins/publish/collect_frames.py index 8d21794c1b..9abbd97826 100644 --- a/openpype/hosts/houdini/plugins/publish/collect_frames.py +++ b/openpype/hosts/houdini/plugins/publish/collect_frames.py @@ -5,12 +5,21 @@ import pyblish.api from openpype.hosts.houdini.api import lib +def splitext(name, allowed_multidot_extensions): + + for ext in allowed_multidot_extensions: + if name.endswith(ext): + return name[:-len(ext)], ext + + return os.path.splitext(name) + + class CollectFrames(pyblish.api.InstancePlugin): """Collect all frames which would be saved from the ROP nodes""" order = pyblish.api.CollectorOrder label = "Collect Frames" - families = ["vdbcache", "imagesequence"] + families = ["vdbcache", "imagesequence", "ass"] def process(self, instance): @@ -19,7 +28,8 @@ class CollectFrames(pyblish.api.InstancePlugin): output_parm = lib.get_output_parameter(ropnode) output = output_parm.eval() - _, ext = os.path.splitext(output) + _, ext = splitext(output, + allowed_multidot_extensions=[".ass.gz"]) file_name = os.path.basename(output) result = file_name diff --git a/openpype/hosts/houdini/plugins/publish/extract_ass.py b/openpype/hosts/houdini/plugins/publish/extract_ass.py new file mode 100644 index 0000000000..c7c5ed6430 --- /dev/null +++ b/openpype/hosts/houdini/plugins/publish/extract_ass.py @@ -0,0 +1,47 @@ +import os + +import pyblish.api +import openpype.api +from openpype.hosts.houdini.api.lib import render_rop + + +class ExtractAss(openpype.api.Extractor): + + order = pyblish.api.ExtractorOrder + 0.1 + label = "Extract Ass" + families = ["ass"] + hosts = ["houdini"] + + def process(self, instance): + + import hou + + ropnode = instance[0] + + # 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) + + 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["frameStart"], + "frameEnd": instance.data["frameEnd"], + } + instance.data["representations"].append(representation)