From 27b4025fe244ecf4f327da9ab27c1c816dfda249 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 15 Nov 2024 17:34:42 +0200 Subject: [PATCH 1/6] propagate the number of inputs of the subnetwork to the HDA --- client/ayon_houdini/plugins/create/create_hda.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/ayon_houdini/plugins/create/create_hda.py b/client/ayon_houdini/plugins/create/create_hda.py index 7613735f7b..27ac1ba72b 100644 --- a/client/ayon_houdini/plugins/create/create_hda.py +++ b/client/ayon_houdini/plugins/create/create_hda.py @@ -222,7 +222,9 @@ def create_instance_node( name=type_name, description=node_name, hda_file_name="$HIP/{}.hda".format(node_name), - ignore_external_references=True + ignore_external_references=True, + min_num_inputs=0, + max_num_inputs=len(to_hda.inputs()) or 1, ) hda_node.layoutChildren() elif self._check_existing(folder_path, node_name): From 4ab72b90ab62ba644166e91740d6a81f596b5591 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 15 Nov 2024 23:29:12 +0200 Subject: [PATCH 2/6] keep user spare parameters when publishing --- .../plugins/publish/extract_hda.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/client/ayon_houdini/plugins/publish/extract_hda.py b/client/ayon_houdini/plugins/publish/extract_hda.py index e4449d11f8..d0651b5a99 100644 --- a/client/ayon_houdini/plugins/publish/extract_hda.py +++ b/client/ayon_houdini/plugins/publish/extract_hda.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- import os -from pprint import pformat import hou import pyblish.api from ayon_houdini.api import plugin @@ -13,17 +12,33 @@ class ExtractHDA(plugin.HoudiniExtractorPlugin): families = ["hda"] def process(self, instance): - self.log.info(pformat(instance.data)) + hda_node = hou.node(instance.data.get("instance_node")) hda_def = hda_node.type().definition() hda_options = hda_def.options() hda_options.setSaveInitialParmsAndContents(True) + hda_options.setSaveSpareParms(True) next_version = instance.data["anatomyData"]["version"] self.log.info("setting version: {}".format(next_version)) hda_def.setVersion(str(next_version)) hda_def.setOptions(hda_options) + + # Get `Extra` AYON parameters + parm_group = hda_node.parmTemplateGroup() + parm_folder = parm_group.findFolder("Extra") # This name is a hard coded name in AYON. + assert parm_folder, f"Extra parm folder does not exist: {hda_node.path()}" + + # Remove `Extra` AYON parameters + parm_group.remove(parm_folder.name()) + hda_node.setParmTemplateGroup(parm_group) + + # Save the HDA file hda_def.save(hda_def.libraryFilePath(), hda_node, hda_options) + + # Add `Extra` AYON parameters back + parm_group.append(parm_folder) + hda_node.setParmTemplateGroup(parm_group) if "representations" not in instance.data: instance.data["representations"] = [] From 06456af59d7e34f6c2a689c1ddbd8327fec87d6e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Dec 2024 11:49:35 +0100 Subject: [PATCH 3/6] Use context manager to revert the original parameter template group --- .../plugins/publish/extract_hda.py | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/client/ayon_houdini/plugins/publish/extract_hda.py b/client/ayon_houdini/plugins/publish/extract_hda.py index d0651b5a99..a2bd8cf1c2 100644 --- a/client/ayon_houdini/plugins/publish/extract_hda.py +++ b/client/ayon_houdini/plugins/publish/extract_hda.py @@ -1,10 +1,25 @@ # -*- coding: utf-8 -*- import os +import contextlib + import hou import pyblish.api + +from ayon_core.pipeline import PublishError from ayon_houdini.api import plugin +@contextlib.contextmanager +def revert_original_parm_template_group(node: "hou.OpNode"): + """Restore parm template group after the context""" + parm_group = node.parmTemplateGroup() + try: + yield + finally: + # Set the original + node.setParmTemplateGroup(parm_group) + + class ExtractHDA(plugin.HoudiniExtractorPlugin): order = pyblish.api.ExtractorOrder @@ -24,21 +39,25 @@ def process(self, instance): hda_def.setVersion(str(next_version)) hda_def.setOptions(hda_options) - # Get `Extra` AYON parameters - parm_group = hda_node.parmTemplateGroup() - parm_folder = parm_group.findFolder("Extra") # This name is a hard coded name in AYON. - assert parm_folder, f"Extra parm folder does not exist: {hda_node.path()}" - - # Remove `Extra` AYON parameters - parm_group.remove(parm_folder.name()) - hda_node.setParmTemplateGroup(parm_group) - - # Save the HDA file - hda_def.save(hda_def.libraryFilePath(), hda_node, hda_options) - - # Add `Extra` AYON parameters back - parm_group.append(parm_folder) - hda_node.setParmTemplateGroup(parm_group) + with revert_original_parm_template_group(hda_node): + # Remove our own custom parameters so that if the HDA definition + # has "Save Spare Parameters" enabled, we don't save our custom + # attributes + # Get our custom `Extra` AYON parameters + parm_group = hda_node.parmTemplateGroup() + # The name 'Extra' is a hard coded name in AYON. + parm_folder = parm_group.findFolder("Extra") + if not parm_folder: + raise PublishError( + f"Extra parm folder does not exist: {hda_node.path()}" + ) + + # Remove `Extra` AYON parameters + parm_group.remove(parm_folder.name()) + hda_node.setParmTemplateGroup(parm_group) + + # Save the HDA file + hda_def.save(hda_def.libraryFilePath(), hda_node, hda_options) if "representations" not in instance.data: instance.data["representations"] = [] From 7f4ac93273b7cdacf52205be8a36127f6a763b92 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Dec 2024 11:50:13 +0100 Subject: [PATCH 4/6] Do not enforce `setSaveSpareParms` to be True - but allow user to enable it manually in the HDA definition if they want --- client/ayon_houdini/plugins/publish/extract_hda.py | 1 - 1 file changed, 1 deletion(-) diff --git a/client/ayon_houdini/plugins/publish/extract_hda.py b/client/ayon_houdini/plugins/publish/extract_hda.py index a2bd8cf1c2..3d49c3332f 100644 --- a/client/ayon_houdini/plugins/publish/extract_hda.py +++ b/client/ayon_houdini/plugins/publish/extract_hda.py @@ -32,7 +32,6 @@ def process(self, instance): hda_def = hda_node.type().definition() hda_options = hda_def.options() hda_options.setSaveInitialParmsAndContents(True) - hda_options.setSaveSpareParms(True) next_version = instance.data["anatomyData"]["version"] self.log.info("setting version: {}".format(next_version)) From 34ed4197dc14bd07dc8614b214bffe436c4320a5 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Dec 2024 11:51:06 +0100 Subject: [PATCH 5/6] Add support to promote spare parameters on Creation (like Houdini default behavior) + fix having just a HDA selected to make that publishable instead of collapsing it. --- .../ayon_houdini/plugins/create/create_hda.py | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/client/ayon_houdini/plugins/create/create_hda.py b/client/ayon_houdini/plugins/create/create_hda.py index 27ac1ba72b..0f411bb01f 100644 --- a/client/ayon_houdini/plugins/create/create_hda.py +++ b/client/ayon_houdini/plugins/create/create_hda.py @@ -141,6 +141,12 @@ def set_tool_submenu(hda_def, # endregion +def promote_spare_parameters(node): + """Promote spare parameters to HDA node type definition""" + ptg = node.parmTemplateGroup() + node.type().definition().setParmTemplateGroup(ptg) + + class CreateHDA(plugin.HoudiniCreator): """Publish Houdini Digital Asset file.""" @@ -178,12 +184,27 @@ def create_instance_node( if pre_create_data is None: pre_create_data = {} + use_promote_spare_parameters = pre_create_data.get( + "use_promote_spare_parameters", True) + if self.selected_nodes: # if we have `use selection` enabled, and we have some # selected nodes ... - if self.selected_nodes[0].type().name() == "subnet": - to_hda = self.selected_nodes[0] + one_node_selected = len(self.selected_nodes) == 1 + first_selected_node = self.selected_nodes[0] + + # If only an HDA is selected, publish just that node as HDA. + if one_node_selected and first_selected_node.type().definition(): + to_hda = first_selected_node + use_promote_spare_parameters = False + + # If only a single subnet is selected, turn that into the HDA. + elif one_node_selected and first_selected_node.type().name() == "subnet": + to_hda = first_selected_node to_hda.setName("{}_subnet".format(node_name), unique_name=True) + + # Collapse all selected nodes into a subnet and turn that into + # the HDA. else: parent_node = self.selected_nodes[0].parent() subnet = parent_node.collapseIntoSubnet( @@ -202,6 +223,7 @@ def create_instance_node( to_hda = parent_node.createNode( "subnet", node_name="{}_subnet".format(node_name)) + if not to_hda.type().definition(): # if node type has not its definition, it is not user # created hda. We test if hda can be created from the node. @@ -226,6 +248,13 @@ def create_instance_node( min_num_inputs=0, max_num_inputs=len(to_hda.inputs()) or 1, ) + + if use_promote_spare_parameters: + # Similar to Houdini default behavior, when enabled this will + # promote spare parameters to type properties on initial + # creation of the HDA. + promote_spare_parameters(hda_node) + hda_node.layoutChildren() elif self._check_existing(folder_path, node_name): raise CreatorError( @@ -281,6 +310,12 @@ def get_pre_create_attr_defs(self): "'AYON/project_name/your_HDA_name'", default=True, label="Use Project as menu entry"), + BoolDef("use_promote_spare_parameters", + tooltip="Similar to Houdini default behavior, when " + "enabled this will promote spare parameters to " + "type properties on initial creation of the HDA.", + default=True, + label="Promote Spare Parameters"), ] def get_dynamic_data( From 72308a4a4debfea3776a79b8a67ca0a80643872e Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Thu, 5 Dec 2024 14:40:53 +0200 Subject: [PATCH 6/6] Move `Extra` parameters folder to the back on updating HDA from scene inventory --- client/ayon_houdini/plugins/load/load_hda.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/ayon_houdini/plugins/load/load_hda.py b/client/ayon_houdini/plugins/load/load_hda.py index fcf0e834f8..41ad6aef42 100644 --- a/client/ayon_houdini/plugins/load/load_hda.py +++ b/client/ayon_houdini/plugins/load/load_hda.py @@ -75,6 +75,16 @@ def update(self, container, context): "representation": repre_entity["id"] }) + # Move the Extra parameter folder to the back. + parm_group = hda_node.parmTemplateGroup() + # The name 'Extra' is a hard coded name in AYON. + parm_folder = parm_group.findFolder("Extra") + # Remove `Extra` AYON parameters + parm_group.remove(parm_folder.name()) + # Add `Extra` AYON parameters back + parm_group.append(parm_folder) + hda_node.setParmTemplateGroup(parm_group) + def remove(self, container): node = container["node"] parent = node.parent()