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

Arnold Scene Source Raw - OP-8014 #6182

Merged
merged 9 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion openpype/hosts/maya/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -1331,7 +1331,7 @@ def is_visible(node,
override_enabled = cmds.getAttr('{}.overrideEnabled'.format(node))
override_visibility = cmds.getAttr('{}.overrideVisibility'.format(
node))
if override_enabled and override_visibility:
if override_enabled and not override_visibility:
return False

if parentHidden:
Expand Down
18 changes: 14 additions & 4 deletions openpype/hosts/maya/plugins/create/create_arnold_scene_source.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from maya import cmds

from openpype.hosts.maya.api import (
lib,
plugin
Expand Down Expand Up @@ -87,16 +89,24 @@ def get_instance_attr_defs(self):

return defs

def create(self, subset_name, instance_data, pre_create_data):

from maya import cmds
class CreateArnoldSceneSourceProxy(CreateArnoldSceneSource):
"""Arnold Scene Source Proxy

This product type facilitates working with proxy geometry in the viewport.
"""

identifier = "io.openpype.creators.maya.assproxy"
label = "Arnold Scene Source Proxy"
family = "assProxy"
icon = "cube"

def create(self, subset_name, instance_data, pre_create_data):
instance = super(CreateArnoldSceneSource, self).create(
subset_name, instance_data, pre_create_data
)

instance_node = instance.get("instance_node")

content = cmds.sets(name=instance_node + "_content_SET", empty=True)
proxy = cmds.sets(name=instance_node + "_proxy_SET", empty=True)
cmds.sets([content, proxy], forceElement=instance_node)
cmds.sets([proxy], forceElement=instance_node)
50 changes: 27 additions & 23 deletions openpype/hosts/maya/plugins/load/load_arnold_standin.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ def get_current_session_fps():
class ArnoldStandinLoader(load.LoaderPlugin):
"""Load as Arnold standin"""

families = ["ass", "animation", "model", "proxyAbc", "pointcache", "usd"]
families = [
"ass",
"assProxy",
"animation",
"model",
"proxyAbc",
"pointcache",
"usd"
]
representations = ["ass", "abc", "usda", "usdc", "usd"]

label = "Load as Arnold standin"
Expand Down Expand Up @@ -99,7 +107,9 @@ def load(self, context, name, namespace, options):
sequence = is_sequence(os.listdir(os.path.dirname(repre_path)))
cmds.setAttr(standin_shape + ".useFrameExtension", sequence)

fps = float(version["data"].get("fps"))or get_current_session_fps()
fps = (
float(version["data"].get("fps")) or get_current_session_fps()
)
tokejepsen marked this conversation as resolved.
Show resolved Hide resolved
cmds.setAttr(standin_shape + ".abcFPS", fps)

nodes = [root, standin, standin_shape]
Expand Down Expand Up @@ -132,6 +142,18 @@ def _get_proxy_path(self, path):
proxy_path = "/".join([os.path.dirname(path), proxy_basename])
return proxy_basename, proxy_path

def _update_operators(self, string_replace_operator, proxy_basename, path):
cmds.setAttr(
string_replace_operator + ".match",
proxy_basename.split(".")[0],
type="string"
)
cmds.setAttr(
string_replace_operator + ".replace",
os.path.basename(path).split(".")[0],
type="string"
)

def _setup_proxy(self, shape, path, namespace):
proxy_basename, proxy_path = self._get_proxy_path(path)

Expand All @@ -154,16 +176,7 @@ def _setup_proxy(self, shape, path, namespace):
"*.(@node=='{}')".format(node_type),
type="string"
)
cmds.setAttr(
string_replace_operator + ".match",
proxy_basename,
type="string"
)
cmds.setAttr(
string_replace_operator + ".replace",
os.path.basename(path),
type="string"
)
self._update_operators(string_replace_operator, proxy_basename, path)

cmds.connectAttr(
string_replace_operator + ".out",
Expand Down Expand Up @@ -197,18 +210,9 @@ def update(self, container, representation):
path = get_representation_path(representation)
proxy_basename, proxy_path = self._get_proxy_path(path)

# Whether there is proxy or so, we still update the string operator.
# Whether there is proxy or not, we still update the string operator.
# If no proxy exists, the string operator won't replace anything.
cmds.setAttr(
string_replace_operator + ".match",
proxy_basename,
type="string"
)
cmds.setAttr(
string_replace_operator + ".replace",
os.path.basename(path),
type="string"
)
self._update_operators(string_replace_operator, proxy_basename, path)

dso_path = path
if os.path.exists(proxy_path):
Expand Down
22 changes: 12 additions & 10 deletions openpype/hosts/maya/plugins/publish/collect_arnold_scene_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ class CollectArnoldSceneSource(pyblish.api.InstancePlugin):
# Offset to be after renderable camera collection.
order = pyblish.api.CollectorOrder + 0.2
label = "Collect Arnold Scene Source"
families = ["ass"]
families = ["ass", "assProxy"]

def process(self, instance):
objsets = instance.data["setMembers"]
instance.data["members"] = []
tokejepsen marked this conversation as resolved.
Show resolved Hide resolved
for set_member in instance.data["setMembers"]:
if cmds.nodeType(set_member) != "objectSet":
instance.data["members"].extend(self.get_hierarchy(set_member))
continue

for objset in objsets:
objset = str(objset)
members = cmds.sets(objset, query=True)
members = cmds.sets(set_member, query=True)
members = cmds.ls(members, long=True)
if members is None:
self.log.warning("Skipped empty instance: \"%s\" " % objset)
self.log.warning(
"Skipped empty instance: \"%s\" " % set_member
)
continue
if objset.endswith("content_SET"):
instance.data["contentMembers"] = self.get_hierarchy(members)
if objset.endswith("proxy_SET"):
if set_member.endswith("proxy_SET"):
instance.data["proxy"] = self.get_hierarchy(members)

# Use camera in object set if present else default to render globals
Expand All @@ -33,7 +35,7 @@ def process(self, instance):
renderable = [c for c in cameras if cmds.getAttr("%s.renderable" % c)]
if renderable:
camera = renderable[0]
for node in instance.data["contentMembers"]:
for node in instance.data["members"]:
camera_shapes = cmds.listRelatives(
node, shapes=True, type="camera"
)
Expand Down
128 changes: 88 additions & 40 deletions openpype/hosts/maya/plugins/publish/extract_arnold_scene_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ class ExtractArnoldSceneSource(publish.Extractor):
label = "Extract Arnold Scene Source"
hosts = ["maya"]
families = ["ass"]
asciiAss = False
asciiAss = True

def process(self, instance):
staging_dir = self.staging_dir(instance)
def _pre_process(self, instance, staging_dir):
file_path = os.path.join(staging_dir, "{}.ass".format(instance.name))

# Mask
Expand Down Expand Up @@ -70,24 +69,38 @@ def process(self, instance):
"mask": mask
}

filenames, nodes_by_id = self._extract(
instance.data["contentMembers"], attribute_data, kwargs
)

if "representations" not in instance.data:
instance.data["representations"] = []

return attribute_data, kwargs

def process(self, instance):
staging_dir = self.staging_dir(instance)
attribute_data, kwargs = self._pre_process(instance, staging_dir)

filenames = self._extract(
instance.data["members"], attribute_data, kwargs
)

self._post_process(
instance, filenames, staging_dir, kwargs["startFrame"]
)

def _post_process(self, instance, filenames, staging_dir, frame_start):
nodes_by_id = self._nodes_by_id(instance[:])
representation = {
"name": "ass",
"ext": "ass",
"files": filenames if len(filenames) > 1 else filenames[0],
"stagingDir": staging_dir,
"frameStart": kwargs["startFrame"]
"frameStart": frame_start
}

instance.data["representations"].append(representation)

json_path = os.path.join(staging_dir, "{}.json".format(instance.name))
json_path = os.path.join(
staging_dir, "{}.json".format(instance.name)
)
with open(json_path, "w") as f:
json.dump(nodes_by_id, f)

Expand All @@ -104,13 +117,68 @@ def process(self, instance):
"Extracted instance {} to: {}".format(instance.name, staging_dir)
)

# Extract proxy.
if not instance.data.get("proxy", []):
return
def _nodes_by_id(self, nodes):
nodes_by_id = defaultdict(list)

for node in nodes:
id = lib.get_id(node)

if id is None:
continue

# Converting Maya hierarchy separator "|" to Arnold separator "/".
nodes_by_id[id].append(node.replace("|", "/"))

return nodes_by_id

def _extract(self, nodes, attribute_data, kwargs):
filenames = []
with lib.attribute_values(attribute_data):
with lib.maintained_selection():
self.log.debug(
"Writing: {}".format(nodes)
)
cmds.select(nodes, noExpand=True)

self.log.debug(
"Extracting ass sequence with: {}".format(kwargs)
)

exported_files = cmds.arnoldExportAss(**kwargs)

for file in exported_files:
filenames.append(os.path.split(file)[1])

self.log.debug("Exported: {}".format(filenames))

return filenames


class ExtractArnoldSceneSourceProxy(ExtractArnoldSceneSource):
"""Extract the content of the instance to an Arnold Scene Source file."""

label = "Extract Arnold Scene Source Proxy"
hosts = ["maya"]
families = ["assProxy"]
asciiAss = True

def process(self, instance):
staging_dir = self.staging_dir(instance)
attribute_data, kwargs = self._pre_process(instance, staging_dir)

