Fold the focus camera-tween into watchFocusTween#358
Merged
Conversation
The focus camera-tween was computed through an engine-injected chain: watchFocusTween -> runFocusTween -> makeRunFocusTween -> FocusTweenTable -> tweenToGalaxy/tweenToStructure/tweenToCameraSnapshot, each dispatching startCameraTween plus an explicit requestRender. Collapse that into the saga itself. watchFocusTween now resolves the ref to a row (resolveDeps), reads the live from-pose + lens FOV via a new cameraRuntime() SagaContext reader, builds the startCameraTween payload with a pure focusTweenDescriptor table (galaxy/structure/milkyWay arms), and dispatches it. The milkyWay arm becomes a peer case in that one table instead of a special tweenToCameraSnapshot snapshot. The explicit requestRender calls are gone: startCameraTween is a camera/* write, so watchWake/WAKE_ROUTES wakes the loop by construction (and the focus ref write also wakes via watchSelectionWake). Deletes makeRunFocusTween, tweenToGalaxy, tweenToStructure, the FocusTweenTable wiring, the orphaned TweenTarget type, and runFocusTween from SagaContext. tweenToCameraSnapshot stays for the home button, minus its redundant requestRender. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
skymap | 9928788 | Commit Preview URL Branch Preview URL |
Jun 20 2026, 04:39 PM |
rulkens
added a commit
that referenced
this pull request
Jun 20, 2026
…spike Brings in the camera-pose-as-derived-state refactor (#357) + the focus-tween fold into watchFocusTween (#358). The CameraDriver contract changed from a mutating apply(cam, nowMs) to a pure pose(s, cam, elapsedMs) that RETURNS a CameraPose; assembleOrbitCamera derives position from it. Migrated the four throwaway spike drivers (webshow / flowshow / flyout / floworbit) to the new contract: - apply(cam) mutation -> pose() returning a fresh CameraPose; no more updatePosition (the resolver derives position via assembleOrbitCamera). - Self-clock via performance.now(): the driver-table elapsed clock (elapsedForWinner) only serves the 'tween'/'autoRotate' ids, so any other driver id receives elapsedMs === 0. - Self-sustain the loop: shouldKeepTicking reads camera liveness off the store (drag/tween/autoRotate), so a spike driver gating on local phase is invisible to it; each driver now pokes requestRender() per frame or the take freezes after one tick. - priority 80 -> 90: orbitDrag now occupies 80, so the takes move above the store movers to keep owning the camera. - Drop the fovYRad set (CameraPose carries no FOV); framing reads the live projection FOV off the forwarded cam. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
The focus camera-tween was computed through an engine-injected chain:
This folds all of that into the saga itself:
Why
watchFocusTweenas a thin resolve→build→dispatch shell, instead of being threaded through an engine-injected runner + table.tweenToCameraSnapshot; it's now a peercasein the purefocusTweenDescriptortable, emitting the samestartCameraTweenas galaxy/structure (tagged-union table dispatch, not a per-type handler set).startCameraTweenis acamera/*write, sowatchWake/WAKE_ROUTESwakes the loop by construction (and the focus-ref write also wakes viawatchSelectionWake). The explicitscheduler.requestRender()calls are gone.cameraRuntime()reader onSagaContext— the same well-worn injection asresolveDeps/reconcile/runTierTransition. The mutablecameraRuntimeResources stay out of the timelesscameraslice by design.Deletes
makeRunFocusTween,tweenToGalaxy,tweenToStructure, theFocusTweenTablewiring inengine.ts, the orphanedTweenTargettype, andrunFocusTweenfromSagaContext.tweenToCameraSnapshotstays for the home button (minus its redundantrequestRender).Net −433 lines.
Tests
focusTweenDescriptorunit tests (per-arm target/distance, yaw/pitch preserved, fresh-array copy).watchFocusTweensaga test (dispatchesstartCameraTweenwith the built descriptor; no-ops on non-focus write / cam-not-ready / null ref).SagaContextcontract test updatedrunFocusTween->cameraRuntime.npm run typecheckclean; full suite 2977 passing.🤖 Generated with Claude Code