Fix 3D drum/keys highways not resizing on fullscreen under splitscreen (#723)

The guitar/bass highway_3d renderer self-detects panel-canvas size changes
in its draw() loop and re-runs applySize() every frame, because the
splitscreen host overrides hw.resize and never calls renderer.resize().
The drum and keys highways lacked that fallback — they only re-framed when
the host explicitly called resize(w, h) — so their panels stayed framed for
the pre-fullscreen size while the guitar/bass panels adapted. Symptom: a
too-small, off-center highway in the drum/keys panels after maximizing a
split-screen session.

Port highway_3d's per-frame drift check into both draw() loops: re-apply on
backing-store change (canvas.width/height) AND on CSS-box drift
(clientWidth/clientHeight vs the last applied logical size, throttled to
every 10th frame). Track _lastHwW/_lastHwH + _appliedW/_appliedH per
instance and reset them in destroy() so a reused instance re-frames on the
next song.

plugins/drum_highway_3d -> 0.3.1, plugins/keys_highway_3d -> 0.1.1.
Tests: tests/js/drum_keys_highway_3d_resize_reframe.test.js.

Signed-off-by: Kris Anderson <topkoa@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
K. O. A.
2026-07-02 18:42:26 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent c7497c758d
commit 4b6cbe8b11
6 changed files with 177 additions and 2 deletions
+46
View File
@@ -1390,6 +1390,16 @@
// multiplied into the device pixel ratio like highway_3d does.
let _renderScale = 1;
// Auto-resize fallback state (PORTED FROM highway_3d — keep in sync).
// The splitscreen host resizes the panel canvas but overrides
// hw.resize and never calls our resize(w,h), so draw() self-detects
// size drift. _lastHwW/H track the backing store last seen; _appliedW/H
// track the logical size last handed to applySize(); the countdown
// throttles the per-frame clientWidth/Height read.
let _lastHwW = 0, _lastHwH = 0;
let _appliedW = 0, _appliedH = 0;
let _boxCheckCountdown = 0;
// Bloom composer state (PORTED FROM highway_3d/screen.js — keep in sync).
let _composer = null;
let _bloomPass = null;
@@ -3106,6 +3116,10 @@
}
cam.aspect = W / H;
cam.updateProjectionMatrix();
// Record the logical size actually framed for, so the draw()
// drift check can tell when the live canvas box has moved away
// from it (PORTED FROM highway_3d).
_appliedW = W; _appliedH = H;
_sizeFxCanvas();
}
@@ -3372,6 +3386,33 @@
_renderScale = newScale;
applySize(highwayCanvas.clientWidth, highwayCanvas.clientHeight);
}
// Keep the render matched to the highway canvas's real box
// (PORTED FROM highway_3d — keep in sync). Two drifts to catch:
// 1. Backing store (canvas.width/height) changed out from under
// us — the splitscreen hw.resize override resizes the element
// but never calls renderer.resize().
// 2. The CSS box (clientWidth/Height) drifted while the backing
// store held — e.g. the flex #highway box settling after a
// fullscreen transition, with no backing-store change and no
// resize() call, so branch 1 never fires. Without this the
// drum/keys panels stay framed for the pre-fullscreen size.
if (highwayCanvas) {
const _bsChanged = highwayCanvas.width !== _lastHwW
|| highwayCanvas.height !== _lastHwH;
_boxCheckCountdown = (_boxCheckCountdown + 1) % 10;
if (_bsChanged || _boxCheckCountdown === 0) {
const _bw = highwayCanvas.clientWidth | 0;
const _bh = highwayCanvas.clientHeight | 0;
if (_bsChanged) {
_lastHwW = highwayCanvas.width;
_lastHwH = highwayCanvas.height;
if (_bw > 0 && _bh > 0) applySize(_bw, _bh);
} else if (_bw > 0 && _bh > 0 &&
(Math.abs(_bw - _appliedW) > 1 || Math.abs(_bh - _appliedH) > 1)) {
applySize(_bw, _bh);
}
}
}
rebuildNotes(bundle);
// Wall-clock FX step (sparks, kick pulse) — decoupled from
// song time so effects keep settling while paused/seeking.
@@ -3447,6 +3488,11 @@
}
if (_instances.size === 0) _midiReleaseSession();
teardown(); // includes _removeHud()
// Instances are reused across songs (destroy() → init()); stale
// applied/backing dims would suppress the first reframe of the
// next song (PORTED FROM highway_3d).
_lastHwW = 0; _lastHwH = 0;
_appliedW = 0; _appliedH = 0;
highwayCanvas = null;
},
// Exposed for module-level MIDI router. The receiver runs on