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 all 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: 26 additions & 24 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,8 +107,8 @@ 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()
cmds.setAttr(standin_shape + ".abcFPS", fps)
fps = version["data"].get("fps") or get_current_session_fps()
cmds.setAttr(standin_shape + ".abcFPS", float(fps))

nodes = [root, standin, standin_shape]
if operator is not None:
Expand Down Expand Up @@ -132,6 +140,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 +174,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 +208,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