Skip to content

fix: stop Replay3DModel self-advancing frames when the parent drives them#915

Open
Anexus5919 wants to merge 1 commit into
Somil450:mainfrom
Anexus5919:fix/replay-single-frame-driver
Open

fix: stop Replay3DModel self-advancing frames when the parent drives them#915
Anexus5919 wants to merge 1 commit into
Somil450:mainfrom
Anexus5919:fix/replay-single-frame-driver

Conversation

@Anexus5919

Copy link
Copy Markdown
Contributor

📌 Related Issue

Fixes #878


📝 Description

While the replay played, two drivers advanced the same currentFrameIdx: ReplayScreen's 66ms setInterval (about 15fps, stops at the last frame) and Replay3DModel's render loop (about 8fps, wraps around) via onFrameChange. They competed, so playback ran faster and more erratically than intended, with contradictory end behaviour (one stops, the other loops).

🔹 What has been changed?

  • src/components/Replay3DModel.tsx: Replay3DModel now self-advances frames only when the frame index is uncontrolled (isFrameControlled = externalFrameIdx !== undefined). When a parent controls the frame index, the render loop renders the parent's currentFrameIdx directly, so the parent (ReplayScreen's interval) is the single driver. The flag is also added to the render-loop effect's dependency list.

🔹 Why are these changes needed?

  • Two independent drivers mutating the same frame index produce erratic playback speed and conflicting end-of-clip behaviour. Making Replay3DModel a pure renderer when controlled preserves ReplayScreen's intended 15fps + stop-at-end behaviour, and keeps Replay3DModel self-driving when it is used standalone.

🛠️ Type of Change

  • 🐛 Bug Fix

🧪 Testing

✅ Tests Performed

  • Tested locally
  • npx tsc --noEmit: Replay3DModel.tsx clean (the only pre-existing tsc errors are in exerciseEngine.ts, unrelated).
  • npx eslint src/components/Replay3DModel.tsx: 0 problems, including no react-hooks/exhaustive-deps warning (the new flag is in the dependency list).
  • Traced the controlled vs uncontrolled paths: when controlled, the loop neither advances frameFloatRef nor calls setCurrentFrameIdx, and renders the parent's currentFrameIdx.

🔹 Note on automated tests

No runtime unit test: Replay3DModel is a Three.js/WebGL component that does not run under the vitest/jsdom environment. Verification is by tsc, eslint, and the path review above.

🌐 Browsers Tested

Not applicable (playback timing/lifecycle).


📷 Screenshots / Demo (if applicable)

Not applicable.


📋 Checklist

  • I have read the project's CONTRIBUTING guidelines
  • My code follows the project style guidelines
  • I have performed a self-review of my code
  • I have tested my changes locally
  • I have added/updated documentation where necessary (not applicable)
  • My changes do not introduce new warnings or errors
  • This PR is linked to an existing issue

💬 Additional Notes

Branched from latest upstream/main (5464425). This touches Replay3DModel.tsx, as do a few other replay PRs (#906, #907, and #879); they change different lines and are independently mergeable, with at most a trivial rebase for whichever lands later.

@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

@Anexus5919 is attempting to deploy a commit to the somiljain2024-4175's projects Team on Vercel.

A member of the Team first needs to authorize it.

@Anexus5919

Copy link
Copy Markdown
Contributor Author

@Somil450 @diksha78dev Kindly have a review on this pr. Thanks!

…them

When a parent passes currentFrameIdx (ReplayScreen, which runs its own
setInterval to advance frames), Replay3DModel's render loop also advanced
the frame via onFrameChange. Two drivers then fought over the same index
at different rates, with conflicting end behaviour (the interval stops at
the last frame, the render loop wraps around).

Only self-advance when the frame index is uncontrolled. When controlled,
render the parent's currentFrameIdx directly so the parent is the single
frame driver.
@Anexus5919 Anexus5919 force-pushed the fix/replay-single-frame-driver branch from febee32 to 4633bab Compare June 23, 2026 17:34
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.

Replay plays via two competing frame drivers (ReplayScreen interval + Replay3DModel render loop)

1 participant