mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 08:24:53 +01:00
improved check to validate if IDs are related to original use shape
This commit is contained in:
parent
3430b6660b
commit
dee1d504bf
1 changed files with 86 additions and 43 deletions
|
|
@ -3,11 +3,10 @@ import maya.cmds as cmds
|
||||||
import pyblish.api
|
import pyblish.api
|
||||||
import colorbleed.api
|
import colorbleed.api
|
||||||
import colorbleed.maya.lib as lib
|
import colorbleed.maya.lib as lib
|
||||||
import avalon.io as io
|
|
||||||
|
|
||||||
|
|
||||||
class ValidateAnimationOutSetRelatedNodeIds(pyblish.api.InstancePlugin):
|
class ValidateAnimationOutSetRelatedNodeIds(pyblish.api.InstancePlugin):
|
||||||
"""Validate rig out_SET nodes have related ids to current context
|
"""Validate if nodes have related IDs to the source (original shapes)
|
||||||
|
|
||||||
An ID is 'related' if its built in the current Item.
|
An ID is 'related' if its built in the current Item.
|
||||||
|
|
||||||
|
|
@ -18,10 +17,10 @@ class ValidateAnimationOutSetRelatedNodeIds(pyblish.api.InstancePlugin):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
order = colorbleed.api.ValidateContentsOrder
|
order = colorbleed.api.ValidateContentsOrder
|
||||||
families = ['colorbleed.animation']
|
families = ['colorbleed.animation', "colorbleed.pointcache"]
|
||||||
hosts = ['maya']
|
hosts = ['maya']
|
||||||
label = 'Animation Out Set Related Node Ids'
|
label = 'Animation Out Set Related Node Ids'
|
||||||
actions = [colorbleed.api.SelectInvalidAction]
|
actions = [colorbleed.api.SelectInvalidAction, colorbleed.api.RepairAction]
|
||||||
optional = True
|
optional = True
|
||||||
|
|
||||||
ignore_types = ("constraint",)
|
ignore_types = ("constraint",)
|
||||||
|
|
@ -29,61 +28,105 @@ class ValidateAnimationOutSetRelatedNodeIds(pyblish.api.InstancePlugin):
|
||||||
def process(self, instance):
|
def process(self, instance):
|
||||||
"""Process all meshes"""
|
"""Process all meshes"""
|
||||||
|
|
||||||
# Ensure all nodes have a cbId
|
# Ensure all nodes have a cbId and a related ID to the original shapes
|
||||||
|
# if a deformer has been created on the shape
|
||||||
invalid = self.get_invalid(instance)
|
invalid = self.get_invalid(instance)
|
||||||
if invalid:
|
if invalid:
|
||||||
raise RuntimeError("Nodes found with non-related "
|
raise RuntimeError("Nodes found with non-related "
|
||||||
"asset IDs: {0}".format(invalid))
|
"asset IDs: {0}".format(invalid))
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_pointcache_nodes(cls, instance):
|
|
||||||
|
|
||||||
# Get out_SET
|
|
||||||
sets = cmds.ls(instance, type='objectSet')
|
|
||||||
pointcache_sets = [x for x in sets if x == 'out_SET']
|
|
||||||
|
|
||||||
nodes = list()
|
|
||||||
for s in pointcache_sets:
|
|
||||||
# Ensure long names
|
|
||||||
members = cmds.ls(cmds.sets(s, query=True), long=True)
|
|
||||||
descendants = cmds.listRelatives(members,
|
|
||||||
allDescendents=True,
|
|
||||||
fullPath=True) or []
|
|
||||||
descendants = cmds.ls(descendants,
|
|
||||||
noIntermediate=True,
|
|
||||||
long=True)
|
|
||||||
hierarchy = members + descendants
|
|
||||||
nodes.extend(hierarchy)
|
|
||||||
|
|
||||||
# ignore certain node types (e.g. constraints)
|
|
||||||
ignore = cmds.ls(nodes, type=cls.ignore_types, long=True)
|
|
||||||
if ignore:
|
|
||||||
ignore = set(ignore)
|
|
||||||
nodes = [node for node in nodes if node not in ignore]
|
|
||||||
|
|
||||||
return nodes
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_invalid(cls, instance):
|
def get_invalid(cls, instance):
|
||||||
invalid_items = []
|
"""Get all nodes which do not match the criteria"""
|
||||||
|
invalid = []
|
||||||
|
|
||||||
# get asset id
|
# get asset id
|
||||||
nodes = cls.get_pointcache_nodes(instance)
|
nodes = instance.data["pointcache_data"]
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
|
node_type = cmds.nodeType(node)
|
||||||
node_id = lib.get_id(node)
|
node_id = lib.get_id(node)
|
||||||
|
|
||||||
|
if node_type == "mesh" and not node_id:
|
||||||
|
invalid.append(node)
|
||||||
|
continue
|
||||||
|
|
||||||
if not node_id:
|
if not node_id:
|
||||||
invalid_items.append(node)
|
continue
|
||||||
|
|
||||||
# TODO: Should we check whether the ids are related to the rig's asset?
|
root_id = cls.get_history_root_id(node=node)
|
||||||
|
if root_id is not None:
|
||||||
|
asset_id = cls.to_item(node_id)
|
||||||
|
if root_id != asset_id:
|
||||||
|
invalid.append(node)
|
||||||
|
|
||||||
# Log invalid item ids
|
return invalid
|
||||||
if invalid_items:
|
|
||||||
for item_id in sorted(invalid_items):
|
|
||||||
cls.log.warning("Found invalid item id: {0}".format(item_id))
|
|
||||||
|
|
||||||
return invalid_items
|
@classmethod
|
||||||
|
def get_history_root_id(cls, node):
|
||||||
|
"""
|
||||||
|
|
||||||
|
Get the original node ID when a node has been deformed
|
||||||
|
Args:
|
||||||
|
node (str): node to retrieve the
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: the asset ID as found in the database
|
||||||
|
"""
|
||||||
|
|
||||||
|
asset_id = None
|
||||||
|
node = cmds.ls(node, long=True)[0]
|
||||||
|
|
||||||
|
# We only check when the node is *not* referenced
|
||||||
|
if cmds.referenceQuery(node, isNodeReferenced=True):
|
||||||
|
return
|
||||||
|
|
||||||
|
# Find all similar nodes in history
|
||||||
|
history = cmds.listHistory(node)
|
||||||
|
node_type = cmds.nodeType(node)
|
||||||
|
similar_nodes = cmds.ls(history, exactType=node_type, long=True)
|
||||||
|
|
||||||
|
# Exclude itself
|
||||||
|
similar_nodes = [x for x in similar_nodes if x != node]
|
||||||
|
|
||||||
|
# The node *must be* under the same parent
|
||||||
|
parent = cls.get_parent(node)
|
||||||
|
similar_nodes = [i for i in similar_nodes if
|
||||||
|
cls.get_parent(i) == parent]
|
||||||
|
|
||||||
|
# Check all of the remaining similar nodes and take the first one
|
||||||
|
# with an id and assume it's the original.
|
||||||
|
for similar_node in similar_nodes:
|
||||||
|
|
||||||
|
_id = lib.get_id(similar_node)
|
||||||
|
if not _id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
asset_id = cls.to_item(_id)
|
||||||
|
break
|
||||||
|
|
||||||
|
return asset_id
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def repair(cls, instance):
|
||||||
|
|
||||||
|
for node in cls.get_invalid(instance):
|
||||||
|
# Get node ID and the asset ID part
|
||||||
|
node_id = lib.get_id(node)
|
||||||
|
asset_id = cls.to_item(node_id)
|
||||||
|
|
||||||
|
# Get root asset ID
|
||||||
|
root_id = cls.get_history_root_id(node=node)
|
||||||
|
|
||||||
|
# Replace errored ID with good ID
|
||||||
|
new_id = node_id.replace(asset_id, root_id)
|
||||||
|
|
||||||
|
cmds.setAttr("%s.cbId" % node, new_id, type="string")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def to_item(_id):
|
def to_item(_id):
|
||||||
"""Split the item id part from a node id"""
|
"""Split the item id part from a node id"""
|
||||||
return _id.rsplit(":", 1)[0]
|
return _id.split(":", 1)[0]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_parent(node):
|
||||||
|
return cmds.listRelatives(node, parent=True, fullPath=True)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue