mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
resolved issue with checking sets content
This commit is contained in:
parent
bb52fca88f
commit
1da91e6751
5 changed files with 188 additions and 102 deletions
|
|
@ -931,3 +931,81 @@ def apply_shaders(relationships, shadernodes, nodes):
|
|||
# endregion
|
||||
|
||||
apply_attributes(attributes, ns_nodes_by_id)
|
||||
|
||||
|
||||
def get_isolate_view_sets():
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
|
||||
view_sets = set()
|
||||
for panel in cmds.getPanel(type="modelPanel"):
|
||||
view_set = cmds.modelEditor(panel, query=True, viewObjects=True)
|
||||
if view_set:
|
||||
view_sets.add(view_set)
|
||||
|
||||
return view_sets
|
||||
|
||||
|
||||
def get_related_sets(node):
|
||||
"""Return objectSets that are relationships for a look for `node`.
|
||||
|
||||
Filters out based on:
|
||||
- id attribute is NOT `pyblish.avalon.container`
|
||||
- shapes and deformer shapes (alembic creates meshShapeDeformed)
|
||||
- set name ends with any from a predefined list
|
||||
- set in not in viewport set (isolate selected for example)
|
||||
|
||||
Args:
|
||||
node (str): name of the current not to check
|
||||
|
||||
Returns:
|
||||
list: The related sets
|
||||
|
||||
"""
|
||||
|
||||
# Ignore specific suffices
|
||||
ignore_suffices = ["out_SET", "controls_SET", "_INST", "_CON"]
|
||||
|
||||
# Default nodes to ignore
|
||||
defaults = ["initialShadingGroup",
|
||||
"defaultLightSet",
|
||||
"defaultObjectSet"]
|
||||
|
||||
# Ids to ignore
|
||||
ignored = ["pyblish.avalon.instance",
|
||||
"pyblish.avalon.container"]
|
||||
|
||||
view_sets = get_isolate_view_sets()
|
||||
|
||||
related_sets = cmds.listSets(object=node, extendToShape=False)
|
||||
if not related_sets:
|
||||
return []
|
||||
|
||||
# Ignore `avalon.container`
|
||||
sets = [s for s in related_sets if
|
||||
not cmds.attributeQuery("id", node=s, exists=True) or
|
||||
not cmds.getAttr("%s.id" % s) in ignored]
|
||||
|
||||
# Exclude deformer sets
|
||||
# Autodesk documentation on listSets command:
|
||||
# type(uint) : Returns all sets in the scene of the given
|
||||
# >>> type:
|
||||
# >>> 1 - all rendering sets
|
||||
# >>> 2 - all deformer sets
|
||||
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]
|
||||
|
||||
# Ignore when the set has a specific suffix
|
||||
sets = [s for s in sets if not any(s.endswith(x) for x in ignore_suffices)]
|
||||
|
||||
# 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]
|
||||
|
||||
return sets
|
||||
|
|
|
|||
|
|
@ -66,9 +66,6 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
label = "Collect Look"
|
||||
hosts = ["maya"]
|
||||
|
||||
# Ignore specifically named sets (check with endswith)
|
||||
IGNORE = ["out_SET", "controls_SET", "_INST", "_CON"]
|
||||
|
||||
def process(self, instance):
|
||||
"""Collect the Look in the instance with the correct layer settings"""
|
||||
|
||||
|
|
@ -90,16 +87,14 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
sets = self.gather_sets(instance)
|
||||
|
||||
# Lookup with absolute names (from root namespace)
|
||||
instance_lookup = set([str(x) for x in cmds.ls(instance,
|
||||
long=True,
|
||||
absoluteName=True)])
|
||||
instance_lookup = set([str(x) for x in cmds.ls(instance, long=True)])
|
||||
|
||||
self.log.info("Gathering set relations..")
|
||||
for objset in sets:
|
||||
self.log.debug("From %s.." % objset)
|
||||
content = cmds.sets(objset, query=True)
|
||||
objset_members = sets[objset]["members"]
|
||||
for member in cmds.ls(content, long=True, absoluteName=True):
|
||||
for member in cmds.ls(content, long=True):
|
||||
member_data = self.collect_member_data(member,
|
||||
objset_members,
|
||||
instance_lookup,
|
||||
|
|
@ -114,7 +109,7 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
self.log.info("Gathering attribute changes to instance members..")
|
||||
|
||||
attributes = self.collect_attributes_changed(instance)
|
||||
looksets = cmds.ls(sets.keys(), absoluteName=True, long=True)
|
||||
looksets = cmds.ls(sets.keys(), long=True)
|
||||
|
||||
self.log.info("Found the following sets: {}".format(looksets))
|
||||
|
||||
|
|
@ -152,19 +147,16 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
dict
|
||||
"""
|
||||
|
||||
# Get view sets (so we can ignore those sets later)
|
||||
sets = dict()
|
||||
view_sets = set()
|
||||
for panel in cmds.getPanel(type="modelPanel"):
|
||||
view_set = cmds.modelEditor(panel, query=True, viewObjects=True)
|
||||
if view_set:
|
||||
view_sets.add(view_set)
|
||||
|
||||
for node in instance:
|
||||
related_sets = self.get_related_sets(node, view_sets)
|
||||
|
||||
related_sets = lib.get_related_sets(node)
|
||||
if not related_sets:
|
||||
continue
|
||||
|
||||
self.log.info("Found sets %s for %s", related_sets, node)
|
||||
|
||||
for objset in related_sets:
|
||||
if objset in sets:
|
||||
continue
|
||||
|
|
@ -174,59 +166,6 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
|
||||
return sets
|
||||
|
||||
def get_related_sets(self, node, view_sets):
|
||||
"""Get the sets which do not belong to any specific group
|
||||
|
||||
Filters out based on:
|
||||
- id attribute is NOT `pyblish.avalon.container`
|
||||
- shapes and deformer shapes (alembic creates meshShapeDeformed)
|
||||
- set name ends with any from a predefined list
|
||||
- set in not in viewport set (isolate selected for example)
|
||||
|
||||
Args:
|
||||
node (str): name of the current not to check
|
||||
"""
|
||||
defaults = ["initialShadingGroup",
|
||||
"defaultLightSet",
|
||||
"defaultObjectSet"]
|
||||
|
||||
ignored = ["pyblish.avalon.instance",
|
||||
"pyblish.avalon.container"]
|
||||
|
||||
related_sets = cmds.listSets(object=node, extendToShape=False)
|
||||
if not related_sets:
|
||||
return []
|
||||
|
||||
# Ignore `avalon.container`
|
||||
sets = [s for s in related_sets if
|
||||
not cmds.attributeQuery("id", node=s, exists=True) or
|
||||
not cmds.getAttr("%s.id" % s) in ignored]
|
||||
|
||||
# Exclude deformer sets
|
||||
# Autodesk documentation on listSets command:
|
||||
# type(uint) : Returns all sets in the scene of the given
|
||||
# >>> type:
|
||||
# >>> 1 - all rendering sets
|
||||
# >>> 2 - all deformer sets
|
||||
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]
|
||||
|
||||
# Ignore specifically named sets
|
||||
sets = [s for s in sets if not any(s.endswith(x) for x in self.IGNORE)]
|
||||
|
||||
# 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" % (sets, node))
|
||||
|
||||
return sets
|
||||
|
||||
def remove_sets_without_members(self, sets):
|
||||
"""Remove any set which does not have any members
|
||||
|
||||
|
|
@ -270,11 +209,6 @@ class CollectLook(pyblish.api.InstancePlugin):
|
|||
if member in [m["name"] for m in objset_members]:
|
||||
return
|
||||
|
||||
# check node type, if mesh get parent!
|
||||
if cmds.nodeType(node) == "mesh":
|
||||
# A mesh will always have a transform node in Maya logic
|
||||
node = cmds.listRelatives(node, parent=True, fullPath=True)[0]
|
||||
|
||||
if not cmds.attributeQuery("cbId", node=node, exists=True):
|
||||
self.log.error("Node '{}' has no attribute 'cbId'".format(node))
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import maya.cmds as cmds
|
||||
|
||||
import pyblish.api
|
||||
import colorbleed.api
|
||||
import colorbleed.maya.lib as lib
|
||||
|
|
@ -67,7 +65,7 @@ class ValidateLookContents(pyblish.api.InstancePlugin):
|
|||
# Validate at least one single relationship is collected
|
||||
if not lookdata["relationships"]:
|
||||
cls.log.error("Look '{}' has no "
|
||||
"`relationship`".format(instance.name))
|
||||
"`relationships`".format(instance.name))
|
||||
invalid.add(instance.name)
|
||||
|
||||
return invalid
|
||||
|
|
|
|||
|
|
@ -31,41 +31,44 @@ class ValidateLookNoDefaultShaders(pyblish.api.InstancePlugin):
|
|||
@classmethod
|
||||
def get_invalid(cls, instance):
|
||||
|
||||
invalid = []
|
||||
disallowed = ["lambert1",
|
||||
"initialShadingGroup",
|
||||
"initialParticleSE",
|
||||
"particleCloud1"]
|
||||
disallowed = set(["lambert1",
|
||||
"initialShadingGroup",
|
||||
"initialParticleSE",
|
||||
"particleCloud1"])
|
||||
|
||||
members = cmds.listRelatives(instance,
|
||||
allDescendents=True,
|
||||
shapes=True,
|
||||
noIntermediate=True) or []
|
||||
for member in members:
|
||||
invalid = set()
|
||||
for node in instance:
|
||||
|
||||
# get connection
|
||||
# listConnections returns a list or None
|
||||
shading_engine = cmds.listConnections(member, type="objectSet")
|
||||
if not shading_engine:
|
||||
cls.log.error("Detected shape without shading engine : "
|
||||
"'{}'".format(member))
|
||||
invalid.append(member)
|
||||
continue
|
||||
object_sets = cmds.listConnections(node, type="objectSet") or []
|
||||
|
||||
# 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))
|
||||
invalid.append(member)
|
||||
else:
|
||||
continue
|
||||
# Ensure the shape in the instances have at least a single shader
|
||||
# connected if it *can* have a shader, like a `surfaceShape` in
|
||||
# Maya.
|
||||
if (cmds.objectType(node, isAType="surfaceShape") and
|
||||
not cmds.ls(object_sets, type="shadingEngine")):
|
||||
cls.log.error("Detected shape without shading engine: "
|
||||
"'{}'".format(node))
|
||||
invalid.add(node)
|
||||
|
||||
return invalid
|
||||
# Check for any disallowed connections
|
||||
if any(s in disallowed for s in object_sets):
|
||||
|
||||
# Explicitly log each individual "wrong" connection.
|
||||
for s in object_sets:
|
||||
if s in disallowed:
|
||||
cls.log.error("Node has unallowed connection to "
|
||||
"'{}': {}".format(s, node))
|
||||
|
||||
invalid.add(node)
|
||||
|
||||
return list(invalid)
|
||||
|
||||
def process(self, instance):
|
||||
"""Process all the nodes in the instance"""
|
||||
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
raise RuntimeError("Invalid shaders found: {0}".format(invalid))
|
||||
raise RuntimeError("Invalid node relationships found: "
|
||||
"{0}".format(invalid))
|
||||
|
|
|
|||
73
colorbleed/plugins/maya/publish/validate_look_sets.py
Normal file
73
colorbleed/plugins/maya/publish/validate_look_sets.py
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
from colorbleed.maya import lib
|
||||
|
||||
import pyblish.api
|
||||
import colorbleed.api
|
||||
|
||||
|
||||
class ValidateLookSets(pyblish.api.InstancePlugin):
|
||||
"""Validate if any sets are missing from the instance and look data
|
||||
|
||||
"""
|
||||
|
||||
order = colorbleed.api.ValidateContentsOrder
|
||||
families = ['colorbleed.lookdev']
|
||||
hosts = ['maya']
|
||||
label = 'Look Sets'
|
||||
actions = [colorbleed.api.SelectInvalidAction]
|
||||
|
||||
def process(self, instance):
|
||||
"""Process all the nodes in the instance"""
|
||||
|
||||
if not instance[:]:
|
||||
raise RuntimeError("Instance is empty")
|
||||
|
||||
self.log.info("Validation '{}'".format(instance.name))
|
||||
invalid = self.get_invalid(instance)
|
||||
if invalid:
|
||||
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))
|
||||
|
||||
lookdata = instance.data["lookData"]
|
||||
relationships = lookdata["relationships"]
|
||||
|
||||
invalid = []
|
||||
for node in instance:
|
||||
sets = lib.get_related_sets(node)
|
||||
if not sets:
|
||||
continue
|
||||
|
||||
missing_sets = [s for s in sets if s not in relationships]
|
||||
if missing_sets:
|
||||
# A set of this node is not coming along, this is wrong!
|
||||
cls.log.error("Missing sets '{}' for node "
|
||||
"'{}'".format(missing_sets, node))
|
||||
invalid.append(node)
|
||||
continue
|
||||
|
||||
# Ensure the node is in the sets that are collected
|
||||
for shaderset, data in relationships.items():
|
||||
if shaderset not in sets:
|
||||
# no need to check for a set if the node
|
||||
# isn't in it anyway
|
||||
continue
|
||||
|
||||
member_nodes = [member['name'] for member in data['members']]
|
||||
if node not in member_nodes:
|
||||
# The node is not found in the collected set
|
||||
# relationships
|
||||
cls.log.error("Missing '{}' in collected set node "
|
||||
"'{}'".format(node, shaderset))
|
||||
invalid.append(node)
|
||||
|
||||
continue
|
||||
|
||||
return invalid
|
||||
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue