166 lines
4.0 KiB
TypeScript
166 lines
4.0 KiB
TypeScript
import type { SceneResultsPayload } from "./sceneData";
|
|
|
|
export const SCENE_CHANNEL = "tjwater:zjb-scene";
|
|
export const SCENE_PROTOCOL_VERSION = 2;
|
|
|
|
export type SceneMode =
|
|
| "network"
|
|
| "hydraulic"
|
|
| "map"
|
|
| "detail"
|
|
| "pump"
|
|
| "meters";
|
|
|
|
export type SceneDisplayMode = "global" | "coordinated";
|
|
export type SceneMetricMode = "uniform" | "velocity" | "pressure" | "direction";
|
|
export type SceneDirectionMode = "none" | "topology" | "results";
|
|
export type SceneLightingPreset = "day" | "studio" | "evening";
|
|
export type SceneQuality = "standard" | "high";
|
|
|
|
export type SceneNetworkStyle = {
|
|
scale: number;
|
|
mode: SceneMetricMode;
|
|
color: string;
|
|
missingColor: string;
|
|
lowColor: string;
|
|
highColor: string;
|
|
opacity: number;
|
|
roughness: number;
|
|
metalness: number;
|
|
nodes: boolean;
|
|
direction: SceneDirectionMode;
|
|
arrowColor: string;
|
|
autoRange: boolean;
|
|
min: number;
|
|
max: number;
|
|
};
|
|
|
|
export type SceneAppearance = {
|
|
preset: SceneLightingPreset;
|
|
exposure: number;
|
|
shadows: boolean;
|
|
effects: boolean;
|
|
quality: SceneQuality;
|
|
};
|
|
|
|
export type SceneCameraView = {
|
|
id: string;
|
|
label: string;
|
|
mode: SceneMode;
|
|
note?: string;
|
|
saved: boolean;
|
|
};
|
|
|
|
export type SceneCameraState = {
|
|
active: string | null;
|
|
note: string;
|
|
views: SceneCameraView[];
|
|
};
|
|
|
|
export type SceneStyleSummary = {
|
|
mode?: SceneMetricMode;
|
|
min?: number;
|
|
max?: number;
|
|
dataLinks?: number;
|
|
totalLinks?: number;
|
|
arrows?: number;
|
|
hasResults?: boolean;
|
|
resultTime?: string | null;
|
|
scale?: number;
|
|
};
|
|
|
|
export type SceneRuntimeState = {
|
|
mode: SceneMode;
|
|
status: string;
|
|
contextVisible: boolean;
|
|
roofVisible: boolean;
|
|
displayMode: SceneDisplayMode;
|
|
style: SceneNetworkStyle;
|
|
styleSummary: SceneStyleSummary;
|
|
appearance: SceneAppearance;
|
|
camera: SceneCameraState;
|
|
};
|
|
|
|
export type SceneAssetField = {
|
|
label: string;
|
|
value: string;
|
|
};
|
|
|
|
export type SceneAssetSection = {
|
|
title: string;
|
|
fields: SceneAssetField[];
|
|
};
|
|
|
|
export type SceneAssetNeighbor = {
|
|
id: string;
|
|
label: string;
|
|
};
|
|
|
|
export type SceneAssetSelection = {
|
|
assetId: string;
|
|
elementId: string;
|
|
kind: string;
|
|
title: string;
|
|
sections: SceneAssetSection[];
|
|
neighbors: SceneAssetNeighbor[];
|
|
};
|
|
|
|
export type SceneCommand =
|
|
| { name: "set-mode"; mode: SceneMode }
|
|
| { name: "visit-camera"; viewId: string }
|
|
| { name: "save-camera"; label: string }
|
|
| { name: "remove-camera"; viewId: string }
|
|
| { name: "set-style"; patch: Partial<SceneNetworkStyle> }
|
|
| { name: "reset-style" }
|
|
| { name: "set-display-mode"; mode: SceneDisplayMode }
|
|
| { name: "set-appearance"; patch: Partial<SceneAppearance> }
|
|
| { name: "toggle-context" }
|
|
| { name: "toggle-roof" }
|
|
| { name: "fit-view" }
|
|
| { name: "select-asset"; assetId: string }
|
|
| { name: "locate-selection" }
|
|
| { name: "clear-selection" };
|
|
|
|
type HostMessageBase = {
|
|
channel: typeof SCENE_CHANNEL;
|
|
version: typeof SCENE_PROTOCOL_VERSION;
|
|
projectCode: string;
|
|
modelId: string;
|
|
};
|
|
|
|
export type SceneHostMessage = HostMessageBase &
|
|
(
|
|
| { type: "results"; payload: SceneResultsPayload }
|
|
| { type: "clear-results" }
|
|
| { type: "command"; command: SceneCommand }
|
|
);
|
|
|
|
export type SceneRuntimeMessage = HostMessageBase &
|
|
(
|
|
| {
|
|
type: "ready";
|
|
nodeIds: string[];
|
|
linkIds: string[];
|
|
state: SceneRuntimeState;
|
|
}
|
|
| { type: "scene-state"; state: SceneRuntimeState }
|
|
| { type: "selection-changed"; selection: SceneAssetSelection | null }
|
|
| { type: "results-applied"; summary: SceneStyleSummary }
|
|
| { type: "results-cleared" }
|
|
| { type: "error"; message: string }
|
|
);
|
|
|
|
export const isSceneRuntimeMessage = (
|
|
input: unknown,
|
|
): input is SceneRuntimeMessage => {
|
|
if (!input || typeof input !== "object") return false;
|
|
const message = input as Partial<SceneRuntimeMessage>;
|
|
return (
|
|
message.channel === SCENE_CHANNEL &&
|
|
message.version === SCENE_PROTOCOL_VERSION &&
|
|
typeof message.projectCode === "string" &&
|
|
typeof message.modelId === "string" &&
|
|
typeof message.type === "string"
|
|
);
|
|
};
|