diff --git a/server_addon/houdini/client/ayon_houdini/plugins/create/create_usdrender.py b/server_addon/houdini/client/ayon_houdini/plugins/create/create_usdrender.py index 2bba71be05..9c7bc0fd3e 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/create/create_usdrender.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/create/create_usdrender.py @@ -29,11 +29,19 @@ class CreateUSDRender(plugin.HoudiniCreator): icon = "magic" description = "Create USD Render" - split_render = True default_renderer = "Karma CPU" + # Default render target + render_target = "farm_split" def create(self, product_name, instance_data, pre_create_data): - import hou # noqa + + # Transfer settings from pre create to instance + creator_attributes = instance_data.setdefault( + "creator_attributes", dict()) + + for key in ["render_target", "review"]: + if key in pre_create_data: + creator_attributes[key] = pre_create_data[key] # TODO: Support creation in /stage if wanted by user # pre_create_data["parent"] = "/stage" @@ -67,7 +75,7 @@ def create(self, product_name, instance_data, pre_create_data): if self.selected_nodes: parms["loppath"] = self.selected_nodes[0].path() - if pre_create_data.get("split_render", self.split_render): + if pre_create_data.get("render_target") == "farm_split": # Do not trigger the husk render, only trigger the USD export parms["runcommand"] = False # By default, the render ROP writes out the render file to a @@ -103,6 +111,30 @@ def create(self, product_name, instance_data, pre_create_data): to_lock = ["productType", "id"] self.lock_parameters(instance_node, to_lock) + def get_instance_attr_defs(self): + """get instance attribute definitions. + Attributes defined in this method are exposed in + publish tab in the publisher UI. + """ + + render_target_items = { + "local": "Local machine rendering", + "local_no_render": "Use existing frames (local)", + "farm": "Farm Rendering", + "farm_split": "Farm Rendering - Split export & render jobs", + } + + return [ + BoolDef("review", + label="Review", + tooltip="Mark as reviewable", + default=True), + EnumDef("render_target", + items=render_target_items, + label="Render target", + default=self.render_target) + ] + def get_pre_create_attr_defs(self): # Retrieve available renderers and convert default renderer to @@ -123,12 +155,11 @@ def get_pre_create_attr_defs(self): default_renderer = None attrs = super(CreateUSDRender, self).get_pre_create_attr_defs() - return attrs + [ + attrs += [ EnumDef("renderer", label="Renderer", default=default_renderer, items=renderer_plugin_to_display_name), - BoolDef("split_render", - label="Split export and render jobs", - default=self.split_render), ] + + return attrs + self.get_instance_attr_defs() diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_farm_instances.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_farm_instances.py index 8fdae06f90..f14ff65518 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_farm_instances.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_farm_instances.py @@ -10,7 +10,8 @@ class CollectFarmInstances(plugin.HoudiniInstancePlugin): "karma_rop", "redshift_rop", "arnold_rop", - "vray_rop"] + "vray_rop", + "usdrender"] targets = ["local", "remote"] label = "Collect farm instances" diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_local_render_instances.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_local_render_instances.py index 259b2378bb..931a79535b 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_local_render_instances.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_local_render_instances.py @@ -21,7 +21,8 @@ class CollectLocalRenderInstances(plugin.HoudiniInstancePlugin): "karma_rop", "redshift_rop", "arnold_rop", - "vray_rop"] + "vray_rop", + "usdrender"] label = "Collect local render instances" diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_render_products.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_render_products.py index ac293d2da4..64b064fd59 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_render_products.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_render_products.py @@ -25,7 +25,9 @@ class CollectRenderProducts(plugin.HoudiniInstancePlugin): """ label = "Collect Render Products" - order = pyblish.api.CollectorOrder + 0.4 + # This plugin should run after CollectUsdRender + # and, before CollectLocalRenderInstances + order = pyblish.api.CollectorOrder + 0.04 families = ["usdrender"] def process(self, instance): @@ -135,8 +137,15 @@ def replace(match): instance.data["files"] = filenames instance.data.setdefault("expectedFiles", []).append(files_by_product) + # Farm Publishing add review logic expects this key to exist and + # be True if render is a multipart Exr. + # otherwise it will most probably fail the AOV filter as multipartExr + # files mostly don't include aov name in the file path. + # Assume multipartExr is 'True' as long as we have one AOV. + instance.data["multipartExr"] = len(files_by_product) <= 1 + def get_aov_identifier(self, render_product): - """Return the AOV identfier for a Render Product + """Return the AOV identifier for a Render Product A Render Product does not really define what 'AOV' it is, it defines the product name (output path) and the render vars to diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_reviewable_instances.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_reviewable_instances.py index 84cd8377a8..1bc797a1c1 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_reviewable_instances.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_reviewable_instances.py @@ -15,7 +15,8 @@ class CollectReviewableInstances(plugin.HoudiniInstancePlugin): "karma_rop", "redshift_rop", "arnold_rop", - "vray_rop"] + "vray_rop", + "usdrender"] def process(self, instance): creator_attribute = instance.data["creator_attributes"] diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_usd_render.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_usd_render.py index e93b753be1..a6e7572a18 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_usd_render.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/collect_usd_render.py @@ -38,10 +38,7 @@ def process(self, instance): rop = hou.node(instance.data.get("instance_node")) - # Store whether we are splitting the render job in an export + render - split_render = not rop.parm("runcommand").eval() - instance.data["splitRender"] = split_render - if split_render: + if instance.data["splitRender"]: # USD file output lop_output = evalParmNoFrame( rop, "lopoutput", pad_character="#" @@ -78,8 +75,6 @@ def replace_to_f(match): if "$F" not in export_file: instance.data["splitRenderFrameDependent"] = False - instance.data["farm"] = True # always submit to farm - # update the colorspace data colorspace_data = get_color_management_preferences() instance.data["colorspaceConfig"] = colorspace_data["config"] diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_render.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_render.py index 8ff8590650..c7ec7603f4 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_render.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/extract_render.py @@ -15,13 +15,20 @@ class ExtractRender(plugin.HoudiniExtractorPlugin): "karma_rop", "redshift_rop", "arnold_rop", - "vray_rop"] + "vray_rop", + "usdrender"] def process(self, instance): creator_attribute = instance.data["creator_attributes"] product_type = instance.data["productType"] rop_node = hou.node(instance.data.get("instance_node")) + # TODO: This section goes against pyblish concepts where + # pyblish plugins should change the state of the scene. + # However, in ayon publisher tool users can have options and + # these options should some how synced with the houdini nodes. + # More info: https://github.com/ynput/ayon-core/issues/417 + # Align split parameter value on rop node to the render target. if instance.data["splitRender"]: if product_type == "arnold_rop": @@ -32,6 +39,8 @@ def process(self, instance): rop_node.setParms({"RS_archive_enable": 1}) elif product_type == "vray_rop": rop_node.setParms({"render_export_mode": "2"}) + elif product_type == "usdrender": + rop_node.setParms({"runcommand": 0}) else: if product_type == "arnold_rop": rop_node.setParms({"ar_ass_export_enable": 0}) @@ -41,6 +50,8 @@ def process(self, instance): rop_node.setParms({"RS_archive_enable": 0}) elif product_type == "vray_rop": rop_node.setParms({"render_export_mode": "1"}) + elif product_type == "usdrender": + rop_node.setParms({"runcommand": 1}) if instance.data.get("farm"): self.log.debug("Render should be processed on farm, skipping local render.") diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_render_arnold.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_render_arnold.py index 5de96e539b..660db0a8bb 100644 --- a/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_render_arnold.py +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_render_arnold.py @@ -35,7 +35,11 @@ def process(self, instance): ) render_chunk_size = submission_data.get("chunk", 1) export_chunk_size = submission_data.get("export_chunk", 1) - usd_file_per_frame = "$F" in instance.data["ifdFile"] + usd_file_per_frame = ( + instance.data["creator_attributes"].get("render_target") == "farm_split" + and + "$F" in instance.data["ifdFile"] + ) frame_start_handle = instance.data["frameStartHandle"] frame_end_handle = instance.data["frameEndHandle"] num_frames = frame_end_handle - frame_start_handle + 1