mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-26 05:42:15 +01:00
Merge pull request #1358 from pypeclub/feature/redshift-proxy-support
Maya: Support for Redshift proxies
This commit is contained in:
commit
15e3663a56
7 changed files with 276 additions and 2 deletions
23
openpype/hosts/maya/plugins/create/create_redshift_proxy.py
Normal file
23
openpype/hosts/maya/plugins/create/create_redshift_proxy.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Creator of Redshift proxy subset types."""
|
||||
|
||||
from openpype.hosts.maya.api import plugin, lib
|
||||
|
||||
|
||||
class CreateRedshiftProxy(plugin.Creator):
|
||||
"""Create instance of Redshift Proxy subset."""
|
||||
|
||||
name = "redshiftproxy"
|
||||
label = "Redshift Proxy"
|
||||
family = "redshiftproxy"
|
||||
icon = "gears"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(CreateRedshiftProxy, self).__init__(*args, **kwargs)
|
||||
|
||||
animation_data = lib.collect_animation_data()
|
||||
|
||||
self.data["animation"] = False
|
||||
self.data["proxyFrameStart"] = animation_data["frameStart"]
|
||||
self.data["proxyFrameEnd"] = animation_data["frameEnd"]
|
||||
self.data["proxyFrameStep"] = animation_data["step"]
|
||||
146
openpype/hosts/maya/plugins/load/load_redshift_proxy.py
Normal file
146
openpype/hosts/maya/plugins/load/load_redshift_proxy.py
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Loader for Redshift proxy."""
|
||||
from avalon.maya import lib
|
||||
from avalon import api
|
||||
from openpype.api import get_project_settings
|
||||
import os
|
||||
import maya.cmds as cmds
|
||||
import clique
|
||||
|
||||
|
||||
class RedshiftProxyLoader(api.Loader):
|
||||
"""Load Redshift proxy"""
|
||||
|
||||
families = ["redshiftproxy"]
|
||||
representations = ["rs"]
|
||||
|
||||
label = "Import Redshift Proxy"
|
||||
order = -10
|
||||
icon = "code-fork"
|
||||
color = "orange"
|
||||
|
||||
def load(self, context, name=None, namespace=None, options=None):
|
||||
"""Plugin entry point."""
|
||||
|
||||
from avalon.maya.pipeline import containerise
|
||||
from openpype.hosts.maya.api.lib import namespaced
|
||||
|
||||
try:
|
||||
family = context["representation"]["context"]["family"]
|
||||
except ValueError:
|
||||
family = "redshiftproxy"
|
||||
|
||||
asset_name = context['asset']["name"]
|
||||
namespace = namespace or lib.unique_namespace(
|
||||
asset_name + "_",
|
||||
prefix="_" if asset_name[0].isdigit() else "",
|
||||
suffix="_",
|
||||
)
|
||||
|
||||
# Ensure Redshift for Maya is loaded.
|
||||
cmds.loadPlugin("redshift4maya", quiet=True)
|
||||
|
||||
with lib.maintained_selection():
|
||||
cmds.namespace(addNamespace=namespace)
|
||||
with namespaced(namespace, new=False):
|
||||
nodes, group_node = self.create_rs_proxy(
|
||||
name, self.fname)
|
||||
|
||||
self[:] = nodes
|
||||
if not nodes:
|
||||
return
|
||||
|
||||
# colour the group node
|
||||
settings = get_project_settings(os.environ['AVALON_PROJECT'])
|
||||
colors = settings['maya']['load']['colors']
|
||||
c = colors.get(family)
|
||||
if c is not None:
|
||||
cmds.setAttr("{0}.useOutlinerColor".format(group_node), 1)
|
||||
cmds.setAttr("{0}.outlinerColor".format(group_node),
|
||||
c[0], c[1], c[2])
|
||||
|
||||
return containerise(
|
||||
name=name,
|
||||
namespace=namespace,
|
||||
nodes=nodes,
|
||||
context=context,
|
||||
loader=self.__class__.__name__)
|
||||
|
||||
def update(self, container, representation):
|
||||
|
||||
node = container['objectName']
|
||||
assert cmds.objExists(node), "Missing container"
|
||||
|
||||
members = cmds.sets(node, query=True) or []
|
||||
rs_meshes = cmds.ls(members, type="RedshiftProxyMesh")
|
||||
assert rs_meshes, "Cannot find RedshiftProxyMesh in container"
|
||||
|
||||
filename = api.get_representation_path(representation)
|
||||
|
||||
for rs_mesh in rs_meshes:
|
||||
cmds.setAttr("{}.fileName".format(rs_mesh),
|
||||
filename,
|
||||
type="string")
|
||||
|
||||
# Update metadata
|
||||
cmds.setAttr("{}.representation".format(node),
|
||||
str(representation["_id"]),
|
||||
type="string")
|
||||
|
||||
def remove(self, container):
|
||||
|
||||
# Delete container and its contents
|
||||
if cmds.objExists(container['objectName']):
|
||||
members = cmds.sets(container['objectName'], query=True) or []
|
||||
cmds.delete([container['objectName']] + members)
|
||||
|
||||
# Remove the namespace, if empty
|
||||
namespace = container['namespace']
|
||||
if cmds.namespace(exists=namespace):
|
||||
members = cmds.namespaceInfo(namespace, listNamespace=True)
|
||||
if not members:
|
||||
cmds.namespace(removeNamespace=namespace)
|
||||
else:
|
||||
self.log.warning("Namespace not deleted because it "
|
||||
"still has members: %s", namespace)
|
||||
|
||||
def switch(self, container, representation):
|
||||
self.update(container, representation)
|
||||
|
||||
def create_rs_proxy(self, name, path):
|
||||
"""Creates Redshift Proxies showing a proxy object.
|
||||
|
||||
Args:
|
||||
name (str): Proxy name.
|
||||
path (str): Path to proxy file.
|
||||
|
||||
Returns:
|
||||
(str, str): Name of mesh with Redshift proxy and its parent
|
||||
transform.
|
||||
|
||||
"""
|
||||
rs_mesh = cmds.createNode(
|
||||
'RedshiftProxyMesh', name="{}_RS".format(name))
|
||||
mesh_shape = cmds.createNode("mesh", name="{}_GEOShape".format(name))
|
||||
|
||||
cmds.setAttr("{}.fileName".format(rs_mesh),
|
||||
path,
|
||||
type="string")
|
||||
|
||||
cmds.connectAttr("{}.outMesh".format(rs_mesh),
|
||||
"{}.inMesh".format(mesh_shape))
|
||||
|
||||
group_node = cmds.group(empty=True, name="{}_GRP".format(name))
|
||||
mesh_transform = cmds.listRelatives(mesh_shape,
|
||||
parent=True, fullPath=True)
|
||||
cmds.parent(mesh_transform, group_node)
|
||||
nodes = [rs_mesh, mesh_shape, group_node]
|
||||
|
||||
# determine if we need to enable animation support
|
||||
files_in_folder = os.listdir(os.path.dirname(path))
|
||||
collections, remainder = clique.assemble(files_in_folder)
|
||||
|
||||
if collections:
|
||||
cmds.setAttr("{}.useFrameExtension".format(rs_mesh), 1)
|
||||
|
||||
return nodes, group_node
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Redshift Proxy extractor."""
|
||||
import os
|
||||
|
||||
import avalon.maya
|
||||
import openpype.api
|
||||
|
||||
from maya import cmds
|
||||
|
||||
|
||||
class ExtractRedshiftProxy(openpype.api.Extractor):
|
||||
"""Extract the content of the instance to a redshift proxy file."""
|
||||
|
||||
label = "Redshift Proxy (.rs)"
|
||||
hosts = ["maya"]
|
||||
families = ["redshiftproxy"]
|
||||
|
||||
def process(self, instance):
|
||||
"""Extractor entry point."""
|
||||
|
||||
staging_dir = self.staging_dir(instance)
|
||||
file_name = "{}.rs".format(instance.name)
|
||||
file_path = os.path.join(staging_dir, file_name)
|
||||
|
||||
anim_on = instance.data["animation"]
|
||||
rs_options = "exportConnectivity=0;enableCompression=1;keepUnused=0;"
|
||||
repr_files = file_name
|
||||
|
||||
if not anim_on:
|
||||
# Remove animation information because it is not required for
|
||||
# non-animated subsets
|
||||
instance.data.pop("proxyFrameStart", None)
|
||||
instance.data.pop("proxyFrameEnd", None)
|
||||
|
||||
else:
|
||||
start_frame = instance.data["proxyFrameStart"]
|
||||
end_frame = instance.data["proxyFrameEnd"]
|
||||
rs_options = "{}startFrame={};endFrame={};frameStep={};".format(
|
||||
rs_options, start_frame,
|
||||
end_frame, instance.data["proxyFrameStep"]
|
||||
)
|
||||
|
||||
root, ext = os.path.splitext(file_path)
|
||||
# Padding is taken from number of digits of the end_frame.
|
||||
# Not sure where Redshift is taking it.
|
||||
repr_files = [
|
||||
"{}.{}{}".format(root, str(frame).rjust(4, "0"), ext) # noqa: E501
|
||||
for frame in range(
|
||||
int(start_frame),
|
||||
int(end_frame) + 1,
|
||||
int(instance.data["proxyFrameStep"]),
|
||||
)]
|
||||
# vertex_colors = instance.data.get("vertexColors", False)
|
||||
|
||||
# Write out rs file
|
||||
self.log.info("Writing: '%s'" % file_path)
|
||||
with avalon.maya.maintained_selection():
|
||||
cmds.select(instance.data["setMembers"], noExpand=True)
|
||||
cmds.file(file_path,
|
||||
pr=False,
|
||||
force=True,
|
||||
type="Redshift Proxy",
|
||||
exportSelected=True,
|
||||
options=rs_options)
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
self.log.debug("Files: {}".format(repr_files))
|
||||
|
||||
representation = {
|
||||
'name': 'rs',
|
||||
'ext': 'rs',
|
||||
'files': repr_files,
|
||||
"stagingDir": staging_dir,
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
|
||||
self.log.info("Extracted instance '%s' to: %s"
|
||||
% (instance.name, staging_dir))
|
||||
|
|
@ -93,7 +93,8 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
|
|||
"harmony.palette",
|
||||
"editorial",
|
||||
"background",
|
||||
"camerarig"
|
||||
"camerarig",
|
||||
"redshiftproxy"
|
||||
]
|
||||
exclude_families = ["clip"]
|
||||
db_representation_context_keys = [
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 911bd8999ab0030d0f7412dde6fd545c1a73b62d
|
||||
Subproject commit 807e8577a0268580a2934ba38889911adad26eb1
|
||||
|
|
@ -691,3 +691,27 @@ under selected hierarchies and match them with shapes loaded with rig (published
|
|||
under `input_SET`). This mechanism uses *cbId* attribute on those shapes.
|
||||
If match is found shapes are connected using their `outMesh` and `outMesh`. Thus you can easily connect existing animation to loaded rig.
|
||||
:::
|
||||
|
||||
## Using Redshift Proxies
|
||||
|
||||
OpenPype supports working with Redshift Proxy files. You can create Redshift Proxy from almost
|
||||
any hierarchy in Maya and it will be included there. Redshift can export animation
|
||||
proxy file per frame.
|
||||
|
||||
### Creating Redshift Proxy
|
||||
|
||||
To mark data to publish as Redshift Proxy, select them in Maya and - **OpenPype → Create ...** and
|
||||
then select **Redshift Proxy**. You can name your subset and hit **Create** button.
|
||||
|
||||
You can enable animation in Attribute Editor:
|
||||
|
||||

|
||||
|
||||
### Publishing Redshift Proxies
|
||||
|
||||
Once data are marked as Redshift Proxy instance, they can be published - **OpenPype → Publish ...**
|
||||
|
||||
### Using Redshift Proxies
|
||||
|
||||
Published proxy files can be loaded with OpenPype Loader. It will create mesh and attach Redshift Proxy
|
||||
parameters to it - Redshift will then represent proxy with bounding box.
|
||||
|
|
|
|||
BIN
website/docs/assets/maya-create_rs_proxy.jpg
Normal file
BIN
website/docs/assets/maya-create_rs_proxy.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Loading…
Add table
Add a link
Reference in a new issue