feat(viewer): add Vue-based HUD, ops strip, and history window

This commit is contained in:
2026-03-19 13:49:56 -04:00
parent 710addf1f5
commit 3ca568c05d
36 changed files with 2648 additions and 1017 deletions

View File

@@ -68,8 +68,6 @@ export interface WorldPresentationContext extends WorldOrbitalContext {
}
export interface GameStatusParams {
statusEl: HTMLDivElement;
summaryEl?: HTMLSpanElement;
world?: WorldState;
activeSystemId?: string;
cameraMode: CameraMode;
@@ -269,8 +267,8 @@ function fmtVec(v: THREE.Vector3, digits: number) {
return `${v.x.toFixed(digits)} ${v.y.toFixed(digits)} ${v.z.toFixed(digits)}`;
}
export function updateGameStatus(params: GameStatusParams) {
const { statusEl, summaryEl, world, activeSystemId, cameraMode, povLevel, selectedItems, mode, galaxyAnchor, systemAnchor } = params;
export function describeGameStatus(params: GameStatusParams) {
const { world, activeSystemId, cameraMode, povLevel, selectedItems, mode, galaxyAnchor, systemAnchor } = params;
const sequence = world?.sequence ?? 0;
const generatedAt = world?.generatedAtUtc
? new Date(world.generatedAtUtc).toLocaleTimeString()
@@ -296,19 +294,27 @@ export function updateGameStatus(params: GameStatusParams) {
? `loc pos: ${fmtVec(systemAnchor.clone().sub(toThreeVector(celestialAnchor)), 0)} km`
: "";
statusEl.textContent = [
`mode: ${mode}`,
`camera: ${cameraModeLabel}`,
`zoom: ${displayPovLevel}`,
`space: ${activeSpace}`,
galPos,
sysPos,
locPos,
`sequence: ${sequence}`,
`snapshot: ${generatedAt}`,
].filter(Boolean).join("\n");
if (summaryEl) {
summaryEl.textContent = `${mode} | ${displayPovLevel} | ${activeSpace}`;
return {
bodyText: [
`mode: ${mode}`,
`camera: ${cameraModeLabel}`,
`zoom: ${displayPovLevel}`,
`space: ${activeSpace}`,
galPos,
sysPos,
locPos,
`sequence: ${sequence}`,
`snapshot: ${generatedAt}`,
].filter(Boolean).join("\n"),
summaryText: `${mode} | ${displayPovLevel} | ${activeSpace}`,
};
}
export function updateGameStatus(params: GameStatusParams & { statusEl: HTMLDivElement; summaryEl?: HTMLSpanElement }) {
const state = describeGameStatus(params);
params.statusEl.textContent = state.bodyText;
if (params.summaryEl) {
params.summaryEl.textContent = state.summaryText;
}
}