Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #3190 from pypeclub/enhancement/OP-3256_support-fo…
Browse files Browse the repository at this point in the history
…r-pxrtexture

Looks: add basic support for Renderman
  • Loading branch information
antirotor authored May 25, 2022
2 parents 5534c44 + 93c4e34 commit 76e1bc7
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 58 deletions.
165 changes: 109 additions & 56 deletions openpype/hosts/maya/plugins/publish/collect_look.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,46 @@
# redshift
"RedshiftMeshParameters"
]

SHAPE_ATTRS = set(SHAPE_ATTRS)


def get_pxr_multitexture_file_attrs(node):
attrs = []
for i in range(9):
if cmds.attributeQuery("filename{}".format(i), node):
file = cmds.getAttr("{}.filename{}".format(node, i))
if file:
attrs.append("filename{}".format(i))
return attrs


FILE_NODES = {
"file": "fileTextureName",

"aiImage": "filename",

"RedshiftNormalMap": "text0",

"PxrBump": "filename",
"PxrNormalMap": "filename",
"PxrMultiTexture": get_pxr_multitexture_file_attrs,
"PxrPtexture": "filename",
"PxrTexture": "filename"
}


def get_attributes(dictionary, attr):
# type: (dict, str) -> list
if callable(dictionary[attr]):
val = dictionary[attr]()
else:
val = dictionary.get(attr, [])

if not isinstance(val, list):
return [val]
return val


def get_look_attrs(node):
"""Returns attributes of a node that are important for the look.
Expand All @@ -51,15 +87,14 @@ def get_look_attrs(node):
if cmds.objectType(node, isAType="shape"):
attrs = cmds.listAttr(node, changedSinceFileOpen=True) or []
for attr in attrs:
if attr in SHAPE_ATTRS:
if attr in SHAPE_ATTRS or \
attr not in SHAPE_ATTRS and attr.startswith('ai'):
result.append(attr)
elif attr.startswith('ai'):
result.append(attr)

return result


def node_uses_image_sequence(node):
def node_uses_image_sequence(node, node_path):
# type: (str) -> bool
"""Return whether file node uses an image sequence or single image.
Determine if a node uses an image sequence or just a single image,
Expand All @@ -74,12 +109,15 @@ def node_uses_image_sequence(node):
"""

# useFrameExtension indicates an explicit image sequence
node_path = get_file_node_path(node).lower()

# The following tokens imply a sequence
patterns = ["<udim>", "<tile>", "<uvtile>", "u<u>_v<v>", "<frame0"]

return (cmds.getAttr('%s.useFrameExtension' % node) or
patterns = ["<udim>", "<tile>", "<uvtile>",
"u<u>_v<v>", "<frame0", "<f4>"]
try:
use_frame_extension = cmds.getAttr('%s.useFrameExtension' % node)
except ValueError:
use_frame_extension = False

return (use_frame_extension or
any(pattern in node_path for pattern in patterns))


Expand Down Expand Up @@ -137,14 +175,15 @@ def seq_to_glob(path):
return path


def get_file_node_path(node):
def get_file_node_paths(node):
# type: (str) -> list
"""Get the file path used by a Maya file node.
Args:
node (str): Name of the Maya file node
Returns:
str: the file path in use
list: the file paths in use
"""
# if the path appears to be sequence, use computedFileTextureNamePattern,
Expand All @@ -163,15 +202,19 @@ def get_file_node_path(node):
"<uvtile>"]
lower = texture_pattern.lower()
if any(pattern in lower for pattern in patterns):
return texture_pattern
return [texture_pattern]

try:
file_attributes = get_attributes(FILE_NODES, cmds.nodeType(node))
except AttributeError:
file_attributes = "fileTextureName"

if cmds.nodeType(node) == 'aiImage':
return cmds.getAttr('{0}.filename'.format(node))
if cmds.nodeType(node) == 'RedshiftNormalMap':
return cmds.getAttr('{}.tex0'.format(node))
files = []
for file_attr in file_attributes:
if cmds.attributeQuery(file_attr, node=node, exists=True):
files.append(cmds.getAttr("{}.{}".format(node, file_attr)))

# otherwise use fileTextureName
return cmds.getAttr('{0}.fileTextureName'.format(node))
return files


def get_file_node_files(node):
Expand All @@ -185,16 +228,21 @@ def get_file_node_files(node):
list: List of full file paths.
"""
paths = get_file_node_paths(node)
sequences = []
replaces = []
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)

