feat(simulation): add worker-gated 3d polygon workspace

This commit is contained in:
DCCONSTRUCTIONS
2026-07-24 21:03:41 +03:00
parent 1995dfdf68
commit 6cc40282e0
10 changed files with 731 additions and 139 deletions
+16 -5
View File
@@ -47,6 +47,7 @@ import type {
import { useRecordedSessionAdmission } from "./core/observation/useRecordedSessionAdmission";
import { useWorkspaceLayoutProfile } from "./core/observation/useWorkspaceLayoutProfile";
import { resolvePolygonRunRoute } from "./core/polygon/runArchive";
import { usePolygonWorkerCapability } from "./core/polygon/usePolygonWorkerCapability";
import {
OBSERVATION_WORKSPACE_ID,
OBSERVATION_WORKSPACE_LAYOUT_VERSION,
@@ -54,7 +55,7 @@ import {
} from "./core/observation/workspaceLayout";
import {
rootById,
roots,
rootsForCapabilities,
workspaceById,
workspacesForRoot,
type RootId,
@@ -150,6 +151,7 @@ function mergeViewerSettings(
export default function App() {
const runtime = useMissionRuntime();
const { selection } = useDevicePluginHost();
const polygonWorker = usePolygonWorkerCapability();
const polygonRunRoute = useMemo(
() => resolvePolygonRunRoute(typeof window === "undefined" ? "" : window.location.search),
[],
@@ -160,7 +162,7 @@ export default function App() {
});
const [activeRoot, setActiveRoot] = useState<RootId | null>(
polygonRunRoute.active ? "system" : null,
polygonRunRoute.active ? "polygon" : null,
);
const [sourceUrl, setSourceUrl] = useState("");
const [recordedReplay, setRecordedReplay] = useState<ObservationSessionReplayLaunch | null>(null);
@@ -197,6 +199,10 @@ export default function App() {
const polygonRunRouteOpenedRef = useRef(false);
const currentRoot = rootById(activeRoot);
const visibleRoots = useMemo(
() => rootsForCapabilities({ polygonWorkerAvailable: polygonWorker.available }),
[polygonWorker.available],
);
const activeDefinition = workspaceById(workspace.activeView);
const spatialWorkspaceActive = Boolean(
workspace.contentOpen && activeDefinition?.kind === "spatial",
@@ -215,7 +221,7 @@ export default function App() {
useEffect(() => {
if (!polygonRunRoute.active || polygonRunRouteOpenedRef.current) return;
polygonRunRouteOpenedRef.current = true;
workspace.openView("polygon-run-internal");
workspace.openView("polygon-run");
}, [polygonRunRoute.active, workspace]);
if (!sceneSettingsCommitterRef.current) {
@@ -413,6 +419,11 @@ export default function App() {
const selectRoot = (rootId: RootId) => {
setActiveRoot(rootId);
if (rootId === "polygon") {
workspace.closeNavigation();
workspace.openView("polygon-run");
return;
}
workspace.closeView();
workspace.openNavigation();
};
@@ -618,7 +629,7 @@ export default function App() {
<HeaderNavigation
label="Архитектурные блоки пункта управления"
value={activeRoot ?? undefined}
items={roots.map((root) => ({ value: root.id, label: root.label }))}
items={visibleRoots.map((root) => ({ value: root.id, label: root.label }))}
onChange={selectRoot}
/>
</>
@@ -733,7 +744,7 @@ export default function App() {
) : null}
</div>
) : activeDefinition.kind === "polygon-run" ? (
<StatusBadge tone="accent">Только чтение</StatusBadge>
<StatusBadge tone="accent">Virtual only</StatusBadge>
) : (
<StatusBadge tone="warning">Интерфейс готов</StatusBadge>
)