300 lines
14 KiB
TypeScript
300 lines
14 KiB
TypeScript
import * as THREE from "three";
|
|
import { ViewerInteractionController } from "./viewerInteractionController";
|
|
import { ViewerNavigationController } from "./viewerNavigationController";
|
|
import { ViewerPresentationController } from "./viewerPresentationController";
|
|
import { ViewerSceneDataController } from "./viewerSceneDataController";
|
|
import { ViewerWorldLifecycle } from "./viewerWorldLifecycle";
|
|
import { ViewerHistoryWindowController } from "./viewerHistoryWindowController";
|
|
import { useViewerSceneStore } from "./ui/stores/viewerScene";
|
|
import { useViewerOrderContextMenuStore } from "./ui/stores/viewerOrderContextMenu";
|
|
import { viewerPinia } from "./ui/stores/pinia";
|
|
|
|
export function createViewerControllers(host: any) {
|
|
const sceneStore = useViewerSceneStore(viewerPinia);
|
|
const orderContextMenuStore = useViewerOrderContextMenuStore(viewerPinia);
|
|
const sceneDataController = new ViewerSceneDataController({
|
|
documentRef: document,
|
|
getWorldOrbitalTimeSeconds: () => host.world?.orbitalTimeSeconds,
|
|
getOrbitalSimulationSpeed: () => host.world?.orbitalSimulation.simulatedSecondsPerRealSecond ?? 0,
|
|
getWorldSeed: () => host.world?.seed ?? 1,
|
|
getWorldTimeSyncMs: () => host.worldTimeSyncMs,
|
|
getWorldPresentationContext: () => host.createWorldPresentationContext(),
|
|
getActiveSystemId: () => host.activeSystemId,
|
|
galaxySystemGroup: host.galaxyLayer.systemGroup,
|
|
systemScene: host.systemLayer.scene,
|
|
celestialGroup: host.systemLayer.celestialGroup,
|
|
nodeGroup: host.systemLayer.nodeGroup,
|
|
stationGroup: host.systemLayer.stationGroup,
|
|
claimGroup: host.systemLayer.claimGroup,
|
|
constructionSiteGroup: host.systemLayer.constructionSiteGroup,
|
|
shipGroup: host.systemLayer.shipGroup,
|
|
galaxySelectableTargets: host.galaxyLayer.selectableTargets,
|
|
systemSelectableTargets: host.systemLayer.selectableTargets,
|
|
systemVisuals: host.galaxyLayer.systemVisuals,
|
|
planetVisuals: host.systemLayer.planetVisuals,
|
|
celestialVisuals: host.systemLayer.celestialVisuals,
|
|
nodeVisuals: host.systemLayer.nodeVisuals,
|
|
stationVisuals: host.systemLayer.stationVisuals,
|
|
claimVisuals: host.systemLayer.claimVisuals,
|
|
constructionSiteVisuals: host.systemLayer.constructionSiteVisuals,
|
|
shipVisuals: host.systemLayer.shipVisuals,
|
|
});
|
|
|
|
const navigationController = new ViewerNavigationController({
|
|
getWorld: () => host.world,
|
|
getWorldTimeSyncMs: () => host.worldTimeSyncMs,
|
|
getActiveSystemId: () => host.activeSystemId,
|
|
setActiveSystemId: (value) => {
|
|
host.activeSystemId = value;
|
|
sceneStore.setViewContext(value ?? null, host.povLevel);
|
|
},
|
|
onActiveSystemChanged: (oldId, newId) => {
|
|
sceneDataController.onActiveSystemChanged(oldId, newId);
|
|
},
|
|
getCameraMode: () => host.cameraMode,
|
|
setCameraMode: (value) => {
|
|
host.cameraMode = value;
|
|
},
|
|
getCameraTargetShipId: () => host.cameraTargetShipId,
|
|
setCameraTargetShipId: (value) => {
|
|
host.cameraTargetShipId = value;
|
|
},
|
|
getCurrentDistance: () => host.currentDistance,
|
|
getPovLevel: () => host.povLevel,
|
|
getSelectedItems: () => host.selectedItems,
|
|
getOrbitYaw: () => host.orbitYaw,
|
|
getFollowOrbitYaw: () => host.followOrbitYaw,
|
|
getFollowOrbitPitch: () => host.followOrbitPitch,
|
|
galaxyAnchor: host.galaxyAnchor,
|
|
systemAnchor: host.systemAnchor,
|
|
galaxyCamera: host.galaxyLayer.camera,
|
|
systemCamera: host.systemLayer.camera,
|
|
shipVisuals: host.systemLayer.shipVisuals,
|
|
nodeVisuals: host.systemLayer.nodeVisuals,
|
|
planetVisuals: host.systemLayer.planetVisuals,
|
|
systemVisuals: host.galaxyLayer.systemVisuals,
|
|
followCameraPosition: host.followCameraPosition,
|
|
followCameraFocus: host.followCameraFocus,
|
|
followCameraDirection: host.followCameraDirection,
|
|
followCameraDesiredDirection: host.followCameraDesiredDirection,
|
|
followCameraOffset: host.followCameraOffset,
|
|
createWorldPresentationContext: () => host.createWorldPresentationContext(),
|
|
updatePanels: () => host.updatePanels(),
|
|
updateGamePanel: (mode: string) => host.updateGamePanel(mode),
|
|
});
|
|
|
|
const presentationController = new ViewerPresentationController({
|
|
renderer: host.renderer,
|
|
hudState: host.hudState,
|
|
galaxyScene: host.galaxyLayer.scene,
|
|
galaxyCamera: host.galaxyLayer.camera,
|
|
systemCamera: host.systemLayer.camera,
|
|
galaxyAnchor: host.galaxyAnchor,
|
|
systemAnchor: host.systemAnchor,
|
|
ambienceGroup: host.universeLayer.ambienceGroup,
|
|
networkStats: host.networkStats,
|
|
performanceStats: host.performanceStats,
|
|
getWorld: () => host.world,
|
|
getActiveSystemId: () => host.activeSystemId,
|
|
getCameraMode: () => host.cameraMode,
|
|
getCameraTargetShipId: () => host.cameraTargetShipId,
|
|
getPovLevel: () => host.povLevel,
|
|
getSelectedItems: () => host.selectedItems,
|
|
getWorldTimeSyncMs: () => host.worldTimeSyncMs,
|
|
getCurrentDistance: () => host.currentDistance,
|
|
planetVisuals: host.systemLayer.planetVisuals,
|
|
systemVisuals: host.galaxyLayer.systemVisuals,
|
|
createWorldPresentationContext: () => host.createWorldPresentationContext(),
|
|
});
|
|
|
|
const worldLifecycle = new ViewerWorldLifecycle({
|
|
getWorld: () => host.world,
|
|
setWorld: (world) => {
|
|
host.world = world;
|
|
},
|
|
getWorldTimeSyncMs: () => host.worldTimeSyncMs,
|
|
setWorldTimeSyncMs: (value) => {
|
|
host.worldTimeSyncMs = value;
|
|
},
|
|
getWorldSignature: () => host.worldSignature,
|
|
setWorldSignature: (value) => {
|
|
host.worldSignature = value;
|
|
},
|
|
getStream: () => host.stream,
|
|
setStream: (stream) => {
|
|
host.stream = stream;
|
|
},
|
|
getCurrentStreamScopeKey: () => host.currentStreamScopeKey,
|
|
setCurrentStreamScopeKey: (value) => {
|
|
host.currentStreamScopeKey = value;
|
|
},
|
|
getPovLevel: () => host.povLevel,
|
|
getActiveSystemId: () => host.activeSystemId,
|
|
getSelectedItems: () => host.selectedItems,
|
|
getCameraMode: () => host.cameraMode,
|
|
getCameraTargetShipId: () => host.cameraTargetShipId,
|
|
getNetworkStats: () => host.networkStats,
|
|
getSystemSummaryVisuals: () => new Map(),
|
|
hudState: host.hudState,
|
|
worldLabel: () => host.world?.label ?? "",
|
|
rebuildSystems: (systems) => sceneDataController.rebuildSystems(systems),
|
|
syncCelestials: (celestials) => sceneDataController.syncCelestials(celestials),
|
|
syncNodes: (nodes) => sceneDataController.syncNodes(nodes),
|
|
syncStations: (stations) => sceneDataController.syncStations(stations),
|
|
syncClaims: (claims) => sceneDataController.syncClaims(claims),
|
|
syncConstructionSites: (sites) => sceneDataController.syncConstructionSites(sites),
|
|
syncShips: (ships, tickIntervalMs) => sceneDataController.syncShips(ships, tickIntervalMs),
|
|
applyCelestialDeltas: (celestials) => sceneDataController.applyCelestialDeltas(celestials),
|
|
applyNodeDeltas: (nodes) => sceneDataController.applyNodeDeltas(nodes),
|
|
applyStationDeltas: (stations) => sceneDataController.applyStationDeltas(stations),
|
|
applyClaimDeltas: (claims) => sceneDataController.applyClaimDeltas(claims),
|
|
applyConstructionSiteDeltas: (sites) => sceneDataController.applyConstructionSiteDeltas(sites),
|
|
applyShipDeltas: (ships, tickIntervalMs) => sceneDataController.applyShipDeltas(ships, tickIntervalMs),
|
|
refreshHistoryWindows: () => host.refreshHistoryWindows(),
|
|
resolveFocusedCelestialId: () => host.resolveFocusedCelestialId(),
|
|
updateSystemSummaries: () => host.updateSystemSummaries(),
|
|
applyZoomPresentation: () => presentationController.applyZoomPresentation(),
|
|
updateNetworkPanel: () => presentationController.updateNetworkPanel(),
|
|
updateSystemPanel: () => host.updateSystemPanel(),
|
|
updateGamePanel: (mode) => host.updateGamePanel(mode),
|
|
describeSelectionParent: (selection) => host.describeSelectionParent(selection),
|
|
});
|
|
|
|
const historyController = new ViewerHistoryWindowController({
|
|
historyWindows: host.historyWindows,
|
|
getWorld: () => host.world,
|
|
getHistoryWindowCounter: () => host.historyWindowCounter,
|
|
setHistoryWindowCounter: (value) => {
|
|
host.historyWindowCounter = value;
|
|
},
|
|
getHistoryWindowZCounter: () => host.historyWindowZCounter,
|
|
setHistoryWindowZCounter: (value) => {
|
|
host.historyWindowZCounter = value;
|
|
},
|
|
getHistoryWindowDragId: () => host.historyWindowDragId,
|
|
setHistoryWindowDragId: (value) => {
|
|
host.historyWindowDragId = value;
|
|
},
|
|
getHistoryWindowDragPointerId: () => host.historyWindowDragPointerId,
|
|
setHistoryWindowDragPointerId: (value) => {
|
|
host.historyWindowDragPointerId = value;
|
|
},
|
|
historyWindowDragOffset: host.historyWindowDragOffset,
|
|
renderRecentEvents: (entityKind, entityId) => presentationController.renderRecentEvents(entityKind, entityId),
|
|
});
|
|
|
|
const interactionController = new ViewerInteractionController({
|
|
renderer: host.renderer,
|
|
raycaster: host.raycaster,
|
|
mouse: host.mouse,
|
|
galaxyCamera: host.galaxyLayer.camera,
|
|
systemCamera: host.systemLayer.camera,
|
|
galaxySelectableTargets: host.galaxyLayer.selectableTargets,
|
|
systemSelectableTargets: host.systemLayer.selectableTargets,
|
|
hoverLabelEl: host.hoverLabelEl,
|
|
hoverConnectorLineEl: host.hoverConnectorLineEl,
|
|
marqueeEl: host.marqueeEl,
|
|
hudState: host.hudState,
|
|
keyState: host.keyState,
|
|
getWorld: () => host.world,
|
|
getActiveSystemId: () => host.activeSystemId,
|
|
getPovLevel: () => host.povLevel,
|
|
getSelectedItems: () => host.selectedItems,
|
|
setSelectedItems: (items) => {
|
|
host.applySelectedItems(items, "viewer");
|
|
},
|
|
getDragMode: () => host.dragMode,
|
|
setDragMode: (mode) => {
|
|
host.dragMode = mode;
|
|
},
|
|
getDragPointerId: () => host.dragPointerId,
|
|
setDragPointerId: (pointerId) => {
|
|
host.dragPointerId = pointerId;
|
|
},
|
|
dragStart: host.dragStart,
|
|
dragLast: host.dragLast,
|
|
getMarqueeActive: () => host.marqueeActive,
|
|
setMarqueeActive: (value) => {
|
|
host.marqueeActive = value;
|
|
},
|
|
getSuppressClickSelection: () => host.suppressClickSelection,
|
|
setSuppressClickSelection: (value) => {
|
|
host.suppressClickSelection = value;
|
|
},
|
|
getDesiredDistance: () => host.desiredDistance,
|
|
setDesiredDistance: (value) => {
|
|
host.desiredDistance = value;
|
|
},
|
|
getCameraMode: () => host.cameraMode,
|
|
setCameraMode: (value) => {
|
|
host.cameraMode = value;
|
|
},
|
|
getCameraTargetShipId: () => host.cameraTargetShipId,
|
|
setCameraTargetShipId: (value) => {
|
|
host.cameraTargetShipId = value;
|
|
},
|
|
getFollowCameraPosition: () => host.followCameraPosition,
|
|
getFollowCameraFocus: () => host.followCameraFocus,
|
|
screenPointFromClient: (x, y) => presentationController.screenPointFromClient(x, y),
|
|
applyOrbitDelta: (delta: THREE.Vector2) => {
|
|
if (host.cameraMode === "follow") {
|
|
host.followOrbitYaw += delta.x * 0.008;
|
|
host.followOrbitPitch = THREE.MathUtils.clamp(host.followOrbitPitch + delta.y * 0.004, 0.02, 1.45);
|
|
} else {
|
|
host.orbitYaw += delta.x * 0.008;
|
|
host.orbitPitch = THREE.MathUtils.clamp(host.orbitPitch + delta.y * 0.004, 0.18, 1.3);
|
|
}
|
|
},
|
|
syncFollowStateFromSelection: () => navigationController.syncFollowStateFromSelection(),
|
|
updatePanels: () => host.updatePanels(),
|
|
focusOnSelection: (selection) => navigationController.focusOnSelection(selection),
|
|
updateGamePanel: (mode) => host.updateGamePanel(mode),
|
|
openOrderContextMenu: (x, y, target) => orderContextMenuStore.open(x, y, target),
|
|
closeOrderContextMenu: () => orderContextMenuStore.close(),
|
|
historyController,
|
|
});
|
|
|
|
return {
|
|
historyController,
|
|
sceneDataController,
|
|
navigationController,
|
|
presentationController,
|
|
worldLifecycle,
|
|
interactionController,
|
|
};
|
|
}
|
|
|
|
export function wireViewerEvents(host: any) {
|
|
const canvas = host.renderer.domElement;
|
|
canvas.addEventListener("pointerdown", host.interactionController.onPointerDown);
|
|
canvas.addEventListener("pointermove", host.interactionController.onPointerMove);
|
|
canvas.addEventListener("pointerup", host.interactionController.onPointerUp);
|
|
canvas.addEventListener("pointerleave", host.interactionController.onPointerUp);
|
|
canvas.addEventListener("click", host.interactionController.onClick);
|
|
canvas.addEventListener("contextmenu", host.interactionController.onContextMenu);
|
|
canvas.addEventListener("dblclick", host.interactionController.onDoubleClick);
|
|
canvas.addEventListener("wheel", host.interactionController.onWheel, { passive: false });
|
|
host.historyLayerEl.addEventListener("click", host.interactionController.onHistoryLayerClick);
|
|
host.historyLayerEl.addEventListener("pointerdown", host.interactionController.onHistoryLayerPointerDown);
|
|
window.addEventListener("pointermove", host.interactionController.onHistoryWindowPointerMove);
|
|
window.addEventListener("pointerup", host.interactionController.onHistoryWindowPointerUp);
|
|
window.addEventListener("keydown", host.interactionController.onKeyDown);
|
|
window.addEventListener("keyup", host.interactionController.onKeyUp);
|
|
return () => {
|
|
canvas.removeEventListener("pointerdown", host.interactionController.onPointerDown);
|
|
canvas.removeEventListener("pointermove", host.interactionController.onPointerMove);
|
|
canvas.removeEventListener("pointerup", host.interactionController.onPointerUp);
|
|
canvas.removeEventListener("pointerleave", host.interactionController.onPointerUp);
|
|
canvas.removeEventListener("click", host.interactionController.onClick);
|
|
canvas.removeEventListener("contextmenu", host.interactionController.onContextMenu);
|
|
canvas.removeEventListener("dblclick", host.interactionController.onDoubleClick);
|
|
canvas.removeEventListener("wheel", host.interactionController.onWheel);
|
|
host.historyLayerEl.removeEventListener("click", host.interactionController.onHistoryLayerClick);
|
|
host.historyLayerEl.removeEventListener("pointerdown", host.interactionController.onHistoryLayerPointerDown);
|
|
window.removeEventListener("pointermove", host.interactionController.onHistoryWindowPointerMove);
|
|
window.removeEventListener("pointerup", host.interactionController.onHistoryWindowPointerUp);
|
|
window.removeEventListener("keydown", host.interactionController.onKeyDown);
|
|
window.removeEventListener("keyup", host.interactionController.onKeyUp);
|
|
};
|
|
}
|