#!/usr/bin/env python3 """ Create a compact animation-only GLB from selected actions in a source GLB. Usage: blender --background --python tools/extract_animation_subset.py -- \ [ ...] The source skeleton is retained, all meshes and unrelated actions are removed, and each requested action is exported as its own NLA track. This keeps external authored animation libraries small enough to ship as retargeting sources. """ import os import sys import bpy argv = sys.argv argv = argv[argv.index("--") + 1:] if "--" in argv else [] if len(argv) < 3: print( "Usage: blender --background --python " "tools/extract_animation_subset.py -- " " [ ...]" ) sys.exit(1) SOURCE = argv[0] OUTPUT = argv[1] REQUESTED = argv[2:] def main(): bpy.ops.object.select_all(action="SELECT") bpy.ops.object.delete() bpy.ops.import_scene.gltf(filepath=SOURCE) armatures = [obj for obj in bpy.data.objects if obj.type == "ARMATURE"] if len(armatures) != 1: print(f"ERROR: expected one armature, found {len(armatures)}") sys.exit(1) armature = armatures[0] missing = [name for name in REQUESTED if bpy.data.actions.get(name) is None] if missing: print(f"ERROR: requested actions not found: {missing}") sys.exit(1) for obj in list(bpy.data.objects): if obj != armature: bpy.data.objects.remove(obj, do_unlink=True) if not armature.animation_data: armature.animation_data_create() for track in list(armature.animation_data.nla_tracks): armature.animation_data.nla_tracks.remove(track) armature.animation_data.action = None keep = set() for name in REQUESTED: action = bpy.data.actions[name] action.use_fake_user = True track = armature.animation_data.nla_tracks.new() track.name = name strip = track.strips.new(name, 0, action) strip.name = name track.mute = True keep.add(action) for action in list(bpy.data.actions): if action not in keep: bpy.data.actions.remove(action) os.makedirs(os.path.dirname(os.path.abspath(OUTPUT)), exist_ok=True) bpy.ops.export_scene.gltf( filepath=OUTPUT, export_format="GLB", export_yup=True, export_animations=True, export_animation_mode="NLA_TRACKS", export_skins=True, export_bake_animation=True, ) print(f"Exported {len(keep)} clips to {OUTPUT}") main()