feat(perception): project recorded results into Rerun

This commit is contained in:
DCCONSTRUCTIONS
2026-07-19 17:39:13 +03:00
parent 31fc4f6567
commit 2b53168149
13 changed files with 1328 additions and 8 deletions
@@ -45,6 +45,7 @@ import {
type RerunPlaybackState,
type RerunSelection,
type RerunViewportStatus,
type RecordedRerunView,
} from "../components/RerunViewport";
import {
capabilityStatusLabel,
@@ -294,6 +295,8 @@ function SpatialWorkspace({
const [selection, setSelection] = useState<RerunSelection | null>(null);
const [playbackState, setPlaybackState] = useState<RerunPlaybackState | null>(null);
const [playbackController, setPlaybackController] = useState<RerunPlaybackController | null>(null);
const [recordedRerunView, setRecordedRerunView] = useState<RecordedRerunView>("spatial");
const [perceptionAvailable, setPerceptionAvailable] = useState(false);
const recordedSource = state?.sourceMode === "replay" || /\.rrd(?:$|[?#])/i.test(sourceUrl);
const recordedSessionGate: RecordedAdmissionPhase = recordedSource
? recordedSessionAdmission?.phase ?? "loading"
@@ -369,6 +372,15 @@ function SpatialWorkspace({
(next: RerunPlaybackController | null) => setPlaybackController(next),
[],
);
const onPerceptionAvailabilityChange = useCallback((available: boolean) => {
setPerceptionAvailable(available);
if (!available) setRecordedRerunView("spatial");
}, []);
useEffect(() => {
setPerceptionAvailable(false);
setRecordedRerunView("spatial");
}, [sourceUrl]);
useEffect(() => {
if (pointCloudVisible && sourceUrl.trim()) return;
@@ -377,6 +389,8 @@ function SpatialWorkspace({
setSelection(null);
setPlaybackState(null);
setPlaybackController(null);
setPerceptionAvailable(false);
setRecordedRerunView("spatial");
}, [pointCloudVisible, sourceUrl]);
useEffect(() => {
@@ -419,6 +433,17 @@ function SpatialWorkspace({
<span className="section-eyebrow">СЦЕНА 3D · RERUN</span>
</div>
<div className="spatial-toolbar__actions">
{recordedSource && perceptionAvailable ? (
<Button
size="compact"
variant={recordedRerunView === "perception" ? "primary" : "secondary"}
icon={<Icon name={recordedRerunView === "perception" ? "globe" : "image"} />}
onClick={() => setRecordedRerunView((current) =>
current === "perception" ? "spatial" : "perception")}
>
{recordedRerunView === "perception" ? "Облако точек" : "Распознавание"}
</Button>
) : null}
<Button size="compact" variant="secondary" icon={<Icon name="network" />} onClick={navigation.openSource}>
Движок
</Button>
@@ -451,6 +476,8 @@ function SpatialWorkspace({
? state?.observationTimeline?.range?.endSeconds
: undefined}
sceneSettings={sceneSettings}
recordedView={recordedRerunView}
onPerceptionAvailabilityChange={onPerceptionAvailabilityChange}
onStatusChange={onStatusChange}
onSelectionChange={onSelectionChange}
onPlaybackChange={onPlaybackChange}
@@ -630,7 +657,7 @@ function SpatialWorkspace({
<span><i data-state="ready" />Траектория</span>
<span><i data-state="ready" />Преобразования</span>
<span><i data-state="contract" />Камеры в 3D</span>
<span><i data-state="contract" />Объекты / маски</span>
<span><i data-state={perceptionAvailable ? "ready" : "contract"} />Объекты / рамки</span>
<span><i data-state="contract" />Компоновка</span>
</div>
</div>