OpenPype
OpenPype copied to clipboard
Maya: per face shaders assignment validator
We need to validate per face shader assignments as it breaks look publishing
per face shaders should be forbidden as we are not able to handle topology changes and identify faces/shaders relationship consistently.
[cuID:2eqzt6m]
There is validator for this but seems that it doesn't work for all cases validate_look_single_shader.py
We need to test it more
If you can provide me scenes that do incorrectly pass the validation let me know how to reproduce and I'd be happy to patch it up.
If we only count the number of shader connections to assume there are component level assignments we are missing the case where you select ALL faces of an object and assign the shader.
So there will be only one shader but on a component level.
Valid point! Will have a look.
We could do this to detect component assignments specifically:
from maya import cmds
NODE_TYPE_FACE_COMPONENTS = {
"mesh": ".f[*]",
"nurbsSurface": ".sf[*][*]"
}
for node in cmds.ls(type=["mesh", "nurbsSurface"]):
sets = cmds.listSets(o=mesh)
shading_engines = cmds.ls(sets, type="shadingEngine")
# Check if any face or surface patch component assignments
# were made to a shadingEngine
node_type = cmds.nodeType(node)
node_components = node + NODE_TYPE_FACE_COMPONENTS[node_type]
for shading_engine in shading_engines:
has_component_assignments = cmds.sets(node_components, anyMember=shading_engine)
print(f"{node} has component assignments with {shading_engine}")
Not sure if there's a simpler way.
Actually, this might be the way:
from maya import cmds
for node in cmds.ls(type=("mesh", "nurbsSurface")):
component_assignments = cmds.listConnections(node + ".compInstObjGroups[*].compObjectGroups[*]", type="shadingEngine")
print(component_assignments)
shape_assignments = cmds.listConnections(node + ".instObjGroups[*].objectGroups[*]", type="shadingEngine")
print(shape_assignments)
If we only count the number of shader connections to assume there are component level assignments we are missing the case where you select ALL faces of an object and assign the shader.
❤️ We actually ran into this with a scene and it wasn't trivial to figure out that that was the issue in the scene. A mixture of Pyblish plug-ins started failing due to this.
Here's the quick workaround I wrote to 'repair' the scene:
# Re-assign shaders that are assigned to *ALL* face components of a mesh
from maya import cmds
for sg in cmds.ls(type="shadingEngine"):
members = cmds.sets(sg, query=True) or []
for member in members:
if ".f[" in member:
node, component = member.split(".", 1)
num_faces = cmds.polyEvaluate(node, face=True)
if member.endswith(f".f[0:{num_faces-1}]"):
print(f"Fixing {member}")
# All faces are assigned. Assign the node instead
cmds.sets(node, forceElement=sg)
Note the Py3 f-string formatting...