fix(viewer): preserve operator camera across AI layers

This commit is contained in:
DCCONSTRUCTIONS
2026-07-23 10:51:18 +03:00
parent a0706fd5d8
commit 3a64f54dea
12 changed files with 425 additions and 109 deletions
@@ -445,6 +445,7 @@ export async function fetchRecordedBlueprintRrd(
identity: RecordedRerunIdentity,
{
origin,
blueprintSessionId,
signal,
activeView = "spatial",
viewResetGeneration = 0,
@@ -457,6 +458,7 @@ export async function fetchRecordedBlueprintRrd(
fetcher = globalThis.fetch,
}: {
origin: string;
blueprintSessionId: string;
signal?: AbortSignal;
activeView?: RecordedRerunView;
viewResetGeneration?: 0 | 1;
@@ -488,7 +490,8 @@ export async function fetchRecordedBlueprintRrd(
perceptionLayers.cuboids3d,
].some((value) => typeof value !== "boolean") ||
identity.applicationId !== "nodedc_mission_core_recorded" ||
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(identity.recordingId)
!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(identity.recordingId) ||
!/^[a-f0-9]{32}$/.test(blueprintSessionId)
) {
throw new Error("Unsafe recorded blueprint request");
}
@@ -502,6 +505,7 @@ export async function fetchRecordedBlueprintRrd(
body: JSON.stringify({
application_id: identity.applicationId,
recording_id: identity.recordingId,
blueprint_session_id: blueprintSessionId,
accumulation_seconds: settings.accumulationSeconds,
show_grid: settings.showGrid,
show_points: settings.showPoints,
@@ -635,6 +639,7 @@ export function RerunViewport({
const perceptionChannelRef = useRef<RerunBlueprintChannel | null>(null);
const loadedPerceptionChannelRef = useRef<RerunBlueprintChannel | null>(null);
const recordedIdentityRef = useRef<RecordedRerunIdentity | null>(null);
const blueprintSessionIdRef = useRef(crypto.randomUUID().replaceAll("-", ""));
const presentationGateRef = useRef(presentationGate);
presentationGateRef.current = presentationGate;
const [blueprintChannelRevision, setBlueprintChannelRevision] = useState(0);
@@ -1223,6 +1228,7 @@ export function RerunViewport({
const abort = new AbortController();
void fetchRecordedBlueprintRrd(recordedBlueprintUrl, sceneSettings, identity, {
origin: window.location.origin,
blueprintSessionId: blueprintSessionIdRef.current,
signal: abort.signal,
activeView: recordedView,
viewResetGeneration: recordedViewResetGeneration,
@@ -336,8 +336,10 @@ function SpatialWorkspace({
(source) => source.capabilities.overlay && source.modality !== "point-cloud",
);
const recordedPerceptionSupported = recordedSource && perceptionAvailability !== "unavailable";
const recordedPerceptionEnabled = showDetections2d || showSegmentation || showCuboids3d;
const unifiedPerception = recordedPerceptionSupported && recordedPerceptionEnabled;
// Keep one stable original-video + world composition for every admitted
// perception recording. Layer buttons then only change entity visibility;
// they never reparent the 3D view or invalidate the operator's camera.
const unifiedPerception = recordedPerceptionSupported;
const livePerceptionAvailable = !recordedSource && streamActive;
const detections2dActive = recordedSource
? showDetections2d