Files
webeditor3d/src/runtime-three/runtime-scene-editor-simulation.ts
Victor Giers 49025115d9 auto-git:
[change] src/runtime-three/runtime-scene-editor-simulation.ts
2026-04-23 02:37:08 +02:00

151 lines
4.4 KiB
TypeScript

import type {
RuntimeResolvedControlChannelValue,
RuntimeResolvedDiscreteControlState
} from "../controls/control-surface";
import type { RuntimeSceneDefinition } from "./runtime-scene-build";
function mutateRuntimeLight(
runtimeScene: RuntimeSceneDefinition,
entityId: string,
mutate: (
light:
| RuntimeSceneDefinition["localLights"]["pointLights"][number]
| RuntimeSceneDefinition["localLights"]["spotLights"][number]
) => void
) {
const pointLight = runtimeScene.localLights.pointLights.find(
(candidate) => candidate.entityId === entityId
);
if (pointLight !== undefined) {
mutate(pointLight);
return;
}
const spotLight = runtimeScene.localLights.spotLights.find(
(candidate) => candidate.entityId === entityId
);
if (spotLight !== undefined) {
mutate(spotLight);
}
}
function applyResolvedDiscreteControlStateToRuntimeScene(
runtimeScene: RuntimeSceneDefinition,
state: RuntimeResolvedDiscreteControlState
) {
switch (state.type) {
case "projectTimePaused":
case "cameraRigOverride":
case "actorPresence":
case "actorAnimationPlayback":
case "actorPathAssignment":
// Runtime scene build already resolves scheduler-owned actor state.
return;
case "modelVisibility": {
const modelInstance = runtimeScene.modelInstances.find(
(candidate) => candidate.instanceId === state.target.modelInstanceId
);
if (modelInstance !== undefined) {
modelInstance.visible = state.value;
}
return;
}
case "soundPlayback": {
const soundEmitter = runtimeScene.entities.soundEmitters.find(
(candidate) => candidate.entityId === state.target.entityId
);
if (soundEmitter !== undefined) {
soundEmitter.autoplay = state.value;
}
return;
}
case "modelAnimationPlayback": {
const modelInstance = runtimeScene.modelInstances.find(
(candidate) => candidate.instanceId === state.target.modelInstanceId
);
if (modelInstance !== undefined) {
modelInstance.animationClipName = state.clipName ?? undefined;
modelInstance.animationAutoplay = state.clipName !== null;
modelInstance.animationLoop =
state.clipName === null ? undefined : state.loop;
}
return;
}
case "lightEnabled":
mutateRuntimeLight(runtimeScene, state.target.entityId, (light) => {
light.enabled = state.value;
});
return;
case "lightColor":
mutateRuntimeLight(runtimeScene, state.target.entityId, (light) => {
light.colorHex = state.value;
});
return;
case "interactionEnabled":
const interactable = runtimeScene.entities.interactables.find(
(candidate) => candidate.entityId === state.target.entityId
);
if (interactable !== undefined) {
interactable.interactionEnabled = state.value;
}
return;
case "ambientLightColor":
runtimeScene.world.ambientLight.colorHex = state.value;
return;
case "sunLightColor":
runtimeScene.world.sunLight.colorHex = state.value;
return;
}
}
function applyResolvedControlChannelValueToRuntimeScene(
runtimeScene: RuntimeSceneDefinition,
channelValue: RuntimeResolvedControlChannelValue
) {
switch (channelValue.type) {
case "lightIntensity":
mutateRuntimeLight(runtimeScene, channelValue.descriptor.target.entityId, (light) => {
light.intensity = channelValue.value;
});
return;
case "soundVolume": {
const soundEmitter = runtimeScene.entities.soundEmitters.find(
(candidate) =>
candidate.entityId === channelValue.descriptor.target.entityId
);
if (soundEmitter !== undefined) {
soundEmitter.volume = channelValue.value;
}
return;
}
case "ambientLightIntensity":
runtimeScene.world.ambientLight.intensity = channelValue.value;
return;
case "sunLightIntensity":
runtimeScene.world.sunLight.intensity = channelValue.value;
return;
}
}
export function applyResolvedControlStateToRuntimeScene(
runtimeScene: RuntimeSceneDefinition
): RuntimeSceneDefinition {
for (const state of runtimeScene.control.resolved.discrete) {
applyResolvedDiscreteControlStateToRuntimeScene(runtimeScene, state);
}
for (const channelValue of runtimeScene.control.resolved.channels) {
applyResolvedControlChannelValueToRuntimeScene(runtimeScene, channelValue);
}
return runtimeScene;
}