Add support for point and spot lights in scene migration

This commit is contained in:
2026-03-31 19:57:57 +02:00
parent 6b3d2a7f61
commit 3b83683d2e

View File

@@ -14,8 +14,10 @@ import {
} from "../assets/project-assets";
import {
createInteractableEntity,
createPointLightEntity,
createPlayerStartEntity,
createSoundEmitterEntity,
createSpotLightEntity,
createTeleportTargetEntity,
createTriggerVolumeEntity,
type EntityInstance
@@ -42,6 +44,7 @@ import {
FACE_MATERIALS_SCENE_DOCUMENT_VERSION,
FIRST_ROOM_POLISH_SCENE_DOCUMENT_VERSION,
FOUNDATION_SCENE_DOCUMENT_VERSION,
LOCAL_LIGHTS_AND_SKYBOX_SCENE_DOCUMENT_VERSION,
MODEL_ASSET_PIPELINE_SCENE_DOCUMENT_VERSION,
RUNNER_V1_SCENE_DOCUMENT_VERSION,
SCENE_DOCUMENT_VERSION,
@@ -572,12 +575,17 @@ function readWorldSettings(value: unknown): WorldSettings {
mode: "solid",
colorHex: expectHexColor(background.colorHex, "world.background.colorHex")
};
} else {
} else if (backgroundMode === "verticalGradient") {
resolvedBackground = {
mode: "verticalGradient",
topColorHex: expectHexColor(background.topColorHex, "world.background.topColorHex"),
bottomColorHex: expectHexColor(background.bottomColorHex, "world.background.bottomColorHex")
};
} else {
resolvedBackground = {
mode: "image",
assetId: expectString(background.assetId, "world.background.assetId")
};
}
return {
@@ -594,6 +602,50 @@ function readWorldSettings(value: unknown): WorldSettings {
};
}
function readPointLightEntity(value: unknown, label: string): EntityInstance {
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
}
const kind = expectLiteralString(value.kind, "pointLight", `${label}.kind`);
const entity = createPointLightEntity({
id: expectString(value.id, `${label}.id`),
position: readVec3(value.position, `${label}.position`),
colorHex: expectHexColor(value.colorHex, `${label}.colorHex`),
intensity: expectNonNegativeFiniteNumber(value.intensity, `${label}.intensity`),
distance: expectPositiveFiniteNumber(value.distance, `${label}.distance`)
});
if (entity.kind !== kind) {
throw new Error(`${label}.kind must be pointLight.`);
}
return entity;
}
function readSpotLightEntity(value: unknown, label: string): EntityInstance {
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
}
const kind = expectLiteralString(value.kind, "spotLight", `${label}.kind`);
const entity = createSpotLightEntity({
id: expectString(value.id, `${label}.id`),
position: readVec3(value.position, `${label}.position`),
direction: readVec3(value.direction, `${label}.direction`),
colorHex: expectHexColor(value.colorHex, `${label}.colorHex`),
intensity: expectNonNegativeFiniteNumber(value.intensity, `${label}.intensity`),
distance: expectPositiveFiniteNumber(value.distance, `${label}.distance`),
angleDegrees: expectFiniteNumber(value.angleDegrees, `${label}.angleDegrees`)
});
if (entity.kind !== kind) {
throw new Error(`${label}.kind must be spotLight.`);
}
return entity;
}
function readPlayerStartEntity(value: unknown, label: string): EntityInstance {
if (!isRecord(value)) {
throw new Error(`${label} must be an object.`);
@@ -708,6 +760,10 @@ function readEntityInstance(value: unknown, label: string): EntityInstance {
}
switch (value.kind) {
case "pointLight":
return readPointLightEntity(value, label);
case "spotLight":
return readSpotLightEntity(value, label);
case "playerStart":
return readPlayerStartEntity(value, label);
case "soundEmitter":
@@ -984,6 +1040,23 @@ export function migrateSceneDocument(source: unknown): SceneDocument {
};
}
if (source.version === LOCAL_LIGHTS_AND_SKYBOX_SCENE_DOCUMENT_VERSION) {
const materials = readMaterialRegistry(source.materials, "materials");
return {
version: SCENE_DOCUMENT_VERSION,
name: expectString(source.name, "name"),
world: readWorldSettings(source.world),
materials,
textures: expectEmptyCollection(source.textures, "textures"),
assets: readAssets(source.assets),
brushes: readBrushes(source.brushes, materials, false),
modelInstances: readModelInstances(source.modelInstances, readAssets(source.assets)),
entities: readEntities(source.entities),
interactionLinks: readInteractionLinks(source.interactionLinks)
};
}
if (source.version !== SCENE_DOCUMENT_VERSION) {
throw new Error(`Unsupported scene document version: ${String(source.version)}.`);
}