Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
1a19cbb
feat(tools): Layer Cutter — browser tool to cut a drawing into clean …
7storm7 Oct 23, 2026
4b3a995
feat(tools): Layer Cutter — undo/redo history + wand add/remove mode
7storm7 Oct 23, 2026
1ffa63f
feat(tools): Layer Cutter emits nexum rig-payload (rig + layer images…
7storm7 Oct 23, 2026
1c33e1d
feat(stage): cut-out puppet nexum plugin — OGCutoutRig bake + capabil…
7storm7 Oct 23, 2026
d05d193
feat(tools): Layer Cutter live 'Preview motion' — assemble + watch th…
7storm7 Oct 23, 2026
4aba26c
feat(tools): Layer Cutter — save/open an ongoing cut (project file + …
7storm7 Oct 23, 2026
c46f927
feat(tools): Layer Cutter — z-order reorder + per-mover angle/speed +…
7storm7 Oct 23, 2026
6f1ec2c
feat(cutter): Face expressions mode — pose happy/sad/angry/shocked fr…
7storm7 Oct 23, 2026
50ab12d
feat(cutter): free-transform face parts — on-canvas stretch/zoom hand…
7storm7 Oct 23, 2026
b438780
feat(cutter): warp a point — local mesh deform of face parts
7storm7 Oct 23, 2026
79366c6
feat(cutter): region/point warp operators + undo-redo for all express…
7storm7 Oct 23, 2026
814eb79
fix(cutter): sliders (Width/Height/Rotate/Zoom/Reach) now record undo…
7storm7 Oct 23, 2026
3493983
feat(cutter): MLS-rigid warp engine + FACS auto-pose for expressions
7storm7 Oct 23, 2026
3fcc3ae
fix(cutter): undoable layer delete + easy one-tap select + 2-row laye…
7storm7 Oct 24, 2026
6ababd2
feat(cutter): layer parenting — a part can 'Swing with' another layer…
7storm7 Oct 24, 2026
9300362
feat(cutter): 'cut out' knocks a part out of its PARENT layer, not ju…
7storm7 Oct 24, 2026
6c26de9
feat(cutter): per-layer ✏️ edit — one tap to re-cut any layer's wand/…
7storm7 Oct 24, 2026
46010c8
fix(cutter): don't nag to pin a joint on movers wired to a parent
7storm7 Oct 24, 2026
9260149
fix(cutter): a wired part already rides its parent's tuck — don't dou…
7storm7 Oct 24, 2026
183d9cd
fix(cutter): gentler happy auto-pose — soft mouth corner-lift, modest…
7storm7 Oct 24, 2026
524129c
feat(cutter): per-layer 🔒 lock + ⟲ reset — stop accidental moves, one…
7storm7 Oct 24, 2026
1d9e25f
fix(cutter): make sad & angry read distinct — mouth/eyes carry the em…
7storm7 Oct 24, 2026
ad3f1f6
feat(cutter): 👄 Lip-line guide — trace the real mouth so FACS bends it
7storm7 Oct 24, 2026
aa19dc0
feat(cutter): auto-retarget mouth from traced lip line — any drawn fa…
7storm7 Oct 24, 2026
611775d
feat(cutter): 🩹 fill cut-out holes with skin — moved mouth/eye reveal…
7storm7 Oct 24, 2026
35a12ab
feat(cutter): per-layer 🔲 see-through cut-out — leave a real hole for…
7storm7 Oct 24, 2026
39704b2
fix(cutter): rebalance FACS sad/angry — sad was reading angrier than …
7storm7 Oct 24, 2026
c5b2c45
fix(cutter): sad brows RAISED HIGH so sad can't read angry (brows are…
7storm7 Oct 24, 2026
182b8a0
fix(cutter): rebuild sad/angry to Özge's emotion rules — soft-droopy …
7storm7 Oct 24, 2026
7954dec
fix(cutter): derive brow/eye viewer-side from GEOMETRY, not l/r names…
7storm7 Oct 24, 2026
96acac6
feat(cutter): 📸 Export face frames — bake posed heads per expression …
7storm7 Oct 24, 2026
40c4426
feat(cutter): 👄 draw each expression's mouth directly (pick expressio…
7storm7 Oct 25, 2026
72b3835
fix(cutter): name exports after the character, not hardcoded "superx"
7storm7 Oct 25, 2026
e62445f
feat(puppet): 🎭 OGPuppet — data-defined cut-out raster puppet primitive
7storm7 Oct 25, 2026
5fcda0d
feat(puppet): headMirror flag (symmetric faces tilt, don't flip) + co…
7storm7 Oct 25, 2026
5be8a63
feat(puppet): headLookInvert — per-puppet head-look direction
7storm7 Oct 25, 2026
5598ddd
chore(cutter): scrub nexum references (neutral host wording) for publ…
7storm7 Oct 25, 2026
754554a
feat(cutter): export the OGPuppet pack (puppet.json + union-framed PNGs)
7storm7 Oct 25, 2026
17bcb47
feat(cutter): 🩹 Patch base — clone-stamp + auto content-aware heal + …
7storm7 Oct 25, 2026
aacc39d
feat(cutter): reveal mover holes in the edit view while patching
7storm7 Oct 25, 2026
419b7e8
feat(cutter): holes live on the layer they're cut from — auto-jump + …
7storm7 Oct 25, 2026
2cd3bd8
fix(cutter): reveal holes on the layer being patched, not only the base
7storm7 Oct 25, 2026
0ced816
feat(cutter): tell the user when a hole can't be patched because it's…
7storm7 Oct 25, 2026
52d2df7
fix(cutter): tapping/dragging the magenta hole now auto-fills it (no …
7storm7 Oct 25, 2026
101e3eb
fix(cutter): re-sync canvas buffer to its CSS box each draw — fixes t…
7storm7 Oct 25, 2026
380b253
fix(cutter): clip patch reveal to the sheet — kill the un-healable pi…
7storm7 Oct 26, 2026
5a59c59
fix(cutter): patch/heal always targets the sheet, not the selected mover
7storm7 Oct 26, 2026
0b90366
fix(cutter): patch grows the base UNDER the mover — rebuild belt behi…
7storm7 Oct 26, 2026
208a6fe
fix(cutter): drop best-effort Auto-heal; clone source is now FIXED (n…
7storm7 Oct 26, 2026
ae184e3
feat(cutter): clone source shows its copy footprint + live ghost preview
7storm7 Oct 26, 2026
a891584
feat(cutter): GIMP-style clone/heal — moving aligned region + Infuse …
7storm7 Oct 26, 2026
ad4bf28
fix(cutter): Infuse no longer tints the patch toward the lifted arm
7storm7 Oct 26, 2026
48270bb
fix(cutter): fixed-source stamp (not aligned) + much bigger brush
7storm7 Oct 26, 2026
0fe91b3
feat(cutter): ▭ Copy-a-box patch mode (region copy→paste), now default
7storm7 Oct 26, 2026
84aa340
fix(cutter): Infuse ignores near-black ink outline when tone-matching
7storm7 Oct 26, 2026
15ff3f7
feat(cutter): ✨ Auto-heal now uses multi-scale PatchMatch content-awa…
7storm7 Oct 26, 2026
20da64d
fix(cutter): add the missing ✨ Auto-heal button to the 🩹 Patch panel
7storm7 Oct 26, 2026
098f85f
feat(cutter): 🧵 Pattern fill — sample a texture, paint a flexible are…
7storm7 Oct 26, 2026
81bd877
fix(cutter): drop the 30% base-colour veil in Patch mode (the mystery…
7storm7 Oct 26, 2026
60003b2
feat(cutter): 🧽 Erase gains Transparent | White targets
7storm7 Oct 26, 2026
df673d6
feat(shape,fx): ❄️🔥 recursive-fractal OGSnowflake + new OGFlame fire …
7storm7 Oct 29, 2026
acf9bfa
feat(glass): 🔍 OGGlass look-behind-glass lens (magnifier / minifier /…
7storm7 Oct 29, 2026
f10303d
feat(glass): 🔍 fixed, play-through lens — grip to move, ✕ to remove
7storm7 Oct 29, 2026
465fea5
feat(stage,particle): 🧣🍃 wind-blown Cloth + raster Image stage layers…
7storm7 Oct 30, 2026
b55a06f
chore(release): 🔖 lib v1.48.0 — Cloth/Image stage layers + gusty part…
7storm7 Oct 30, 2026
f6897cc
fix(glass): 🔍 no more doubled content under the lens — punch the base…
7storm7 Oct 30, 2026
8b12acc
feat(glass): 🔍 grip reads as a handle — drag-dots, not a "+"
7storm7 Oct 30, 2026
2082de2
chore(release): 🔖 lib v1.48.1 — OGGlass fixes (no doubling + drag-han…
7storm7 Oct 30, 2026
34fc5c4
docs: 📝 document 1.48.0 — GLASS / FLAME / PUPPET + Cloth/Image stage,…
7storm7 Oct 30, 2026
61ceac4
feat(glass): 🔍 configurable lens shape — aspect + cornerRadius (circl…
7storm7 Oct 30, 2026
d457bff
fix(glass): 🔍 lens handles stay on the rim at screen edges
7storm7 Oct 30, 2026
7f82a70
fix(glass): 🔍 loupe can pan onto edge content (no more chopped leadin…
7storm7 Oct 30, 2026
8a28ea7
fix(glass): 🔍 grip at bottom-centre → lens pans symmetrically to both…
7storm7 Oct 30, 2026
607da13
fix(control): 🔘 OGControl reserves default horizontal label padding
7storm7 Oct 30, 2026
d1cc7d0
feat(lib): 🌊🔥✨ Gerstner waves + KH flame edges + curl-noise particles
7storm7 Nov 1, 2026
33ed387
feat(fx): aurora curtains + Kuramoto fireflies + Worthington ripples …
7storm7 Nov 2, 2026
bf15727
feat(cutter): step-by-step UI redesign — 5-step guided flow with coll…
7storm7 Nov 4, 2026
5c6bb95
feat(fx): campfire flame on Thunder burn; quake gray/black abyss; flo…
7storm7 Nov 4, 2026
98208b5
feat(fx): single flame on Thunder burn; remove whirlpool & sweep floo…
7storm7 Nov 5, 2026
3c2dae8
feat(fx): brand-new cinematic quake rift + bigger thunder flame
7storm7 Nov 5, 2026
3c3aec6
feat(fx): synchronized earthquake cracks & hole sequence, tile-sized …
7storm7 Nov 7, 2026
5a6a19f
feat(fx): realistic seismic cracks, directional tile rift chasm & flu…
7storm7 Nov 7, 2026
2a7cf2a
feat(fx): auxiliary board cracks, top-down hole drop clipping & rando…
7storm7 Nov 7, 2026
25433d2
fix(fx): restore original thunder strike mechanics while keeping orga…
7storm7 Nov 7, 2026
0fb823b
fix(fx): restore proven thunder strike architecture, proper graphicsL…
7storm7 Nov 7, 2026
edf181c
feat(cutter): Smart Cut — k-means auto background removal with option…
7storm7 Nov 7, 2026
760f9a7
feat(control): OGPressEffect.Tactile, 3D extruded OGControl, game pre…
7storm7 Nov 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ Basic "show an SVG on both platforms" is now a solved problem (Coil 3, Kamel, La
| **Cloth sheet** — a 2-D Verlet sheet that drapes over & collides with capsule "poles": tarp / curtain / banner / flag (`OGCloth` / `OGClothCollider`) | ✅ | ❌ | ❌ |
| **Photo → an editable vector SCENE** — gradients, texture, glow, scatter + make-it-live motion day→night (`OGSceneSpec`) | ✅ | ❌ | ❌ |
| **Clickable-joints mesh rig** — bind joints & bend a dense mesh live (`OGRig`) | ✅ | ❌ | ❌ |
| **Cut-out puppet** — a jointed raster figure (base + movers) that breathes, leans & watches a look target (`OGPuppet` / `OGPuppetView`) | ✅ | ❌ | ❌ |
| **Fire** — a data-defined flickering flame (candle / campfire / torch / inferno) (`OGFlame` / `OGFlameView`) | ✅ | ❌ | ❌ |
| **Look-behind-glass lens** — a draggable magnifier / minifier / coloured glass over any content (`OGGlass`) | ✅ | ❌ | ❌ |
| Bundled image + audio + video suite | ✅ | ❌ | ❌ |

If all you need is a static SVG loaded from the network, a general image loader is the simpler choice. Reach for KMPMedia when you need media to **move, respond, compose, or change at runtime**.
Expand Down Expand Up @@ -208,6 +211,7 @@ Here's the full rundown of this wave (📷 live camera is the one effect not sho
- **🖼️ Living AI scenes** *(v1.38.0 – v1.40.0)* — the `OGSceneSpec` "photo → vector scene" format grew up. **v1.38.0** adds per-shape **gradient fills** (OKLab-resampled, no banding) plus a scene background + colour grade; **v1.39.0** adds richer stills — a procedural **texture** (fur / grass / grain), an additive **glow** halo, and a seeded **scatter** that stamps one shape into a whole field (trees / tufts); **v1.40.0** makes it **live** — a region declares its own looping motion (translate / scale / rotate / fade) and the scene swings a colour grade + sky over time (day → dusk → night), all pure and `t`-addressable so the compositor can scrub + export it. Backward-compatible, pure codec, 60fps, same code on Android & iOS.
- **🦁 Clickable-joints rig** *(v1.41.0)* — a deform **rig** for a dense scene mesh: `OGRig` binds a handful of joints to the mesh once (linear-blend skinning, partition-of-unity weights), then a drag warps the whole mesh around the joint, re-skinned every frame — the one case the rasterise-once / cache path can't cover. ~1.3 ms to skin 20k vertices; `deformInto` is zero-allocation, `nearestJoint` is the touch hit-test, and a released joint springs home with `OGSpring`. Pure maths, zero dependency, 60fps, frame-identical on Android & iOS.
- **🎞️ OGStage — one JSON, a whole movie** *(v1.42.0 – v1.45.0)* — the capstone that unifies every pack onto one serializable timeline: `OGStage` stacks `solid` / `scene` / `particles` / `slash` / `lightning` / `speedlines` / styled-**text** layers, each transformed by the compositor's keyframe tracks and graded by a look. One `OGStageView` plays it at 60fps and scrubs it; `OGStage.exportGif()` / `exportMp4()` render it off-screen with **every layer kind baked in** (the iOS README clip was rendered headless on the simulator through that very path). A language model authors the whole movie from one line via `OGStages.stagePrompt()` — the codec tolerates real model output (bare-number tracks, case-insensitive enums, markdown fences), and three model-written movies (STORM / HANAMI / RUSH) ship in the demo and are pinned as regression tests. **v1.44.0 makes it interactive:** any layer can carry an `onTap` trigger — tap it and it springs to life (`BOUNCE` / `SHAKE` / `SPIN` via the dynamics `OGSpring`, or `SEEK` / `PLAY_PAUSE`), the Rive-style interactivity the CMP players led on, as plain model-authorable data. **v1.45.0 closes the describe→movie loop:** `OGStageAuthor` turns a plain sentence into a playable stage, and `OGOfflineStageAuthor` does it with **no model, no key and no network** (a deterministic director that reads the words for mood / subject) — so the loop always works; wire your own model (cloud or on-device) into the same loop via `OGStageModel` / `OGStageAuthoring.resilient(...)` for richer movies. Thin orchestration, no new per-frame cost, same code on Android & iOS. See [**docs/STAGE.md**](docs/STAGE.md) and [**docs/AI_AUTHORING.md**](docs/AI_AUTHORING.md).
- **🔥🔍🎭 Fire, a glass lens & cut-out puppets** *(v1.48.0)* — three new primitives plus more wind. **`OGFlame`** (`com.solidkey.painpoints.fx`) is a data-defined body of fire — upward-licking tongues that wave with `OGFxNoise` and flicker over time, a hot-core → cool-tip gradient, four presets (`candle` / `campfire` / `torch` / `inferno`) and a prevailing `wind` you can drive from a scene's breeze; pure maths, no shader, frame-identical on both platforms. **`OGGlass`** (`com.solidkey.painpoints.glass`) lays a round, **draggable** look-behind-glass lens over any content — a magnifier (`zoom > 1`), a minifier (`zoom < 1`) or a coloured-glass tint — recording the content once into a `GraphicsLayer` and redrawing it scaled + clipped, its body pointer-transparent so you keep tapping underneath (an accessibility win as much as an effect). **`OGPuppet`** (`com.solidkey.painpoints.puppet`) is a data-defined **cut-out raster puppet** — a still base plus jointed movers that breathe, lean and *watch* a look target (with `headMirror` / `headLookInvert` for a one-sided vs symmetric head), authored by the Layer Cutter tool. Plus **`OGSnowflake`** is now a **recursive-fractal** crystal (a `depth` knob grows real dendrites), and **particles gained the cloth wind model** (`wind` + seeded `windAmplitude` / `windFrequency` / `windSeed` gusts) so cloth and particles blow as one breeze. OGStage gains two layer kinds to match — a wind-blown **`cloth`** strip and a frame-swappable raster **`image`** cutout. Zero dependency, 60fps, same code on Android & iOS. See [**docs/FLAME.md**](docs/FLAME.md) · [**docs/GLASS.md**](docs/GLASS.md) · [**docs/PUPPET.md**](docs/PUPPET.md) · [**docs/PARTICLES.md**](docs/PARTICLES.md) · [**docs/STAGE.md**](docs/STAGE.md).

*(📷 Live camera is the one effect without a GIF here — it needs a real device's camera (there's nothing to film on a headless emulator), so run the [demo](https://github.com/SolidKeyAB/kmpmedia-demo/releases) on a device to see it live.)*

Expand Down
86 changes: 86 additions & 0 deletions docs/COMPETITIVE_LANDSCAPE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# KMPMedia vs. the Field — Competitive Comparison (2025/2026)

> Research snapshot, Oct 2026. KMPMedia = `se.solidkey:kmpmedia-lib`: a zero-extra-dependency,
> pure-Compose (no custom shaders, no Skia-direct), data-defined, LLM-authorable KMP graphics/animation
> toolkit (Android + iOS via Compose Multiplatform). Below are the competitors a developer would
> realistically evaluate instead, with current versions / licenses / platform facts.

## 1. Capability matrix

Legend: ✅ first-class · ⚠️ partial / possible-with-work / caveat · ❌ not offered

| Capability | KMPMedia | Rive (+Rive-CMP) | Compottie | Lottie (Airbnb) | Skiko / Skia-direct | Haze | Konfetti / ConfettiKit | Spine | DragonBones | Compose built-in | Korge |
|---|---|---|---|---|---|---|---|---|---|---|---|
| KMP-native (iOS+Android, pure Kotlin) | ✅ | ⚠️ community wrapper | ✅ pure-Kotlin | ❌ Android-only | ✅ (is the engine) | ✅ | ⚠️ ConfettiKit ✅ / Konfetti Android | ⚠️ no CMP | ⚠️ no CMP | ⚠️ Android; CMP partial | ✅ engine |
| Skeletal / cut-out puppet rig | ✅ raster puppet | ✅ bones+meshes | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ best-in-class | ✅ | ❌ | ⚠️ plugins |
| Vector keyframe anim (AE/JSON) | ⚠️ stage timeline | ✅ own format | ✅ Lottie | ✅ Lottie | ⚠️ DIY | ❌ | ❌ | ⚠️ own | ⚠️ own | ⚠️ DIY | ⚠️ |
| Interactive state machines | ⚠️ tap triggers | ✅ signature | ❌ | ❌ | ❌ | ❌ | ❌ | ⚠️ events | ❌ | ⚠️ manual | ✅ |
| Particles | ✅ data-defined | ⚠️ in-editor | ❌ | ❌ | ⚠️ DIY | ❌ | ✅ confetti only | ❌ | ❌ | ⚠️ DIY | ✅ |
| Blur / glassmorphism | ❌ no true blur | ❌ | ❌ | ❌ | ✅ shader | ✅ specialty | ❌ | ❌ | ❌ | ⚠️ Android | ⚠️ |
| Custom shaders (SkSL/AGSL) | ❌ by design | ⚠️ own renderer | ❌ | ❌ | ✅ full | ✅ | ❌ | ❌ | ❌ | ⚠️ GL | ⚠️ |
| Action/anime FX (slash/lightning/speed-lines) | ✅ unique | ⚠️ hand-animate | ⚠️ | ⚠️ | ⚠️ DIY | ❌ | ❌ | ⚠️ | ⚠️ | ❌ | ⚠️ |
| Color grade / blend modes | ✅ ColorMatrix | ⚠️ in-editor | ⚠️ | ⚠️ | ✅ | ⚠️ tint | ❌ | ❌ | ❌ | ⚠️ | ⚠️ |
| Audio-reactive (FFT→visuals) | ✅ unique | ❌ | ❌ | ❌ | ⚠️ DIY | ❌ | ❌ | ❌ | ❌ | ⚠️ DIY | ⚠️ |
| Gesture interactivity (grab/pinch/twist + hit-test) | ✅ | ✅ pointer→SM | ⚠️ | ⚠️ | ⚠️ DIY | ❌ | ❌ | ⚠️ | ⚠️ | ⚠️ manual | ✅ |
| GIF/MP4 off-screen export | ✅ built-in | ⚠️ editor | ❌ | ❌ | ⚠️ DIY | ❌ | ❌ | ⚠️ editor | ⚠️ editor | ❌ | ⚠️ |
| LLM / data-authorable (JSON) | ✅ core thesis | ⚠️ .riv binary | ✅ consumes JSON | ✅ consumes JSON | ❌ | ❌ | ⚠️ config | ❌ binary | ❌ binary | ❌ | ❌ |
| Needs external design tool | ✅ none (Layer Cutter optional) | ❌ Editor | ❌ After Effects | ❌ After Effects | ✅ none | ✅ none | ✅ none | ❌ Spine | ❌ tool | ✅ none | ⚠️ plugin |
| License | **MIT** | MIT runtime (Editor closed) | MIT | Apache-2.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 / MIT | commercial ($69+) | MIT (tool abandoned) | Apache-2.0 | Apache-2.0 |

## 2. Per-competitor profiles

**Rive (+ Rive-CMP).** Interactive state-machine 2D animation with its own vector editor (bones, meshes, IK, pointer-driven state machines). Runtimes/renderer/format MIT; the **Editor is closed-source** (free tier generous; OpenRive is an MIT community editor). Official runtimes: android/ios/web/C++ — **no official Compose Multiplatform runtime**; `dev.muazkadan:rive-cmp` (community, ~v0.2.1 Dec 2025) bridges the native runtimes. Beats us on the **visual state-machine editor + designer-driven interactivity**. <https://github.com/rive-app/rive-runtime> · <https://github.com/muazkadan/Rive-CMP>

**Lottie (Airbnb) / lottie-compose.** After Effects → Bodymovin JSON vector playback. Apache-2.0, ~6.7.1 (Oct 2025), **Android-only — Airbnb do not support KMP/CMP**. Massive designer ecosystem (LottieFiles). <https://central.sonatype.com/artifact/com.airbnb.android/lottie-compose>

**Compottie.** `io.github.alexzhirkevich:compottie`, **MIT**, ~2.3.3 (2026). A **pure-Kotlin Lottie renderer** (no native bridge) for CMP — Android/iOS/JVM/macOS/Web. Strongest KMP-native vector-animation competitor, but confined to the Lottie format + needs AE to author. <https://github.com/alexzhirkevich/compottie>

**Skiko / Skia-direct.** The engine Compose MP renders on (Metal on iOS). Gives raw **RuntimeShader/SkSL** (AGSL on Android), path ops, true blur/bloom — everything we deliberately forgo. Apache-2.0. The floor you drop to for real shaders. <https://en.wikipedia.org/wiki/Skia_Graphics_Engine>

**Haze (Chris Banes).** Specialty **background blur / glassmorphism** for CMP (Android/iOS/macOS/Desktop/Web). Apache-2.0, **2.0 (Sep 2026)** — split `hazeBlur`/`hazeGlass`, hardware-accelerated. Fills our missing blur/glass. <https://chrisbanes.me/posts/haze-2.0.0/>

**Konfetti / ConfettiKit.** Konfetti (`nl.dionsegijn`, Apache-2.0, ~2.0.5) = classic **Android** confetti. **ConfettiKit** (`io.github.vinceglb`, ~0.8.0 Feb 2026) = KMP/CMP port. Confetti only — a narrow subset of our particle pack. <https://github.com/vinceglb/ConfettiKit>

**Spine (Esoteric Software).** Industry-standard **2D skeletal animation** (bones, meshes, IK) + commercial editor (Essential $69 / Pro $299); runtime license requires users to own Spine to redistribute (updated Apr 2025). Broad engine runtimes, **no CMP runtime**. Gold standard for rigging — far deeper than our raster puppet, but paid + tool-bound. <https://en.esotericsoftware.com/spine-runtimes-license>

**DragonBones.** Free, **MIT** 2D skeletal tool; desktop editor effectively **abandoned**, runtimes live on GitHub, no CMP runtime. Free puppet alternative to Spine but stagnant. <https://github.com/openfl/dragonbones>

**Telegram rlottie.** Standalone **C++** Lottie renderer (Samsung/Telegram). Mixed licensing (LGPL-2.1 / MIT-with-bundled). Fast, but C++/native, no Kotlin/CMP API. <https://github.com/Samsung/rlottie>

**Jetpack Compose built-in animation.** `animate*AsState`, `Animatable`, `Transition`, `AnimatedVisibility` — Apache-2.0, the baseline. Great for property/UI tweening; **no particles, FX, puppets, color-grade, export, or authoring format**. <https://developer.android.com/develop/ui/compose/animation/value-based>

**Honorable mentions.** Orbital (skydoves, shared-element transitions, CMP), compose-shimmer (`com.valentinilk.shimmer`, ~1.4.0) — narrow single-effect libs, little overlap. **Korge** (~6.0.0, May 2025, Apache-2.0) — full KMP **game engine**; an alternative only if you're building a game, not UI animation.

## 3. KMPMedia's genuine differentiators

1. **Data / LLM-authorable by design** — every pack is a JSON spec a model can emit (describe→movie, stage docs). No competitor's *authoring* story is LLM-first; Compottie only *consumes* model-friendly JSON, can't generate its own feature set from prose.
2. **Breadth in one pure-Kotlin KMP artifact** — the field is fragmented (Haze=blur, ConfettiKit=confetti, Compottie=vector, Rive/Spine=rigs, Skiko=shaders). We bundle styles, particles, FX, looks, motion, dynamics, audio-reactive, gesture, camera, stage+export, puppet, fog, light/shadow, skin behind one dependency.
3. **No external tool, no native/shader dependency** — zero extra deps, no Editor subscription (Rive/Spine), no NDK/C++ bridge (rlottie, Rive-CMP), no AE license. Layer Cutter is a free web tool, not a paywall.
4. **Cross-platform pixel-identical + 60fps fixed-capacity sims** — staying in pure Compose avoids the platform-shader divergence Rive-CMP (per-platform native runtimes) and Haze (platform render effects) inherently carry.
5. **Audio-reactive vectors** — essentially unique among Compose/KMP UI libraries.

## 4. Honest gaps

- **No visual editor / designer ecosystem** — Rive's state-machine editor, Spine's rigging tool, LottieFiles' marketplace are each a moat we don't match. Decisive for designer-driven teams.
- **No true blur/bloom/custom shaders** — the no-shader rule means Haze (glass/blur) and Skiko (SkSL) beat us for glassmorphism / gaussian bloom / arbitrary pixel FX.
- **Puppet is raster cut-out, not true skeletal** — Spine/DragonBones/Rive offer bones + mesh deform + IK; ours is jointed PNG movers (lighter, less expressive).
- **Not the AE/Lottie standard** — for importing existing motion-design assets, Compottie/Lottie win outright (huge existing content library).
- **Interactivity is tap-triggers, not a full state machine** — Rive wins on branching interactive logic.

## 5. When to reach for which

- Designer owns the animation + branching interactivity → **Rive**.
- Importing After Effects motion design into KMP → **Compottie** (Lottie if Android-only).
- Just background blur / frosted glass → **Haze**.
- Just confetti → **ConfettiKit** (KMP) / **Konfetti** (Android).
- Deep 2D character rigging → **Spine** (paid, best) / **DragonBones** (free, abandoned).
- Custom shaders / true bloom / bespoke pixel FX → **Skiko/SkSL** (+ Haze for blur).
- Shipping a game, not UI → **Korge**.
- Simple property/UI transitions → **Compose built-in**.
- One KMP dependency doing FX + particles + motion + puppet + stage/export, authored from JSON / by an LLM, pixel-identical on iOS+Android, no editor or shaders → **KMPMedia** — the only combination the rest of the field can't assemble from a single library.

## Note / to verify
- **KMPMedia's own license** — **MIT** (© 2025 Özge Güner / SolidKey AB), per the repo `LICENSE`. So KMPMedia is the *only* all-in-one here that's both MIT-licensed AND KMP-native with no editor/shaders — Spine is paid, Rive's editor is closed, and the rest are single-purpose.
- **rlottie licensing** is genuinely mixed across forks (LGPL-2.1 vs MIT-with-bundled) — verify per fork.
- **Rive CMP** — only the community Rive-CMP wrapper exists as of these sources; Rive has signaled interest in a first-party CMP runtime — recheck.
- Context: Compose Multiplatform for iOS went **Stable in 1.8.0 (May 2025)**, underpinning every "KMP-native on iOS" claim.
Loading
Loading