diff --git a/colorbleed/plugins/maya/publish/validate_rig_contents.py b/colorbleed/plugins/maya/publish/validate_rig_contents.py index 6ebf807762..4445a48fca 100644 --- a/colorbleed/plugins/maya/publish/validate_rig_contents.py +++ b/colorbleed/plugins/maya/publish/validate_rig_contents.py @@ -16,17 +16,16 @@ class ValidateRigContents(pyblish.api.InstancePlugin): order = colorbleed.api.ValidateContentsOrder label = "Rig Contents" hosts = ["maya"] - families = ["colorbleed.rig", "colorbleed.rigcontrols", - "colorbleed.rigpointcache"] + families = ["colorbleed.rig"] + + accepted_output = ["mesh", "transform"] + accepted_controllers = ["transform"] + ignore_nodes = [] def process(self, instance): objectsets = ("controls_SET", "out_SET") - - missing = list() - for objectset in objectsets: - if objectset not in instance: - missing.append(objectset) + missing = [obj for obj in objectsets if obj not in instance] assert not missing, ("%s is missing %s" % (instance, missing)) @@ -38,33 +37,78 @@ class ValidateRigContents(pyblish.api.InstancePlugin): "(Empty instance?)") self.log.info("Evaluating contents of object sets..") + not_meshes = list() + not_transforms = list() + invalid_hierachy = list() - # Ensure contents in sets - members = cmds.sets("out_SET", query=True) or [] - assert members, "Must have members in rig out_SET" + error = False - controls = cmds.sets("controls_SET", query=True) or [] - assert controls, "Must have controls in rig control_SET" + # Ensure contents in sets and retrieve long path for all objects + out_members = cmds.sets("out_SET", query=True) or [] + assert out_members, "Must have members in rig out_SET" + out_members = cmds.ls(out_members, long=True) + + controls_members = cmds.sets("controls_SET", query=True) or [] + controls_members = cmds.ls(controls_members, long=True) + assert controls_members, "Must have controls in rig control_SET" + + root_node = cmds.ls(set_members, assemblies=True) + root_content = cmds.listRelatives(root_node, + allDescendents=True, + fullPath=True) # Validate the contents further - shapes = cmds.listRelatives(members, + shapes = cmds.listRelatives(out_members, allDescendents=True, shapes=True, fullPath=True) or [] - for shape in shapes: - if cmds.nodeType(shape) != "mesh": + + # The user can add the shape node to the out_set, this will result + # in none when querying allDescendents + out_shapes = out_members + shapes + + # geometry + for shape in out_shapes: + nodetype = cmds.nodeType(shape) + if nodetype in self.ignore_nodes: + continue + + if nodetype not in self.accepted_output: not_meshes.append(shape) - not_transforms = list() - for node in cmds.sets("controls_SET", query=True) or []: - if cmds.nodeType(node) != "transform": - not_meshes.append(node) + # check if controllers are in the root group + if shape not in root_content: + invalid_hierachy.append(shape) - assert not_transforms == [], ( - "Only transforms can be part of the controls_SET: %s" - % not_transforms) + # curves + for node in controls_members: + nodetype = cmds.nodeType(node) + if nodetype in self.ignore_nodes: + continue - assert not_meshes == [], ( - "Only meshes can be part of the out_SET: %s" - % not_meshes) + if nodetype not in self.accepted_controllers: + not_transforms.append(node) + + # check if controllers are in the root group + if node not in root_content: + invalid_hierachy.append(node) + + if invalid_hierachy: + self.log.error("Found nodes which reside outside of root group " + "while they are set up for publishing." + "\n%s" % invalid_hierachy) + error = True + + if not_transforms: + self.log.error("Only transforms can be part of the controls_SET." + "\n%s" % not_transforms) + error = True + + if not_meshes: + self.log.error("Only meshes can be part of the out_SET\n%s" + % not_meshes) + error = True + + if error: + raise RuntimeError("Invalid rig content. See log for details.") diff --git a/colorbleed/plugins/maya/publish/validate_rig_controllers.py b/colorbleed/plugins/maya/publish/validate_rig_controllers.py new file mode 100644 index 0000000000..dd9f77006c --- /dev/null +++ b/colorbleed/plugins/maya/publish/validate_rig_controllers.py @@ -0,0 +1,80 @@ +from maya import cmds + +import pyblish.api +import colorbleed.api + + +class ValidateRigControllers(pyblish.api.InstancePlugin): + """Check if the controllers have the transformation attributes set to + default values, locked vibisility attributes and are not keyed + """ + order = colorbleed.api.ValidateContentsOrder + 0.05 + label = "Rig Controllers" + hosts = ["maya"] + families = ["colorbleed.rig"] + + def process(self, instance): + + error = False + is_keyed = list() + not_locked = list() + is_offset = list() + + controls = cmds.sets("controls_SET", query=True) + assert controls, "Must have controls in rig control_SET" + + for control in controls: + valid_keyed = self.validate_keyed_state(control) + if not valid_keyed: + is_keyed.append(control) + + # check if visibility is locked + attribute = "{}.visibility".format(control) + locked = cmds.getAttr(attribute, lock=True) + if not locked: + not_locked.append(control) + + valid_transforms = self.validate_transforms(control) + if not valid_transforms: + is_offset.append(control) + + if is_keyed: + self.log.error("No controls can be keyes. Failed :\n" + "%s" % is_keyed) + + if is_offset: + self.log.error("All controls default transformation values. " + "Failed :\n%s" % is_offset) + + if not_locked: + self.log.error("All controls must have visibility " + "attribute locked. Failed :\n" + "%s" % not_locked) + + if error: + raise RuntimeError("Invalid rig controllers. See log for details.") + + def validate_transforms(self, control): + tolerance = 1e-30 + identity = [1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0] + + matrix = cmds.xform(control, query=True, matrix=True, objectSpace=True) + if not all(abs(x - y) < tolerance for x, y in zip(identity, matrix)): + return False + return True + + def validate_keyed_state(self, control): + """Check if the control has an animation curve attached + Args: + control: + + Returns: + + """ + animation_curves = cmds.keyframe(control, query=True, name=True) + if animation_curves: + return False + return True