# Gum Tool Animations

> Gum Tool Animations

- Skill: `vchelaru/gum-tool-animations` (Agent Skill)
- Install (CLI): `npx skillmds@latest add vchelaru/gum-tool-animations`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vchelaru/gum-tool-animations/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: vchelaru (https://skillmd.com/u/vchelaru)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vchelaru/gum-tool-animations

---


# Gum Tool Animations

State-based animation authoring in the **editor**: timeline animations that interpolate
between named **States** over time. NOT the same as runtime AnimationChains (see Landmines).

## Where it lives
- Split like the editor tab (phase 80 of the Avalonia migration): the neutral
  `Tool/StateAnimationPlugin.Core` (net10.0) holds `StateAnimationPluginBase` (all event wiring,
  menu, tab, undo, delete option), the load/save and settings managers, the shared list hotkeys
  (`AnimationTabKeyHandler`), and the timeline math (`Timeline/TimelineLayout`,
  `InterpolationCurve`). Each head derives the exported plugin: WPF `MainStateAnimationPlugin`
  (`Gum/StateAnimationPlugin/`, views `Views/MainWindow.xaml`, `Timeline.xaml`, `StateView.xaml`)
  and Avalonia `AvaloniaStateAnimationPlugin` (`Tool/Gum.Avalonia/Plugins/StateAnimation/`, whose
  `TimelineView` draws natively in `Render`). A behavior change to the tab belongs in the core, not
  in either view. Tab is hidden until View ▸ View Animations.
- VMs (in Gum.Presentation): `ElementAnimationsViewModel` → `AnimationViewModel` →
  `AnimatedKeyframeViewModel`; the business logic is `AnimationTabController`.

## Data model & serialization
- Persisted as a **per-element `.ganx` sidecar**: `<ElementName>Animations.ganx` next to
  the element's `.gucx/.gusx` (path: `Managers/AnimationFilePathService.cs`). NOT embedded
  in the element file or `.gumx`. Load/save: `Managers/AnimationCollectionViewModelManager.cs`.
- Save classes live in `GumDataTypes/SaveClasses/*`, namespace `Gum.StateAnimation.SaveClasses`.
  `ElementAnimationsSave` → `List<AnimationSave>`; each `AnimationSave` holds **three parallel
  keyframe lists**: state keyframes, sub-animation refs, named events.
- A state keyframe binds to a state **by name string**, `"Category/State"` convention
  (uncategorized = no slash). Resolution: `AnimationViewModel.GetStateFromCategorizedName`.
- Keyframes are **cumulative** — each combines with prior ones; preview rebuilds via
  `RefreshCumulativeStates`.

## Named events — FRB-only
"Add Named Event" authors a `NamedEventSave` (name + time). It round-trips to `.ganx`, but
**Gum's own runtime never dispatches it** — only FlatRedBall consumes named events. Skip in
non-FRB docs.

## Runtime relationship (do NOT conflate)
- **State animations (this skill)** — `.ganx`, interpolate between states. Runtime driver:
  `GumCommon/Runtime/AnimationController.cs` + `AnimationRuntime.cs` (undocumented elsewhere).
- **AnimationChains** — `.achx`, sprite-sheet flipbook on Sprite/NineSlice; see
  [[gum-runtime-animation-chains]]. **Different concept, different file, different runtime.**

## Landmines
- **"Keyframe" is a union of 3 things.** `AnimatedKeyframeViewModel` is a state keyframe OR
  sub-animation ref OR named event, discriminated by which string is non-empty (StateName →
  state, else AnimationName → sub-anim, else event). No type enum; fans out into 3 lists on save.
- **Misleading names on `AnimationSave`.** `States` = state *keyframes* (not element states);
  `Animations` = sub-animation *keyframes* (not child animations).
- **Interpolation types come from a NuGet package, not Gum.** `InterpolationType`/`Easing`
  (state keyframes only) are `FlatRedBall.Glue.StateInterpolation` types from the standalone
  **`FlatRedBall.InterpolationCore`** package — an easing/tweening library under the FlatRedBall
  brand, NOT the FRB engine. The animation data model serializes these into `.ganx`.
- **Sidecar must follow the element.** Element rename/duplicate/delete must move the `.ganx`;
  wired via RenameManager/DuplicateService/ElementDeleteService in `AssignEvents`.
- **Save is whitelist-filtered.** `HandleDataChange` only re-saves on specific property
  changes; a new persisted keyframe field won't save unless added there.

## Docs
User-facing content today is a 4-part tutorial under
`docs/gum-tool/tutorials-and-examples/animation-tutorials/`. Issue #480 wants a *reference*
section on the Animations tab itself (data model, named events, the tab UI), not tutorial-style.

