Skip to content

validate_usd_asset_contribution_default_prim

ValidateUSDAssetContributionDefaultPrim

Bases: 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.

Source code in client/ayon_houdini/plugins/publish/validate_usd_asset_contribution_default_prim.py
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
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]

    # TODO: Unfortunately currently this does not show as optional toggle
    #   because the product type is `usd` and not `usdrop` - however we do
    #   not want to run this for ALL `usd` product types?
    optional = True

    def process(self, instance):
        if not self.is_active(instance.data):
            return

        # Check if instance is set to be an asset contribution
        settings = self.get_attr_values_from_data_for_plugin_name(
            "CollectUSDLayerContributions", instance.data
        )
        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()}",
                description=self.get_description()
            )

        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}')"
                ,
                description=self.get_description()
            )

    @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, {})
        )

    def get_description(self):
        return inspect.cleandoc(
            """### Default primitive not set to current asset

            The USD instance has **USD Contribution** enabled and is set to
            initialize as **asset**. The asset requires a default root
            primitive with the name of the folder it's related to.

            For example, you're working in `/asset/char_hero` then the
            folder's name is `char_hero`. For the asset hence all prims should
            live under `/char_hero` root primitive.

            This validation solely ensures the **default primitive** on the ROP
            node is set to match the folder name.
            """
        )