filenames, _ = self._duplicate_extract(
instance.data["members"], attribute_data, kwargs
)

self._post_process(
instance, filenames, staging_dir, kwargs["startFrame"]
)

kwargs["filename"] = file_path.replace(".ass", "_proxy.ass")
kwargs["filename"] = os.path.join(
staging_dir, "{}_proxy.ass".format(instance.name)
)

filenames, _ = self._extract(
filenames, _ = self._duplicate_extract(
instance.data["proxy"], attribute_data, kwargs
)

Expand All @@ -125,12 +193,11 @@ def process(self, instance):

instance.data["representations"].append(representation)

def _extract(self, nodes, attribute_data, kwargs):
def _duplicate_extract(self, nodes, attribute_data, kwargs):
self.log.debug(
"Writing {} with:\n{}".format(kwargs["filename"], kwargs)
)
filenames = []
nodes_by_id = defaultdict(list)
# Duplicating nodes so they are direct children of the world. This
# makes the hierarchy of any exported ass file the same.
with lib.delete_after() as delete_bin:
Expand All @@ -147,7 +214,9 @@ def _extract(self, nodes, attribute_data, kwargs):
if not shapes:
continue

duplicate_transform = cmds.duplicate(node)[0]
basename = cmds.duplicate(node)[0]
parents = cmds.ls(node, long=True)[0].split("|")[:-1]
duplicate_transform = "|".join(parents + [basename])

if cmds.listRelatives(duplicate_transform, parent=True):
duplicate_transform = cmds.parent(
Expand All @@ -172,28 +241,7 @@ def _extract(self, nodes, attribute_data, kwargs):
duplicate_nodes.extend(shapes)
delete_bin.append(duplicate_transform)

# Copy cbId to mtoa_constant.
for node in duplicate_nodes:
# Converting Maya hierarchy separator "|" to Arnold
# separator "/".
nodes_by_id[lib.get_id(node)].append(node.replace("|", "/"))

with lib.attribute_values(attribute_data):
with lib.maintained_selection():
self.log.debug(
"Writing: {}".format(duplicate_nodes)
)
cmds.select(duplicate_nodes, noExpand=True)

self.log.debug(
"Extracting ass sequence with: {}".format(kwargs)
)

exported_files = cmds.arnoldExportAss(**kwargs)

for file in exported_files:
filenames.append(os.path.split(file)[1])

self.log.debug("Exported: {}".format(filenames))
nodes_by_id = self._nodes_by_id(duplicate_nodes)
filenames = self._extract(duplicate_nodes, attribute_data, kwargs)

return filenames, nodes_by_id
Loading
Loading