Commit Graph

12 Commits

Author SHA1 Message Date
evanpelle 4936ae3d59 restore spawn-phase glow with a true breathing animation
SpawnOverlayPass had everything wired except a caller. WebGLFrameBuilder
now collects spawned human players each tick during spawn phase and
pushes their territory centroid + color through view.updateSpawnOverlay.
myPlayer reads as white so the local-player ring stands out.

Reshaped the shader animation: dropped the growing-disc effect, gave
the ring a true breath — radius scales 0.5×→1.15× while opacity pulses
35%→100% in phase. Replaced the sharp inner-edge ramp with a smooth
center-to-boundary fill so there's no hard cutoff or empty hole in
the middle. animSpeed bumped to 0.0035 (~1 breath/sec).
2026-05-18 09:43:14 -07:00
evanpelle 61f6d2fdd4 restore alt-view (space hold) toggle
InputHandler still emits AlternateViewEvent on space down/up, and the
renderer still has setAltView. The bridge between them lived in
MapInteraction's applyAltView, which got deleted with the rest of
MapInteraction — nothing was wiring the event to the view anymore.
Expose view.setAltView and have ClientGameRunner subscribe.
2026-05-18 09:10:05 -07:00
evanpelle 4cd22a9b5c rename render/ files to UpperCamelCase to match client convention
The render/ tree was the only place in the client still using kebab-case
filenames. Brings ~80 files in line with the rest of src/client/
(BuildPreviewController, TransformHandler, etc.). Directories kept as
they were (name-pass/, fx-pass/, passes/, utils/, debug/) since the
codebase already mixes those.

Two collisions surfaced and got resolved: render/types/ is a directory,
not a file, so its imports kept the lowercase form; and the sed pass
incidentally normalized core/pathfinding imports, which had to be
reverted since that file is actually lowercase on disk despite some
imports having referenced it as ./Types under macOS case-insensitive
resolution.
2026-05-17 21:21:05 -07:00
evanpelle 5a9694e2bd replace MapInteraction with HoverHighlightController; one input system
MapInteraction bound DOM events to the WebGL canvas, but the canvas has
pointer-events: none post-migration so its pointermove/down/up/wheel/
keydown listeners never fired — duplicating InputHandler (which owns
the inputOverlay div + EventBus pipeline) and leaving most features
dead. The one alive bit was hover→setHighlightOwner, which I'd
manually forwarded as a workaround.

Now there's a HoverHighlightController that listens to MouseMoveEvent,
computes the cursor's tile owner, and pushes setHighlightOwner. Delete
map-interaction.ts (418 lines) + keyboard-pan.ts, trim the DOM-binding
constructor + proxy methods (setFitZoomOnDoubleClick, setPanSpeed,
setZoomSpeed, etc.) out of GameView, and drop the ClientGameRunner
pointermove forwarder.

Input flows through one path: DOM → inputOverlay → InputHandler →
EventBus → controllers/renderer.
2026-05-17 20:46:02 -07:00
evanpelle fb45c27d82 add subtle player-tile highlight on nation hover
The hover wiring already pushed setHighlightOwner into the border pass,
but the WebGL canvas has pointer-events: none (post-migration to the
inputOverlay div) so MapInteraction's pointermove listener never fired.
Forward pointermove from the input overlay to view.handlePointerMove
so hover actually triggers.

While there, brighten every tile owned by the hovered player — the
territory frag shader now reads uHighlightOwner / uHighlightBrighten
and mixes toward white when the tile owner matches. Wired through
territory-pass.ts; renderer.setHighlightOwner forwards to both border
and territory passes. New highlightFillBrighten setting (0.15) keeps
the fill tint tunable independently of the existing highlightBrighten
border setting, which is dropped from 0.6 → 0.25 so neither effect
blows out.
2026-05-17 20:35:22 -07:00
evanpelle c197f5864f replace day/night cycle with a binary light/dark mode tied to UserSettings
The cycling sun/moon animation was distracting and not a fan favorite.
Drops the cycle path entirely — RenderSettings.dayNight.mode is now
"light" | "dark", and the cycle-only fields (cycleTicks, startPhase,
noonHold, nightHold) plus the passEnabled.dayNight toggle are gone.
getAmbient is a one-liner. The in-game mode follows the existing
darkMode UserSetting (same one that drives the page-level CSS class);
ClientGameRunner applies it on startup and on the per-key change event.
2026-05-17 20:01:23 -07:00
evanpelle b8d72d3a4e set crossOrigin on WebGL atlas image loaders
Atlases now load from the CDN; without crossOrigin = "anonymous" the
browser refuses to texImage2D the cross-origin image. Requires the CDN
to send Access-Control-Allow-Origin for /_assets/atlases/.
2026-05-17 14:03:58 -07:00
evanpelle 8a4b12c4d6 move WebGL atlases into resources/atlases/, route through assetUrl()
src/client/render/gl/assets/ held 11 atlas files (PNGs + JSON metadata)
that bypassed the asset-manifest pipeline — they were imported via
Vite's ?url query, bundled, and served same-origin instead of going
through the CDN like every other game asset. Moved them to
resources/atlases/, switched the PNG imports to assetUrl("atlases/...")
so they flow through the manifest, and updated the JSON metadata
imports to "resources/atlases/..." paths. Also dropped an orphan copy
of MissileSiloIconWhite.svg (no callers; resources/images/ already had
the canonical version).

render-settings.json stays in src/ — it's renderer tuning config
consumed at bundle time, not a URL-served asset.
2026-05-17 12:54:57 -07:00
evanpelle 923cba8c2d 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.
2026-05-16 20:02:31 -07:00
evanpelle e87e2cd58c add iconGrowZoom for structures that scale with deep zoom
Previously structures capped at iconScale = 1.0 once zoomed past
iconScaleFactorZoomedOut, staying at a fixed pixel size no matter how
far you zoomed in. They felt overlaid on the map instead of part of it.

Add a third zoom band controlled by structure.iconGrowZoom. Past this
threshold iconScale = uZoom / iconGrowZoom — structures grow with the
canvas (world-anchored, fixed map-area coverage). Plumbed via the
uIconGrowZoom uniform on StructurePass.

Default 7 keeps normal play unchanged; only kicks in at deep zoom.
2026-05-16 17:34:53 -07:00
evanpelle bb619c2c44 add configurable dot size for zoomed-out structures
Structures collapse to a dot when zoomed out past dotsZoomThreshold.
The dot scale was hardcoded to 1.0 / 2.5 (≈0.4) in structure.vert.glsl.

Promote it to a render setting (`structure.dotScale`) so it's tunable
alongside iconSize / dotsZoomThreshold. Default 0.4 preserves current
behavior. Plumbed via uDotScale uniform on StructurePass.
2026-05-16 17:22:45 -07:00
evanpelle 9c4ba757c2 add webgl renderer 2026-05-16 08:54:20 -07:00