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

+12 -5
View File
@@ -1,3 +1,5 @@
import { displayPanelScroller } from './displayPanelScroll.js';
/** Move the existing Display groups between their two presentation surfaces. */
export class CockpitDisplayPortal {
constructor({ standardPanel, cockpitPanel, groups, layout }) {
@@ -20,15 +22,18 @@ export class CockpitDisplayPortal {
group.before(anchor);
return [{ name, group, slot, anchor }];
});
this.standardScrollTop = standardPanel?.scrollTop || 0;
this.standardScrollTop =
displayPanelScroller(standardPanel)?.scrollTop || 0;
this.cockpitScrollTop = cockpitPanel?.scrollTop || 0;
const options = { passive: true, signal: this.listeners.signal };
standardPanel?.addEventListener(
'scroll',
() => {
if (!this.active) this.standardScrollTop = standardPanel.scrollTop;
if (!this.active)
this.standardScrollTop =
displayPanelScroller(standardPanel).scrollTop;
},
options,
{ ...options, capture: true },
);
cockpitPanel?.addEventListener(
'scroll',
@@ -85,7 +90,8 @@ export class CockpitDisplayPortal {
if (nextActive && this.cockpitPanel)
this.cockpitPanel.scrollTop = this.cockpitScrollTop;
if (!nextActive && this.standardPanel)
this.standardPanel.scrollTop = this.standardScrollTop;
displayPanelScroller(this.standardPanel).scrollTop =
this.standardScrollTop;
};
if (!settle) {
restoreScroll();
@@ -121,7 +127,8 @@ export class CockpitDisplayPortal {
}
this.cockpitPanel?.classList.remove('uses-shared-display-controls');
if (this.standardPanel)
this.standardPanel.scrollTop = this.standardScrollTop;
displayPanelScroller(this.standardPanel).scrollTop =
this.standardScrollTop;
this.records = [];
this.restoreOwner = null;
}