Hey, I was wondering if there’s an option that to bake different groups to different animation layers. I read this topic from jul 2023 AnimLayer-per-Group Baking and I think Marcus was planning to add this feature.
Is this option avaliable?
I could create a script to extract the anim of the controls to a different layer, but in my case they’ll have different names and I think I would have to manually update the script for each character.
The script could do that too, or you would use Ragdoll -> Select -> Groups to select all of them, ahead of running the script. I’ll see if I can put something together for you this week. Ping me (again!) otherwise.
Ok, here we go. Tested on Maya 2025, should work from 2019 and above. If nothing happens, make sure you’ve selected a layer and the shape nodes of each group. Remove the selected=True to extract all groups in the scene.
It’s only tested on this Manikin, with a single namespace. But should hold up to more complex rigs, let me know!
# USAGE:
#
# 1. Record onto a layer
# 2. Select recorded layer
# 3. Select one or more group *shapes*
# 4. Run script
from ragdoll import interactive as ri
import maya.cmds as cmds
import maya.mel as mel
def _find_anim_layer_panel():
# Animation Layers editor is implemented as a treeView
# name commonly contains 'animLayerEditor'
tvs = cmds.lsUI(type='treeView') or []
for tv in tvs:
if 'animLayerEditor' in tv:
return tv
return None
def _to_mel_array(items):
# Convert Python list of strings -> MEL array literal: {"a","b"}
out = ", ".join('"%s"' % i for i in items)
return "{%s}" % out
def extract_selected_objects():
tv = _find_anim_layer_panel()
if not tv:
raise RuntimeError(
"Could not find the Animation Layer Editor treeView. "
"Ensure the Animation Layers panel is open."
)
# Items selected in the Anim Layers UI
# (can include layers and/or child object rows)
ui_sel = cmds.treeView(tv, query=True, selectItem=True) or []
if not ui_sel:
raise RuntimeError("Nothing selected in the Animation Layers UI.")
layers = []
objects = []
for item in ui_sel:
if not cmds.objExists(item):
# Some tree items can be UI-only identifiers; ignore those
continue
ntype = cmds.nodeType(item)
if ntype == 'animLayer':
layers.append(item)
else:
# Typically DAG paths (controls/joints) or node names
objects.append(item)
if not layers:
raise RuntimeError(
"No animation layer selected in the Animation Layers UI."
)
# If the user did not explicitly select object rows in the tree,
# the RMB menu commonly operates on viewport selection; include it as well.
scene_sel = cmds.ls(sl=True, long=True) or []
for s in scene_sel:
if s not in objects:
objects.append(s.rsplit("|", 1)[-1])
if not objects:
raise RuntimeError(
"No objects to extract (no object rows selected "
"in the Anim Layers UI, and nothing selected in the scene)."
)
cmd = 'layerEditorExtractObjectsAnimLayer({0}, {1});'.format(
_to_mel_array(objects),
_to_mel_array(layers)
)
before = set(cmds.ls(type="animLayer") or [])
mel.eval(cmd)
# Identify newly created layer(s)
after = set(cmds.ls(type='animLayer') or [])
created = list(after - before)
if not created:
raise RuntimeError("No new animLayer detected after extract.")
return created
for group in cmds.ls(selection=True, type="rdGroup"):
cmds.select(group)
ri.select_group_members()
ri.select_assigned_from_markers()
layer = extract_selected_objects()
layer_name = group
# Remove namespace
layer_name = layer_name.rsplit(":", 1)[-1]
# Remove hierarchy
layer_name = layer_name.rsplit("|", 1)[-1]
# Add suffix
layer_name += "Layer"
cmds.rename(layer, layer_name)
else:
raise RuntimeError("Select the shape of each Group node")