diff --git a/README.md b/README.md index f35e57d..a8888a3 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,9 @@ immutable donor revision remains a packaging and CI prerequisite. The Observation spatial workspace embeds the open-source Rerun Web Viewer inside the Mission Core shell. It can open a compatible RRD file over HTTP(S) or a Rerun gRPC/proxy source such as `rerun+http://127.0.0.1:9876/proxy`. It does not -use an external hosted viewer UI. +use an external hosted viewer UI. Dynamic point-cloud and camera source +composition, host-owned window layout and the current live-only timeline contract +are fixed in [`ADR 0006`](docs/adr/0006-vendor-neutral-observation-sources-and-live-only-timeline.md). The first K1 live session or replay in a `k1link serve` process creates one local Rerun `RecordingStream`, starts its gRPC/proxy server on TCP 9876 and publishes diff --git a/apps/control-station/src/App.tsx b/apps/control-station/src/App.tsx index ee55016..5d75cd7 100644 --- a/apps/control-station/src/App.tsx +++ b/apps/control-station/src/App.tsx @@ -29,6 +29,7 @@ import { LandingStage } from "./components/LandingStage"; import { useDevicePluginHost } from "./core/device-plugins/DevicePluginHost"; import { useMissionRuntime } from "./core/runtime/MissionRuntimeContext"; import type { ViewerSettings } from "./core/runtime/contracts"; +import { useObservationLayout } from "./core/observation/useObservationLayout"; import { rootById, roots, @@ -132,6 +133,7 @@ export default function App() { const activeSceneWindow = sceneWindowOrder[sceneWindowOrder.length - 1] ?? null; const automaticSourceUrl = runtime.state?.spatialSource?.url.trim() ?? ""; const effectiveSourceUrl = sourceUrl || automaticSourceUrl; + const observationLayout = useObservationLayout(runtime.state?.observationSources ?? []); useEffect(() => { const remote = runtime.state?.viewerSettings; @@ -238,7 +240,7 @@ export default function App() { if (activeDefinition?.kind === "spatial") { actions.push( - { label: "Настроить источник", icon: "network", onClick: openSource }, + { label: "Настроить визуальный движок", icon: "network", onClick: openSource }, { label: "Настроить отображение", icon: "sliders", onClick: openDisplay }, { label: "Открыть слои", icon: "list", onClick: openLayers }, ); @@ -370,6 +372,7 @@ export default function App() { backendStatus={runtime.backendStatus} sourceUrl={effectiveSourceUrl} sceneSettings={sceneSettings} + observationLayout={observationLayout} navigation={{ openView, openSource, @@ -384,8 +387,8 @@ export default function App() { ; + rect?: ObservationWindowRect; + maximized: boolean; + active: boolean; + onRectChange: (rect: ObservationWindowRect) => void; + onMaximizedChange: (maximized: boolean) => void; + onActivate: () => void; + onClose: () => void; +}) { + return ( + +