Add test for runtime scene editor simulation

This commit is contained in:
2026-04-14 20:54:32 +02:00
parent caedbb17f8
commit 00dff0edd1

View File

@@ -0,0 +1,147 @@
import { describe, expect, it } from "vitest";
import { createModelInstance } from "../../src/assets/model-instances";
import {
createProjectAssetStorageKey,
type ModelAssetRecord
} from "../../src/assets/project-assets";
import {
createActiveSceneControlTargetRef,
createInteractionControlTargetRef,
createLightControlTargetRef,
createModelInstanceControlTargetRef,
createSetAmbientLightIntensityControlEffect,
createSetInteractionEnabledControlEffect,
createSetLightIntensityControlEffect,
createSetModelInstanceVisibleControlEffect
} from "../../src/controls/control-surface";
import { createEmptySceneDocument } from "../../src/document/scene-document";
import {
createInteractableEntity,
createPointLightEntity
} from "../../src/entities/entity-instances";
import { createRuntimeClockState } from "../../src/runtime-three/runtime-project-time";
import { buildRuntimeSceneFromDocument } from "../../src/runtime-three/runtime-scene-build";
import { applyResolvedControlStateToRuntimeScene } from "../../src/runtime-three/runtime-scene-editor-simulation";
import { createProjectScheduleRoutine } from "../../src/scheduler/project-scheduler";
describe("runtime scene editor simulation", () => {
it("applies resolved scheduler-controlled state onto runtime scene data for editor rendering", () => {
const pointLight = createPointLightEntity({
id: "entity-point-light-night-lamp",
intensity: 1.25
});
const interactable = createInteractableEntity({
id: "entity-interactable-market-stall",
interactionEnabled: true
});
const modelAsset = {
id: "asset-model-stall-awning",
kind: "model" as const,
sourceName: "stall-awning.glb",
mimeType: "model/gltf-binary",
storageKey: createProjectAssetStorageKey("asset-model-stall-awning"),
byteLength: 1024,
metadata: {
kind: "model" as const,
format: "glb" as const,
sceneName: null,
nodeCount: 1,
meshCount: 1,
materialNames: [],
textureNames: [],
animationNames: [],
boundingBox: null,
warnings: []
}
} satisfies ModelAssetRecord;
const modelInstance = createModelInstance({
id: "model-instance-stall-awning",
assetId: modelAsset.id,
visible: true
});
const lightTarget = createLightControlTargetRef("pointLight", pointLight.id);
const interactionTarget = createInteractionControlTargetRef(
"interactable",
interactable.id
);
const modelTarget = createModelInstanceControlTargetRef(modelInstance.id);
const sceneTarget = createActiveSceneControlTargetRef();
const document = createEmptySceneDocument();
document.time.startTimeOfDayHours = 21;
document.entities[pointLight.id] = pointLight;
document.entities[interactable.id] = interactable;
document.assets[modelAsset.id] = modelAsset;
document.modelInstances[modelInstance.id] = modelInstance;
document.scheduler.routines["routine-night-light"] =
createProjectScheduleRoutine({
id: "routine-night-light",
title: "Night Light",
target: lightTarget,
startHour: 18,
endHour: 6,
effect: createSetLightIntensityControlEffect({
target: lightTarget,
intensity: 3.5
})
});
document.scheduler.routines["routine-close-stall"] =
createProjectScheduleRoutine({
id: "routine-close-stall",
title: "Close Stall",
target: interactionTarget,
startHour: 18,
endHour: 6,
effect: createSetInteractionEnabledControlEffect({
target: interactionTarget,
enabled: false
})
});
document.scheduler.routines["routine-hide-awning"] =
createProjectScheduleRoutine({
id: "routine-hide-awning",
title: "Hide Awning",
target: modelTarget,
startHour: 18,
endHour: 6,
effect: createSetModelInstanceVisibleControlEffect({
target: modelTarget,
visible: false
})
});
document.scheduler.routines["routine-night-ambient"] =
createProjectScheduleRoutine({
id: "routine-night-ambient",
title: "Night Ambient",
target: sceneTarget,
startHour: 18,
endHour: 6,
effect: createSetAmbientLightIntensityControlEffect({
target: sceneTarget,
intensity: 0.2
})
});
const runtimeScene = buildRuntimeSceneFromDocument(document, {
runtimeClock: createRuntimeClockState(document.time)
});
expect(runtimeScene.localLights.pointLights[0]?.intensity).toBe(1.25);
expect(runtimeScene.entities.interactables[0]?.interactionEnabled).toBe(true);
expect(runtimeScene.modelInstances[0]?.visible).toBe(true);
expect(runtimeScene.world.ambientLight.intensity).toBe(
document.world.ambientLight.intensity
);
expect(applyResolvedControlStateToRuntimeScene(runtimeScene)).toBe(
runtimeScene
);
expect(runtimeScene.localLights.pointLights[0]?.intensity).toBe(3.5);
expect(runtimeScene.entities.interactables[0]?.interactionEnabled).toBe(
false
);
expect(runtimeScene.modelInstances[0]?.visible).toBe(false);
expect(runtimeScene.world.ambientLight.intensity).toBe(0.2);
});
});