Merge pull request #5595 from BigRoy/bugfix/maya_validate_rig_sets

This commit is contained in:
Ondřej Samohel 2023-09-08 09:56:41 +02:00 committed by GitHub
commit e331a07589
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 108 additions and 31 deletions

View file

@ -0,0 +1,39 @@
import pyblish.api
from maya import cmds
class CollectRigSets(pyblish.api.InstancePlugin):
"""Ensure rig contains pipeline-critical content
Every rig must contain at least two object sets:
"controls_SET" - Set of all animatable controls
"out_SET" - Set of all cacheable meshes
"""
order = pyblish.api.CollectorOrder + 0.05
label = "Collect Rig Sets"
hosts = ["maya"]
families = ["rig"]
accepted_output = ["mesh", "transform"]
accepted_controllers = ["transform"]
def process(self, instance):
# Find required sets by suffix
searching = {"controls_SET", "out_SET"}
found = {}
for node in cmds.ls(instance, exactType="objectSet"):
for suffix in searching:
if node.endswith(suffix):
found[suffix] = node
searching.remove(suffix)
break
if not searching:
break
self.log.debug("Found sets: {}".format(found))
rig_sets = instance.data.setdefault("rig_sets", {})
for name, objset in found.items():
rig_sets[name] = objset

View file

@ -2,7 +2,9 @@ import pyblish.api
from maya import cmds
from openpype.pipeline.publish import (
PublishValidationError, ValidateContentsOrder)
PublishValidationError,
ValidateContentsOrder
)
class ValidateRigContents(pyblish.api.InstancePlugin):
@ -24,31 +26,45 @@ class ValidateRigContents(pyblish.api.InstancePlugin):
def process(self, instance):
objectsets = ("controls_SET", "out_SET")
missing = [obj for obj in objectsets if obj not in instance]
assert not missing, ("%s is missing %s" % (instance, missing))
# Find required sets by suffix
required = ["controls_SET", "out_SET"]
missing = [
key for key in required if key not in instance.data["rig_sets"]
]
if missing:
raise PublishValidationError(
"%s is missing sets: %s" % (instance, ", ".join(missing))
)
controls_set = instance.data["rig_sets"]["controls_SET"]
out_set = instance.data["rig_sets"]["out_SET"]
# Ensure there are at least some transforms or dag nodes
# in the rig instance
set_members = instance.data['setMembers']
if not cmds.ls(set_members, type="dagNode", long=True):
raise PublishValidationError(
("No dag nodes in the pointcache instance. "
"(Empty instance?)"))
"No dag nodes in the pointcache instance. "
"(Empty instance?)"
)
# Ensure contents in sets and retrieve long path for all objects
output_content = cmds.sets("out_SET", query=True) or []
assert output_content, "Must have members in rig out_SET"
output_content = cmds.sets(out_set, query=True) or []
if not output_content:
raise PublishValidationError("Must have members in rig out_SET")
output_content = cmds.ls(output_content, long=True)
controls_content = cmds.sets("controls_SET", query=True) or []
assert controls_content, "Must have members in rig controls_SET"
controls_content = cmds.sets(controls_set, query=True) or []
if not controls_content:
raise PublishValidationError(
"Must have members in rig controls_SET"
)
controls_content = cmds.ls(controls_content, long=True)
# Validate members are inside the hierarchy from root node
root_node = cmds.ls(set_members, assemblies=True)
hierarchy = cmds.listRelatives(root_node, allDescendents=True,
fullPath=True)
root_nodes = cmds.ls(set_members, assemblies=True, long=True)
hierarchy = cmds.listRelatives(root_nodes, allDescendents=True,
fullPath=True) + root_nodes
hierarchy = set(hierarchy)
invalid_hierarchy = []

View file

@ -52,22 +52,30 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
def process(self, instance):
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError('{} failed, see log '
'information'.format(self.label))
raise PublishValidationError(
'{} failed, see log information'.format(self.label)
)
@classmethod
def get_invalid(cls, instance):
controllers_sets = [i for i in instance if i == "controls_SET"]
controls = cmds.sets(controllers_sets, query=True)
assert controls, "Must have 'controls_SET' in rig instance"
controls_set = instance.data["rig_sets"].get("controls_SET")
if not controls_set:
cls.log.error(
"Must have 'controls_SET' in rig instance"
)
return [instance.data["instance_node"]]
controls = cmds.sets(controls_set, query=True)
# Ensure all controls are within the top group
lookup = set(instance[:])
assert all(control in lookup for control in cmds.ls(controls,
long=True)), (
"All controls must be inside the rig's group."
)
if not all(control in lookup for control in cmds.ls(controls,
long=True)):
cls.log.error(
"All controls must be inside the rig's group."
)
return [controls_set]
# Validate all controls
has_connections = list()
@ -181,9 +189,17 @@ class ValidateRigControllers(pyblish.api.InstancePlugin):
@classmethod
def repair(cls, instance):
controls_set = instance.data["rig_sets"].get("controls_SET")
if not controls_set:
cls.log.error(
"Unable to repair because no 'controls_SET' found in rig "
"instance: {}".format(instance)
)
return
# Use a single undo chunk
with undo_chunk():
controls = cmds.sets("controls_SET", query=True)
controls = cmds.sets(controls_set, query=True)
for control in controls:
# Lock visibility

View file

@ -56,11 +56,11 @@ class ValidateRigControllersArnoldAttributes(pyblish.api.InstancePlugin):
@classmethod
def get_invalid(cls, instance):
controllers_sets = [i for i in instance if i == "controls_SET"]
if not controllers_sets:
controls_set = instance.data["rig_sets"].get("controls_SET")
if not controls_set:
return []
controls = cmds.sets(controllers_sets, query=True) or []
controls = cmds.sets(controls_set, query=True) or []
if not controls:
return []

View file

@ -38,16 +38,19 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
# if a deformer has been created on the shape
invalid = self.get_invalid(instance)
if invalid:
raise PublishValidationError("Nodes found with mismatching "
"IDs: {0}".format(invalid))
raise PublishValidationError(
"Nodes found with mismatching IDs: {0}".format(invalid)
)
@classmethod
def get_invalid(cls, instance):
"""Get all nodes which do not match the criteria"""
invalid = []
out_set = instance.data["rig_sets"].get("out_SET")
if not out_set:
return []
out_set = next(x for x in instance if x.endswith("out_SET"))
invalid = []
members = cmds.sets(out_set, query=True)
shapes = cmds.ls(members,
dag=True,

View file

@ -47,7 +47,10 @@ class ValidateRigOutputIds(pyblish.api.InstancePlugin):
invalid = {}
if compute:
out_set = next(x for x in instance if "out_SET" in x)
out_set = instance.data["rig_sets"].get("out_SET")
if not out_set:
instance.data["mismatched_output_ids"] = invalid
return invalid
instance_nodes = cmds.sets(out_set, query=True, nodesOnly=True)
instance_nodes = cmds.ls(instance_nodes, long=True)