Takes a flat SVG and restructures it into an Adobe Character Animator puppet hierarchy using a JSON mapping file. No hardcoded indexes in Python — all character-specific assignments live in mappings/.
src/
svg_puppet.py ← main CLI
auto_group_character.py
auto_group_character_v2.py
auto_group_head.py
auto_group_head_v2.py
convert_svg_to_ai_puppet.py
convert_svg_to_ai_puppet_v2.py
mappings/
char_2_172.json ← 172-path full-body character (2.svg)
2.svg ← source SVG
2_grouped.svg ← output grouped SVG
# 1. Inspect drawables (0-based paint-order indexes)
python3 src/svg_puppet.py inventory 2.svg
# 2. Write or edit a mapping file in mappings/
# 3. Validate before writing
python3 src/svg_puppet.py validate 2.svg --mapping mappings/char_2_172.json
# 4. Group
python3 src/svg_puppet.py group 2.svg \
--mapping mappings/char_2_172.json \
--output 2_grouped.svg \
--overwrite \
--allow-z-order-change{
"version": 1,
"character_name": "Character2",
"expected": { "drawable_count": 172 },
"groups": [
{
"name": "+Head",
"children": [
{
"name": "Face_Base",
"elements": { "ranges": [[107, 112], [114, 116]] }
},
{
"name": "+Right Eye",
"elements": { "ranges": [[59, 64]], "indices": [126, 130, 131] }
}
]
},
{
"name": "+Right Arm",
"elements": { "ranges": [[0, 9], [41, 44]], "indices": [113, 117] }
}
]
}- Ranges are inclusive:
[0, 9]means indexes 0 through 9. +prefix = independent animatable group in Character Animator.- Mix
rangesandindicesfreely in the sameelementsblock. - Groups with
childrendo not need their ownelements.
When a drawable sits inside a <g transform="..."> or <g opacity="..."> in the source SVG, that wrapper is cloned into the output group so visual properties are preserved — transforms, opacity, clip-path, mask, filter, style. IDs are stripped from clones to prevent duplicates.
inventory <svg>
--output FILE Write JSON inventory to file
validate <svg> --mapping FILE
--allow-unassigned
--allow-z-order-change Warn instead of error on paint-order conflicts
group <svg> --mapping FILE
--output FILE Output SVG path
--overwrite Overwrite existing output
--allow-unassigned Place unassigned paths in _Unassigned group
--allow-z-order-change Proceed despite paint-order conflicts
--dry-run Validate only, do not write
--report FILE Write JSON validation report
--verbose / --strict
--export-ai Save .ai via Illustrator (macOS only)
--ai-output FILE
--illustrator-timeout SEC
- Out-of-range or unknown indexes
- Duplicate assignments
- Unassigned drawables
- Duplicate group names
expected.drawable_countmismatch- Paint-order / z-order interleaving (error unless
--allow-z-order-change) - Overwriting output without
--overwrite
Grouping non-contiguous source elements changes their relative paint order. The tool detects every such conflict and refuses to write by default. Pass --allow-z-order-change to proceed.
For 2.svg, z-order conflicts are expected — stroke and fill paths for different body parts are interleaved in the source DOM, so semantic grouping always reorders them.
+prefix on a group = independent limb (draggable, walk cycle, etc.)- Never merge paths — always use
<g>groups. Merging destroys animation. - SVG paint order (DOM order) = visual stacking. Later element = on top.
- Right/Left labels follow the character's perspective, not the viewer's.