Add support and migration logic for Spline Corridor Junctions

This commit is contained in:
2026-05-13 13:12:12 +02:00
parent 611738d1a0
commit abed515db3

View File

@@ -254,6 +254,7 @@ import {
NPC_PRESENCE_SCENE_DOCUMENT_VERSION, NPC_PRESENCE_SCENE_DOCUMENT_VERSION,
NPC_TARGETING_SCENE_DOCUMENT_VERSION, NPC_TARGETING_SCENE_DOCUMENT_VERSION,
PATH_TERRAIN_GLUE_SCENE_DOCUMENT_VERSION, PATH_TERRAIN_GLUE_SCENE_DOCUMENT_VERSION,
SPLINE_CORRIDOR_JUNCTIONS_SCENE_DOCUMENT_VERSION,
SPLINE_CORRIDOR_COLLISION_SCENE_DOCUMENT_VERSION, SPLINE_CORRIDOR_COLLISION_SCENE_DOCUMENT_VERSION,
SPLINE_ROAD_EDGES_SCENE_DOCUMENT_VERSION, SPLINE_ROAD_EDGES_SCENE_DOCUMENT_VERSION,
SPLINE_REPEATERS_SCENE_DOCUMENT_VERSION, SPLINE_REPEATERS_SCENE_DOCUMENT_VERSION,
@@ -331,6 +332,15 @@ import {
type ScenePathRoadSettings, type ScenePathRoadSettings,
type ScenePathPoint type ScenePathPoint
} from "./paths"; } from "./paths";
import {
createSplineCorridorJunction,
isSplineCorridorJunctionTerrainMode,
normalizeSplineCorridorJunctionClipDistance,
normalizeSplineCorridorJunctionMaterialId,
normalizeSplineCorridorJunctionRadius,
type SplineCorridorJunction,
type SplineCorridorJunctionConnection
} from "./spline-corridor-junctions";
import { import {
createTerrain, createTerrain,
normalizeTerrainCellSize, normalizeTerrainCellSize,
@@ -5976,6 +5986,107 @@ function readScenePaths(value: unknown): SceneDocument["paths"] {
return paths; return paths;
} }
function readSplineCorridorJunctionConnectionValue(
value: unknown,
label: string
): SplineCorridorJunctionConnection {
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
}
return {
id: expectString(value.id, `${label}.id`),
pathId: expectString(value.pathId, `${label}.pathId`),
progress: readOptionalFiniteNumber(value.progress, `${label}.progress`, 0),
clipDistance: normalizeSplineCorridorJunctionClipDistance(
readOptionalFiniteNumber(
value.clipDistance,
`${label}.clipDistance`,
1.5
)
)
};
}
function readSplineCorridorJunctionValue(
value: unknown,
label: string
): SplineCorridorJunction {
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
}
if (!Array.isArray(value.connections)) {
throw new Error(`${label}.connections must be an array.`);
}
return createSplineCorridorJunction({
id: expectString(value.id, `${label}.id`),
name:
value.name === undefined
? undefined
: expectString(value.name, `${label}.name`),
visible: readOptionalBoolean(value.visible, `${label}.visible`, true),
enabled: readOptionalBoolean(value.enabled, `${label}.enabled`, true),
center: readVec3(value.center, `${label}.center`),
radius: normalizeSplineCorridorJunctionRadius(
readOptionalFiniteNumber(value.radius, `${label}.radius`, 1.5)
),
materialId: normalizeSplineCorridorJunctionMaterialId(
value.materialId === undefined || value.materialId === null
? null
: expectString(value.materialId, `${label}.materialId`)
),
terrainMode:
value.terrainMode === undefined
? undefined
: isSplineCorridorJunctionTerrainMode(value.terrainMode)
? value.terrainMode
: expectLiteralString(
value.terrainMode,
"flattenAndPaint",
`${label}.terrainMode`
),
connections: value.connections.map((connectionValue, index) =>
readSplineCorridorJunctionConnectionValue(
connectionValue,
`${label}.connections.${index}`
)
)
});
}
function readSplineCorridorJunctions(
value: unknown
): SceneDocument["splineCorridorJunctions"] {
if (value === undefined) {
return {};
}
if (!isRecord(value)) {
throw new Error("splineCorridorJunctions must be a record.");
}
const junctions: SceneDocument["splineCorridorJunctions"] = {};
for (const [junctionId, junctionValue] of Object.entries(value)) {
const junction = readSplineCorridorJunctionValue(
junctionValue,
`splineCorridorJunctions.${junctionId}`
);
if (junction.id !== junctionId) {
throw new Error(
`splineCorridorJunctions.${junctionId}.id must match the registry key.`
);
}
junctions[junctionId] = junction;
}
return junctions;
}
export function migrateSceneDocument(source: unknown): SceneDocument { export function migrateSceneDocument(source: unknown): SceneDocument {
if (!isRecord(source)) { if (!isRecord(source)) {
throw new Error("Scene document must be a JSON object."); throw new Error("Scene document must be a JSON object.");