feat(studio): GSAP keyframe + motion-path editing#1567
Open
miguel-heygen wants to merge 2 commits into
Open
Conversation
e347d3a to
07a6321
Compare
e450a92 to
eb1c51f
Compare
cd33fda to
12707a3
Compare
a01743d to
1dbedb6
Compare
12707a3 to
8bf425e
Compare
1dbedb6 to
6aafc8a
Compare
8bf425e to
231bf67
Compare
6aafc8a to
d133735
Compare
231bf67 to
6b3aa33
Compare
Consolidates the studio side of the GSAP keyframe/motion-path work into one
PR: runtime read layer + shared helpers, drag/commit/bridge editing infra,
motion-path geometry + commit helpers, on-canvas motion-path overlay, and the
keyframes flag with gesture recording + timeline/selection refinements.
Makes "Add keyframe at playhead" do the right thing for every GSAP animation
shape, never disabling or silently no-oping:
- Array-form keyframe tweens (keyframes: [{x,y},…]): readElementPosition now
derives the captured props from the keyframe stops (top-level properties is
empty for array form), and the percentage uses the tween range, not the clip
range — so the add lands at the right spot instead of no-oping.
- Out of the tween range, the action extends the tween to reach the playhead
and adds a hold there, rescaling existing keyframes to keep their absolute
timing (was: disabled / destructive).
- Flat tweens (to/from/fromTo) convert to their natural keyframes, then take
the same add/extend path.
- set() is promoted to a two-stop tween from the set's time to the playhead.
- motionPath/arc tweens add a waypoint at the on-path position (matching
segment, so the curve is preserved) instead of being linearized; outside the
range they extend their duration, with a merge threshold against duplicates.
Also fixes deep-link hydration. A URL with ?t=…&selId=… restored neither the
playhead nor the selection on a fresh load: useStudioUrlState requests the seek
before the player runtime mounts its requestedSeekTime subscription, so the
request never reached pendingSeekRef, and initializeAdapter (which drained only
pendingSeekRef when the adapter became ready) started at 0 — which also blocked
selection hydration (gated on the seek settling). Fixed at the source:
initializeAdapter now reconciles the store's requestedSeekTime as well, so a seek
requested any time before the adapter is ready lands deterministically.
Supersedes the separately-reviewed studio PRs #1557, #1558, #1559, #1560, #1561.
…eline Dragging or rotating an element writes into the GSAP timeline (the single source of truth) instead of a parallel --hf-studio-offset / --hf-studio-rotation CSS var: static elements commit a tl.set (idempotent on re-edit), tweened elements edit keyframes, and the live preview moves via gsap.set so what you see equals what is written and renders. Removes the dual-channel CSS-var/transform reconciliation behind the fling / disappear / runaway / double-stack / wrong-start bug class — for BOTH position and rotation (gesture base read from the gsap transform, gsap.set live preview, tl.set/ keyframe commit, dropped the handleDom*Commit CSS fallbacks). Subcompositions edit the same single-source way, which surfaced and fixes: - resolve a subcomp element's source file via the composition-id map (the runtime drops the source linkage when inlining the subcomposition); - a selected element's selection box AND motion path use basic visibility, not the occlusion heuristic (a backgroundless opacity-1 scene above it is not an opaque cover); - soft reload rebuilds ONLY the committed composition's timeline, leaving other compositions' timelines intact (no cross-composition revert); - read keyframes from the element's OWN composition timeline (scan all timelines, not the first unstable key); - delete-all uses a soft reload too, so editing no longer hard-reloads the iframe.
d133735 to
b79f553
Compare
6b3aa33 to
b2b2e98
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidates the studio side of the GSAP keyframe/motion-path work into a single reviewable PR. The combined diff is byte-identical to the previously-reviewed studio stack.
What's here
Context
Supersedes the separately-reviewed (and already-approved) studio PRs #1557, #1558, #1559, #1560, #1561, which were consolidated here so the studio work has a single mergeable path to main. The keyframes CLI command + skill remain isolated in their own PR (#1556) on top of this one.
Single-source manual offset + rotation + subcomposition editing (added)
Dragging or rotating an element writes into the GSAP timeline (single source of truth) instead of a parallel
--hf-studio-offset/--hf-studio-rotationCSS var: static elements commit atl.set(idempotent on re-edit), tweened elements edit keyframes, live preview moves viagsap.set. What you see = what is written = what renders. Removes the dual-channel reconciliation behind the fling / disappear / runaway / double-stack / wrong-start bugs — for both position and rotation.Editing elements inside subcompositions works the same way, which surfaced and fixes:
opacity:1scene above an element is not an opaque cover).