From f0aafec1faec80da9beeb7e5160d6aef1b2b0b22 Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 17:09:52 +0200 Subject: [PATCH 01/24] improved get_id function --- colorbleed/maya/lib.py | 8 +-- .../maya/publish/validate_node_ids_related.py | 51 +++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 colorbleed/plugins/maya/publish/validate_node_ids_related.py diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 343847a4fb..28d2c43129 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -663,14 +663,10 @@ def get_id(node): if node is None: return - try: - attr = "{}.cbId".format(node) - attribute_value = cmds.getAttr(attr) - except Exception as e: - log.debug(e) + if not cmds.attributeQuery("cbId", node=node, exists=True): return - return attribute_value + return cmds.getAttr("{}.cbId".format(node)) def get_representation_file(representation, template=TEMPLATE): diff --git a/colorbleed/plugins/maya/publish/validate_node_ids_related.py b/colorbleed/plugins/maya/publish/validate_node_ids_related.py new file mode 100644 index 0000000000..37e0bda5c9 --- /dev/null +++ b/colorbleed/plugins/maya/publish/validate_node_ids_related.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 + + + From d9734e5f19e03743d1506b8006261aa7994dcea9 Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 17:11:09 +0200 Subject: [PATCH 02/24] updated get_invalid to validate nodes from instance --- colorbleed/plugins/maya/publish/validate_node_ids.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index 37e0bda5c9..7ae19dfe1a 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -33,14 +33,12 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): @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 + # We do want to check the referenced nodes as it might be # part of the end product - nodes = lib.filter_out_nodes(set(instance_shape), defaults=True) + nodes = lib.filter_out_nodes(set(instance[:]), defaults=True) for node in nodes: if not lib.get_id(node): invalid.append(node) From 67a3f63ceef4f581d7822b662e649f40fccef236 Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 17:12:36 +0200 Subject: [PATCH 03/24] improved get_invalid to verify node id is related to asset id of instance --- .../maya/publish/validate_node_ids_related.py | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids_related.py b/colorbleed/plugins/maya/publish/validate_node_ids_related.py index 37e0bda5c9..eb9f736fc9 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids_related.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids_related.py @@ -1,18 +1,18 @@ -import maya.cmds as cmds - import pyblish.api import colorbleed.api +import avalon.io as io + from colorbleed.maya import lib -class ValidateNodeIDs(pyblish.api.InstancePlugin): - """Validate nodes have a Colorbleed Id +class ValidateNodeIDsRelated(pyblish.api.InstancePlugin): + """Validate nodes have a related Colorbleed Id to the instance asset """ order = colorbleed.api.ValidatePipelineOrder - label = 'Node Ids (ID)' + label = 'Node Ids Related (ID)' hosts = ['maya'] families = ["colorbleed.model", "colorbleed.lookdev", @@ -22,27 +22,33 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): colorbleed.api.GenerateUUIDsOnInvalidAction] def process(self, instance): - """Process all meshes""" - + """Process all nodes in instance (incl. hierarchy)""" # Ensure all nodes have a cbId invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Nodes found without " - "IDs: {0}".format(invalid)) + raise RuntimeError("Nodes IDs found that are not related to asset " + "'{}' : {}".format(instance.data['asset'], + 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") + asset = instance.data['asset'] + asset_data = io.find_one({"name": asset, + "type": "asset"}, + projection={"_id": True}) + asset_id = str(asset_data['_id']) # 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): + for node in instance: + _id = lib.get_id(node) + if not _id: + continue + node_asset_id = _id.split(":", 1)[0] + if node_asset_id != asset_id: invalid.append(node) return invalid From 4c091e8eb1b831c7cbe733c21e6a97c57aa3ad56 Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 17:16:36 +0200 Subject: [PATCH 04/24] cosmetics --- colorbleed/plugins/maya/publish/validate_node_ids_related.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids_related.py b/colorbleed/plugins/maya/publish/validate_node_ids_related.py index eb9f736fc9..84c28c6427 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids_related.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids_related.py @@ -22,7 +22,7 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin): colorbleed.api.GenerateUUIDsOnInvalidAction] def process(self, instance): - """Process all nodes in instance (incl. hierarchy)""" + """Process all nodes in instance (including hierarchy)""" # Ensure all nodes have a cbId invalid = self.get_invalid(instance) if invalid: @@ -44,9 +44,11 @@ class ValidateNodeIDsRelated(pyblish.api.InstancePlugin): # We do want to check the referenced nodes as we it might be # part of the end product for node in instance: + _id = lib.get_id(node) if not _id: continue + node_asset_id = _id.split(":", 1)[0] if node_asset_id != asset_id: invalid.append(node) From 1569ad2d3e0ba574680d15e579dc1e58f3b04d1c Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 17:18:20 +0200 Subject: [PATCH 05/24] cosmetics --- colorbleed/maya/lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 28d2c43129..73f25bbe68 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -618,8 +618,8 @@ def filter_out_nodes(nodes, defaults=False, referenced_nodes=False): Args: nodes (set): nodes to filter - locked (bool): set True to filter out lockedNodes - readonly (bool): set True to filter out readOnly + defaults (bool): set True to filter out default nodes + referenced_nodes (bool): set True to filter out reference nodes Returns: nodes (list): list of filtered nodes """ From 52a36f3c94224c95503f282ae12f452a205680bb Mon Sep 17 00:00:00 2001 From: aardschok Date: Tue, 8 Aug 2017 18:05:35 +0200 Subject: [PATCH 06/24] added list of default cameras --- .../maya/publish/validate_look_contents.py | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index 1dc6a7c849..81a22812b4 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -1,3 +1,5 @@ +import maya.cmds as cmds + import pyblish.api import colorbleed.api @@ -34,11 +36,13 @@ class ValidateLookContents(pyblish.api.InstancePlugin): @classmethod def get_invalid(cls, instance): + """Get all invalid nodes""" - invalid_attr = list(cls.validate_lookdata_attributes(instance)) - invalid_rels = list(cls.validate_relationships(instance)) + attributes = list(cls.validate_lookdata_attributes(instance)) + relationships = list(cls.validate_relationships(instance)) + non_defaults = cls.validate_non_defaults(instance) - invalid = invalid_attr + invalid_rels + invalid = attributes + relationships + non_defaults return invalid @@ -74,9 +78,35 @@ class ValidateLookContents(pyblish.api.InstancePlugin): look_name = relationship["name"] for key, value in relationship.items(): if value is None: - cls.errors.append("{} has invalid attribite " + cls.errors.append("{} has invalid attribute " "'{}'".format(look_name, key)) invalid.add(look_name) return invalid + + @classmethod + def validate_non_defaults(cls, instance): + """Check if instance content items are part of the default nodes""" + + invalid = [] + cams = cmds.ls(['frontShape', 'perspShape', 'sideShape', 'topShape'], + long=True) + defaults = cmds.ls(long=True, defaultNodes=True) + defaults.extend(cams) + + for node in cmds.ls(instance[:], long=True): + # might be a transform of a default item listed + if cmds.nodeType(node) == "transform": + node = cmds.listRelatives(node, + children=True, + fullPath=True)[0] or None + + print node, node in defaults + + if node in defaults: + invalid.append(node) + cls.errors.append("'{}' is part of Maya default " + "nodes".format(node)) + + return invalid From 2dd251473c472e1f03a7943124460e1afb3ae99c Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 12:02:16 +0200 Subject: [PATCH 07/24] improved validation --- .../maya/publish/validate_look_contents.py | 22 +++++++++++-------- .../plugins/maya/publish/validate_node_ids.py | 17 ++++++++++++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index 81a22812b4..9f0323c6cc 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -90,19 +90,23 @@ class ValidateLookContents(pyblish.api.InstancePlugin): """Check if instance content items are part of the default nodes""" invalid = [] - cams = cmds.ls(['frontShape', 'perspShape', 'sideShape', 'topShape'], - long=True) - defaults = cmds.ls(long=True, defaultNodes=True) - defaults.extend(cams) + cams = ["perspShape", "topShape", "frontShape", "sideShape"] + cameras = cmds.ls(cams, long=True) + references = cmds.ls(referencedNodes=True) + default_nodes = cmds.ls(defaultNodes=True, long=True) + + defaults = list(set(cameras + references + default_nodes)) for node in cmds.ls(instance[:], long=True): # might be a transform of a default item listed if cmds.nodeType(node) == "transform": - node = cmds.listRelatives(node, - children=True, - fullPath=True)[0] or None - - print node, node in defaults + children = cmds.listRelatives(node, + children=True, + fullPath=True) + if children: + node = children + else: + continue if node in defaults: invalid.append(node) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index 7ae19dfe1a..b3a1644e93 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -12,7 +12,7 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): """ order = colorbleed.api.ValidatePipelineOrder - label = 'Node Ids (ID)' + label = 'Instance Nodes Have ID' hosts = ['maya'] families = ["colorbleed.model", "colorbleed.lookdev", @@ -41,9 +41,22 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): nodes = lib.filter_out_nodes(set(instance[:]), defaults=True) for node in nodes: if not lib.get_id(node): + + # check if siblings have IDs + valid_hierarchy = cls.validate_children(node) + if valid_hierarchy: + continue + invalid.append(node) return invalid + @staticmethod + def validate_children(node): + """Validate the children of the node if the ID is not present""" - + children = cmds.listRelatives(node, children=True) + for child in children: + if lib.get_id(child): + return True + return False From 1000a03fef44ac33ee1c726b8453edf52b7fdd8e Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 12:06:07 +0200 Subject: [PATCH 08/24] improved get_invalid function --- .../maya/publish/validate_look_members_node_ids.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) 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 7c256f8399..de406e3f42 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -34,14 +34,10 @@ class ValidateLookMembersHaveId(pyblish.api.InstancePlugin): def get_invalid(cls, instance): # Get all members from the sets - members = [] + members = set() 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)) + members.update([member['name'] for member in relation['members']]) # Ensure all nodes have a cbId invalid = list() From b5f009d231615788e87d3949d14906713cfbf1e0 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 12:06:43 +0200 Subject: [PATCH 09/24] removed print --- colorbleed/maya/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/colorbleed/maya/__init__.py b/colorbleed/maya/__init__.py index 94f315faee..071d2e91fe 100644 --- a/colorbleed/maya/__init__.py +++ b/colorbleed/maya/__init__.py @@ -111,5 +111,4 @@ def on_save(_): # generate the ids for node in nodes: - print node _set_uuid(str(asset_id["_id"]), node) From 42d7779ce0555c4508e77d0c6b6a1134d85a47b5 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 12:08:31 +0200 Subject: [PATCH 10/24] improved get_invalid --- .../plugins/maya/publish/validate_look_members_node_ids.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) 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 de406e3f42..942dbd996f 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -40,9 +40,6 @@ class ValidateLookMembersHaveId(pyblish.api.InstancePlugin): members.update([member['name'] for member in relation['members']]) # Ensure all nodes have a cbId - invalid = list() - for node in members: - if not lib.get_id(node): - invalid.append(node) + invalid = [m for m in members if not lib.get_id(m)] return invalid From 6442c16964e1fb14e8e8bdcd3d06844a0470f615 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 12:34:28 +0200 Subject: [PATCH 11/24] improved functions, list comprehension --- ...lidate_look_default_shaders_connections.py | 17 +++++------- .../publish/validate_look_members_unique.py | 26 +++++-------------- .../publish/validate_look_node_unique_ids.py | 13 +++------- .../maya/publish/validate_no_animation.py | 14 +++++----- .../plugins/maya/publish/validate_node_ids.py | 13 ++-------- 5 files changed, 25 insertions(+), 58 deletions(-) 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 f24011d3c9..dce90dc0df 100644 --- a/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py +++ b/colorbleed/plugins/maya/publish/validate_look_default_shaders_connections.py @@ -1,3 +1,5 @@ +from maya import cmds + import pyblish.api import colorbleed.api @@ -20,11 +22,10 @@ class ValidateLookDefaultShadersConnections(pyblish.api.InstancePlugin): label = 'Look Default Shader Connections' # The default connections to check - DEFAULTS = [ - ("initialShadingGroup.surfaceShader", "lambert1"), - ("initialParticleSE.surfaceShader", "lambert1"), - ("initialParticleSE.volumeShader", "particleCloud1") - ] + DEFAULTS = [("initialShadingGroup.surfaceShader", "lambert1"), + ("initialParticleSE.surfaceShader", "lambert1"), + ("initialParticleSE.volumeShader", "particleCloud1") + ] def process(self, instance): @@ -33,19 +34,15 @@ class ValidateLookDefaultShadersConnections(pyblish.api.InstancePlugin): # the family is not present in an instance. key = "__validate_look_default_shaders_connections_checked" context = instance.context - is_run = context.data.get(key, - False) + is_run = context.data.get(key, False) if is_run: return else: context.data[key] = True # Process as usual - from maya import cmds - invalid = list() for plug, input_node in self.DEFAULTS: - inputs = cmds.listConnections(plug, source=True, destination=False) or None diff --git a/colorbleed/plugins/maya/publish/validate_look_members_unique.py b/colorbleed/plugins/maya/publish/validate_look_members_unique.py index 6d85ce5339..41ffed93c2 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_unique.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_unique.py @@ -4,15 +4,7 @@ from maya import cmds import pyblish.api import colorbleed.api - - -def get_unique_id(node): - attr = 'cbId' - unique_id = None - has_attribute = cmds.attributeQuery(attr, node=node, exists=True) - if has_attribute: - unique_id = cmds.getAttr("{}.{}".format(node, attr)) - return unique_id +import colorbleed.maya.lib as lib class ValidateNonDuplicateRelationshipMembers(pyblish.api.InstancePlugin): @@ -43,26 +35,22 @@ class ValidateNonDuplicateRelationshipMembers(pyblish.api.InstancePlugin): # Get all members from the sets members = [] relationships = instance.data["lookData"]["relationships"] - for sg in relationships: - sg_members = [member['name'] for member in sg['members']] - members.extend(sg_members) + for relationship in relationships: + members.extend([i['name'] for i in relationship['members']]) # Ensure we don't have components but the objects - members = cmds.ls(members, objectsOnly=True, long=True) - members = list(set(members)) + members = set(cmds.ls(members, objectsOnly=True, long=True)) + members = list(members) # Group members per id id_nodes = defaultdict(set) for node in members: - node_id = get_unique_id(node) + node_id = lib.get_id(node) if not node_id: continue id_nodes[node_id].add(node) - invalid = list() - for nodes in id_nodes.itervalues(): - if len(nodes) > 1: - invalid.extend(nodes) + invalid = [n for n in id_nodes.itervalues() if len(n) > 1] return invalid 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 251ecbf24f..d4fd034710 100644 --- a/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py @@ -1,9 +1,8 @@ from collections import defaultdict -import maya.cmds as cmds - import pyblish.api import colorbleed.api +import colorbleed.maya.lib as lib class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): @@ -25,19 +24,13 @@ class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): # Ensure all nodes have a cbId id_sets = defaultdict(list) - invalid = list() for node in nodes: - unique_id = None - if cmds.attributeQuery("cbId", node=node, exists=True): - unique_id = cmds.getAttr("{}.cbId".format(node)) + unique_id = lib.get_id(node) if not unique_id: continue - id_sets[unique_id].append(node) - for unique_id, nodes in id_sets.iteritems(): - if len(nodes) > 1: - invalid.extend(nodes) + invalid = [n for n in id_sets.itervalues() if len(n) > 1] return invalid diff --git a/colorbleed/plugins/maya/publish/validate_no_animation.py b/colorbleed/plugins/maya/publish/validate_no_animation.py index 6c57183d31..8b0da47d89 100644 --- a/colorbleed/plugins/maya/publish/validate_no_animation.py +++ b/colorbleed/plugins/maya/publish/validate_no_animation.py @@ -20,11 +20,16 @@ class ValidateNoAnimation(pyblish.api.Validator): optional = True actions = [colorbleed.api.SelectInvalidAction] + def process(self, instance): + + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError("Keyframes found: {0}".format(invalid)) + @staticmethod def get_invalid(instance): nodes = instance[:] - if not nodes: return [] @@ -33,10 +38,3 @@ class ValidateNoAnimation(pyblish.api.Validator): return list(set(cmds.listConnections(curves))) return [] - - def process(self, instance): - - invalid = self.get_invalid(instance) - - if invalid: - raise RuntimeError("Keyframes found: {0}".format(invalid)) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index b3a1644e93..2a9d9ea25f 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -34,20 +34,11 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): def get_invalid(cls, instance): """Return the member nodes that are invalid""" - invalid = list() - # We do want to check the referenced nodes as it might be # part of the end product nodes = lib.filter_out_nodes(set(instance[:]), defaults=True) - for node in nodes: - if not lib.get_id(node): - - # check if siblings have IDs - valid_hierarchy = cls.validate_children(node) - if valid_hierarchy: - continue - - invalid.append(node) + invalid = [n for n in nodes if not lib.get_id(n) + and not cls.validate_children(n)] return invalid From d19223e26abf3bd0855b3273b9a24360b35b4c0b Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 13:46:37 +0200 Subject: [PATCH 12/24] added single shader validation --- .../publish/validate_look_single_shader.py | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 colorbleed/plugins/maya/publish/validate_look_single_shader.py diff --git a/colorbleed/plugins/maya/publish/validate_look_single_shader.py b/colorbleed/plugins/maya/publish/validate_look_single_shader.py new file mode 100644 index 0000000000..fabdfb1a6d --- /dev/null +++ b/colorbleed/plugins/maya/publish/validate_look_single_shader.py @@ -0,0 +1,61 @@ +from maya import cmds + +import pyblish.api +import colorbleed.api + + +class ValidateSingleShader(pyblish.api.InstancePlugin): + """Validate default shaders in the scene have their default connections. + + For example the lambert1 could potentially be disconnected from the + initialShadingGroup. As such it's not lambert1 that will be identified + as the default shader which can have unpredictable results. + + To fix the default connections need to be made again. See the logs for + more details on which connections are missing. + + """ + + order = colorbleed.api.ValidateContentsOrder + families = ['colorbleed.lookdev'] + hosts = ['maya'] + label = 'Look Single Shader Per Shape' + + # The default connections to check + def process(self, instance): + + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError("Found shapes which have multiple " + "shadingEngines connected." + "\n{}".format(invalid)) + + @classmethod + def get_invalid(cls, instance): + invalid = [] + shape_types = ["numrbsCurve", "nurbsSurface", "mesh"] + + # Get all shapes from the instance + shapes = set() + for node in instance[:]: + + nodetype = cmds.nodeType(node) + if nodetype in shape_types: + shapes.add(node) + + elif nodetype == "transform": + shape = cmds.listRelatives(node, children=True, + type="shape", fullPath=True) + if not shape: + continue + shapes.add(shape[0]) + + # Check the number of connected shadingEngines per shape + for shape in shapes: + shading_engines = cmds.listConnections(shape, + destination=True, + type="shadingEngine") + if len(shading_engines) > 1: + invalid.append(shape) + + return invalid From fea156097833655787c9f9b252fac2633a425e59 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 16:34:29 +0200 Subject: [PATCH 13/24] look validation improvements --- colorbleed/maya/__init__.py | 7 +- colorbleed/maya/lib.py | 20 ++++-- .../plugins/maya/publish/collect_look.py | 8 ++- .../maya/publish/validate_look_contents.py | 71 +++++-------------- .../publish/validate_look_members_node_ids.py | 22 +++--- .../validate_look_no_default_shaders.py | 17 +++-- .../publish/validate_look_single_shader.py | 2 +- .../plugins/maya/publish/validate_node_ids.py | 18 ++--- 8 files changed, 66 insertions(+), 99 deletions(-) diff --git a/colorbleed/maya/__init__.py b/colorbleed/maya/__init__.py index 071d2e91fe..94288646a0 100644 --- a/colorbleed/maya/__init__.py +++ b/colorbleed/maya/__init__.py @@ -97,11 +97,8 @@ def on_save(_): avalon.logger.info("Running callback on save..") - 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) + nodes = lib.get_id_required_nodes(defaults=True, + referenced_nodes=True) # Lead with asset ID from the database asset = os.environ["AVALON_ASSET"] diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 73f25bbe68..29160a339c 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -613,7 +613,7 @@ def remap_resource_nodes(resources, folder=None): cmds.file(save=True, type="mayaAscii") -def filter_out_nodes(nodes, defaults=False, referenced_nodes=False): +def get_id_required_nodes(defaults=True, referenced_nodes=True): """Filter out any node which are locked (reference) or readOnly Args: @@ -621,11 +621,13 @@ def filter_out_nodes(nodes, defaults=False, referenced_nodes=False): defaults (bool): set True to filter out default nodes referenced_nodes (bool): set True to filter out reference nodes Returns: - nodes (list): list of filtered nodes + nodes (set): 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 + camera_shapes = ["frontShape", "sideShape", "topShape", "perspShape"] ignore = set() if referenced_nodes: @@ -633,16 +635,26 @@ def filter_out_nodes(nodes, defaults=False, referenced_nodes=False): if defaults: ignore |= set(cmds.ls(long=True, defaultNodes=defaults)) + ignore |= set(cmds.ls(camera_shapes, long=True)) + + # establish set of nodes to ignore + types = ["objectSet", "file", "mesh", "nurbsCurve", "nurbsSurface"] + + # We *always* ignore intermediate shapes, so we filter them out + # directly + nodes = cmds.ls(type=types, long=True, noIntermediate=True) # The items which need to pass the id to their parent # Add the collected transform to the nodes - dag = cmds.ls(list(nodes), + dag = cmds.ls(nodes, type="dagNode", long=True) # query only dag nodes + transforms = cmds.listRelatives(dag, parent=True, fullPath=True) or [] + nodes = set(nodes) nodes |= set(transforms) nodes -= ignore # Remove the ignored nodes diff --git a/colorbleed/plugins/maya/publish/collect_look.py b/colorbleed/plugins/maya/publish/collect_look.py index d8f7ec08f9..4b76a17ce3 100644 --- a/colorbleed/plugins/maya/publish/collect_look.py +++ b/colorbleed/plugins/maya/publish/collect_look.py @@ -123,9 +123,11 @@ class CollectLook(pyblish.api.InstancePlugin): "relationships": sets.values(), "sets": looksets} - # Collect file nodes used by shading engines - history = cmds.listHistory(looksets) - files = cmds.ls(history, type="file", long=True) + # Collect file nodes used by shading engines (if we have any) + files = list() + if looksets: + history = cmds.listHistory(looksets) + files = cmds.ls(history, type="file", long=True) # Collect textures resources = [self.collect_resource(n) for n in files] diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index 9f0323c6cc..70aec3c70c 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -1,5 +1,3 @@ -import maya.cmds as cmds - import pyblish.api import colorbleed.api @@ -15,34 +13,27 @@ class ValidateLookContents(pyblish.api.InstancePlugin): order = colorbleed.api.ValidateContentsOrder families = ['colorbleed.lookdev'] hosts = ['maya'] - label = 'Look Contents' + label = 'Look Data Contents' actions = [colorbleed.api.SelectInvalidAction] - invalid = [] - errors = [] - def process(self, instance): """Process all the nodes in the instance""" if not instance[:]: raise RuntimeError("Instance is empty") - self.get_invalid(instance) - - if self.errors: - error_string = "\n".join(self.errors) - raise RuntimeError("Invalid look content. " - "Errors : {}".format(error_string)) + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError("Invalid look content") @classmethod def get_invalid(cls, instance): """Get all invalid nodes""" attributes = list(cls.validate_lookdata_attributes(instance)) - relationships = list(cls.validate_relationships(instance)) - non_defaults = cls.validate_non_defaults(instance) + relationships = list(cls.validate_relationship_ids(instance)) - invalid = attributes + relationships + non_defaults + invalid = attributes + relationships return invalid @@ -61,14 +52,18 @@ class ValidateLookContents(pyblish.api.InstancePlugin): lookdata = instance.data["lookData"] for attr in attributes: if attr not in lookdata: - cls.errors.append("Look Data has no attribute " - "'{}'".format(attr)) + cls.log.error("Look Data has no attribute " + "'{}'".format(attr)) invalid.add(instance.name) + if not lookdata["relationships"] or not lookdata["sets"]: + cls.log.error("Look has no `relationship` or `sets`") + invalid.add(instance.name) + return invalid @classmethod - def validate_relationships(cls, instance): + def validate_relationship_ids(cls, instance): """Validate and update lookData relationships""" invalid = set() @@ -76,41 +71,9 @@ class ValidateLookContents(pyblish.api.InstancePlugin): 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 attribute " - "'{}'".format(look_name, key)) - - invalid.add(look_name) - - return invalid - - @classmethod - def validate_non_defaults(cls, instance): - """Check if instance content items are part of the default nodes""" - - invalid = [] - cams = ["perspShape", "topShape", "frontShape", "sideShape"] - cameras = cmds.ls(cams, long=True) - references = cmds.ls(referencedNodes=True) - default_nodes = cmds.ls(defaultNodes=True, long=True) - - defaults = list(set(cameras + references + default_nodes)) - - for node in cmds.ls(instance[:], long=True): - # might be a transform of a default item listed - if cmds.nodeType(node) == "transform": - children = cmds.listRelatives(node, - children=True, - fullPath=True) - if children: - node = children - else: - continue - - if node in defaults: - invalid.append(node) - cls.errors.append("'{}' is part of Maya default " - "nodes".format(node)) + uuid = relationship["uuid"] + if not uuid: + cls.errors.append("{} has invalid ID ") + invalid.add(look_name) return invalid 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 942dbd996f..f168ba3b39 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -1,9 +1,11 @@ +import maya.cmds as cmds + import pyblish.api import colorbleed.api import colorbleed.maya.lib as lib -class ValidateLookMembersHaveId(pyblish.api.InstancePlugin): +class ValidateLookMembers(pyblish.api.InstancePlugin): """Validate look members have colorbleed id attributes Looks up the contents of the look to see if all its members have @@ -18,28 +20,28 @@ class ValidateLookMembersHaveId(pyblish.api.InstancePlugin): order = colorbleed.api.ValidatePipelineOrder families = ['colorbleed.lookdev'] hosts = ['maya'] - label = 'Look Members Have ID Attribute' + label = 'Look Members' actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.GenerateUUIDsOnInvalidAction] def process(self, instance): """Process all meshes""" - invalid = self.get_invalid(instance) - if invalid: + invalid_ids = self.get_invalid(instance) + if invalid_ids: raise RuntimeError("Members found without " - "asset IDs: {0}".format(invalid)) + "asset IDs: {0}".format(invalid_ids)) @classmethod def get_invalid(cls, instance): - # Get all members from the sets members = set() - relations = instance.data["lookData"]["relationships"] - for relation in relations: + relationships = instance.data["lookData"]["relationships"] + for relation in relationships: members.update([member['name'] for member in relation['members']]) - # Ensure all nodes have a cbId invalid = [m for m in members if not lib.get_id(m)] + if invalid: + raise RuntimeError("Found invalid nodes.\nNo ID : " + "{}".format(invalid)) - return 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 4f33e15b1c..5042d01796 100644 --- a/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py +++ b/colorbleed/plugins/maya/publish/validate_look_no_default_shaders.py @@ -37,16 +37,15 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin): "initialParticleSE", "particleCloud1"] - setmembers = instance.data["setMembers"] - members = cmds.listRelatives(setmembers, + members = cmds.listRelatives(instance, allDescendents=True, - type="shape") - + shapes=True, + noIntermediate=True) or [] for member in members: # get connection # listConnections returns a list or None - shading_engine = cmds.listConnections(member, type="shadingEngine") + shading_engine = cmds.listConnections(member, type="objectSet") if not shading_engine: cls.log.error("Detected shape without shading engine : " "'{}'".format(member)) @@ -58,6 +57,7 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin): if shading_engine in disallowed: cls.log.error("Member connected to a disallows objectSet: " "'{}'".format(member)) + invalid.append(member) else: continue @@ -66,7 +66,6 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin): def process(self, instance): """Process all the nodes in the instance""" - # sets = self.get_invalid_sets(instance) - sets = self.get_invalid(instance) - if sets: - raise RuntimeError("Invalid shaders found: {0}".format(sets)) + invalid = self.get_invalid(instance) + if invalid: + raise RuntimeError("Invalid shaders found: {0}".format(invalid)) diff --git a/colorbleed/plugins/maya/publish/validate_look_single_shader.py b/colorbleed/plugins/maya/publish/validate_look_single_shader.py index fabdfb1a6d..1d780bc302 100644 --- a/colorbleed/plugins/maya/publish/validate_look_single_shader.py +++ b/colorbleed/plugins/maya/publish/validate_look_single_shader.py @@ -54,7 +54,7 @@ class ValidateSingleShader(pyblish.api.InstancePlugin): for shape in shapes: shading_engines = cmds.listConnections(shape, destination=True, - type="shadingEngine") + type="shadingEngine") or [] if len(shading_engines) > 1: invalid.append(shape) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index 2a9d9ea25f..a5d8ce2d83 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -36,18 +36,10 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): # We do want to check the referenced nodes as it might be # part of the end product - nodes = lib.filter_out_nodes(set(instance[:]), defaults=True) - invalid = [n for n in nodes if not lib.get_id(n) - and not cls.validate_children(n)] + id_nodes = lib.get_id_required_nodes(defaults=True, + referenced_nodes=False) + + nodes = instance[:] + invalid = [n for n in nodes if n in id_nodes and not lib.get_id(n)] return invalid - - @staticmethod - def validate_children(node): - """Validate the children of the node if the ID is not present""" - - children = cmds.listRelatives(node, children=True) - for child in children: - if lib.get_id(child): - return True - return False From d439c3605d5aa3e648f21980f1a3fdf911813cc5 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 16:51:53 +0200 Subject: [PATCH 14/24] changed get_id_required_nodes --- colorbleed/maya/__init__.py | 4 ++-- colorbleed/maya/lib.py | 9 ++++----- colorbleed/plugins/maya/publish/validate_node_ids.py | 4 ++-- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/colorbleed/maya/__init__.py b/colorbleed/maya/__init__.py index 94288646a0..2ca8040158 100644 --- a/colorbleed/maya/__init__.py +++ b/colorbleed/maya/__init__.py @@ -97,8 +97,8 @@ def on_save(_): avalon.logger.info("Running callback on save..") - nodes = lib.get_id_required_nodes(defaults=True, - referenced_nodes=True) + nodes = lib.get_id_required_nodes(defaults=False, + referenced_nodes=False) # Lead with asset ID from the database asset = os.environ["AVALON_ASSET"] diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 29160a339c..fbbd444b1a 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -613,27 +613,26 @@ def remap_resource_nodes(resources, folder=None): cmds.file(save=True, type="mayaAscii") -def get_id_required_nodes(defaults=True, referenced_nodes=True): +def get_id_required_nodes(defaults=False, referenced_nodes=False): """Filter out any node which are locked (reference) or readOnly Args: nodes (set): nodes to filter - defaults (bool): set True to filter out default nodes + defaults (bool): set to False to filter out default nodes referenced_nodes (bool): set True to filter out reference nodes Returns: nodes (set): list of filtered nodes """ - # `readOnly` flag is obsolete as of Maya 2016 therefor we explicitly remove # default nodes and reference nodes camera_shapes = ["frontShape", "sideShape", "topShape", "perspShape"] ignore = set() - if referenced_nodes: + if not referenced_nodes: ignore |= set(cmds.ls(long=True, referencedNodes=referenced_nodes)) - if defaults: + if not defaults: ignore |= set(cmds.ls(long=True, defaultNodes=defaults)) ignore |= set(cmds.ls(camera_shapes, long=True)) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index a5d8ce2d83..6df5bea4e1 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -36,8 +36,8 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): # We do want to check the referenced nodes as it might be # part of the end product - id_nodes = lib.get_id_required_nodes(defaults=True, - referenced_nodes=False) + id_nodes = lib.get_id_required_nodes(defaults=False, + referenced_nodes=True) nodes = instance[:] invalid = [n for n in nodes if n in id_nodes and not lib.get_id(n)] From eff87c7b3f7c73a1ce0466681709c21918127569 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 16:52:07 +0200 Subject: [PATCH 15/24] removed maya import --- colorbleed/plugins/maya/publish/validate_node_ids.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index 6df5bea4e1..fe2a0cb6a8 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -1,5 +1,3 @@ -import maya.cmds as cmds - import pyblish.api import colorbleed.api From e703fa97ee49cdf7720465a88dfcdfc85b4cde0d Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 16:55:31 +0200 Subject: [PATCH 16/24] removed unused function --- colorbleed/maya/lib.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index fbbd444b1a..425c959770 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -595,24 +595,6 @@ def maya_temp_folder(): return tmp_dir -def remap_resource_nodes(resources, folder=None): - - log.info("Updating resource nodes ...") - for resource in resources: - source = resource["source"] - if folder: - fname = os.path.basename(source) - fpath = os.path.join(folder, fname) - else: - fpath = source - - node_attr = resource["attribute"] - cmds.setAttr(node_attr, fpath, type="string") - - log.info("Saving file ...") - cmds.file(save=True, type="mayaAscii") - - def get_id_required_nodes(defaults=False, referenced_nodes=False): """Filter out any node which are locked (reference) or readOnly From 39557270920af557054b6bc117d314df5f19f050 Mon Sep 17 00:00:00 2001 From: aardschok Date: Wed, 9 Aug 2017 17:16:37 +0200 Subject: [PATCH 17/24] cosmetics --- colorbleed/maya/lib.py | 1 - 1 file changed, 1 deletion(-) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 425c959770..0edf3010cf 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -599,7 +599,6 @@ def get_id_required_nodes(defaults=False, referenced_nodes=False): """Filter out any node which are locked (reference) or readOnly Args: - nodes (set): nodes to filter defaults (bool): set to False to filter out default nodes referenced_nodes (bool): set True to filter out reference nodes Returns: From a324e5db91b2fa80375ef426ca8534ec56fa6018 Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 10:46:08 +0200 Subject: [PATCH 18/24] refactored collector and validators to match new lookdata formatting --- .../plugins/maya/publish/collect_look.py | 8 ++- .../maya/publish/validate_look_contents.py | 16 +++--- .../publish/validate_look_members_node_ids.py | 5 +- .../publish/validate_look_members_unique.py | 2 +- .../publish/validate_look_node_unique_ids.py | 53 ++++++++++++++----- 5 files changed, 54 insertions(+), 30 deletions(-) diff --git a/colorbleed/plugins/maya/publish/collect_look.py b/colorbleed/plugins/maya/publish/collect_look.py index 4b76a17ce3..19c63c7dda 100644 --- a/colorbleed/plugins/maya/publish/collect_look.py +++ b/colorbleed/plugins/maya/publish/collect_look.py @@ -120,8 +120,7 @@ class CollectLook(pyblish.api.InstancePlugin): # Store data on the instance instance.data["lookData"] = {"attributes": attributes, - "relationships": sets.values(), - "sets": looksets} + "relationships": sets} # Collect file nodes used by shading engines (if we have any) files = list() @@ -134,7 +133,7 @@ class CollectLook(pyblish.api.InstancePlugin): instance.data["resources"] = resources # Log a warning when no relevant sets were retrieved for the look. - if not instance.data["lookData"]["sets"]: + if not instance.data["lookData"]["relationships"]: self.log.warning("No sets found for the nodes in the instance: " "%s" % instance[:]) @@ -170,8 +169,7 @@ class CollectLook(pyblish.api.InstancePlugin): if objset in sets: continue - sets[objset] = {"name": objset, - "uuid": lib.get_id(objset), + sets[objset] = {"uuid": lib.get_id(objset), "members": list()} return sets diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index 70aec3c70c..15ba682540 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -48,7 +48,7 @@ class ValidateLookContents(pyblish.api.InstancePlugin): invalid = set() - attributes = ["sets", "relationships", "attributes"] + attributes = ["relationships", "attributes"] lookdata = instance.data["lookData"] for attr in attributes: if attr not in lookdata: @@ -56,8 +56,10 @@ class ValidateLookContents(pyblish.api.InstancePlugin): "'{}'".format(attr)) invalid.add(instance.name) - if not lookdata["relationships"] or not lookdata["sets"]: - cls.log.error("Look has no `relationship` or `sets`") + # Validate at least one single relationship is collected + if not lookdata["relationships"]: + cls.log.error("Look '{}' has no `relationship` or " + "`sets`".format(instance.name)) invalid.add(instance.name) return invalid @@ -69,11 +71,11 @@ class ValidateLookContents(pyblish.api.InstancePlugin): invalid = set() relationships = instance.data["lookData"]["relationships"] - for relationship in relationships: - look_name = relationship["name"] - uuid = relationship["uuid"] + for objectset, members in relationships.items(): + uuid = members["uuid"] if not uuid: - cls.errors.append("{} has invalid ID ") + look_name = members["name"] + cls.log.error("{} has invalid ID ".format(look_name)) invalid.add(look_name) return invalid 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 f168ba3b39..92c33bf9b5 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -1,5 +1,3 @@ -import maya.cmds as cmds - import pyblish.api import colorbleed.api import colorbleed.maya.lib as lib @@ -37,11 +35,10 @@ class ValidateLookMembers(pyblish.api.InstancePlugin): members = set() relationships = instance.data["lookData"]["relationships"] - for relation in relationships: + for relation in relationships.values(): members.update([member['name'] for member in relation['members']]) invalid = [m for m in members if not lib.get_id(m)] if invalid: raise RuntimeError("Found invalid nodes.\nNo ID : " "{}".format(invalid)) - diff --git a/colorbleed/plugins/maya/publish/validate_look_members_unique.py b/colorbleed/plugins/maya/publish/validate_look_members_unique.py index 41ffed93c2..1dfac3f3f1 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_unique.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_unique.py @@ -35,7 +35,7 @@ class ValidateNonDuplicateRelationshipMembers(pyblish.api.InstancePlugin): # Get all members from the sets members = [] relationships = instance.data["lookData"]["relationships"] - for relationship in relationships: + for relationship in relationships.values(): members.extend([i['name'] for i in relationship['members']]) # Ensure we don't have components but the objects 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 d4fd034710..fbfc007a9a 100644 --- a/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_node_unique_ids.py @@ -1,3 +1,4 @@ +import pprint from collections import defaultdict import pyblish.api @@ -17,20 +18,44 @@ class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.RepairAction] - @staticmethod - def get_invalid(instance): + @classmethod + def get_invalid(cls, instance): - nodes = instance.data["lookData"]["sets"] + invalid = [] + uuids_dict = defaultdict(list) - # Ensure all nodes have a cbId - id_sets = defaultdict(list) - for node in nodes: - unique_id = lib.get_id(node) - if not unique_id: - continue - id_sets[unique_id].append(node) + relationships = instance.data["lookData"]["relationships"] + pprint.pprint(relationships) + for objectset, relationship in relationships.items(): + cls.log.info("Validating lookData for '%s'" % objectset) + # check if node has UUID and this matches with found node + for member in relationship["members"]: + node = member["name"] + member_uuid = member["uuid"] + uuid_query = lib.get_id(node) - invalid = [n for n in id_sets.itervalues() if len(n) > 1] + if not member_uuid: + cls.log.error("No UUID found for '{}'".format(node)) + invalid.append(node) + continue + + if uuid_query != member_uuid: + cls.log.error("UUID in lookData does not match with " + "queried UUID of '{}'".format(node)) + invalid.append(node) + continue + + # check if the uuid has already passed through the check + # if so it means its a duplicate. + uuids_dict[objectset].append(uuid_query) + + for objectset, member_uuids in uuids_dict.items(): + stored = len(member_uuids) + unique = len(set(member_uuids)) + if unique != stored: + rel_members = relationships[objectset]["members"] + invalid.extend([i["name"] for i in rel_members if + i["uuid"] not in unique]) return invalid @@ -39,5 +64,7 @@ class ValidateLookNodeUniqueIds(pyblish.api.InstancePlugin): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Nodes found without " - "asset IDs: {0}".format(invalid)) + for item in invalid: + self.log.error("Invalid node : %s" % item) + raise RuntimeError("Nodes found without unique " + "IDs, see records") From 76873371bf6aad2ae46e2eb2bfb0ae700b23070d Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 10:52:17 +0200 Subject: [PATCH 19/24] removed runtime error form get_invalid --- colorbleed/plugins/maya/publish/collect_look.py | 2 +- .../maya/publish/validate_look_members_node_ids.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/colorbleed/plugins/maya/publish/collect_look.py b/colorbleed/plugins/maya/publish/collect_look.py index 19c63c7dda..d9f1b8067f 100644 --- a/colorbleed/plugins/maya/publish/collect_look.py +++ b/colorbleed/plugins/maya/publish/collect_look.py @@ -67,7 +67,7 @@ class CollectLook(pyblish.api.InstancePlugin): hosts = ["maya"] # Ignore specifically named sets (check with endswith) - IGNORE = ["out_SET", "controls_SET", "_INST"] + IGNORE = ["out_SET", "controls_SET", "_INST", "_CON"] def process(self, instance): """Collect the Look in the instance with the correct layer settings""" 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 92c33bf9b5..9ecc8cd5fa 100644 --- a/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_look_members_node_ids.py @@ -27,8 +27,8 @@ class ValidateLookMembers(pyblish.api.InstancePlugin): invalid_ids = self.get_invalid(instance) if invalid_ids: - raise RuntimeError("Members found without " - "asset IDs: {0}".format(invalid_ids)) + raise RuntimeError("Found invalid nodes.\nNo ID : " + "{}".format(invalid_ids)) @classmethod def get_invalid(cls, instance): @@ -39,6 +39,6 @@ class ValidateLookMembers(pyblish.api.InstancePlugin): members.update([member['name'] for member in relation['members']]) invalid = [m for m in members if not lib.get_id(m)] - if invalid: - raise RuntimeError("Found invalid nodes.\nNo ID : " - "{}".format(invalid)) + + return invalid + From ea80950b3091e7da6c8d60592b60f1a8a0884771 Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 13:53:53 +0200 Subject: [PATCH 20/24] removed import --- colorbleed/plugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/colorbleed/plugin.py b/colorbleed/plugin.py index 70b2c76c6f..84e64f6392 100644 --- a/colorbleed/plugin.py +++ b/colorbleed/plugin.py @@ -1,7 +1,5 @@ import tempfile import pyblish.api -import avalon.maya - ValidatePipelineOrder = pyblish.api.ValidatorOrder + 0.05 ValidateContentsOrder = pyblish.api.ValidatorOrder + 0.1 From 4a2d28b1e17327570194cb97f49947cace2b2877 Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 13:54:19 +0200 Subject: [PATCH 21/24] updated function ards --- colorbleed/maya/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/colorbleed/maya/__init__.py b/colorbleed/maya/__init__.py index 2ca8040158..2a28f61684 100644 --- a/colorbleed/maya/__init__.py +++ b/colorbleed/maya/__init__.py @@ -97,8 +97,7 @@ def on_save(_): avalon.logger.info("Running callback on save..") - nodes = lib.get_id_required_nodes(defaults=False, - referenced_nodes=False) + nodes = lib.get_id_required_nodes(referenced_nodes=False) # Lead with asset ID from the database asset = os.environ["AVALON_ASSET"] From c0cfc0bc03b185998ee44f2ebab22182a03ee8bb Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 13:55:03 +0200 Subject: [PATCH 22/24] updated look assignment function --- colorbleed/maya/lib.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 0edf3010cf..6d05450e02 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -595,11 +595,10 @@ def maya_temp_folder(): return tmp_dir -def get_id_required_nodes(defaults=False, referenced_nodes=False): +def get_id_required_nodes(referenced_nodes=False): """Filter out any node which are locked (reference) or readOnly Args: - defaults (bool): set to False to filter out default nodes referenced_nodes (bool): set True to filter out reference nodes Returns: nodes (set): list of filtered nodes @@ -611,11 +610,11 @@ def get_id_required_nodes(defaults=False, referenced_nodes=False): ignore = set() if not referenced_nodes: - ignore |= set(cmds.ls(long=True, referencedNodes=referenced_nodes)) + ignore |= set(cmds.ls(long=True, referencedNodes=True)) - if not defaults: - ignore |= set(cmds.ls(long=True, defaultNodes=defaults)) - ignore |= set(cmds.ls(camera_shapes, long=True)) + # list all defaultNodes to filter out from the rest + ignore |= set(cmds.ls(long=True, defaultNodes=True)) + ignore |= set(cmds.ls(camera_shapes, long=True)) # establish set of nodes to ignore types = ["objectSet", "file", "mesh", "nurbsCurve", "nurbsSurface"] @@ -626,9 +625,7 @@ def get_id_required_nodes(defaults=False, referenced_nodes=False): # The items which need to pass the id to their parent # Add the collected transform to the nodes - dag = cmds.ls(nodes, - type="dagNode", - long=True) # query only dag nodes + dag = cmds.ls(nodes, type="dagNode", long=True) # query only dag nodes transforms = cmds.listRelatives(dag, parent=True, @@ -636,6 +633,7 @@ def get_id_required_nodes(defaults=False, referenced_nodes=False): nodes = set(nodes) nodes |= set(transforms) + nodes -= ignore # Remove the ignored nodes return nodes @@ -898,7 +896,7 @@ def apply_shaders(relationships, shadernodes, nodes): """ attributes = relationships.get("attributes", []) - shader_sets = relationships.get("sets", []) + shader_data = relationships.get("relationships", {}) shading_engines = cmds.ls(shadernodes, type="objectSet", long=True) assert len(shading_engines) > 0, ("Error in retrieving objectSets " @@ -915,10 +913,10 @@ def apply_shaders(relationships, shadernodes, nodes): # endregion # region assign - for shader_set in shader_sets: + for shader, data in shader_data.items(): # collect all unique IDs of the set members - shader_uuid = shader_set["uuid"] - member_uuids = [member["uuid"] for member in shader_set["members"]] + shader_uuid = data["uuid"] + member_uuids = [member["uuid"] for member in data["members"]] filtered_nodes = list() for uuid in member_uuids: From 1d94a9f0b24014cd101edad76166f1dabf844bc3 Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 13:56:44 +0200 Subject: [PATCH 23/24] updated lookdev validations and extractor --- .../plugins/maya/publish/extract_look.py | 4 +-- .../maya/publish/validate_look_contents.py | 34 ++++++++++++++++--- .../plugins/maya/publish/validate_node_ids.py | 8 ++--- .../maya/publish/validate_rig_contents.py | 1 - 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/colorbleed/plugins/maya/publish/extract_look.py b/colorbleed/plugins/maya/publish/extract_look.py index 46d45400a4..eb7e7228d0 100644 --- a/colorbleed/plugins/maya/publish/extract_look.py +++ b/colorbleed/plugins/maya/publish/extract_look.py @@ -41,7 +41,7 @@ class ExtractLook(colorbleed.api.Extractor): # exported file by accident self.log.info("Extract sets (Maya ASCII) ...") lookdata = instance.data["lookData"] - sets = lookdata["sets"] + sets = lookdata["relationships"].keys() resources = instance.data["resources"] remap = {} @@ -72,7 +72,7 @@ class ExtractLook(colorbleed.api.Extractor): # Write the JSON data self.log.info("Extract json..") data = {"attributes": lookdata["attributes"], - "sets": lookdata["relationships"]} + "relationships": lookdata["relationships"]} with open(json_path, "w") as f: json.dump(data, f) diff --git a/colorbleed/plugins/maya/publish/validate_look_contents.py b/colorbleed/plugins/maya/publish/validate_look_contents.py index 15ba682540..1bdd3d0aef 100644 --- a/colorbleed/plugins/maya/publish/validate_look_contents.py +++ b/colorbleed/plugins/maya/publish/validate_look_contents.py @@ -1,5 +1,8 @@ +import maya.cmds as cmds + import pyblish.api import colorbleed.api +import colorbleed.maya.lib as lib class ValidateLookContents(pyblish.api.InstancePlugin): @@ -24,16 +27,21 @@ class ValidateLookContents(pyblish.api.InstancePlugin): invalid = self.get_invalid(instance) if invalid: - raise RuntimeError("Invalid look content") + raise RuntimeError("'{}' has invalid look " + "content".format(instance.name)) @classmethod def get_invalid(cls, instance): """Get all invalid nodes""" + cls.log.info("Validating look content for " + "'{}'".format(instance.name)) + + instance_items = cls.validate_instance_items(instance) attributes = list(cls.validate_lookdata_attributes(instance)) relationships = list(cls.validate_relationship_ids(instance)) - invalid = attributes + relationships + invalid = instance_items + attributes + relationships return invalid @@ -58,8 +66,8 @@ class ValidateLookContents(pyblish.api.InstancePlugin): # Validate at least one single relationship is collected if not lookdata["relationships"]: - cls.log.error("Look '{}' has no `relationship` or " - "`sets`".format(instance.name)) + cls.log.error("Look '{}' has no " + "`relationship`".format(instance.name)) invalid.add(instance.name) return invalid @@ -74,8 +82,24 @@ class ValidateLookContents(pyblish.api.InstancePlugin): for objectset, members in relationships.items(): uuid = members["uuid"] if not uuid: - look_name = members["name"] + look_name = objectset cls.log.error("{} has invalid ID ".format(look_name)) invalid.add(look_name) return invalid + + @classmethod + def validate_instance_items(cls, instance): + + required_nodes = lib.get_id_required_nodes(referenced_nodes=False) + + invalid = [node for node in instance if node in required_nodes + and not lib.get_id(node)] + if invalid: + nr_of_invalid = len(invalid) + cls.log.error("Found {} nodes without ID: {}".format(nr_of_invalid, + invalid)) + return invalid + + + diff --git a/colorbleed/plugins/maya/publish/validate_node_ids.py b/colorbleed/plugins/maya/publish/validate_node_ids.py index fe2a0cb6a8..733af05d4f 100644 --- a/colorbleed/plugins/maya/publish/validate_node_ids.py +++ b/colorbleed/plugins/maya/publish/validate_node_ids.py @@ -34,10 +34,8 @@ class ValidateNodeIDs(pyblish.api.InstancePlugin): # We do want to check the referenced nodes as it might be # part of the end product - id_nodes = lib.get_id_required_nodes(defaults=False, - referenced_nodes=True) - - nodes = instance[:] - invalid = [n for n in nodes if n in id_nodes and not lib.get_id(n)] + id_nodes = lib.get_id_required_nodes(referenced_nodes=True) + invalid = [n for n in instance[:] if n in id_nodes + and not lib.get_id(n)] return invalid diff --git a/colorbleed/plugins/maya/publish/validate_rig_contents.py b/colorbleed/plugins/maya/publish/validate_rig_contents.py index 3ef1220e56..d07fafe362 100644 --- a/colorbleed/plugins/maya/publish/validate_rig_contents.py +++ b/colorbleed/plugins/maya/publish/validate_rig_contents.py @@ -100,7 +100,6 @@ class ValidateRigContents(pyblish.api.InstancePlugin): """ errors = [] for node in nodes: - print node if node not in hierarchy: errors.append(node) return errors From bb52fca88f7b1c5dd15699c3c37aaf5c5d5c2f3e Mon Sep 17 00:00:00 2001 From: aardschok Date: Thu, 10 Aug 2017 14:23:05 +0200 Subject: [PATCH 24/24] changed items() to values() --- colorbleed/maya/lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/colorbleed/maya/lib.py b/colorbleed/maya/lib.py index 6d05450e02..8b7d04ef87 100644 --- a/colorbleed/maya/lib.py +++ b/colorbleed/maya/lib.py @@ -913,7 +913,7 @@ def apply_shaders(relationships, shadernodes, nodes): # endregion # region assign - for shader, data in shader_data.items(): + for data in shader_data.values(): # collect all unique IDs of the set members shader_uuid = data["uuid"] member_uuids = [member["uuid"] for member in data["members"]]