mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge pull request #407 from pypeclub/feature/determine-maya-scene-type-by-preset
Maya: make choice about ma/mb configurable per family type
This commit is contained in:
commit
fab38ca8e6
5 changed files with 130 additions and 99 deletions
|
|
@ -1,5 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Extract camera to Maya file."""
|
||||
"""Extract camera as Maya Scene."""
|
||||
import os
|
||||
|
||||
from maya import cmds
|
||||
|
|
@ -67,47 +67,8 @@ def unlock(plug):
|
|||
cmds.disconnectAttr(source, destination)
|
||||
|
||||
|
||||
def bake_attribute(camera,
|
||||
attributes,
|
||||
step=1.0, simulation=True, frame_range=None):
|
||||
"""Bake specified attributes on camera.
|
||||
|
||||
Args:
|
||||
camera (str): Camera name.
|
||||
attributes (list): List of attributes to bake.
|
||||
step (float): Animation step used for baking.
|
||||
simulation (bool): Perform simulation instead of just evaluating
|
||||
each attribute separately over the range of time.
|
||||
frame_rage (list, tuple): start and end frame to define range.
|
||||
|
||||
.. See also:
|
||||
http://download.autodesk.com/us/maya/2011help/Commandspython/bakeResults.html
|
||||
|
||||
"""
|
||||
|
||||
if frame_range is None:
|
||||
frame_range = [cmds.playbackOptions(query=True, minTime=True),
|
||||
cmds.playbackOptions(query=True, maxTime=True)]
|
||||
|
||||
# If frame range is single frame bake one frame more,
|
||||
# otherwise maya.cmds.bakeResults gets confused
|
||||
if frame_range[1] == frame_range[0]:
|
||||
frame_range[1] += 1
|
||||
|
||||
assert isinstance(attributes, (list, tuple)), (
|
||||
"Attributes to bake must be specified as a list"
|
||||
)
|
||||
|
||||
with lib.keytangent_default(in_tangent_type='auto',
|
||||
out_tangent_type='auto'):
|
||||
cmds.bakeResults(camera, attribute=attributes,
|
||||
simulation=simulation,
|
||||
time=(frame_range[0], frame_range[1]),
|
||||
sampleBy=step)
|
||||
|
||||
|
||||
class ExtractCameraMayaAscii(pype.api.Extractor):
|
||||
"""Extract a Camera as Maya Ascii.
|
||||
class ExtractCameraMayaScene(pype.api.Extractor):
|
||||
"""Extract a Camera as Maya Scene.
|
||||
|
||||
This will create a duplicate of the camera that will be baked *with*
|
||||
substeps and handles for the required frames. This temporary duplicate
|
||||
|
|
@ -122,14 +83,28 @@ class ExtractCameraMayaAscii(pype.api.Extractor):
|
|||
|
||||
"""
|
||||
|
||||
label = "Camera (Maya Ascii)"
|
||||
label = "Camera (Maya Scene)"
|
||||
hosts = ["maya"]
|
||||
families = ["camera"]
|
||||
bake_attributes = []
|
||||
scene_type = "ma"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
"""Plugin entry point."""
|
||||
# get settings
|
||||
ext_mapping = instance.context.data["presets"]["maya"].get("ext_mapping") # noqa: E501
|
||||
if ext_mapping:
|
||||
self.log.info("Looking in presets for scene type ...")
|
||||
# use extension mapping for first family found
|
||||
for family in self.families:
|
||||
try:
|
||||
self.scene_type = ext_mapping[family]
|
||||
self.log.info(
|
||||
"Using {} as scene type".format(self.scene_type))
|
||||
break
|
||||
except AttributeError:
|
||||
# no preset found
|
||||
pass
|
||||
|
||||
framerange = [instance.data.get("frameStart", 1),
|
||||
instance.data.get("frameEnd", 1)]
|
||||
handles = instance.data.get("handles", 0)
|
||||
|
|
@ -137,7 +112,7 @@ class ExtractCameraMayaAscii(pype.api.Extractor):
|
|||
bake_to_worldspace = instance.data("bakeToWorldSpace", True)
|
||||
|
||||
if not bake_to_worldspace:
|
||||
self.log.warning("Camera (Maya Ascii) export only supports world"
|
||||
self.log.warning("Camera (Maya Scene) export only supports world"
|
||||
"space baked camera extractions. The disabled "
|
||||
"bake to world space is ignored...")
|
||||
|
||||
|
|
@ -157,7 +132,7 @@ class ExtractCameraMayaAscii(pype.api.Extractor):
|
|||
|
||||
# Define extract output file path
|
||||
dir_path = self.staging_dir(instance)
|
||||
filename = "{0}.ma".format(instance.name)
|
||||
filename = "{0}.{1}".format(instance.name, self.scene_type)
|
||||
path = os.path.join(dir_path, filename)
|
||||
|
||||
# Perform extraction
|
||||
|
|
@ -190,19 +165,11 @@ class ExtractCameraMayaAscii(pype.api.Extractor):
|
|||
unlock(plug)
|
||||
cmds.setAttr(plug, value)
|
||||
|
||||
if self.bake_attributes:
|
||||
self.log.info(
|
||||
"Baking attributes: {}".format(
|
||||
self.bake_attributes))
|
||||
bake_attribute(
|
||||
cam, self.bake_attributes,
|
||||
frame_range=range_with_handles, step=step)
|
||||
|
||||
self.log.info("Performing extraction..")
|
||||
cmds.select(baked_shapes, noExpand=True)
|
||||
cmds.file(path,
|
||||
force=True,
|
||||
typ="mayaAscii",
|
||||
typ="mayaAscii" if self.scene_type == "ma" else "mayaBinary", # noqa: E501
|
||||
exportSelected=True,
|
||||
preserveReferences=False,
|
||||
constructionHistory=False,
|
||||
|
|
@ -214,15 +181,15 @@ class ExtractCameraMayaAscii(pype.api.Extractor):
|
|||
# Delete the baked hierarchy
|
||||
if bake_to_worldspace:
|
||||
cmds.delete(baked)
|
||||
|
||||
massage_ma_file(path)
|
||||
if self.scene_type == "ma":
|
||||
massage_ma_file(path)
|
||||
|
||||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'ma',
|
||||
'ext': 'ma',
|
||||
'name': self.scene_type,
|
||||
'ext': self.scene_type,
|
||||
'files': filename,
|
||||
"stagingDir": dir_path,
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Extract data as Maya scene (raw)."""
|
||||
import os
|
||||
|
||||
from maya import cmds
|
||||
|
|
@ -6,24 +8,37 @@ import avalon.maya
|
|||
import pype.api
|
||||
|
||||
|
||||
class ExtractMayaAsciiRaw(pype.api.Extractor):
|
||||
"""Extract as Maya Ascii (raw)
|
||||
class ExtractMayaSceneRaw(pype.api.Extractor):
|
||||
"""Extract as Maya Scene (raw).
|
||||
|
||||
This will preserve all references, construction history, etc.
|
||||
|
||||
"""
|
||||
|
||||
label = "Maya ASCII (Raw)"
|
||||
label = "Maya Scene (Raw)"
|
||||
hosts = ["maya"]
|
||||
families = ["mayaAscii",
|
||||
"setdress",
|
||||
"layout"]
|
||||
scene_type = "ma"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
"""Plugin entry point."""
|
||||
ext_mapping = instance.context.data["presets"]["maya"].get("ext_mapping") # noqa: E501
|
||||
if ext_mapping:
|
||||
self.log.info("Looking in presets for scene type ...")
|
||||
# use extension mapping for first family found
|
||||
for family in self.families:
|
||||
try:
|
||||
self.scene_type = ext_mapping[family]
|
||||
self.log.info(
|
||||
"Using {} as scene type".format(self.scene_type))
|
||||
break
|
||||
except AttributeError:
|
||||
# no preset found
|
||||
pass
|
||||
# Define extract output file path
|
||||
dir_path = self.staging_dir(instance)
|
||||
filename = "{0}.ma".format(instance.name)
|
||||
filename = "{0}.{1}".format(instance.name, self.scene_type)
|
||||
path = os.path.join(dir_path, filename)
|
||||
|
||||
# Whether to include all nodes in the instance (including those from
|
||||
|
|
@ -38,12 +53,12 @@ class ExtractMayaAsciiRaw(pype.api.Extractor):
|
|||
members = instance[:]
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
self.log.info("Performing extraction ...")
|
||||
with avalon.maya.maintained_selection():
|
||||
cmds.select(members, noExpand=True)
|
||||
cmds.file(path,
|
||||
force=True,
|
||||
typ="mayaAscii",
|
||||
typ="mayaAscii" if self.scene_type == "ma" else "mayaBinary", # noqa: E501
|
||||
exportSelected=True,
|
||||
preserveReferences=True,
|
||||
constructionHistory=True,
|
||||
|
|
@ -55,8 +70,8 @@ class ExtractMayaAsciiRaw(pype.api.Extractor):
|
|||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'ma',
|
||||
'ext': 'ma',
|
||||
'name': self.scene_type,
|
||||
'ext': self.scene_type,
|
||||
'files': filename,
|
||||
"stagingDir": dir_path
|
||||
}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Extract model as Maya Scene."""
|
||||
import os
|
||||
|
||||
from maya import cmds
|
||||
|
|
@ -8,7 +10,7 @@ from pype.hosts.maya import lib
|
|||
|
||||
|
||||
class ExtractModel(pype.api.Extractor):
|
||||
"""Extract as Model (Maya Ascii)
|
||||
"""Extract as Model (Maya Scene).
|
||||
|
||||
Only extracts contents based on the original "setMembers" data to ensure
|
||||
publishing the least amount of required shapes. From that it only takes
|
||||
|
|
@ -22,19 +24,33 @@ class ExtractModel(pype.api.Extractor):
|
|||
|
||||
"""
|
||||
|
||||
label = "Model (Maya ASCII)"
|
||||
label = "Model (Maya Scene)"
|
||||
hosts = ["maya"]
|
||||
families = ["model"]
|
||||
scene_type = "ma"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
"""Plugin entry point."""
|
||||
ext_mapping = instance.context.data["presets"]["maya"].get("ext_mapping") # noqa: E501
|
||||
if ext_mapping:
|
||||
self.log.info("Looking in presets for scene type ...")
|
||||
# use extension mapping for first family found
|
||||
for family in self.families:
|
||||
try:
|
||||
self.scene_type = ext_mapping[family]
|
||||
self.log.info(
|
||||
"Using {} as scene type".format(self.scene_type))
|
||||
break
|
||||
except AttributeError:
|
||||
# no preset found
|
||||
pass
|
||||
# Define extract output file path
|
||||
stagingdir = self.staging_dir(instance)
|
||||
filename = "{0}.ma".format(instance.name)
|
||||
filename = "{0}.{1}".format(instance.name, self.scene_type)
|
||||
path = os.path.join(stagingdir, filename)
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
self.log.info("Performing extraction ...")
|
||||
|
||||
# Get only the shape contents we need in such a way that we avoid
|
||||
# taking along intermediateObjects
|
||||
|
|
@ -59,7 +75,7 @@ class ExtractModel(pype.api.Extractor):
|
|||
cmds.select(members, noExpand=True)
|
||||
cmds.file(path,
|
||||
force=True,
|
||||
typ="mayaAscii",
|
||||
typ="mayaAscii" if self.scene_type == "ma" else "mayaBinary", # noqa: E501
|
||||
exportSelected=True,
|
||||
preserveReferences=False,
|
||||
channels=False,
|
||||
|
|
@ -73,8 +89,8 @@ class ExtractModel(pype.api.Extractor):
|
|||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'ma',
|
||||
'ext': 'ma',
|
||||
'name': self.scene_type,
|
||||
'ext': self.scene_type,
|
||||
'files': filename,
|
||||
"stagingDir": stagingdir,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Extract rig as Maya Scene."""
|
||||
import os
|
||||
|
||||
from maya import cmds
|
||||
|
|
@ -7,26 +9,40 @@ import pype.api
|
|||
|
||||
|
||||
class ExtractRig(pype.api.Extractor):
|
||||
"""Extract rig as Maya Ascii"""
|
||||
"""Extract rig as Maya Scene."""
|
||||
|
||||
label = "Extract Rig (Maya ASCII)"
|
||||
label = "Extract Rig (Maya Scene)"
|
||||
hosts = ["maya"]
|
||||
families = ["rig"]
|
||||
scene_type = "ma"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
"""Plugin entry point."""
|
||||
ext_mapping = instance.context.data["presets"]["maya"].get("ext_mapping") # noqa: E501
|
||||
if ext_mapping:
|
||||
self.log.info("Looking in presets for scene type ...")
|
||||
# use extension mapping for first family found
|
||||
for family in self.families:
|
||||
try:
|
||||
self.scene_type = ext_mapping[family]
|
||||
self.log.info(
|
||||
"Using {} as scene type".format(self.scene_type))
|
||||
break
|
||||
except AttributeError:
|
||||
# no preset found
|
||||
pass
|
||||
# Define extract output file path
|
||||
dir_path = self.staging_dir(instance)
|
||||
filename = "{0}.ma".format(instance.name)
|
||||
filename = "{0}.{1}".format(instance.name, self.scene_type)
|
||||
path = os.path.join(dir_path, filename)
|
||||
|
||||
# Perform extraction
|
||||
self.log.info("Performing extraction..")
|
||||
self.log.info("Performing extraction ...")
|
||||
with avalon.maya.maintained_selection():
|
||||
cmds.select(instance, noExpand=True)
|
||||
cmds.file(path,
|
||||
force=True,
|
||||
typ="mayaAscii",
|
||||
typ="mayaAscii" if self.scene_type == "ma" else "mayaBinary", # noqa: E501
|
||||
exportSelected=True,
|
||||
preserveReferences=False,
|
||||
channels=True,
|
||||
|
|
@ -38,12 +54,11 @@ class ExtractRig(pype.api.Extractor):
|
|||
instance.data["representations"] = []
|
||||
|
||||
representation = {
|
||||
'name': 'ma',
|
||||
'ext': 'ma',
|
||||
'name': self.scene_type,
|
||||
'ext': self.scene_type,
|
||||
'files': filename,
|
||||
"stagingDir": dir_path
|
||||
}
|
||||
instance.data["representations"].append(representation)
|
||||
|
||||
|
||||
self.log.info("Extracted instance '%s' to: %s" % (instance.name, path))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Extract Yeti rig."""
|
||||
|
||||
import os
|
||||
import json
|
||||
import contextlib
|
||||
|
|
@ -11,7 +14,7 @@ import pype.hosts.maya.lib as maya
|
|||
|
||||
@contextlib.contextmanager
|
||||
def disconnect_plugs(settings, members):
|
||||
|
||||
"""Disconnect and store attribute connections."""
|
||||
members = cmds.ls(members, long=True)
|
||||
original_connections = []
|
||||
try:
|
||||
|
|
@ -55,7 +58,7 @@ def disconnect_plugs(settings, members):
|
|||
|
||||
@contextlib.contextmanager
|
||||
def yetigraph_attribute_values(assumed_destination, resources):
|
||||
|
||||
"""Get values from Yeti attributes in graph."""
|
||||
try:
|
||||
for resource in resources:
|
||||
if "graphnode" not in resource:
|
||||
|
|
@ -89,14 +92,28 @@ def yetigraph_attribute_values(assumed_destination, resources):
|
|||
|
||||
|
||||
class ExtractYetiRig(pype.api.Extractor):
|
||||
"""Extract the Yeti rig to a MayaAscii and write the Yeti rig data"""
|
||||
"""Extract the Yeti rig to a Maya Scene and write the Yeti rig data."""
|
||||
|
||||
label = "Extract Yeti Rig"
|
||||
hosts = ["maya"]
|
||||
families = ["yetiRig"]
|
||||
scene_type = "ma"
|
||||
|
||||
def process(self, instance):
|
||||
|
||||
"""Plugin entry point."""
|
||||
ext_mapping = instance.context.data["presets"]["maya"].get("ext_mapping") # noqa: E501
|
||||
if ext_mapping:
|
||||
self.log.info("Looking in presets for scene type ...")
|
||||
# use extension mapping for first family found
|
||||
for family in self.families:
|
||||
try:
|
||||
self.scene_type = ext_mapping[family]
|
||||
self.log.info(
|
||||
"Using {} as scene type".format(self.scene_type))
|
||||
break
|
||||
except AttributeError:
|
||||
# no preset found
|
||||
pass
|
||||
yeti_nodes = cmds.ls(instance, type="pgYetiMaya")
|
||||
if not yeti_nodes:
|
||||
raise RuntimeError("No pgYetiMaya nodes found in the instance")
|
||||
|
|
@ -106,7 +123,8 @@ class ExtractYetiRig(pype.api.Extractor):
|
|||
settings_path = os.path.join(dirname, "yeti.rigsettings")
|
||||
|
||||
# Yeti related staging dirs
|
||||
maya_path = os.path.join(dirname, "yeti_rig.ma")
|
||||
maya_path = os.path.join(
|
||||
dirname, "yeti_rig.{}".format(self.scene_type))
|
||||
|
||||
self.log.info("Writing metadata file")
|
||||
|
||||
|
|
@ -153,7 +171,7 @@ class ExtractYetiRig(pype.api.Extractor):
|
|||
cmds.file(maya_path,
|
||||
force=True,
|
||||
exportSelected=True,
|
||||
typ="mayaAscii",
|
||||
typ="mayaAscii" if self.scene_type == "ma" else "mayaBinary", # noqa: E501
|
||||
preserveReferences=False,
|
||||
constructionHistory=True,
|
||||
shader=False)
|
||||
|
|
@ -163,21 +181,21 @@ class ExtractYetiRig(pype.api.Extractor):
|
|||
if "representations" not in instance.data:
|
||||
instance.data["representations"] = []
|
||||
|
||||
self.log.info("rig file: {}".format("yeti_rig.ma"))
|
||||
self.log.info("rig file: {}".format(maya_path))
|
||||
instance.data["representations"].append(
|
||||
{
|
||||
'name': "ma",
|
||||
'ext': 'ma',
|
||||
'files': "yeti_rig.ma",
|
||||
'name': self.scene_type,
|
||||
'ext': self.scene_type,
|
||||
'files': os.path.basename(maya_path),
|
||||
'stagingDir': dirname
|
||||
}
|
||||
)
|
||||
self.log.info("settings file: {}".format("yeti.rigsettings"))
|
||||
self.log.info("settings file: {}".format(settings))
|
||||
instance.data["representations"].append(
|
||||
{
|
||||
'name': 'rigsettings',
|
||||
'ext': 'rigsettings',
|
||||
'files': 'yeti.rigsettings',
|
||||
'files': os.path.basename(settings),
|
||||
'stagingDir': dirname
|
||||
}
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue