Skip to content

KyleSullivan321/AE-Figma-Plugin

Repository files navigation

AE ↔ Figma ↔ Cavalry

Move a motion design between After Effects, Figma Motion (beta), and Cavalry — layers, transforms, keyframes, and easing intact. Three apps, one JSON file, no network and no account.

⚠️ Figma's Motion API is in beta. This tool depends on it and may break as Figma changes the API. Expect rough edges.

Every route, in both directions

There is no pairwise conversion code. Every app reads and writes the same file, so each new exporter lights up every existing importer for free:

   After Effects            Figma Motion              Cavalry
        ▲ │                     ▲ │                    ▲ │
        │ ▼                     │ ▼                    │ ▼
     ae-export.jsx        figma plugin           cavalry-export.js
     figma-import.jsx     (Import / Export)      cavalry-import.js
        │ ▲                     │ ▲                    │ ▲
        └─┴──────────▶  motion.json  ◀────────────────┴─┘
Route Producer Consumer
AE → Figma ae-export.jsx Figma plugin → Import
Figma → AE Figma plugin → Export figma-import.jsx
Figma → Cavalry Figma plugin → Export cavalry-import.js
AE → Cavalry ae-export.jsx cavalry-import.js
Cavalry → Figma cavalry-export.js Figma plugin → Import
Cavalry → AE cavalry-export.js figma-import.jsx

What transfers

Layers text, shapes (rect / ellipse / star / polygon / bezier paths), solids, still images
Transform position, scale, rotation, opacity, anchor
Hierarchy AE parenting and precomps ↔ Figma frames and groups
Keyframes position / scale / rotation / opacity, plus path trim (write-on)
Easing full cubic-bézier both ways, per-axis, hold/step, dimension-separated aware

The interchange format

One file, schema:1, in AE-native units — pixels, top-left origin, Y-down, degrees clockwise, 0–100 scale and opacity, {influence, speed} easing. It's the format ae-export.jsx already wrote, so every consumer speaks one language.

All Figma→AE unit conversion happens once, inside the Figma plugin's exporter (opacity 0–1→0–100, scale ×→%, rotation ccw→cw, translation deltas→absolute position, cubic bézier→ influence/speed). The AE and Cavalry importers therefore never need to know Figma exists.

A pleasant side effect: figma-import.jsx can re-import ae-export.jsx's own output, so AE acts as an oracle for its own importer — which is exactly how tools/roundtrip.jsx tests it.

Install & use

After Effects

Copy ae-export.jsx and figma-import.jsx into AE's ScriptUI Panels folder:

  • Windows: C:\Program Files\Adobe\Adobe After Effects <version>\Support Files\Scripts\ScriptUI Panels\
  • macOS: /Applications/Adobe After Effects <version>/Scripts/ScriptUI Panels/

Then Edit ▸ Preferences ▸ Scripting & Expressions → enable Allow Scripts to Write Files and Access Network. Restart AE; both panels appear under the Window menu.

No install? File ▸ Scripts ▸ Run Script File… runs either one ad-hoc.

⚠️ Installing makes a COPY. After pulling changes, re-copy the script or AE keeps running the old one — silently, since a stale exporter still produces perfectly valid JSON. (The ScriptUI Panels folder lives under Program Files, so the copy needs an admin shell.) Same applies to Cavalry's Scripts folder.

  • Export: select a comp → Export composition… → save the .json. Images are copied into a <name>_assets folder beside it.
  • Import: Import JSON… → pick a .json exported from Figma (or from AE).

Figma

Plugins ▸ Development ▸ Import plugin from manifest… → pick figma-plugin/manifest.json.

  • Import: select the .json (and optionally the images from _assets — multi-select).
  • Export: select the top-level frame holding your animation, pick a frame rate, and click Export JSON. It downloads a .json for AE or Cavalry.

Keyframes need the Motion (beta) feature enabled on your account. Without it, import still works statically and export reports that there's nothing to read.

Cavalry

Window ▸ Script Editor → open cavalry-import.js or cavalry-export.jsRun. (Or drop them in Cavalry's Scripts folder to get them under Window ▸ Scripts.)

  • Import creates a new composition named after the source and builds into it.
  • Export writes the active composition out as JSON.

If you install the scripts into Cavalry's Scripts folder, remember that's a copy — re-copy it after pulling changes, or you'll be running a stale importer.

Cavalry exposes no keyframe curve to scripting (no keyframe getter, and magicEasing isn't a readable expression), so the exporter recovers the easing by sampling the animation and fitting a cubic bezier. On a round-trip it reconstructs the original curve to within ~0.3%.

Limitations

  • Springs have no AE/Cavalry equivalent — approximated as a bézier ease, and the exporter warns. Check the timing.
  • Text: fonts are matched by family/style and fall back to a default if not installed. Text is placed by its glyph box; a fixed-width text frame may sit a pixel or two off.
  • Text animators (per-character/word/line) don't convert — text stays static. See experimental/ for in-progress per-character splitting.
  • Gradients: Figma→Cavalry carries real colour stops. AE can't read or write gradient stops from scripting, so anything touching AE degrades to a solid.
  • AE→Cavalry anchors: a Cavalry primitive pivots on its geometric centre. Figma always pivots on the centre too, so that route is exact — but an AE layer whose anchor has been moved off-centre will rotate/scale about the wrong point in Cavalry.
  • Cavalry→* easing is recovered, not read (Cavalry doesn't expose it). It reconstructs a hand-authored curve to ~0.3%, but a segment only 1–2 frames long has too few samples to fit and falls back to linear.
  • Cavalry→* geometry: rectangles, ellipses, polygons, stars and text transfer. A custom editableShape path exports as its bounding box (its geometry doesn't come across yet).
  • Cavalry→* groups: a group becomes a transform-only rig, so a group's own opacity animation doesn't transfer — the exporter warns and tells you to put it on the children.
  • Fill/stroke colour animation, Figma auto-layout/constraints/components, masks, blend modes, boolean ops, video footage, 3D, cameras and lights are not transferred.
  • AE→Figma shape export still simplifies some multi-group shape layers.

Development

node figma-plugin/test-convert.js   # conversion maths, incl. the easing round-trip. No app needed.
node tools/export-test.js           # runs the REAL Figma exporter against a captured node tree
node tools/cav-test.js              # imports into a LIVE Cavalry and checks the scene back
node tools/cav-export-test.js       # Cavalry import -> export -> diff (Cavalry as its own oracle)
pwsh tools/ae.ps1 -mode runfile -file tools/roundtrip.jsx && node tools/compare.js
pwsh tools/ae.ps1 -mode runfile -file tools/ae-scale-check.jsx   # the squared-scale regression

tools/ drives the real apps rather than mocking them:

  • ae.ps1 — runs a .jsx in a headless After Effects and returns its value. It picks the newest installed AE: afterfx.com only drives its own AfterFX.exe, and mixing versions boots the app but silently never runs the script.
  • roundtrip.jsx + compare.js — builds a fixture comp, exports it, re-imports it, exports again, and diffs. Bounds, transforms, keyframes, easing, and parenting must match.
  • export-test.js — loads the export half of figma-plugin/code.js and runs it against figma-dump.json (a verbatim capture of a live Figma motion file). Tests the shipping code, offline.
  • cav-test.js — Cavalry has no CLI, so this POSTs to the api.WebServer bridge on :8090 to run the importer inside a live Cavalry and read the scene back.

License

MIT — see LICENSE. Use it, fork it, sell your services around it. No warranty.

If it saves you time, a GitHub Sponsor is appreciated but never expected.

About

No description, website, or topics provided.

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages