merge the arnold PR to this PR

This commit is contained in:
Kayla Man 2023-04-11 16:15:13 +08:00
commit 396c962745
5 changed files with 249 additions and 4 deletions

View file

@ -0,0 +1,56 @@
from openpype.hosts.houdini.api import plugin
class CreateArnoldRop(plugin.HoudiniCreator):
"""Arnold ROP"""
identifier = "io.openpype.creators.houdini.arnold_rop"
label = "Arnold ROP"
family = "arnold_rop"
icon = "magic"
defaults = ["master"]
# Default extension
ext = ".exr"
def create(self, subset_name, instance_data, pre_create_data):
import hou
# Remove the active, we are checking the bypass flag of the nodes
instance_data.pop("active", None)
instance_data.update({"node_type": "arnold"})
# Add chunk size attribute
instance_data["chunkSize"] = 1
instance = super(CreateArnoldRop, self).create(
subset_name,
instance_data,
pre_create_data) # type: plugin.CreatedInstance
instance_node = hou.node(instance.get("instance_node"))
# Hide Properties Tab on Arnold ROP since that's used
# for rendering instead of .ass Archive Export
parm_template_group = instance_node.parmTemplateGroup()
parm_template_group.hideFolder("Properties", True)
instance_node.setParmTemplateGroup(parm_template_group)
filepath = "{}{}".format(
hou.text.expandString("$HIP/pyblish/"),
"{}.$F4{}".format(subset_name, self.ext)
)
parms = {
# Render frame range
"trange": 1,
# Arnold ROP settings
"ar_picture": filepath,
"ar_exr_half_precision": 1 # half precision
}
instance_node.setParms(parms)
# Lock any parameters in this list
to_lock = ["family", "id"]
self.lock_parameters(instance_node, to_lock)

View file

@ -0,0 +1,174 @@
import re
import os
import hou
import pyblish.api
def get_top_referenced_parm(parm):
processed = set() # disallow infinite loop
while True:
if parm.path() in processed:
raise RuntimeError("Parameter references result in cycle.")
processed.add(parm.path())
ref = parm.getReferencedParm()
if ref.path() == parm.path():
# It returns itself when it doesn't reference
# another parameter
return ref
else:
parm = ref
def evalParmNoFrame(node, parm, pad_character="#"):
parameter = node.parm(parm)
assert parameter, "Parameter does not exist: %s.%s" % (node, parm)
# If the parameter has a parameter reference, then get that
# parameter instead as otherwise `unexpandedString()` fails.
parameter = get_top_referenced_parm(parameter)
# Substitute out the frame numbering with padded characters
try:
raw = parameter.unexpandedString()
except hou.Error as exc:
print("Failed: %s" % parameter)
raise RuntimeError(exc)
def replace(match):
padding = 1
n = match.group(2)
if n and int(n):
padding = int(n)
return pad_character * padding
expression = re.sub(r"(\$F([0-9]*))", replace, raw)
with hou.ScriptEvalContext(parameter):
return hou.expandStringAtFrame(expression, 0)
class CollectArnoldROPRenderProducts(pyblish.api.InstancePlugin):
"""Collect Arnold ROP Render Products
Collects the instance.data["files"] for the render products.
Provides:
instance -> files
"""
label = "Arnold ROP Render Products"
order = pyblish.api.CollectorOrder + 0.4
hosts = ["houdini"]
families = ["arnold_rop"]
def process(self, instance):
rop = hou.node(instance.data.get("instance_node"))
# Collect chunkSize
chunk_size_parm = rop.parm("chunkSize")
if chunk_size_parm:
chunk_size = int(chunk_size_parm.eval())
instance.data["chunkSize"] = chunk_size
self.log.debug("Chunk Size: %s" % chunk_size)
default_prefix = evalParmNoFrame(rop, "ar_picture")
render_products = []
# Default beauty AOV
beauty_product = self.get_render_product_name(prefix=default_prefix,
suffix=None)
render_products.append(beauty_product)
files_by_aov = {
"": self.generate_expected_files(instance, beauty_product)
}
num_aovs = rop.evalParm("ar_aovs")
for index in range(num_aovs):
i = index + 1
# Skip disabled AOVs
if not rop.evalParm("ar_enable_aov%s" % i):
continue
if rop.evalParm("ar_aov_exr_enable_layer_name%s" % i):
label = rop.evalParm("ar_aov_exr_layer_name%s" % i)
else:
label = evalParmNoFrame(rop, "ar_aov_label%s" % i)
aov_product = self.get_render_product_name(default_prefix,
suffix=label)
render_products.append(aov_product)
files_by_aov[label] = self.generate_expected_files(instance,
aov_product)
for product in render_products:
self.log.debug("Found render product: %s" % product)
filenames = list(render_products)
instance.data["files"] = filenames
# For now by default do NOT try to publish the rendered output
instance.data["publishJobState"] = "Suspended"
instance.data["attachTo"] = [] # stub required data
if "expectedFiles" not in instance.data:
instance.data["expectedFiles"] = list()
instance.data["expectedFiles"].append(files_by_aov)
def get_render_product_name(self, prefix, suffix):
"""Return the output filename using the AOV prefix and suffix"""
# When AOV is explicitly defined in prefix we just swap it out
# directly with the AOV suffix to embed it.
# Note: ${AOV} seems to be evaluated in the parameter as %AOV%
has_aov_in_prefix = "%AOV%" in prefix
if has_aov_in_prefix:
# It seems that when some special separator characters are present
# before the %AOV% token that Redshift will secretly remove it if
# there is no suffix for the current product, for example:
# foo_%AOV% -> foo.exr
pattern = "%AOV%" if suffix else "[._-]?%AOV%"
product_name = re.sub(pattern,
suffix,
prefix,
flags=re.IGNORECASE)
else:
if suffix:
# Add ".{suffix}" before the extension
prefix_base, ext = os.path.splitext(prefix)
product_name = prefix_base + "." + suffix + ext
else:
product_name = prefix
return product_name
def generate_expected_files(self, instance, path):
"""Create expected files in instance data"""
dir = os.path.dirname(path)
file = os.path.basename(path)
if "#" in file:
pparts = file.split("#")
padding = "%0{}d".format(len(pparts) - 1)
file = pparts[0] + padding + pparts[-1]
if "%" not in file:
return path
expected_files = []
start = instance.data["frameStart"]
end = instance.data["frameEnd"]
for i in range(int(start), (int(end) + 1)):
expected_files.append(
os.path.join(dir, (file % i)).replace("\\", "/"))
return expected_files

