feat(hud): Cyber HUD theme with GPU contact sonar (#706)

Add the opt-in Cyber HUD layout with coordinated map and cockpit panel
styling, GPU-only contact sonar (rings, range, power, opacity, sector) with
native-rendering fallback, and set_cyber_sonar voice controls. Sonar visual
style inspired by kk376's tactical naval sonar (#214).

Co-authored-by: Sameh Khamis <[email protected]>
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
authored and GitHub committed 2026-09-23 20:31:56 -07:00
1 parent f913066cf2
commit 513dc87a0e
74 files changed
+7320 -90

No files matched your search

+33 -3
View File
@@ -22,6 +22,11 @@ import { bindClearLayersControl } from './layers.js';
import { bindCameraOrientationControls } from './cameraOrientationControls.js';
import { createMapSourceControls } from './mapSource.js';
import { STYLES } from './effects.js';
import { isHudLayout } from '../hudLayouts.js';
import {
getCyberSonarControlState,
setCyberSonarControls,
} from './cyberSonarControls.js';
import * as Cesium from 'cesium';
@@ -191,6 +196,17 @@ export class StyleManager extends ShellFacade {
_detectionOpacityValue: this._detectionOpacityValue,
_detectionSliderRow: this._detectionSliderRow,
_hudBtn: this._hudBtn,
_cyberSonarBtn: this._cyberSonarBtn,
_cyberSonarRings: this._cyberSonarRings,
_cyberSonarRingsValue: this._cyberSonarRingsValue,
_cyberSonarRange: this._cyberSonarRange,
_cyberSonarRangeValue: this._cyberSonarRangeValue,
_cyberSonarIntensity: this._cyberSonarIntensity,
_cyberSonarIntensityValue: this._cyberSonarIntensityValue,
_cyberSonarOpacity: this._cyberSonarOpacity,
_cyberSonarOpacityValue: this._cyberSonarOpacityValue,
_cyberSonarSector: this._cyberSonarSector,
_cyberSonarSectorValue: this._cyberSonarSectorValue,
_hudLayoutRow: this._hudLayoutRow,
_hudLayoutSelect: this._hudLayoutSelect,
_ppToggles: this._ppToggles,
@@ -486,6 +502,12 @@ export class StyleManager extends ShellFacade {
_scopeFeatherSlider: this._scopeFeatherSlider,
_hudLayoutSelect: this._hudLayoutSelect,
_hudBtn: this._hudBtn,
_cyberSonarBtn: this._cyberSonarBtn,
_cyberSonarRings: this._cyberSonarRings,
_cyberSonarRange: this._cyberSonarRange,
_cyberSonarIntensity: this._cyberSonarIntensity,
_cyberSonarOpacity: this._cyberSonarOpacity,
_cyberSonarSector: this._cyberSonarSector,
_cleanViewBtn: this._cleanViewBtn,
_cleanViewExitBtn: this._cleanViewExitBtn,
_detectionDensitySlider: this._detectionDensitySlider,
@@ -511,6 +533,8 @@ export class StyleManager extends ShellFacade {
_applySharpenIntensity: (...args) =>
this._applySharpenIntensity(...args),
_setHudVariant: (...args) => this._setHudVariant(...args),
_setCyberSonarEnabled: (...args) => this._setCyberSonarEnabled(...args),
_setCyberSonarSetting: (...args) => this._setCyberSonarSetting(...args),
_applyDetectionDensityFromUi: (...args) =>
this._applyDetectionDensityFromUi(...args),
_setDetectionAllocation: (...args) =>
@@ -1071,16 +1095,16 @@ export class StyleManager extends ShellFacade {
/**
* Switches the HUD layout variant.
* @param {'tactical'|'operator'|'minimal'} variantName - Layout variant.
* @param {'tactical'|'operator'|'minimal'|'cyber'} variantName - Layout variant.
* @returns {{ok: boolean, layout?: string, visible?: boolean, error?: string}}
*/
setHudLayout(variantName) {
const variant = String(variantName ?? '').toLowerCase();
if (!['tactical', 'operator', 'minimal'].includes(variant)) {
if (!isHudLayout(variant)) {
return { ok: false, error: `Unknown HUD layout: ${variantName}` };
}
this.shareLinkManager?.claimRestoreLane?.('visual');
this._setHudVariant(variant);
this._setHudVariant(variant, { applyVisualDefaults: true });
return {
ok: true,
layout: this.hud.getVariant(),
@@ -1196,6 +1220,11 @@ export class StyleManager extends ShellFacade {
};
}
/** Apply Cyber-only sonar settings through the shared visual controls. */
setCyberSonar(settings) {
return setCyberSonarControls(this, settings);
}
/**
* Full control-state snapshot — single source for voice read-back so the
* agent confirms from the same state it acted on.
@@ -1208,6 +1237,7 @@ export class StyleManager extends ShellFacade {
hud: {
visible: !!this.hud?.visible,
layout: this.hud?.getVariant?.() || null,
sonar: getCyberSonarControlState(),
},
detection: this.getDetectionState(),
bloom: {