Out of the many ways to export/import animation in Maya, from the built-in .atom format from 2013 to the .anim file format form 1993, here's a different take.
---> Export related animCurve nodes as a mayaAscii scene
<--- Import animCurve nodes from the mayaAscii scene, elsewhere
-><- Connect each node to their corresponding target
It is..
Simple ~100 lines of Python, no "clipboard", no "views", no "templates", no MEL, no smarts
Robust In that the original animation is preserved exactly
Lightweight In that only animated channels are exported, no pre-processing required
Fast As fast as Maya is able to export and import scene files
Native As a regular Maya Ascii file, import it yourself, anywhere and without the need for Python
With a few caveats..
No static channels
No animation layers
No partial-range export or import
Names must match exactly between export/import targets
Each of which could potentially be solved with some further tinkering.
Copy/paste the implementation below, and use it like this..
Based on your current selection
# Custom suffix
fname = cmds.file("anim1.manim", expandName=True, query=True)
# From scene A
export_animation(fname)
# From scene B
import_animation(fname)
Implementation
import cmdx
from maya import cmds # for select()
def export_animation(fname):
"""Export animation for selected nodes to `fname`
Animation is exported as native Maya nodes, e.g. animCurveTU
and later imported and re-connected to their original nodes
Limitations:
- No animation layers
- Names much match exactly between exported and imported nodes
"""
animation = []
for node in cmdx.selection(type="transform"): # Optionally limited to transform nodes
# Find any curve connecting to this node
for curve in node.connections():
if not isinstance(curve, cmdx.AnimCurve):
continue
# Encode target connection as string attribute
# for retrieval during `import_animation`
if not curve.has_attr("target"):
curve["target"] = cmdx.String()
# Find the attribute to which this curve connects
plug = curve.connection(plug=True)
curve["target"] = plug.path()
animation.append(curve)
if not animation:
cmds.warning(
"Select objects in the scene to "
"export any connected animation"
)
return cmds.warning("No animation found, see Script Editor for details")
previous_selection = cmds.ls(selection=True)
cmds.select(map(str, animation))
try:
cmds.file(
fname,
# Overwrite existing
force=True,
# Use our own suffix
defaultExtensions=False,
# Internal format, despite our format
type="mayaAscii",
exportSelected=True,
# We don't want anything but the selected animation curves
constructionHistory=False
)
except Exception:
import traceback
traceback.print_exc()
cmds.warning("Something unexpected happened when trying to export, see Script Editor for details.")
finally:
cmds.select(previous_selection)
print("Successfully exported '%s'" % fname)
def import_animation(fname):
previous_selection = cmds.ls(selection=True)
try:
animation = cmds.file(fname, i=True, returnNewNodes=True)
except Exception:
import traceback
traceback.print_exc()
return cmds.warning(
"Something unexpected happened when trying "
"to import '%s', see Script Editor for details"
% fname
)
finally:
cmds.select(previous_selection)
for curve in animation:
curve = cmdx.encode(curve)
if not curve.has_attr("target"):
cmds.warning("Skipped: '%s' did not have the `target` "
"attribute used to reconnect the animation"
% curve)
continue
# Stored as "<node>.<attr>" e.g. "pCube1.tx"
node, attr = curve["target"].read().rsplit(".", 1)
try:
target = cmdx.encode(node)
except cmdx.ExistError:
cmds.warning("Skipped: '%s' did not exist" % node)
continue
# Make the connection, replacing any existing
curve["output"] >> target[attr]
print("Successfully imported '%s'!" % fname)
Next Steps
Avoid nameclashes When importing animation the second time, the curve nodes share a name which throws a warning. By importing into a namespace, any node matching the name outside of this namespace can be removed prior to import
Search-and-replace To support alternative names, namespaces and multiple instances of the same character or scene
Animation Layers It'd be a matter of exporting not just the curve, but the network leading into the node being animated, which would include the animation layer setup.
An example of how names clash.
When to Use
That is, why not use .anim or .atom? If you can, you probably should. The are already installed (or are they?), they've got documentation (or do they?), they've got more features (of value?) and others may be able to help out when things go south (or can they?).
I would use it when what I want is to export/import animation from one scene to another without fuss; when I don't remember my login details to HighEnd3D and aren't interested in experimenting with the various MEL alternatives on there, and when I haven't got the budget nor time to understand or implement support for ATOM.
Out of the many ways to export/import animation in Maya, from the built-in
.atom
format from 2013 to the.anim
file format form 1993, here's a different take.--->
Export relatedanimCurve
nodes as amayaAscii
scene<---
ImportanimCurve
nodes from themayaAscii
scene, elsewhere-><-
Connect each node to their corresponding targetIt is..
With a few caveats..
Each of which could potentially be solved with some further tinkering.
Usage
~/maya/scripts
folderImplementation
Next Steps
An example of how names clash.
When to Use
That is, why not use
.anim
or.atom
? If you can, you probably should. The are already installed (or are they?), they've got documentation (or do they?), they've got more features (of value?) and others may be able to help out when things go south (or can they?).I would use it when what I want is to export/import animation from one scene to another without fuss; when I don't remember my login details to HighEnd3D and aren't interested in experimenting with the various MEL alternatives on there, and when I haven't got the budget nor time to understand or implement support for ATOM.
YMMV :) Let me know what you think!