Skip to content

fix(studio): keep GSAP timeline clips stable#540

Merged
miguel-heygen merged 1 commit intomainfrom
fix/studio-gsap-clip-offset
Apr 28, 2026
Merged

fix(studio): keep GSAP timeline clips stable#540
miguel-heygen merged 1 commit intomainfrom
fix/studio-gsap-clip-offset

Conversation

@miguel-heygen
Copy link
Copy Markdown
Collaborator

@miguel-heygen miguel-heygen commented Apr 28, 2026

Problem

Studio timeline clips backed by GSAP timeline metadata could appear to drift while playback advanced. The clip range itself was stable, but the runtime metadata lookup used the timeline-local playhead instead of clip-local time.

What this fixes

  • Keeps GSAP timeline clip metadata pinned to the actual composition element range.
  • Adds regression coverage proving clip metadata is resolved from the child timeline duration instead of advancing with the parent playhead.

Root cause

getTimelineMetadata() was called with the parent timeline playhead for nested GSAP child timelines. That meant the metadata fallback could resolve against the wrong point in the child timeline, so Studio rendered ranges as if they were moving forward during playback.

Verification

Local

  • bun run --filter @hyperframes/core test src/runtime/timeline.test.ts
  • bunx oxlint packages/core/src/runtime/timeline.ts packages/core/src/runtime/timeline.test.ts
  • bunx oxfmt --check packages/core/src/runtime/timeline.ts packages/core/src/runtime/timeline.test.ts
  • bun run --filter @hyperframes/core typecheck

Browser

  • Previewed hf-designer-talk in Studio at http://localhost:5190/?project=hf-designer-talk&record=1#project/hf-designer-talk.
  • Recorded playback and confirmed clip left / width values stayed fixed while the playhead advanced.

Notes

Follow-up timeline pinch zoom and ruler display work is split into a stacked PR on top of this branch.

Copy link
Copy Markdown
Collaborator

@jrusso1020 jrusso1020 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — small, surgical, and provably correct.

The bug is exactly as described: tween.startTime() is parent-relative, so the climb summing parents converts to absolute. The previous loop kept climbing past the master, adding masterTimeline.startTime() (which moves with the gsap globalTimeline as playback proceeds), so every derived clip drifted forward by the current playback offset. Stopping at parent !== masterTimeline is the right tree-walk semantics — the master is the time-frame the function reports relative to, so its own startTime shouldn't be summed in.

Type tightening (parent?: GsapTween with recursive parent) is a nice cleanup that makes the intent obvious.

Symmetric proof I ran: checked out the fix branch, reverted only timeline.ts while keeping the new tests, ran the suite. Both new tests fail red:

  • "does not offset GSAP scene clips by the master timeline start time" ✗
  • "keeps nested GSAP timeline offsets below the master timeline" ✗

Restoring the fix → 551/551 pass. So the tests genuinely cover the bug.

Scoped audit: tween.parent / parent.startTime only appears in this one walk in runtime/timeline.ts. No sister GSAP-introspection paths suffer from the same parent-chain inclusion bug.

— Review by Rames Jusso

@miguel-heygen miguel-heygen merged commit 0a542f8 into main Apr 28, 2026
81 of 89 checks passed
@miguel-heygen miguel-heygen deleted the fix/studio-gsap-clip-offset branch April 28, 2026 22:09
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.

2 participants