Remove unused background overlay and update tests

This commit is contained in:
2026-04-13 14:11:18 +02:00
parent 4f67e7b655
commit 5bbcb2c850
4 changed files with 77 additions and 60 deletions

View File

@@ -1258,13 +1258,6 @@ button:disabled {
pointer-events: auto;
}
.runner-canvas__background-overlay {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
}
.runner-canvas__loading-overlay--hidden {
opacity: 0;
visibility: hidden;

View File

@@ -15,14 +15,12 @@ import type { RuntimeInteractionPrompt } from "../runtime-three/runtime-interact
import {
areRuntimeClockStatesEqual,
createRuntimeClockState,
resolveRuntimeDayNightWorldState,
type RuntimeClockState
} from "../runtime-three/runtime-project-time";
import type {
RuntimeNavigationMode,
RuntimeSceneDefinition
} from "../runtime-three/runtime-scene-build";
import { createWorldBackgroundStyle } from "../shared-ui/world-background-style";
const FORWARD_RUNTIME_CLOCK_INTERVAL_MS = 240;
@@ -73,28 +71,13 @@ export function RunnerCanvas({
useState<RuntimeInteractionPrompt | null>(null);
const [firstPersonTelemetry, setFirstPersonTelemetry] =
useState<FirstPersonTelemetry | null>(null);
const [visualRuntimeClock, setVisualRuntimeClock] = useState(runtimeClock);
const overlayMessage = runnerMessage ?? sceneLoadState.message;
const overlayStatus =
overlayMessage !== null ? "error" : sceneLoadState.status;
const runnerReady = overlayStatus === "ready";
const resolvedWorld = resolveRuntimeDayNightWorldState(
runtimeScene.world,
runtimeScene.time,
visualRuntimeClock
);
onRuntimeClockChangeRef.current = onRuntimeClockChange;
useEffect(() => {
lastForwardedRuntimeClockRef.current = runtimeClock;
setVisualRuntimeClock((currentClock) =>
areRuntimeClockStatesEqual(currentClock, runtimeClock)
? currentClock
: runtimeClock
);
}, [runtimeClock.dayCount, runtimeClock.dayLengthMinutes, runtimeClock.timeOfDayHours]);
useEffect(() => {
const container = containerRef.current;
@@ -111,12 +94,6 @@ export function RunnerCanvas({
runtimeHost.setRuntimeMessageHandler(onRuntimeMessageChange);
runtimeHost.setSceneLoadStateHandler(setSceneLoadState);
runtimeHost.setRuntimeClockStateHandler?.((clock) => {
setVisualRuntimeClock((currentClock) =>
areRuntimeClockStatesEqual(currentClock, clock)
? currentClock
: clock
);
const now = performance.now();
if (
@@ -226,35 +203,7 @@ export function RunnerCanvas({
data-testid="runner-shell"
aria-label="Built-in scene runner"
aria-busy={!runnerReady}
style={createWorldBackgroundStyle(
resolvedWorld.background,
resolvedWorld.background.mode === "image"
? (loadedImageAssets[resolvedWorld.background.assetId]
?.sourceUrl ?? null)
: null
)}
>
{resolvedWorld.nightBackgroundOverlay === null ? null : (
<div
className="runner-canvas__background-overlay"
data-testid="runner-night-background-overlay"
aria-hidden="true"
style={{
...createWorldBackgroundStyle(
{
mode: "image",
assetId: resolvedWorld.nightBackgroundOverlay.assetId,
environmentIntensity:
resolvedWorld.nightBackgroundOverlay.environmentIntensity
},
loadedImageAssets[
resolvedWorld.nightBackgroundOverlay.assetId
]?.sourceUrl ?? null
),
opacity: resolvedWorld.nightBackgroundOverlay.opacity
}}
/>
)}
<div
className={`runner-canvas__loading-overlay ${runnerReady ? "runner-canvas__loading-overlay--hidden" : ""}`}
data-testid="runner-loading-overlay"

View File

@@ -389,7 +389,7 @@ describe("RunnerCanvas", () => {
).toHaveBeenCalledTimes(2);
});
it("renders the night background overlay behind the scene when the night profile is active", async () => {
it("does not render a DOM night background overlay because the runtime host owns background blending", async () => {
const document = createEmptySceneDocument();
document.assets["asset-night-sky"] = {
id: "asset-night-sky",
@@ -439,7 +439,9 @@ describe("RunnerCanvas", () => {
expect(runtimeHostInstances).toHaveLength(1);
});
expect(screen.getByTestId("runner-night-background-overlay")).toBeVisible();
expect(
screen.queryByTestId("runner-night-background-overlay")
).toBeNull();
});
it("keeps the crosshair hidden in third-person mode while still showing interaction prompts", async () => {

View File

@@ -0,0 +1,73 @@
import { Texture } from "three";
import { describe, expect, it } from "vitest";
import { createDefaultWorldSettings } from "../../src/document/world-settings";
import { resolveWorldEnvironmentState } from "../../src/rendering/world-background-renderer";
describe("resolveWorldEnvironmentState", () => {
it("keeps the authored day environment when no night overlay is active", () => {
const world = createDefaultWorldSettings();
const dayTexture = new Texture();
world.background = {
mode: "image",
assetId: "asset-day-sky",
environmentIntensity: 0.65
};
expect(
resolveWorldEnvironmentState(world.background, dayTexture, null)
).toEqual({
texture: dayTexture,
intensity: 0.65
});
});
it("hands the environment off through zero intensity during a day-to-night crossfade", () => {
const world = createDefaultWorldSettings();
const dayTexture = new Texture();
const nightTexture = new Texture();
world.background = {
mode: "image",
assetId: "asset-day-sky",
environmentIntensity: 0.4
};
expect(
resolveWorldEnvironmentState(world.background, dayTexture, {
texture: nightTexture,
opacity: 0.25,
environmentIntensity: 0.8
})
).toEqual({
texture: dayTexture,
intensity: 0.2
});
expect(
resolveWorldEnvironmentState(world.background, dayTexture, {
texture: nightTexture,
opacity: 0.75,
environmentIntensity: 0.8
})
).toEqual({
texture: nightTexture,
intensity: 0.4
});
});
it("fades the night environment in when the authored day background has no image environment", () => {
const world = createDefaultWorldSettings();
const nightTexture = new Texture();
expect(
resolveWorldEnvironmentState(world.background, null, {
texture: nightTexture,
opacity: 0.5,
environmentIntensity: 0.7
})
).toEqual({
texture: nightTexture,
intensity: 0.35
});
});
});