From 27b4025fe244ecf4f327da9ab27c1c816dfda249 Mon Sep 17 00:00:00 2001 From: MustafaJafar Date: Fri, 15 Nov 2024 17:34:42 +0200 Subject: [PATCH 1/9] 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/9] 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 e5caf2fa58ad4fea48d7a4e5ea47213128e44133 Mon Sep 17 00:00:00 2001 From: ynbot Date: Tue, 26 Nov 2024 15:17:29 +0000 Subject: [PATCH 3/9] [Automated] Update assign_pr_to_project caller workflow --- .github/workflows/assign_pr_to_project.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.github/workflows/assign_pr_to_project.yml b/.github/workflows/assign_pr_to_project.yml index 4bb3d1742c..92d2ff2916 100644 --- a/.github/workflows/assign_pr_to_project.yml +++ b/.github/workflows/assign_pr_to_project.yml @@ -1,5 +1,16 @@ name: 🔸Auto assign pr on: + workflow_dispatch: + inputs: + pr_number: + type: number + description: "Run workflow for this PR number" + required: true + project_id: + type: number + description: "Github Project Number" + required: true + default: 16 pull_request: types: - opened @@ -9,7 +20,7 @@ jobs: uses: ynput/ops-repo-automation/.github/workflows/pr_to_project.yml@main with: repo: "${{ github.repository }}" - project_id: 16 - pull_request_number: ${{ github.event.pull_request.number }} + project_id: ${{ inputs.project_id || 16 }} + pull_request_number: ${{ github.event.pull_request.number || inputs.pr_number }} secrets: token: ${{ secrets.YNPUT_BOT_TOKEN }} From 2d515a4f1b0b474146e4328c223742ae16b53861 Mon Sep 17 00:00:00 2001 From: ynbot Date: Fri, 29 Nov 2024 08:16:59 +0000 Subject: [PATCH 4/9] [Automated] Update assign_pr_to_project caller workflow --- .github/workflows/assign_pr_to_project.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/assign_pr_to_project.yml b/.github/workflows/assign_pr_to_project.yml index 92d2ff2916..14e1a02075 100644 --- a/.github/workflows/assign_pr_to_project.yml +++ b/.github/workflows/assign_pr_to_project.yml @@ -17,10 +17,11 @@ on: jobs: auto-assign-pr: + if: ${{ github.event.pull_request.head.repo.full_name == github.repository }} uses: ynput/ops-repo-automation/.github/workflows/pr_to_project.yml@main with: repo: "${{ github.repository }}" - project_id: ${{ inputs.project_id || 16 }} - pull_request_number: ${{ github.event.pull_request.number || inputs.pr_number }} + project_id: "${{ inputs.project_id }}" + pull_request_number: "${{ github.event.pull_request.number || inputs.pr_number }}" secrets: token: ${{ secrets.YNPUT_BOT_TOKEN }} From cacbe68dbaf2297575e5620ff1b1494bfe958763 Mon Sep 17 00:00:00 2001 From: ynbot Date: Sat, 30 Nov 2024 14:31:10 +0000 Subject: [PATCH 5/9] [Automated] Update assign_pr_to_project caller workflow --- .github/workflows/assign_pr_to_project.yml | 35 +++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/assign_pr_to_project.yml b/.github/workflows/assign_pr_to_project.yml index 14e1a02075..e61d281c2a 100644 --- a/.github/workflows/assign_pr_to_project.yml +++ b/.github/workflows/assign_pr_to_project.yml @@ -3,25 +3,46 @@ on: workflow_dispatch: inputs: pr_number: - type: number + type: string description: "Run workflow for this PR number" required: true project_id: - type: number + type: string description: "Github Project Number" required: true - default: 16 + default: "16" pull_request: types: - opened +env: + GH_TOKEN: ${{ github.token }} + jobs: + get-pr-repo: + runs-on: ubuntu-latest + outputs: + pr_repo_name: ${{ steps.get-repo-name.outputs.repo_name || github.event.pull_request.head.repo.full_name }} + + # INFO `github.event.pull_request.head.repo.full_name` is not available on manual triggered (dispatched) runs + steps: + - name: Get PR repo name + if: ${{ github.event_name == 'workflow_dispatch' }} + id: get-repo-name + run: | + repo_name=$(gh pr view ${{ inputs.pr_number }} --json headRepository,headRepositoryOwner --repo ${{ github.repository }} | jq -r '.headRepositoryOwner.login + "/" + .headRepository.name') + echo "repo_name=$repo_name" >> $GITHUB_OUTPUT + auto-assign-pr: - if: ${{ github.event.pull_request.head.repo.full_name == github.repository }} + needs: + - get-pr-repo + if: ${{ needs.get-pr-repo.outputs.pr_repo_name == github.repository }} uses: ynput/ops-repo-automation/.github/workflows/pr_to_project.yml@main with: repo: "${{ github.repository }}" - project_id: "${{ inputs.project_id }}" - pull_request_number: "${{ github.event.pull_request.number || inputs.pr_number }}" + project_id: ${{ inputs.project_id != '' && fromJSON(inputs.project_id) || 16 }} + pull_request_number: ${{ github.event.pull_request.number || fromJSON(inputs.pr_number) }} secrets: - token: ${{ secrets.YNPUT_BOT_TOKEN }} + # INFO fallback to default `github.token` is required for PRs from forks + # INFO organization secrets won't be available to forks + token: ${{ secrets.YNPUT_BOT_TOKEN || github.token}} From 06456af59d7e34f6c2a689c1ddbd8327fec87d6e Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Thu, 5 Dec 2024 11:49:35 +0100 Subject: [PATCH 6/9] 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 7/9] 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 8/9] 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 9/9] 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()