feat(viewer): add Vue-based HUD, ops strip, and history window
This commit is contained in:
3
apps/viewer/src/ui/stores/pinia.ts
Normal file
3
apps/viewer/src/ui/stores/pinia.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { createPinia } from "pinia";
|
||||
|
||||
export const viewerPinia = createPinia();
|
||||
108
apps/viewer/src/ui/stores/viewerSelection.ts
Normal file
108
apps/viewer/src/ui/stores/viewerSelection.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { defineStore } from "pinia";
|
||||
import type { Selectable } from "../../viewerTypes";
|
||||
|
||||
export type ViewerSelectionSource = "viewer" | "ui" | null;
|
||||
|
||||
export interface ViewerSelectionSummary {
|
||||
id: string;
|
||||
kind: Selectable["kind"];
|
||||
label?: string | null;
|
||||
}
|
||||
|
||||
export function selectionToEntityId(selection: Selectable): string {
|
||||
switch (selection.kind) {
|
||||
case "planet":
|
||||
return `${selection.systemId}:${selection.planetIndex}`;
|
||||
case "moon":
|
||||
return `${selection.systemId}:${selection.planetIndex}:${selection.moonIndex}`;
|
||||
default:
|
||||
return selection.id;
|
||||
}
|
||||
}
|
||||
|
||||
export function entityIdToSelectable(
|
||||
kind: Selectable["kind"] | null,
|
||||
entityId: string | null,
|
||||
): Selectable | null {
|
||||
if (!kind || !entityId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (kind === "planet") {
|
||||
const [systemId, planetIndex] = entityId.split(":");
|
||||
if (!systemId || planetIndex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
kind,
|
||||
systemId,
|
||||
planetIndex: Number(planetIndex),
|
||||
};
|
||||
}
|
||||
|
||||
if (kind === "moon") {
|
||||
const [systemId, planetIndex, moonIndex] = entityId.split(":");
|
||||
if (!systemId || planetIndex == null || moonIndex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
kind,
|
||||
systemId,
|
||||
planetIndex: Number(planetIndex),
|
||||
moonIndex: Number(moonIndex),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
kind,
|
||||
id: entityId,
|
||||
} as Selectable;
|
||||
}
|
||||
|
||||
export const useViewerSelectionStore = defineStore("viewerSelection", {
|
||||
state: () => ({
|
||||
selectedEntityId: null as string | null,
|
||||
selectedEntityKind: null as Selectable["kind"] | null,
|
||||
selectedEntityLabel: null as string | null,
|
||||
hoveredEntityId: null as string | null,
|
||||
inspectedEntityId: null as string | null,
|
||||
selectionSource: null as ViewerSelectionSource,
|
||||
}),
|
||||
actions: {
|
||||
selectEntity(id: string | null, source: ViewerSelectionSource = null) {
|
||||
this.selectedEntityId = id;
|
||||
this.selectionSource = source;
|
||||
if (id == null) {
|
||||
this.selectedEntityKind = null;
|
||||
this.selectedEntityLabel = null;
|
||||
}
|
||||
},
|
||||
selectSelection(selection: ViewerSelectionSummary | null, source: ViewerSelectionSource = null) {
|
||||
if (!selection) {
|
||||
this.clearSelection(source);
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedEntityId = selection.id;
|
||||
this.selectedEntityKind = selection.kind;
|
||||
this.selectedEntityLabel = selection.label ?? null;
|
||||
this.selectionSource = source;
|
||||
},
|
||||
clearSelection(source: ViewerSelectionSource = null) {
|
||||
this.selectedEntityId = null;
|
||||
this.selectedEntityKind = null;
|
||||
this.selectedEntityLabel = null;
|
||||
this.selectionSource = source;
|
||||
},
|
||||
hoverEntity(id: string | null) {
|
||||
this.hoveredEntityId = id;
|
||||
},
|
||||
inspectEntity(id: string | null) {
|
||||
this.inspectedEntityId = id;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export type ViewerSelectionStore = ReturnType<typeof useViewerSelectionStore>;
|
||||
Reference in New Issue
Block a user