From 7ef29e37f67f763c62704fe97795d4dd43cba93c Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 15:07:14 +0200 Subject: [PATCH] improved validating look, improved save function, added filter_out_nodes --- colorbleed/maya/__init__.py | 33 +++------ colorbleed/maya/lib.py | 44 ++++++++++-- .../maya/publish/_validate_node_ids.py | 46 ------------- .../plugins/maya/publish/collect_look.py | 38 +++++------ .../maya/publish/validate_frame_range.py | 5 +- .../maya/publish/validate_look_contents.py | 68 +++++++++++++++---- ...lidate_look_default_shaders_connections.py | 2 +- .../publish/validate_look_deformed_shapes.py | 2 +- .../validate_look_ignore_color_space.py | 2 +- .../publish/validate_look_members_node_ids.py | 55 +++++++-------- .../publish/validate_look_members_unique.py | 19 +++--- .../validate_look_no_default_shaders.py | 66 +++++++----------- .../publish/validate_look_node_unique_ids.py | 6 +- .../maya/publish/validate_model_content.py | 2 - .../plugins/maya/publish/validate_node_ids.py | 51 ++++++++++++++ .../maya/publish/validate_unique_node_ids.py | 25 ++++--- ...tion.py => collect_assumed_destination.py} | 15 ++-- colorbleed/plugins/publish/collect_comment.py | 2 +- 18 files changed, 271 insertions(+), 210 deletions(-) delete mode 100644 colorbleed/plugins/maya/publish/_validate_node_ids.py create mode 100644 colorbleed/plugins/maya/publish/validate_node_ids.py rename colorbleed/plugins/publish/{collect_resource_destination.py => collect_assumed_destination.py} (87%) diff --git a/colorbleed/maya/__init__.py b/colorbleed/maya/__init__.py index 8bf5764a0a..94f315faee 100644 --- a/colorbleed/maya/__init__.py +++ b/colorbleed/maya/__init__.py @@ -8,6 +8,7 @@ from pyblish import api as pyblish from maya import cmds from . import menu +from . import lib PARENT_DIR = os.path.dirname(__file__) PACKAGE_DIR = os.path.dirname(PARENT_DIR) @@ -96,31 +97,19 @@ def on_save(_): avalon.logger.info("Running callback on save..") - # establish set of nodes to ignore - ignore = set(["initialShadingGroup", "initialParticleSE"]) - ignore |= set(cmds.ls(long=True, readOnly=True)) - ignore |= set(cmds.ls(long=True, lockedNodes=True)) - - types = ["shadingEngine", "file", "mesh", "nurbsCurve"] - - # the items which need to pass the id to their parent - nodes = set(cmds.ls(type=types, long=True)) - - # Add the collected transform to the nodes - transforms = cmds.listRelatives(list(nodes), - parent=True, - fullPath=True) or [] - - nodes |= set(transforms) - - # Remove the ignored nodes - nodes -= ignore + types = ["objectSet", "file", "mesh", "nurbsCurve", "nurbsSurface"] + type_nodes = set(cmds.ls(type=types, long=True)) + nodes = lib.filter_out_nodes(type_nodes, + defaults=True, + referenced_nodes=True) # Lead with asset ID from the database asset = os.environ["AVALON_ASSET"] - asset_id = io.find_one({"type": "asset", "name": asset}) + asset_id = io.find_one({"type": "asset", "name": asset}, + projection={"_id": True}) # generate the ids - for node in nodes: - _set_uuid(str(asset_id["_id"]), node) + for node in nodes: + print node + _set_uuid(str(asset_id["_id"]), node) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index c73d1f412a..343847a4fb 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -613,7 +613,43 @@ def remap_resource_nodes(resources, folder=None): cmds.file(save=True, type="mayaAscii") -def _get_id(node): +def filter_out_nodes(nodes, defaults=False, referenced_nodes=False): + """Filter out any node which are locked (reference) or readOnly + + Args: + nodes (set): nodes to filter + locked (bool): set True to filter out lockedNodes + readonly (bool): set True to filter out readOnly + Returns: + nodes (list): list of filtered nodes + """ + # establish set of nodes to ignore + # `readOnly` flag is obsolete as of Maya 2016 therefor we explicitly remove + # default nodes and reference nodes + + ignore = set() + if referenced_nodes: + ignore |= set(cmds.ls(long=True, referencedNodes=referenced_nodes)) + + if defaults: + ignore |= set(cmds.ls(long=True, defaultNodes=defaults)) + + # The items which need to pass the id to their parent + # Add the collected transform to the nodes + dag = cmds.ls(list(nodes), + type="dagNode", + long=True) # query only dag nodes + transforms = cmds.listRelatives(dag, + parent=True, + fullPath=True) or [] + + nodes |= set(transforms) + nodes -= ignore # Remove the ignored nodes + + return nodes + + +def get_id(node): """ Get the `cbId` attribute of the given node Args: @@ -817,7 +853,7 @@ def assign_look(nodes, subset="lookDefault"): # Group all nodes per asset id grouped = defaultdict(list) for node in nodes: - colorbleed_id = _get_id(node) + colorbleed_id = get_id(node) if not colorbleed_id: continue @@ -883,11 +919,11 @@ def apply_shaders(relationships, shadernodes, nodes): # region compute lookup ns_nodes_by_id = defaultdict(list) for node in nodes: - ns_nodes_by_id[_get_id(node)].append(node) + ns_nodes_by_id[get_id(node)].append(node) shading_engines_by_id = defaultdict(list) for shad in shading_engines: - shading_engines_by_id[_get_id(shad)].append(shad) + shading_engines_by_id[get_id(shad)].append(shad) # endregion # region assign diff --git a/colorbleed/plugins/maya/publish/_validate_node_ids.py b/colorbleed/plugins/maya/publish/_validate_node_ids.py deleted file mode 100644 index bfb47abe33..0000000000 --- a/colorbleed/plugins/maya/publish/_validate_node_ids.py +++ /dev/null @@ -1,46 +0,0 @@ -import pyblish.api -import colorbleed.api - - -class ValidateNodeIds(pyblish.api.InstancePlugin): - """Validate nodes have colorbleed id attributes - - All look sets should have id attributes. - - """ - - label = 'Node Id Attributes' - families = ['colorbleed.look', 'colorbleed.model'] - hosts = ['maya'] - order = colorbleed.api.ValidatePipelineOrder - actions = [colorbleed.api.SelectInvalidAction, - colorbleed.api.GenerateUUIDsOnInvalidAction] - - @staticmethod - def get_invalid(instance): - import maya.cmds as cmds - - nodes = instance.data["setMembers"] - - # Ensure all nodes have a cbId - data_id = {} - invalid = [] - for node in nodes: - try: - uuid = cmds.getAttr("{}.cbId".format(node)) - data_id[uuid] = node - if uuid in data_id: - invalid.append(node) - except RuntimeError: - pass - - return invalid - - def process(self, instance): - """Process all meshes""" - - invalid = self.get_invalid(instance) - - if invalid: - raise RuntimeError("Nodes found with invalid" - "asset IDs: {0}".format(invalid)) diff --git a/colorbleed/plugins/maya/publish/collect_look.py b/colorbleed/plugins/maya/publish/collect_look.py index 8f5ff22897..d8f7ec08f9 100644 --- a/colorbleed/plugins/maya/publish/collect_look.py +++ b/colorbleed/plugins/maya/publish/collect_look.py @@ -1,8 +1,8 @@ from maya import cmds import pyblish.api +import colorbleed.maya.lib as lib from cb.utils.maya import context, shaders -import cbra.utils.maya.node_uuid as id_utils SHAPE_ATTRS = ["castsShadows", "receiveShadows", @@ -13,6 +13,7 @@ SHAPE_ATTRS = ["castsShadows", "visibleInRefractions", "doubleSided", "opposite"] + SHAPE_ATTRS = set(SHAPE_ATTRS) @@ -167,10 +168,10 @@ class CollectLook(pyblish.api.InstancePlugin): if objset in sets: continue - unique_id = cmds.getAttr("%s.cbId" % objset) sets[objset] = {"name": objset, - "uuid": unique_id, + "uuid": lib.get_id(objset), "members": list()} + return sets def get_related_sets(self, node, view_sets): @@ -185,8 +186,12 @@ class CollectLook(pyblish.api.InstancePlugin): Args: node (str): name of the current not to check """ + defaults = ["initialShadingGroup", + "defaultLightSet", + "defaultObjectSet"] - ignored = ["pyblish.avalon.instance", "pyblish.avalon.container"] + ignored = ["pyblish.avalon.instance", + "pyblish.avalon.container"] related_sets = cmds.listSets(object=node, extendToShape=False) if not related_sets: @@ -206,6 +211,7 @@ class CollectLook(pyblish.api.InstancePlugin): deformer_sets = cmds.listSets(object=node, extendToShape=False, type=2) or [] + deformer_sets = set(deformer_sets) # optimize lookup sets = [s for s in sets if s not in deformer_sets] @@ -215,8 +221,9 @@ class CollectLook(pyblish.api.InstancePlugin): # Ignore viewport filter view sets (from isolate select and # viewports) sets = [s for s in sets if s not in view_sets] + sets = [s for s in sets if s not in defaults] - self.log.info("Found sets %s for %s" % (related_sets, node)) + self.log.info("Found sets %s for %s" % (sets, node)) return sets @@ -263,21 +270,14 @@ class CollectLook(pyblish.api.InstancePlugin): if member in [m["name"] for m in objset_members]: return - # check node type, if mesh get parent! makes assigning shaders easier + # check node type, if mesh get parent! if cmds.nodeType(node) == "mesh": - parent = cmds.listRelatives(node, parent=True, fullPath=True) - # a mesh NEEDS to have a parent in Maya logic, no reason for - # assertions or extra checking - parent = parent[0] - if cmds.attributeQuery("cbId", node=parent, exists=True): - node = parent - else: - self.log.error("Transform group of mesh '{}' has no attribute " - "'cbId', this is manditory") - return + # A mesh will always have a transform node in Maya logic + node = cmds.listRelatives(node, parent=True, fullPath=True)[0] - if verbose: - self.log.debug("Such as %s.." % member) + if not cmds.attributeQuery("cbId", node=node, exists=True): + self.log.error("Node '{}' has no attribute 'cbId'".format(node)) + return member_data = {"name": node, "uuid": cmds.getAttr("{}.cbId".format(node))} @@ -321,7 +321,7 @@ class CollectLook(pyblish.api.InstancePlugin): node_attributes[attr] = cmds.getAttr(attribute) attributes.append({"name": node, - "uuid": id_utils.get_id(node), + "uuid": cmds.getAttr("{}.cbId".format(node)), "attributes": node_attributes}) return attributes diff --git a/colorbleed/plugins/maya/publish/validate_frame_range.py b/colorbleed/plugins/maya/publish/validate_frame_range.py index 7072bebdf4..bbc3f935aa 100644 --- a/colorbleed/plugins/maya/publish/validate_frame_range.py +++ b/colorbleed/plugins/maya/publish/validate_frame_range.py @@ -15,9 +15,10 @@ class ValidateFrameRange(pyblish.api.InstancePlugin): """ + label = "Validate Frame Range" order = colorbleed.api.ValidateContentsOrder - - label = "Frame Range" + families = ["colorbleed.animation", + "colorbleed.render"] def process(self, instance): diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index c32dfc130f..1dc6a7c849 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -11,28 +11,72 @@ class ValidateLookContents(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidateContentsOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look Contents' + actions = [colorbleed.api.SelectInvalidAction] + + invalid = [] + errors = [] def process(self, instance): """Process all the nodes in the instance""" - error = False - - attributes = ["sets", - "relationships", - "attributes"] - if not instance[:]: raise RuntimeError("Instance is empty") - # Required look data + self.get_invalid(instance) + + if self.errors: + error_string = "\n".join(self.errors) + raise RuntimeError("Invalid look content. " + "Errors : {}".format(error_string)) + + @classmethod + def get_invalid(cls, instance): + + invalid_attr = list(cls.validate_lookdata_attributes(instance)) + invalid_rels = list(cls.validate_relationships(instance)) + + invalid = invalid_attr + invalid_rels + + return invalid + + @classmethod + def validate_lookdata_attributes(cls, instance): + """Check if the lookData has the required attributes + + Args: + instance + + """ + + invalid = set() + + attributes = ["sets", "relationships", "attributes"] lookdata = instance.data["lookData"] for attr in attributes: if attr not in lookdata: - self.log.error("No %s found in data" % attr) - error = True + cls.errors.append("Look Data has no attribute " + "'{}'".format(attr)) + invalid.add(instance.name) - if error: - raise RuntimeError("Invalid look content. See log for details.") + return invalid + + @classmethod + def validate_relationships(cls, instance): + """Validate and update lookData relationships""" + + invalid = set() + + relationships = instance.data["lookData"]["relationships"] + for relationship in relationships: + look_name = relationship["name"] + for key, value in relationship.items(): + if value is None: + cls.errors.append("{} has invalid attribite " + "'{}'".format(look_name, key)) + + invalid.add(look_name) + + return invalid diff --git a/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py b/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py index 30ad75c482..f24011d3c9 100644 --- a/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py +++ b/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py @@ -15,7 +15,7 @@ class ValidateLookDefaultShadersConnections(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidateContentsOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look Default Shader Connections' diff --git a/colorbleed/plugins/maya/publish/validate_look_deformed_shapes.py b/colorbleed/plugins/maya/publish/validate_look_deformed_shapes.py index f688072972..b2d400e5ff 100644 --- a/colorbleed/plugins/maya/publish/validate_look_deformed_shapes.py +++ b/colorbleed/plugins/maya/publish/validate_look_deformed_shapes.py @@ -102,7 +102,7 @@ class ValidateLookDeformedShapes(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidateContentsOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look deformed shapes' actions = [colorbleed.api.SelectInvalidAction, CopyUUIDsFromHistory] diff --git a/colorbleed/plugins/maya/publish/validate_look_ignore_color_space.py b/colorbleed/plugins/maya/publish/validate_look_ignore_color_space.py index 58f0bb2f23..432f6844d6 100644 --- a/colorbleed/plugins/maya/publish/validate_look_ignore_color_space.py +++ b/colorbleed/plugins/maya/publish/validate_look_ignore_color_space.py @@ -18,7 +18,7 @@ class ValidateLookIgnoreColorSpace(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidateContentsOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look RAW Ignore color space' actions = [colorbleed.api.SelectInvalidAction] diff --git a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py index 4e851e0b21..7c256f8399 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -1,14 +1,13 @@ -import maya.cmds as cmds - import pyblish.api import colorbleed.api +import colorbleed.maya.lib as lib -class ValidateLookMembersNodeIds(pyblish.api.InstancePlugin): +class ValidateLookMembersHaveId(pyblish.api.InstancePlugin): """Validate look members have colorbleed id attributes Looks up the contents of the look to see if all its members have - colorbleed id attributes so they can be connected correctly. + Colorbleed Id attributes so they can be connected correctly. When invalid it's very likely related to the model not having the id attributes that it should have. These should have been generated in the @@ -17,35 +16,12 @@ class ValidateLookMembersNodeIds(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidatePipelineOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] - label = 'Look Members Id Attributes' + label = 'Look Members Have ID Attribute' actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.GenerateUUIDsOnInvalidAction] - @staticmethod - def get_invalid(instance): - - # Get all members from the sets - members = [] - relations = instance.data["lookData"]["relationships"] - for sg in relations: - sg_members = sg['members'] - sg_members = [member['name'] for member in sg_members] - members.extend(sg_members) - - # Get all sets - - members = list(set(members)) - - # Ensure all nodes have a cbId - invalid = list() - for node in members: - if not cmds.getAttr("{}.cbId".format(node)): - invalid.append(node) - - return invalid - def process(self, instance): """Process all meshes""" @@ -53,3 +29,24 @@ class ValidateLookMembersNodeIds(pyblish.api.InstancePlugin): if invalid: raise RuntimeError("Members found without " "asset IDs: {0}".format(invalid)) + + @classmethod + def get_invalid(cls, instance): + + # Get all members from the sets + members = [] + relations = instance.data["lookData"]["relationships"] + for relation in relations: + members = [member['name'] for member in relation['members']] + members.extend(members) + + # Get all sets + members = list(set(members)) + + # Ensure all nodes have a cbId + invalid = list() + for node in members: + if not lib.get_id(node): + invalid.append(node) + + return invalid diff --git a/colorbleed/plugins/maya/publish/validate_look_members_unique.py b/colorbleed/plugins/maya/publish/validate_look_members_unique.py index 48dce8b8d7..6d85ce5339 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_unique.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_unique.py @@ -15,8 +15,9 @@ def get_unique_id(node): return unique_id -class ValidateLookMembersUnique(pyblish.api.InstancePlugin): - """Validate members of look are unique. +class ValidateNonDuplicateRelationshipMembers(pyblish.api.InstancePlugin): + """Validate the relational nodes of the look data to ensure every node is + unique. This ensures the same id is not present as more than one node in the look. @@ -29,9 +30,10 @@ class ValidateLookMembersUnique(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidatePipelineOrder - families = ['colorbleed.look'] + label = 'Non Duplicate Relationship Members (ID)' hosts = ['maya'] - label = 'Look Members Unique' + families = ['colorbleed.lookdev'] + actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.GenerateUUIDsOnInvalidAction] @@ -42,8 +44,7 @@ class ValidateLookMembersUnique(pyblish.api.InstancePlugin): members = [] relationships = instance.data["lookData"]["relationships"] for sg in relationships: - sg_members = sg['members'] - sg_members = [member['name'] for member in sg_members] + sg_members = [member['name'] for member in sg['members']] members.extend(sg_members) # Ensure we don't have components but the objects @@ -68,9 +69,7 @@ class ValidateLookMembersUnique(pyblish.api.InstancePlugin): def process(self, instance): """Process all meshes""" - print self.actions - invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Members found without " - "asset IDs: {0}".format(invalid)) + raise RuntimeError("Members found without asset IDs: " + "{0}".format(invalid)) diff --git a/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py b/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py index 44b5a3331b..4f33e15b1c 100644 --- a/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py +++ b/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py @@ -22,65 +22,51 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin): """ - order = colorbleed.api.ValidateContentsOrder - families = ['colorbleed.look'] + order = colorbleed.api.ValidateContentsOrder + 0.01 + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look No Default Shaders' actions = [colorbleed.api.SelectInvalidAction] @classmethod - def get_invalid_sets(cls, instance): + def get_invalid(cls, instance): + invalid = [] disallowed = ["lambert1", "initialShadingGroup", "initialParticleSE", "particleCloud1"] - disallowed = set(disallowed) - # Check among the sets - lookdata = instance.data["lookData"] - sets = lookdata['sets'] - lookup = set(sets) - intersect = lookup.intersection(disallowed) - if intersect: - cls.log.error("Default shaders found in the " - "look: {0}".format(list(intersect))) - return list(intersect) + setmembers = instance.data["setMembers"] + members = cmds.listRelatives(setmembers, + allDescendents=True, + type="shape") - # Check among history/inputs of the sets - history = cmds.listHistory(sets) or [] - lookup = set(history) + for member in members: - intersect = lookup.intersection(disallowed) - if intersect: - cls.log.error("Default shaders found in the history of the " - "look: {0}".format(list(intersect))) - return list(intersect) + # get connection + # listConnections returns a list or None + shading_engine = cmds.listConnections(member, type="shadingEngine") + if not shading_engine: + cls.log.error("Detected shape without shading engine : " + "'{}'".format(member)) + invalid.append(member) + continue - return list() - - @classmethod - def get_invalid(cls, instance): - - shaders = cls.get_invalid_sets(instance) - nodes = instance[:] - - # Get members of the shaders - all = set() - for shader in shaders: - members = cmds.sets(shader, query=True) or [] - members = cmds.ls(members, long=True) - all.update(members) - - # Get the instance nodes among the shader members - invalid = all.intersection(nodes) - invalid = list(invalid) + # retrieve the shading engine out of the list + shading_engine = shading_engine[0] + if shading_engine in disallowed: + cls.log.error("Member connected to a disallows objectSet: " + "'{}'".format(member)) + else: + continue return invalid def process(self, instance): """Process all the nodes in the instance""" - sets = self.get_invalid_sets(instance) + # sets = self.get_invalid_sets(instance) + sets = self.get_invalid(instance) if sets: raise RuntimeError("Invalid shaders found: {0}".format(sets)) diff --git a/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py b/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py index 653e8a347c..251ecbf24f 100644 --- a/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py @@ -12,7 +12,7 @@ class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidatePipelineOrder - families = ['colorbleed.look'] + families = ['colorbleed.lookdev'] hosts = ['maya'] label = 'Look Id Unique Attributes' actions = [colorbleed.api.SelectInvalidAction, @@ -28,8 +28,8 @@ class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): invalid = list() for node in nodes: unique_id = None - if cmds.attributeQuery("mbId", node=node, exists=True): - unique_id = cmds.getAttr("{}.mbId".format(node)) + if cmds.attributeQuery("cbId", node=node, exists=True): + unique_id = cmds.getAttr("{}.cbId".format(node)) if not unique_id: continue diff --git a/colorbleed/plugins/maya/publish/validate_model_content.py b/colorbleed/plugins/maya/publish/validate_model_content.py index 7797054c27..75959f66b0 100644 --- a/colorbleed/plugins/maya/publish/validate_model_content.py +++ b/colorbleed/plugins/maya/publish/validate_model_content.py @@ -24,8 +24,6 @@ class ValidateModelContent(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): - pprint.pprint(instance.data) - content_instance = instance.data.get("setMembers", None) if not content_instance: cls.log.error("Instance has no nodes!") diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py new file mode 100644 index 0000000000..37e0bda5c9 --- /dev/null +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -0,0 +1,51 @@ +import maya.cmds as cmds + +import pyblish.api +import colorbleed.api + +from colorbleed.maya import lib + + +class ValidateNodeIDs(pyblish.api.InstancePlugin): + """Validate nodes have a Colorbleed Id + + """ + + order = colorbleed.api.ValidatePipelineOrder + label = 'Node Ids (ID)' + hosts = ['maya'] + families = ["colorbleed.model", + "colorbleed.lookdev", + "colorbleed.rig"] + + actions = [colorbleed.api.SelectInvalidAction, + colorbleed.api.GenerateUUIDsOnInvalidAction] + + def process(self, instance): + """Process all meshes""" + + # Ensure all nodes have a cbId + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError("Nodes found without " + "IDs: {0}".format(invalid)) + + @classmethod + def get_invalid(cls, instance): + """Return the member nodes that are invalid""" + invalid = list() + + # TODO: Implement check on only nodes like on_save callback. + instance_shape = cmds.ls(instance, type="shape") + + # We do want to check the referenced nodes as we it might be + # part of the end product + nodes = lib.filter_out_nodes(set(instance_shape), defaults=True) + for node in nodes: + if not lib.get_id(node): + invalid.append(node) + + return invalid + + + diff --git a/colorbleed/plugins/maya/publish/validate_unique_node_ids.py b/colorbleed/plugins/maya/publish/validate_unique_node_ids.py index edae718c02..3de16d5a15 100644 --- a/colorbleed/plugins/maya/publish/validate_unique_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_unique_node_ids.py @@ -1,20 +1,22 @@ from collections import defaultdict -import maya.cmds as cmds - import pyblish.api import colorbleed.api +import colorbleed.maya.lib as lib -class ValidateUniqueNodeIds(pyblish.api.InstancePlugin): - """Validate nodes have colorbleed id attributes""" +class ValidateNonDuplicateInstanceMembers(pyblish.api.InstancePlugin): + """Validate the nodes in the instance have a unique Colorbleed Id + + Here we ensure that what has been added to the instance is unique + """ order = colorbleed.api.ValidatePipelineOrder - label = 'Unique Id Attributes' + label = 'Non Duplicate Instance Members (ID)' hosts = ['maya'] - families = ['colorbleed.model', - 'colorbleed.lookdev', - 'colorbleed.rig'] + families = ["colorbleed.model", + "colorbleed.lookdev", + "colorbleed.rig"] actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.GenerateUUIDsOnInvalidAction] @@ -23,15 +25,12 @@ class ValidateUniqueNodeIds(pyblish.api.InstancePlugin): def get_invalid_dict(cls, instance): """Return a dictionary mapping of id key to list of member nodes""" - uuid_attr = "cbId" - # Collect each id with their members ids = defaultdict(list) for member in instance: - if not cmds.attributeQuery(uuid_attr, node=member, exists=True): + object_id = lib.get_id(member) + if not object_id: continue - - object_id = cmds.getAttr("{}.{}".format(member, uuid_attr)) ids[object_id].append(member) # Skip those without IDs (if everything should have an ID that should diff --git a/colorbleed/plugins/publish/collect_resource_destination.py b/colorbleed/plugins/publish/collect_assumed_destination.py similarity index 87% rename from colorbleed/plugins/publish/collect_resource_destination.py rename to colorbleed/plugins/publish/collect_assumed_destination.py index 814f6fb612..47aec83ea1 100644 --- a/colorbleed/plugins/publish/collect_resource_destination.py +++ b/colorbleed/plugins/publish/collect_assumed_destination.py @@ -4,10 +4,10 @@ import os import avalon.io as io -class CollectResourceDestination(pyblish.api.InstancePlugin): +class CollectAssumedDestination(pyblish.api.InstancePlugin): """This plug-ins displays the comment dialog box per default""" - label = "Collect Resource Destination" + label = "Collect Assumed Destination" order = pyblish.api.CollectorOrder + 0.499 def process(self, instance): @@ -63,15 +63,22 @@ class CollectResourceDestination(pyblish.api.InstancePlugin): # get all the stuff from the database subset_name = instance.data["subset"] + asset_name = instance.data["asset"] project_name = os.environ["AVALON_PROJECT"] project = io.find_one({"type": "project", "name": project_name}, projection={"config": True}) + template = project["config"]["template"]["publish"] + asset = io.find_one({"type": "asset", + "name": asset_name, + "parent": project["_id"]}) + subset = io.find_one({"type": "subset", - "name": subset_name}) + "name": subset_name, + "parent": asset["_id"]}) # assume there is no version yet, we start at `1` version_number = 1 @@ -85,7 +92,7 @@ class CollectResourceDestination(pyblish.api.InstancePlugin): template_data = {"root": os.environ["AVALON_ROOT"], "project": project_name, "silo": os.environ["AVALON_SILO"], - "asset": instance.data["asset"], + "asset": asset_name, "subset": subset_name, "version": version_number, "representation": "TEMP"} diff --git a/colorbleed/plugins/publish/collect_comment.py b/colorbleed/plugins/publish/collect_comment.py index e3da4486c4..416e505e17 100644 --- a/colorbleed/plugins/publish/collect_comment.py +++ b/colorbleed/plugins/publish/collect_comment.py @@ -4,7 +4,7 @@ import pyblish.api class CollectMindbenderComment(pyblish.api.ContextPlugin): """This plug-ins displays the comment dialog box per default""" - label = "Collect Mindbender Time" + label = "Collect Comment" order = pyblish.api.CollectorOrder def process(self, context):