path = get_file_node_path(node)
path = cmds.workspace(expandName=path)
if node_uses_image_sequence(node):
glob_pattern = seq_to_glob(path)
return glob.glob(glob_pattern)
elif os.path.exists(path):
return [path]
else:
return []
for index in replaces:
paths.pop(index)

paths.extend(sequences)

return [p for p in paths if os.path.exists(p)]


class CollectLook(pyblish.api.InstancePlugin):
Expand Down Expand Up @@ -238,13 +286,13 @@ def collect(self, instance):
"for %s" % instance.data['name'])

# Discover related object sets
self.log.info("Gathering sets..")
self.log.info("Gathering sets ...")
sets = self.collect_sets(instance)

# Lookup set (optimization)
instance_lookup = set(cmds.ls(instance, long=True))

self.log.info("Gathering set relations..")
self.log.info("Gathering set relations ...")
# Ensure iteration happen in a list so we can remove keys from the
# dict within the loop

Expand Down Expand Up @@ -326,7 +374,10 @@ def collect(self, instance):
"volumeShader",
"displacementShader",
"aiSurfaceShader",
"aiVolumeShader"]
"aiVolumeShader",
"rman__surface",
"rman__displacement"
]
if look_sets:
materials = []

Expand Down Expand Up @@ -374,9 +425,10 @@ def collect(self, instance):
or []
)

files = cmds.ls(history, type="file", long=True)
files.extend(cmds.ls(history, type="aiImage", long=True))
files.extend(cmds.ls(history, type="RedshiftNormalMap", long=True))
all_supported_nodes = FILE_NODES.keys()
files = []
for node_type in all_supported_nodes:
files.extend(cmds.ls(history, type=node_type, long=True))

self.log.info("Collected file nodes:\n{}".format(files))
# Collect textures if any file nodes are found
Expand Down Expand Up @@ -510,27 +562,24 @@ def collect_resource(self, node):
Returns:
dict
"""

self.log.debug("processing: {}".format(node))
if cmds.nodeType(node) not in ["file", "aiImage", "RedshiftNormalMap"]:
all_supported_nodes = FILE_NODES.keys()
if cmds.nodeType(node) not in all_supported_nodes:
self.log.error(
"Unsupported file node: {}".format(cmds.nodeType(node)))
raise AssertionError("Unsupported file node")

if cmds.nodeType(node) == 'file':
self.log.debug(" - file node")
attribute = "{}.fileTextureName".format(node)
computed_attribute = "{}.computedFileTextureNamePattern".format(node)
elif cmds.nodeType(node) == 'aiImage':
self.log.debug("aiImage node")
attribute = "{}.filename".format(node)
computed_attribute = attribute
elif cmds.nodeType(node) == 'RedshiftNormalMap':
self.log.debug("RedshiftNormalMap node")
attribute = "{}.tex0".format(node)
computed_attribute = attribute

source = cmds.getAttr(attribute)
self.log.debug(" - got {}".format(cmds.nodeType(node)))

attribute = FILE_NODES.get(cmds.nodeType(node))
source = cmds.getAttr("{}.{}".format(
node,
attribute
))
computed_attribute = "{}.{}".format(node, attribute)
if attribute == "fileTextureName":
computed_attribute = node + ".computedFileTextureNamePattern"

self.log.info(" - file source: {}".format(source))
color_space_attr = "{}.colorSpace".format(node)
try:
Expand Down Expand Up @@ -567,11 +616,15 @@ def collect_resource(self, node):
self.log.info(" - color space: {}".format(color_space))

# Define the resource
return {"node": node,
"attribute": attribute,
"source": source, # required for resources
"files": files,
"color_space": color_space} # required for resources
return {
"node": node,
# here we are passing not only attribute, but with node again
# this should be simplified and changed extractor.
"attribute": "{}.{}".format(node, attribute),
"source": source, # required for resources
"files": files,
"color_space": color_space
} # required for resources


class CollectModelRenderSets(CollectLook):
Expand Down
6 changes: 4 additions & 2 deletions openpype/hosts/maya/plugins/publish/extract_look.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,12 @@ def process_resources(self, instance, staging_dir):

if mode == COPY:
transfers.append((source, destination))
self.log.info('copying')
self.log.info('file will be copied {} -> {}'.format(
source, destination))
elif mode == HARDLINK:
hardlinks.append((source, destination))
self.log.info('hardlinking')
self.log.info('file will be hardlinked {} -> {}'.format(
source, destination))

# Store the hashes from hash to destination to include in the
# database
Expand Down

0 comments on commit 76e1bc7

Please sign in to comment.