move multi-unit warship selection box to WebGL SelectionBoxPass

SelectionBoxPass now stores an array of selections and renders one
quad per entry. GPURenderer gains setSelectedUnits(ids) — the
single-unit setSelectedUnit becomes a wrapper. Position + color are
rebuilt each frame from lastUnits; dead unit IDs get pruned in place.

ClientGameRunner's UnitSelectionEvent listener forwards both single
and multi to view.setSelectedUnits — no more single/multi split.

UILayer drops everything canvas2D-related: the offscreen canvas +
context, theme, selectionAnimTime, multiSelectionBoxCenters,
SELECTION_BOX_SIZE, drawSelectionBoxMulti, paintSelectionBoxAt,
clearSelectionBox, paintCell, clearCell, and renderLayer / redraw /
shouldTransform. tick() now only prunes destroyed warships from the
selection list; the layer is purely state + click handling. ~120 LOC
gone.

Tests: UILayer.test.ts updated — drops the canvas/redraw asserts,
adds a multi-selection state assertion.
This commit is contained in:
evanpelle
2026-05-16 20:02:31 -07:00
parent ede0fb7668
commit 923cba8c2d
6 changed files with 133 additions and 235 deletions
+7 -9
View File
@@ -346,21 +346,19 @@ function mountWebGLDebugRenderer(
view.showMoveIndicator(tx, ty, firstUnit.owner().smallID());
});
// Single-unit warship selection box: forward UnitSelectionEvent to the
// renderer's SelectionBoxPass. Multi-selection (event.units.length > 0)
// stays canvas2D for now — SelectionBoxPass only supports one unit.
// Warship selection boxes: forward UnitSelectionEvent to the renderer's
// SelectionBoxPass for both single and multi selections.
eventBus.on(UnitSelectionEvent, (e) => {
if (!e.isSelected) {
view.setSelectedUnit(null);
view.setSelectedUnits([]);
return;
}
if ((e.units ?? []).length > 0) {
// Multi-selection: drop any prior single highlight; canvas2D draws
// the multi outlines in UILayer.
view.setSelectedUnit(null);
const multi = e.units ?? [];
if (multi.length > 0) {
view.setSelectedUnits(multi.map((u) => u.id()));
return;
}
view.setSelectedUnit(e.unit?.id() ?? null);
view.setSelectedUnits(e.unit ? [e.unit.id()] : []);
});
return { builder: new WebGLFrameBuilder(view), syncCamera };