From aa6a2b9dddcf520ba3af66021b5209de1d320ba3 Mon Sep 17 00:00:00 2001 From: Roy Nieterau Date: Mon, 1 Jul 2024 18:06:19 +0200 Subject: [PATCH] Add validation for default prim when contributing to asset instead of shot --- ...ate_usd_asset_contribution_default_prim.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_asset_contribution_default_prim.py diff --git a/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_asset_contribution_default_prim.py b/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_asset_contribution_default_prim.py new file mode 100644 index 0000000000..c3f20be183 --- /dev/null +++ b/server_addon/houdini/client/ayon_houdini/plugins/publish/validate_usd_asset_contribution_default_prim.py @@ -0,0 +1,76 @@ +import hou +import pyblish.api + +from ayon_core.pipeline import PublishValidationError +from ayon_core.pipeline.publish import RepairAction, OptionalPyblishPluginMixin + +from ayon_houdini.api.action import SelectROPAction +from ayon_houdini.api import plugin + + +class ValidateUSDAssetContributionDefaultPrim(plugin.HoudiniInstancePlugin, + OptionalPyblishPluginMixin): + """Validate the default prim is set when USD contribution is set to asset. + + If the USD asset contributions is enabled and the user has it set to + initialize asset as "asset" then most likely they are looking to publish + into an asset structure - which should have a default prim that matches + the folder's name. To ensure that's the case we force require the + value to be set on the ROP node. + + Note that another validator "Validate USD Rop Default Prim" enforces the + primitive actually exists (or has modifications) if the ROP specifies + a default prim - so that does not have to be validated with this validator. + + """ + + order = pyblish.api.ValidatorOrder + families = ["usdrop"] + hosts = ["houdini"] + label = "Validate USD Asset Contribution Default Prim" + actions = [SelectROPAction, RepairAction] + optional = True + + def process(self, instance): + + # Check if instance is set to be an asset contribution + settings = self.get_attr_values_from_data_for_plugin_name( + "CollectUSDLayerContributions", instance.data + ) + self.log.info(settings) + if ( + not settings.get("contribution_enabled", False) + or settings.get("contribution_target_product_init") != "asset" + ): + return + + rop_node = hou.node(instance.data["instance_node"]) + default_prim = rop_node.evalParm("defaultprim") + if not default_prim: + raise PublishValidationError( + f"No default prim specified on ROP node: {rop_node.path()}" + ) + + folder_name = instance.data["folderPath"].rsplit("/", 1)[-1] + if not default_prim.lstrip("/") == folder_name: + raise PublishValidationError( + f"Default prim specified on ROP node does not match the " + f"asset's folder name: '{default_prim}' " + f"(should be: '/{folder_name}')" + ) + + @classmethod + def repair(cls, instance): + rop_node = hou.node(instance.data["instance_node"]) + rop_node.parm("defaultprim").set( + "/`strsplit(chs(\"folderPath\"), \"/\", -1)`" + ) + + @staticmethod + def get_attr_values_from_data_for_plugin_name( + plugin_name: str, data: dict) -> dict: + return ( + data + .get("publish_attributes", {}) + .get(plugin_name, {}) + )