Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

propagate the number of inputs of the subnetwork to the HDA and support publishing HDAs with spare parameters #172

Merged
43 changes: 40 additions & 3 deletions client/ayon_houdini/plugins/create/create_hda.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""

Expand Down Expand Up @@ -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(
Expand All @@ -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.
Expand All @@ -222,8 +244,17 @@ 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,
)

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(
Expand Down Expand Up @@ -279,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(
Expand Down
10 changes: 10 additions & 0 deletions client/ayon_houdini/plugins/load/load_hda.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
39 changes: 36 additions & 3 deletions client/ayon_houdini/plugins/publish/extract_hda.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
# -*- coding: utf-8 -*-
import os
from pprint import pformat
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
label = "Extract HDA"
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()
Expand All @@ -23,7 +37,26 @@ def process(self, instance):
self.log.info("setting version: {}".format(next_version))
hda_def.setVersion(str(next_version))
hda_def.setOptions(hda_options)
hda_def.save(hda_def.libraryFilePath(), hda_node, hda_options)

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"] = []
Expand Down
Loading