Skip to content

feat: animation window v1 (local transform animator with easing graph) - #26

Merged
AlexZ005 merged 18 commits into
mainfrom
feature/animation-tab
Jul 19, 2026
Merged

feat: animation window v1 (local transform animator with easing graph)#26
AlexZ005 merged 18 commits into
mainfrom
feature/animation-tab

Conversation

@AlexZ005

Copy link
Copy Markdown
Collaborator

Adds a local-only Animation window for authoring and previewing per-object transform movements, opened from the Flow + add-view menu. This is the second, isolated PR planned after the beta -> main release (PR #25).

What it does

  • Floating window (tab-groups with Flow, tears off to detach) targeting the current selection.
  • Left — movement tracks (layers): each animates one transform channel (Position X/Y/Z, Rotation X/Y/Z, Scale).
  • Centre — a cubic-bezier easing-curve editor with two draggable control dots (the "speed graph", After Effects style) plus presets (linear / ease / ease-in / ease-out / ease-in-out).
  • Right — selected-track properties (channel, from/to) + duration + loop mode (loop / once / ping-pong).
  • Transport — play / pause / stop + a scrubber. Stop restores the pose captured at Play.

Design

  • src/lib/animationPreview.js runtime drives the object per frame from Scene's useTask, coordinating with flowRuntime (suspend/resume) so it never fights a flow-driven object.
  • src/components/editors/AnimationWindow.svelte mirrors the FlowCode window scaffolding (dragWindow / focusStack / tabbable).
  • Local-only and no layer blending in v1 (deliberate scope): the authored animation lives in a local store, so it never enters peer sync or the golden-rule broadcast path.

Deliberately deferred (a later batch)

  • Persistence across reload (authored animation is currently in-memory).
  • Peer sync / sharing of authored clips.
  • Layer blending.
  • Integration with imported GLTF clip play/pause (already handled by animatedImports).

Verification

  • npm run build green; npx svelte-check holds the baseline (502 errors / 77 warnings).
  • e2e animation-window (10/10): easing math, window renders for the selection, track list, Play drives the object, Stop restores the base pose, local-only (store, not userData).

AlexZ005 and others added 18 commits July 18, 2026 20:59
- new floating Animation window (mirrors FlowCode: dragWindow/focusStack/
  tabbable) opened from the Flow + add-view menu; targets the current selection
- left = movement tracks (one transform channel each: position/rotation/scale),
  centre = a cubic-bezier easing curve editor with draggable control dots (the
  speed graph), right = selected-track properties + easing presets + duration/loop
- animationPreview.js: local-only runtime; play/pause/stop/scrub drive the object
  per frame from Scene useTask, coordinating with flowRuntime suspend/resume;
  Stop restores the pose captured at Play
- NOT replicated and no layer blending in v1 (deliberate scope) so it never enters
  peer sync or the golden-rule broadcast path; persistence + sharing are a later batch
- e2e animation-window: easing math, window renders for the selection, track list,
  Play drives the object, Stop restores base, local-only (store not userData)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Scene/Object settings (Inspector drawer): the header with the X close button
  is now sticky so it stays visible while the panel scrolls instead of scrolling
  away; the drawer drops its top padding so the pinned header sits flush with no
  content peeking above it
- on narrow screens the drawer now insets above the Controls pill/HUD footprint
  (new --controls-inset, sized per the <=820 and <=600 reflows) the same way it
  already insets above an open docked panel (--bottom-inset), so Controls no
  longer covers the settings view

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- touch has no HTML5 drag-and-drop, so dragging a node from the palette did
  nothing on mobile (only tap-to-add worked). A horizontal-dominant touch drag
  now drags a ghost of the node onto the canvas and drops it at the finger
  position (Sidebar onPlaceAt -> Nodes screenToFlowPosition + addNode)
- vertical swipes still scroll the palette (touch-action: pan-y); a plain tap
  still adds at the pane centre; desktop keeps native HTML5 drag unchanged
- extend flow-palette-touch e2e with the drag-to-place case

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the Scene/Object settings drawer shared the mic/chat/+ z tier (--z-drawer=30)
  so the mic button painted over it on the bottom-right; raise the drawer to
  just under the dock (calc(--z-bottom - 1)) so it is never covered by the mic,
  while staying below the dock and floating windows

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the bottom dock now shows ONE panel at a time. Node editor, Flow Code and
  Animation are notebook TABS in a shared dock (DockTabs); each starts docked
  and has an undock button that floats it into a resizable window
- Flow Code + Animation gained docked+floating dual mode (mirroring the Node
  editor); the docked Flow Code shows its Apply + Reload buttons in the toolbar
- Explorer is a separate, mutually EXCLUSIVE dock panel: activating any Flow
  tab closes the Explorer, and the Explorer shows no tab strip of its own
- bottomDock.js reworked: single visible panel (visibleDockKey), flow-family
  tabs (flowTabs), shared dockHeight, activateDock() enforces the exclusivity
- Controls Node editor / Explorer buttons drive the new activate/close model
- undocked Flow Code + Animation windows are corner-resizable like the object list
- e2e: new flow-dock-tabs (tabs + Apply-in-dock + undock resize); updated
  flow-explorer-dock (exclusivity), flow-code + animation-window (docked tab)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-left

- the floating Node editor / Flow Code / Animation / Explorer windows drove
  width+height through a reactive style=... attribute. Re-rendering it (on a
  resize, or a tab-group move) REPLACED the whole inline style and wiped the
  left/top that dragWindow and windowTabs set imperatively, so the window snapped
  to the top-left while a grouped window left its tab strip behind
- drive size via style:width / style:height DIRECTIVES instead: they set only
  those properties and leave left/top intact (matches how the Object List, which
  never had the bug, sizes itself)
- e2e: flow-dock-tabs asserts a resize keeps the window position; new
  window-tabs-move asserts a grouped window stays under its tab strip when moved

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- grouped windows share one rect, but a corner-grip resize only changed the
  active member size; the other tabs synced only on the next tab switch
- windowTabs.resizeGroup(key,w,h) updates the shared group rect + re-applies it
  to every member; each floating window (Node editor / Flow Code / Animation /
  Explorer) calls it on resize AND displays the group rect while grouped
  (effW/effH), so a resize on any tab shows on all of them live
- e2e window-tabs-move: resizing a grouped window resizes every tab

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the Explorer and the Flow-family share ONE dock slot, so a DOCKED Node editor
  taking the dock closes the Explorer. But activateDock closed it for ANY
  Flow-family activation, including when the Node editor was FLOATING (which does
  not compete for the dock)
- move the close to a reactive rule: close the Explorer only when a Flow-family
  panel actually becomes the VISIBLE dock panel (i.e. it is docked). A floating
  Node editor never becomes the visible dock key, so a docked Explorer is left
  alone. Closing happens only when BOTH are docked.
- e2e dock-float-exclusivity: a floating flow keeps the Explorer; docking it closes it

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n show/hide

- the Node editor / Explorer toolbar icons went dark whenever the panel was a
  FLOATING window (the highlight only tracked the docked occupant). They now tint
  whenever the panel is shown at all -- as the visible dock tab OR as a floating
  window
- clicking a toolbar button now simply shows its panel (in whatever mode it is,
  docked tab or floating window) or hides it if already shown; docking/undocking
  stays on each panel header. A floating Node editor no longer disturbs a docked
  Explorer (it just hides itself)
- e2e dock-float-exclusivity: both a floating Node editor and a docked Explorer
  read as highlighted; clicking a shown floating panel hides it

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- a tab-grouped window has its header covered by the tab strip, so Flow Code lost
  its Apply + Reload buttons (they lived in the drag header) once grouped
- move the actions into the CONTENT (a toolbar row below the header), so they show
  in every mode: docked, floating, and floating+grouped
- e2e window-tabs-move: a grouped Flow Code shows its Apply button below the strip

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lick

- when the Object List is tab-grouped its dragMe handler now defers geometry to
  the group: moving/resizing drives the shared group (moveGroupOf / resizeGroup)
  so its size matches the tab strip and the strip follows the window instead of
  staying behind while the window moves
- clicking the Object List toolbar button now RAISES the floating window to the
  front (bring-to-front); clicking again while it is already at the front closes it
- windowFocus gains raiseWindow(key) / isTopWindow(key) + an optional key on
  focusStack; windowTabs gains moveGroupOf(key, dx, dy)
- e2e object-list-raise

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…w when grouped

- the buttons previously always lived in a content row; now they sit in the header
  when the window is floating (ungrouped) or docked, and only move to a content row
  when the window is tab-grouped (where the strip covers the header)
- e2e flow-dock-tabs: ungrouped floating Flow Code shows Apply in its header

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the docked Animation container set no text colour, so its native select/option
  items inherited a dark colour and were unreadable; the floating window got the
  light colour from ui-panel. Give the dock container matching text colours
  (gray-800 light theme / gray-200 dark) so dropdown items read correctly docked
- e2e animation-window: the docked dropdown text is light

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…a floating Explorer alone

- when the docked flow group is shown, clicking Node editor now hides ALL of its
  tabs (Node editor + Flow Code + Animation), remembering which were open, and
  clicking again restores them. Before it closed only the Node editor tab, so the
  dock stayed up showing the other tabs
- a shown floating Node editor still just hides itself; neither showing nor hiding
  it closes a floating Explorer (they do not share the dock)
- e2e: flow-dock-toggle (whole-group show/hide) + flow-explorer-floating

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ow Code/Animation

- when hiding the docked flow group, close only the tabs that are actually docked;
  an undocked (floating) Flow Code / Animation window stays open (the Node editor
  button controls the dock, not those separate floating windows)
- e2e flow-dock-mixed: Node editor docked + Flow Code floating -> clicking Node
  editor hides the docked Node editor and leaves the floating Flow Code open

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the Node editor button now branches on the Node editor's OWN mode: when it is a
  FLOATING window the button only shows/hides that window; when DOCKED it toggles the
  docked flow group. Previously a floating Node editor alongside a docked Flow Code /
  Animation would hide the docked group instead of the Node editor window
- e2e flow-node-undocked: Node editor floating + Flow Code docked -> clicking Node
  editor hides only the floating Node editor, the docked Flow Code stays visible

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the Object List floating window was capped at max-width:50% / max-height:70% (a
  CSS cap the Node editor and other floating windows do not have), and its dragMe
  clamps used 0.9/0.85 of the viewport. Remove the CSS cap and raise the clamps to
  the viewport (innerWidth-8 / innerHeight) so it can grow as large as the Node editor
- this also fixes the tab-group bug: a grouped Object List no longer renders smaller
  than its shared group rect (the 50% cap limited the rendered size while the strip
  and the other members used the full width)
- e2e object-list-size

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- the tab strip was pinned at z-index 44 (top of the window band), so another
  floating window dragged in front of a tab group still had the group's strip
  painted on top of everything. The strip now takes its group active-member z
  (recomputed on a focusTick bump), so a raised window covers the strip like any
  other window
- grabbing the strip or clicking a tab also raises its group to the front
  (windowFocus raiseWindowNode)
- e2e tab-strip-zorder

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@AlexZ005
AlexZ005 merged commit 6c691f0 into main Jul 19, 2026
@AlexZ005
AlexZ005 deleted the feature/animation-tab branch August 5, 2026 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant