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:
Milan Kolar 2020-08-06 09:40:58 +02:00 committed by GitHub
commit fab38ca8e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 130 additions and 99 deletions

View file

@ -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,
}

View file

@ -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
}

View file

@ -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,
}

View file

@ -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))

View file

@ -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
}
)