Refactor to existing lib function + plugin

This commit is contained in:
Derek Severin 2022-03-02 18:47:07 +07:00
parent 51957dd3ae
commit d714e52921
5 changed files with 38 additions and 121 deletions

View file

@ -1751,18 +1751,24 @@ def remove_other_uv_sets(mesh):
cmds.removeMultiInstance(attr, b=True)
def get_id_from_history(node):
def get_id_from_sibling(node, history_only=True):
"""Return first node id in the history chain that matches this node.
The nodes in history must be of the exact same node type and must be
parented under the same parent.
If no matching node is found in history, the siblings of the node
are checked. Additionally to having the same parent, the sibling must
be marked as 'intermediate object'.
Args:
node (str): node to retrieve the
node (str): node to retrieve the history from
history_only (bool): also looks in node's siblings if True
and if nothing found in history
Returns:
str or None: The id from the node in history or None when no id found
on any valid nodes in the history.
str or None: The id from the sibling node or None when no id found
on any valid nodes in the history or siblings.
"""
@ -1791,6 +1797,22 @@ def get_id_from_history(node):
if _id:
return _id
if not history_only:
# Get siblings of same type
similar_nodes = cmds.listRelatives(parent,
type=node_type,
fullPath=True)
# Exclude itself
similar_nodes = [x for x in similar_nodes if x != node]
for similar_node in similar_nodes:
# Check if "intermediate object"
if cmds.getAttr(similar_node + ".io"):
_id = get_id(similar_node)
if _id:
return _id
# Project settings
def set_scene_fps(fps, update=True):

View file

@ -65,7 +65,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
invalid.append(node)
continue
history_id = lib.get_id_from_history(node)
history_id = lib.get_id_from_sibling(node)
if history_id is not None and node_id != history_id:
invalid.append(node)
@ -76,7 +76,7 @@ class ValidateOutRelatedNodeIds(pyblish.api.InstancePlugin):
for node in cls.get_invalid(instance):
# Get the original id from history
history_id = lib.get_id_from_history(node)
history_id = lib.get_id_from_sibling(node)
if not history_id:
cls.log.error("Could not find ID in history for '%s'", node)
continue

View file

@ -48,7 +48,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin):
invalid = []
for shape in shapes:
history_id = lib.get_id_from_history(shape)
history_id = lib.get_id_from_sibling(shape)
if history_id:
current_id = lib.get_id(shape)
if current_id != history_id:
@ -61,7 +61,7 @@ class ValidateNodeIdsDeformedShape(pyblish.api.InstancePlugin):
for node in cls.get_invalid(instance):
# Get the original id from history
history_id = lib.get_id_from_history(node)
history_id = lib.get_id_from_sibling(node)
if not history_id:
cls.log.error("Could not find ID in history for '%s'", node)
continue

View file

@ -1,105 +0,0 @@
from maya import cmds
import pyblish.api
import openpype.api
import openpype.hosts.maya.api.action
from openpype.hosts.maya.api import lib
class ValidateNodeIdsDeformerTransfer(pyblish.api.InstancePlugin):
"""Validate if deformed shapes have related IDs to the original
shapes.
When a deformer is applied in the scene on a mesh,
Maya creates a new "deformer" shape node for the mesh.
This new node does not get the original ID and later references
to the original node ID don't match.
This validator checks whether the IDs are valid on all the shape
nodes in the instance.
"""
order = openpype.api.ValidateContentsOrder
families = ['rig']
hosts = ['maya']
label = 'Deformed shape ids transferred'
actions = [
openpype.hosts.maya.api.action.SelectInvalidAction,
openpype.api.RepairAction
]
def process(self, instance):
"""Process all the nodes in the instance"""
# Ensure nodes with sibling share the same ID
invalid = self.get_invalid(instance)
if invalid:
raise RuntimeError(
"Shapes found that are considered 'Deformed'"
" with invalid object ids: {0}".format(invalid)
)
@classmethod
def get_invalid(cls, instance):
"""Get all nodes which do not match the criteria"""
shapes = cmds.ls(instance[:],
dag=True,
leaf=True,
shapes=True,
long=True,
noIntermediate=True)
invalid = []
for shape in shapes:
sibling_id = cls._get_id_from_sibling(shape)
if not sibling_id:
continue
current_id = lib.get_id(shape)
if current_id != sibling_id:
invalid.append(shape)
return invalid
@classmethod
def _get_id_from_sibling(cls, node):
"""In some cases, the history of the deformed shapes cannot be used
to get the original shape, as the relation with the orignal shape
has been lost.
The original shape can be found as a sibling of the deformed shape
(sharing same transform parent), which has the "intermediate object"
attribute set.
The ID of that shape node can then be transferred to the deformed
shape node.
"""
# Get long name
node = cmds.ls(node, long=True)[0]
parent = cmds.listRelatives(node, parent=True, fullPath=True)
# Get siblings of same type
node_type = cmds.nodeType(node)
similar_nodes = cmds.listRelatives(parent, type=node_type, fullPath=1)
# Exclude itself
similar_nodes = [x for x in similar_nodes if x != node]
for similar_node in similar_nodes:
# Make sure it is an "intermediate object"
if cmds.getAttr(similar_node + ".io"):
_id = lib.get_id(similar_node)
if _id:
return _id
@classmethod
def repair(cls, instance):
for node in cls.get_invalid(instance):
# Get the original id from sibling
sibling_id = cls._get_id_from_sibling(node)
if not sibling_id:
cls.log.error("Could not find ID from sibling for '%s'", node)
continue
lib.set_id(node, sibling_id, overwrite=True)

View file

@ -51,10 +51,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
noIntermediate=True)
for shape in shapes:
history_id = lib.get_id_from_history(shape)
if history_id:
sibling_id = lib.get_id_from_sibling(shape, history_only=False)
if sibling_id:
current_id = lib.get_id(shape)
if current_id != history_id:
if current_id != sibling_id:
invalid.append(shape)
return invalid
@ -63,10 +63,10 @@ class ValidateRigOutSetNodeIds(pyblish.api.InstancePlugin):
def repair(cls, instance):
for node in cls.get_invalid(instance):
# Get the original id from history
history_id = lib.get_id_from_history(node)
if not history_id:
cls.log.error("Could not find ID in history for '%s'", node)
# Get the original id from sibling
sibling_id = lib.get_id_from_sibling(node, history_only=False)
if not sibling_id:
cls.log.error("Could not find ID in siblings for '%s'", node)
continue
lib.set_id(node, history_id, overwrite=True)
lib.set_id(node, sibling_id, overwrite=True)