Bases: HoudiniInstancePlugin
, OptionalPyblishPluginMixin
Validate all geometry prims have a material binding.
This does not necessarily validate the material binding is authored
by the current layers if the input already had material bindings.
Source code in client/ayon_houdini/plugins/publish/validate_usd_look_assignments.py
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
104
105
106
107
108
109
110
111 | class ValidateUsdLookAssignments(plugin.HoudiniInstancePlugin,
OptionalPyblishPluginMixin):
"""Validate all geometry prims have a material binding.
Note: This does not necessarily validate the material binding is authored
by the current layers if the input already had material bindings.
"""
order = pyblish.api.ValidatorOrder
families = ["look"]
hosts = ["houdini"]
label = "Validate All Geometry Has Material Assignment"
actions = [SelectROPAction]
optional = True
# The USD documentation mentions that it's okay to have custom material
# purposes but the USD standard only supports 2 (technically 3, since
# allPurpose is empty)
allowed_material_purposes = (
UsdShade.Tokens.full,
UsdShade.Tokens.preview,
UsdShade.Tokens.allPurpose,
)
def process(self, instance):
if not self.is_active(instance.data):
return
# Get Usd.Stage from "Collect ROP Sdf Layers and USD Stage" plug-in
stage = instance.data.get("stage")
if not stage:
self.log.debug("No USD stage found.")
return
stage: Usd.Stage
# We iterate the composed stage for code simplicity; however this
# means that it does not validate across e.g. multiple model variants
# but only checks against the current composed stage. Likely this is
# also what you actually want to validate, because your look might not
# apply to *all* model variants.
invalid: List[Sdf.Path] = []
for prim in stage.Traverse():
if not prim.IsA(UsdGeom.Gprim):
continue
if not has_material(prim, purposes=self.allowed_material_purposes):
invalid.append(prim.GetPath())
for path in sorted(invalid):
self.log.warning("No material binding on: %s", path.pathString)
if invalid:
raise PublishValidationError(
"Found geometry without material bindings.",
title="No assigned materials",
description=self.get_description()
)
@staticmethod
def get_description():
return inspect.cleandoc(
"""### Geometry has no material assignments.
A look publish should usually define a material assignment for all
geometry of a model. As such, this validates whether all geometry
currently has at least one material binding applied.
"""
)
|