Refactor interaction link handling in App.tsx and update tests

This commit is contained in:
2026-04-02 19:19:54 +02:00
parent 7bc4ca3293
commit 74e7be5073
4 changed files with 62 additions and 29 deletions

View File

@@ -84,7 +84,6 @@ import {
DEFAULT_POINT_LIGHT_COLOR_HEX,
DEFAULT_POINT_LIGHT_DISTANCE,
DEFAULT_POINT_LIGHT_INTENSITY,
DEFAULT_POINT_LIGHT_POSITION,
DEFAULT_SOUND_EMITTER_GAIN,
DEFAULT_SOUND_EMITTER_RADIUS,
DEFAULT_TELEPORT_TARGET_YAW_DEGREES,
@@ -93,7 +92,6 @@ import {
DEFAULT_SPOT_LIGHT_DISTANCE,
DEFAULT_SPOT_LIGHT_DIRECTION,
DEFAULT_SPOT_LIGHT_INTENSITY,
DEFAULT_SPOT_LIGHT_POSITION,
DEFAULT_TRIGGER_VOLUME_SIZE,
areEntityInstancesEqual,
createInteractableEntity,
@@ -1623,21 +1621,45 @@ export function App({ store, initialStatusMessage }: AppProps) {
return;
}
const nextLink =
link.action.type === "teleportPlayer"
? createTeleportPlayerInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetEntityId: link.action.targetEntityId
})
: createToggleVisibilityInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetBrushId: link.action.targetBrushId,
visible: link.action.visible
});
let nextLink: InteractionLink;
switch (link.action.type) {
case "teleportPlayer":
nextLink = createTeleportPlayerInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetEntityId: link.action.targetEntityId
});
break;
case "toggleVisibility":
nextLink = createToggleVisibilityInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetBrushId: link.action.targetBrushId,
visible: link.action.visible
});
break;
case "playAnimation":
nextLink = createPlayAnimationInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetModelInstanceId: link.action.targetModelInstanceId,
clipName: link.action.clipName,
loop: link.action.loop
});
break;
case "stopAnimation":
nextLink = createStopAnimationInteractionLink({
id: link.id,
sourceEntityId: link.sourceEntityId,
trigger,
targetModelInstanceId: link.action.targetModelInstanceId
});
break;
}
commitInteractionLinkChange(link, nextLink, `Updated ${getInteractionTriggerLabel(trigger).toLowerCase()} trigger link.`);
};
@@ -1671,14 +1693,17 @@ export function App({ store, initialStatusMessage }: AppProps) {
}
if (actionType === "playAnimation") {
const firstInstance = modelInstanceDisplayList[0];
const targetModelInstance =
(link.action.type === "playAnimation" || link.action.type === "stopAnimation"
? editorState.document.modelInstances[link.action.targetModelInstanceId]
: undefined) ?? modelInstanceDisplayList[0]?.modelInstance;
if (firstInstance === undefined) {
if (targetModelInstance === undefined) {
setStatusMessage("Place a model instance before switching this link to play animation.");
return;
}
const asset = editorState.document.assets[firstInstance.modelInstance.assetId];
const asset = editorState.document.assets[targetModelInstance.assetId];
const firstClip = asset?.kind === "model" ? (asset.metadata.animationNames[0] ?? "") : "";
if (firstClip === "") {
@@ -1692,7 +1717,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
id: link.id,
sourceEntityId: sourceEntity.id,
trigger: link.trigger,
targetModelInstanceId: firstInstance.modelInstance.id,
targetModelInstanceId: targetModelInstance.id,
clipName: firstClip
}),
"Switched link action to play animation."
@@ -1701,9 +1726,12 @@ export function App({ store, initialStatusMessage }: AppProps) {
}
if (actionType === "stopAnimation") {
const firstInstance = modelInstanceDisplayList[0];
const targetModelInstance =
(link.action.type === "playAnimation" || link.action.type === "stopAnimation"
? editorState.document.modelInstances[link.action.targetModelInstanceId]
: undefined) ?? modelInstanceDisplayList[0]?.modelInstance;
if (firstInstance === undefined) {
if (targetModelInstance === undefined) {
setStatusMessage("Place a model instance before switching this link to stop animation.");
return;
}
@@ -1714,7 +1742,7 @@ export function App({ store, initialStatusMessage }: AppProps) {
id: link.id,
sourceEntityId: sourceEntity.id,
trigger: link.trigger,
targetModelInstanceId: firstInstance.modelInstance.id
targetModelInstanceId: targetModelInstance.id
}),
"Switched link action to stop animation."
);

View File

@@ -226,7 +226,8 @@ describe("buildRuntimeSceneFromDocument", () => {
};
document.world.background = {
mode: "image",
assetId: imageAsset.id
assetId: imageAsset.id,
environmentIntensity: 0.75
};
document.world.ambientLight.intensity = 0.55;
document.world.sunLight.direction = {

View File

@@ -237,7 +237,8 @@ describe("validateSceneDocument", () => {
};
document.world.background = {
mode: "image",
assetId: imageAsset.id
assetId: imageAsset.id,
environmentIntensity: 0.5
};
const validation = validateSceneDocument(document);
@@ -273,7 +274,8 @@ describe("validateSceneDocument", () => {
};
document.world.background = {
mode: "image",
assetId: "asset-missing-background"
assetId: "asset-missing-background",
environmentIntensity: 0.5
};
const validation = validateSceneDocument(document);

View File

@@ -42,14 +42,16 @@ describe("world settings helpers", () => {
expect(imageBackground).toEqual({
mode: "image",
assetId: "asset-background-panorama"
assetId: "asset-background-panorama",
environmentIntensity: 0.5
});
const nextImageBackground = changeWorldBackgroundMode(imageBackground, "image", "asset-background-panorama-2");
expect(nextImageBackground).toEqual({
mode: "image",
assetId: "asset-background-panorama-2"
assetId: "asset-background-panorama-2",
environmentIntensity: 0.5
});
const world = createDefaultWorldSettings();