View file

@ -2,7 +2,10 @@ import pyblish.api
from openpype.lib import version_up
from openpype.pipeline import registered_host
from openpype.action import get_errored_plugins_from_data
from openpype.hosts.houdini.api import HoudiniHost
from openpype.pipeline.publish import KnownPublishError
class IncrementCurrentFile(pyblish.api.ContextPlugin):
"""Increment the current file.
@ -24,12 +27,22 @@ class IncrementCurrentFile(pyblish.api.ContextPlugin):
def process(self, context):
errored_plugins = get_errored_plugins_from_data(context)
if any(
plugin.__name__ == "HoudiniSubmitPublishDeadline"
for plugin in errored_plugins
):
raise KnownPublishError(
"Skipping incrementing current file because "
"submission to deadline failed."
)
# Filename must not have changed since collecting
host = registered_host() # type: HoudiniHost
current_file = host.current_file()
assert (
context.data["currentFile"] == current_file
), "Collected filename from current scene name."
), "Collected filename mismatches from current scene name."
new_filepath = version_up(current_file)
host.save_workfile(new_filepath)

View file

@ -39,6 +39,7 @@ class HoudiniSubmitDeadline(abstract_submit_deadline.AbstractSubmitDeadline):
hosts = ["houdini"]
families = ["usdrender",
"redshift_rop",
"arnold_rop",
"mantra_rop",
"karma_rop"]
targets = ["local"]

View file

@ -118,13 +118,14 @@ class ProcessSubmittedJobOnFarm(pyblish.api.InstancePlugin):
deadline_plugin = "OpenPype"
targets = ["local"]
hosts = ["fusion", "max", "maya", "nuke",
hosts = ["fusion", "max", "maya", "nuke", "houdini",
"celaction", "aftereffects", "harmony"]
families = ["render.farm", "prerender.farm",
"renderlayer", "imagesequence",
"maxrender", "vrayscene",
"mantra_rop", "karma_rop"]
"vrayscene", "maxrender",
"arnold_rop", "mantra_rop",
"karma_rop"]
aov_filter = {"maya": [r".*([Bb]eauty).*"],
"aftereffects": [r".*"], # for everything from AE