Cleanup code

- Refactor `get_file_node_files` because popping from `paths` by index should have been done in reversed order anyway. It's now changed to not need popping at all.
- Removed unused `RENDERER_NODE_TYPES` and if-branch which collected `node_attrs` list which was unused + collected members which was also done outside of the if branch and thus generated no extra data.
- Collected all materials from look set attributes at once instead of multiple queries
- Collected all file nodes in history from a single query instead of per type
- Restructured assignment of `instance.data["resources"]` to be more readable
- Cached `PXR_NODES` only ones (Note: plugin load is checked on discovery of the collect look plugin) instead of querying plugin load and its nodes per file node per attribute
- Removed some debug logs or combined some messages
This commit is contained in:
Roy Nieterau 2023-07-06 00:51:48 +02:00
parent 587b98d65e
commit 5c44f12b37

View file

@ -17,11 +17,6 @@ SHAPE_ATTRS = ["castsShadows",
"visibleInRefractions",
"doubleSided",
"opposite"]
RENDERER_NODE_TYPES = [
# redshift
"RedshiftMeshParameters"
]
SHAPE_ATTRS = set(SHAPE_ATTRS)
@ -36,12 +31,13 @@ def get_pxr_multitexture_file_attrs(node):
FILE_NODES = {
# maya
"file": "fileTextureName",
# arnold (mtoa)
"aiImage": "filename",
# redshift
"RedshiftNormalMap": "tex0",
# renderman
"PxrBump": "filename",
"PxrNormalMap": "filename",
"PxrMultiTexture": get_pxr_multitexture_file_attrs,
@ -49,6 +45,15 @@ FILE_NODES = {
"PxrTexture": "filename"
}
# Cache pixar dependency node types so we can perform a type lookup against it
PXR_NODES = set()
if cmds.pluginInfo("RenderMan_for_Maya", query=True, loaded=True):
PXR_NODES = set(
cmds.pluginInfo("RenderMan_for_Maya",
query=True,
dependNode=True)
)
def get_attributes(dictionary, attr, node=None):
# type: (dict, str, str) -> list
@ -232,20 +237,17 @@ def get_file_node_files(node):
"""
paths = get_file_node_paths(node)
sequences = []
replaces = []
# For sequences get all files and filter to only existing files
result = []
for index, path in enumerate(paths):
if node_uses_image_sequence(node, path):
glob_pattern = seq_to_glob(path)
sequences.extend(glob.glob(glob_pattern))
replaces.append(index)
result.extend(glob.glob(glob_pattern))
elif os.path.exists(path):
result.append(path)
for index in replaces:
paths.pop(index)
paths.extend(sequences)
return [p for p in paths if os.path.exists(p)]
return result
class CollectLook(pyblish.api.InstancePlugin):
@ -260,7 +262,7 @@ class CollectLook(pyblish.api.InstancePlugin):
membership relations.
Collects:
lookAttribtutes (list): Nodes in instance with their altered attributes
lookAttributes (list): Nodes in instance with their altered attributes
lookSetRelations (list): Sets and their memberships
lookSets (list): List of set names included in the look
@ -285,76 +287,31 @@ class CollectLook(pyblish.api.InstancePlugin):
instance: Instance to collect.
"""
self.log.info("Looking for look associations "
"for %s" % instance.data['name'])
# Discover related object sets
self.log.info("Gathering sets ...")
sets = self.collect_sets(instance)
self.log.debug("Looking for look associations "
"for %s" % instance.data['name'])
# Lookup set (optimization)
instance_lookup = set(cmds.ls(instance, long=True))
self.log.info("Gathering set relations ...")
# Ensure iteration happen in a list so we can remove keys from the
# Discover related object sets
self.log.debug("Gathering sets ...")
sets = self.collect_sets(instance)
# Ensure iteration happen in a list to allow removing keys from the
# dict within the loop
# skipped types of attribute on render specific nodes
disabled_types = ["message", "TdataCompound"]
self.log.info("Gathering set relations ...")
for obj_set in list(sets):
self.log.debug("From {}".format(obj_set))
# if node is specified as renderer node type, it will be
# serialized with its attributes.
if cmds.nodeType(obj_set) in RENDERER_NODE_TYPES:
self.log.info("- {} is {}".format(
obj_set, cmds.nodeType(obj_set)))
node_attrs = []
# serialize its attributes so they can be recreated on look
# load.
for attr in cmds.listAttr(obj_set):
# skip publishedNodeInfo attributes as they break
# getAttr() and we don't need them anyway
if attr.startswith("publishedNodeInfo"):
continue
# skip attributes types defined in 'disabled_type' list
if cmds.getAttr("{}.{}".format(obj_set, attr), type=True) in disabled_types: # noqa
continue
node_attrs.append((
attr,
cmds.getAttr("{}.{}".format(obj_set, attr)),
cmds.getAttr(
"{}.{}".format(obj_set, attr), type=True)
))
for member in cmds.ls(
cmds.sets(obj_set, query=True), long=True):
member_data = self.collect_member_data(member,
instance_lookup)
if not member_data:
continue
# Add information of the node to the members list
sets[obj_set]["members"].append(member_data)
# Get all nodes of the current objectSet (shadingEngine)
for member in cmds.ls(cmds.sets(obj_set, query=True), long=True):
member_data = self.collect_member_data(member,
instance_lookup)
if not member_data:
continue
# Add information of the node to the members list
sets[obj_set]["members"].append(member_data)
if member_data:
# Add information of the node to the members list
sets[obj_set]["members"].append(member_data)
# Remove sets that didn't have any members assigned in the end
# Thus the data will be limited to only what we need.
self.log.info("obj_set {}".format(sets[obj_set]))
if not sets[obj_set]["members"]:
self.log.info(
"Removing redundant set information: {}".format(obj_set))
@ -382,35 +339,26 @@ class CollectLook(pyblish.api.InstancePlugin):
"rman__displacement"
]
if look_sets:
materials = []
self.log.debug("Found look sets:\n{}".format(look_sets))
# Get all material attrs for all look sets to retrieve their inputs
existing_attrs = []
for look in look_sets:
for at in shader_attrs:
try:
con = cmds.listConnections("{}.{}".format(look, at))
except ValueError:
# skip attributes that are invalid in current
# context. For example in the case where
# Arnold is not enabled.
continue
if con:
materials.extend(con)
for attr in shader_attrs:
if cmds.attributeQuery(attr, node=look_sets, exists=True):
existing_attrs.append("{}.{}".format(look, attr))
materials = cmds.listConnections(existing_attrs,
source=True,
destination=False) or []
self.log.debug("Found materials:\n{}".format(materials))
self.log.info("Found materials:\n{}".format(materials))
self.log.info("Found the following sets:\n{}".format(look_sets))
# Get the entire node chain of the look sets
# history = cmds.listHistory(look_sets)
history = []
for material in materials:
history.extend(cmds.listHistory(material, ac=True))
# handle VrayPluginNodeMtl node - see #1397
vray_plugin_nodes = cmds.ls(
history, type="VRayPluginNodeMtl", long=True)
for vray_node in vray_plugin_nodes:
history.extend(cmds.listHistory(vray_node, ac=True))
# history = cmds.listHistory(look_sets, allConnections=True)
history = cmds.listHistory(materials, allConnections=True)
# Since we retrieved history only of the connected materials
# connected to the look sets above we now add direct history
# for some of the look sets directly
# handling render attribute sets
render_set_types = [
"VRayDisplacement",
@ -428,20 +376,17 @@ class CollectLook(pyblish.api.InstancePlugin):
or []
)
all_supported_nodes = FILE_NODES.keys()
files = []
for node_type in all_supported_nodes:
files.extend(cmds.ls(history, type=node_type, long=True))
files = cmds.ls(history,
type=list(FILE_NODES.keys()),
long=True)
self.log.info("Collected file nodes:\n{}".format(files))
self.log.info("Collected file nodes:{}".format(files))
# Collect textures if any file nodes are found
instance.data["resources"] = []
for n in files:
for res in self.collect_resources(n):
instance.data["resources"].append(res)
self.log.info("Collected resources: {}".format(
instance.data["resources"]))
resources = []
for node in files:
resources.extend(self.collect_resources(node))
instance.data["resources"] = resources
self.log.debug("Collected resources: {}".format(resources))
# Log warning when no relevant sets were retrieved for the look.
if (
@ -456,7 +401,7 @@ class CollectLook(pyblish.api.InstancePlugin):
instance.extend(shader for shader in look_sets if shader
not in instance_lookup)
self.log.info("Collected look for %s" % instance)
self.log.debug("Collected look for %s" % instance)
def collect_sets(self, instance):
"""Collect all objectSets which are of importance for publishing
@ -536,14 +481,14 @@ class CollectLook(pyblish.api.InstancePlugin):
# Collect changes to "custom" attributes
node_attrs = get_look_attrs(node)
self.log.info(
"Node \"{0}\" attributes: {1}".format(node, node_attrs)
)
# Only include if there are any properties we care about
if not node_attrs:
continue
self.log.debug(
"Node \"{0}\" attributes: {1}".format(node, node_attrs)
)
node_attributes = {}
for attr in node_attrs:
if not cmds.attributeQuery(attr, node=node, exists=True):
@ -574,14 +519,12 @@ class CollectLook(pyblish.api.InstancePlugin):
Returns:
dict
"""
self.log.debug("processing: {}".format(node))
all_supported_nodes = FILE_NODES.keys()
if cmds.nodeType(node) not in all_supported_nodes:
if cmds.nodeType(node) not in FILE_NODES:
self.log.error(
"Unsupported file node: {}".format(cmds.nodeType(node)))
raise AssertionError("Unsupported file node")
self.log.debug(" - got {}".format(cmds.nodeType(node)))
self.log.debug("processing: {} ({})".format(node, cmds.nodeType(node)))
attributes = get_attributes(FILE_NODES, cmds.nodeType(node), node)
for attribute in attributes:
@ -613,14 +556,7 @@ class CollectLook(pyblish.api.InstancePlugin):
# renderman allows nodes to have filename attribute empty while
# you can have another incoming connection from different node.
pxr_nodes = set()
if cmds.pluginInfo("RenderMan_for_Maya", query=True, loaded=True):
pxr_nodes = set(
cmds.pluginInfo("RenderMan_for_Maya",
query=True,
dependNode=True)
)
if not source and cmds.nodeType(node) in pxr_nodes:
if not source and cmds.nodeType(node) in PXR_NODES:
self.log.info("Renderman: source is empty, skipping...")
continue
# We replace backslashes with forward slashes because V-Ray