Skip to content

fix(editor): restore scene auto-framing on load - #766

Open
ActArtech wants to merge 4 commits into
pascalorg:mainfrom
ActArtech:fix/camera-framing-main
Open

fix(editor): restore scene auto-framing on load#766
ActArtech wants to merge 4 commits into
pascalorg:mainfrom
ActArtech:fix/camera-framing-main

Conversation

@ActArtech

@ActArtech ActArtech commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Restores scene auto-framing on load and stops the level-follow effect from clobbering the framed camera pose.

  • Mount useAutoFrame() in EditorContent again (it was dropped in an earlier refactor)
  • On viewer scene-ready, re-emit camera-controls:fit-scene so fast client navigations keep the framed pose
  • Level-follow: skip the initial null→level transition; only apply the default look-at when the scene graph is empty
  • Expose window.__pascalCameraControls without a NODE_ENV gate (client Turbopack leaves process undefined)

How to test

  1. bun test packages/editor/src/hooks/use-auto-frame.wiring.test.ts — all pass
  2. bun run check packages/editor/src/hooks/use-auto-frame.wiring.test.ts packages/editor/src/components/editor/custom-camera-controls.tsx packages/editor/src/components/editor/index.tsx
  3. Optional smoke with bun dev: open a non-empty scene and confirm the camera frames the content instead of a black / default distant pose

Screenshots / screen recording

N/A for the unit path (wiring + controls). Optional recording of load framing welcome if reviewers want visual proof.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

Note

Medium Risk
Changes load-time and level-switch camera orchestration; regressions could show wrong framing or unexpected pans, but scope is editor viewport behavior only.

Overview
Restores automatic camera framing when a scene loads and stops the level-follow camera logic from overriding that framed pose on fast client navigations.

EditorContent mounts useAutoFrame() again and, once the viewer reports scene-ready, re-emits camera-controls:fit-scene with XZ bounds from computeSceneBoundsXZ so framing wins after other load-time camera effects.

In CustomCameraControls, the level-follow effect now tracks prior level id and levelMode, applies the default setLookAt(20,20,20…) only on first load when the scene graph is empty, and pans vertically on later level or mode changes. window.__pascalCameraControls is always exposed (no NODE_ENV gate) because Turbopack can leave process undefined in aliased packages.

Adds use-auto-frame.wiring.test.ts to lock in these integration points via source assertions.

Reviewed by Cursor Bugbot for commit 38f224f. Bugbot is set up for automated code reviews on this repo. Configure here.

ActArtech and others added 2 commits September 6, 2026 15:21
…obbering it

useAutoFrame was accidentally removed in e688792, so nothing emitted camera-controls:fit-scene on load; the level-follow effect's first-run default pose then reset the camera after framing on fast client-side navigations. Restore the hook, gate the default pose to scene-less editors, skip the initial null->level transition, and re-emit fit-scene once the viewer signals scene-ready.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Assert EditorContent mounts useAutoFrame and re-emits fit-scene on
viewer scene-ready, and that CustomCameraControls keeps the
__pascalCameraControls helper ungated by NODE_ENV.
@pascal

pascal Bot commented Sep 6, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 67426f0f-caa3-4001-a1cd-88e8b4ac5c0a

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/custom-camera-controls.tsx Outdated
Bugbot on pascalorg#766: the level-follow early return treated every same-id rerun
and every null->level as a no-op. Keep the first auto-select skip so
auto-frame still owns load, but follow exploded/stacked Y changes and a
level pick after building/breadcrumb/resetSelection.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Comment thread packages/editor/src/components/editor/custom-camera-controls.tsx Outdated
Bugbot on pascalorg#766: skipping the first null->level in the controls lifetime
also dropped a real pick when load restored site phase (levelId null).
Keep first-load auto-frame / empty-scene default pose; after that, pan
on level or levelMode changes. Y-idempotence still swallows no-ops.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 38f224f. Configure here.

if (Object.keys(useScene.getState().nodes).length === 0) {
controls.current.setLookAt(20, 20, 20, 0, 0, 0, true)
}
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Load framing skipped after first-person

Medium Severity

A scene that becomes ready while first-person is active never receives the restored orbit frame. The new fit-scene re-emit is ignored in that mode, and the rewritten firstLoad path then skips both the default pose and the level-follow pan when first-person ends, so the remounted orbit camera stays on the unframed default.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 38f224f. Configure here.

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