From c1f1ff74880efe3f53489f4f8f64b596d13737e6 Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Tue, 14 Apr 2026 01:40:15 +0200 Subject: [PATCH] auto-git: [change] src/app/App.tsx [change] src/controls/control-surface.ts [change] src/document/migrate-scene-document.ts [change] src/document/scene-document-validation.ts [change] src/document/scene-document.ts [change] src/interactions/interaction-links.ts [change] src/runtime-three/runtime-audio-system.ts [change] src/runtime-three/runtime-host.ts [change] src/runtime-three/runtime-interaction-system.ts [change] src/runtime-three/runtime-scene-build.ts [change] tests/domain/runtime-control-foundation.test.ts [change] tests/domain/runtime-interaction-system.test.ts [change] tests/serialization/control-interaction-links.test.ts [change] tests/unit/runtime-host.test.ts --- src/app/App.tsx | 1348 ++++++++++------- src/controls/control-surface.ts | 26 +- src/document/migrate-scene-document.ts | 145 +- src/document/scene-document-validation.ts | 80 +- src/document/scene-document.ts | 18 +- src/interactions/interaction-links.ts | 15 +- src/runtime-three/runtime-audio-system.ts | 97 +- src/runtime-three/runtime-host.ts | 69 +- .../runtime-interaction-system.ts | 133 +- src/runtime-three/runtime-scene-build.ts | 109 +- .../domain/runtime-control-foundation.test.ts | 7 +- .../domain/runtime-interaction-system.test.ts | 106 +- .../control-interaction-links.test.ts | 6 +- tests/unit/runtime-host.test.ts | 5 +- 14 files changed, 1354 insertions(+), 810 deletions(-) diff --git a/src/app/App.tsx b/src/app/App.tsx index cf9f704f..6abf1006 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -928,7 +928,11 @@ function getSelectedPathPointState( ): { point: ScenePathPoint; index: number } | null { const selectedPathPoint = getSingleSelectedPathPoint(selection); - if (selectedPathPoint === null || path === null || selectedPathPoint.pathId !== path.id) { + if ( + selectedPathPoint === null || + path === null || + selectedPathPoint.pathId !== path.id + ) { return null; } @@ -1062,7 +1066,9 @@ function getBrushLabel(brush: BoxBrush, index: number): string { function getPathLabelById(pathId: string, paths: ScenePath[]): string { const pathIndex = paths.findIndex((path) => path.id === pathId); - return pathIndex === -1 ? "Path" : getScenePathLabel(paths[pathIndex], pathIndex); + return pathIndex === -1 + ? "Path" + : getScenePathLabel(paths[pathIndex], pathIndex); } function formatAuthoredObjectStateSummary(state: { @@ -1124,12 +1130,15 @@ function describeSelection( case "paths": return `${selection.ids.length} path${selection.ids.length === 1 ? "" : "s"} selected (${getPathLabelById(selection.ids[0], paths)})`; case "pathPoint": { - const path = paths.find((candidatePath) => candidatePath.id === selection.pathId); + const path = paths.find( + (candidatePath) => candidatePath.id === selection.pathId + ); const pointIndex = path === undefined ? -1 : getScenePathPointIndex(path, selection.pointId); - const pointLabel = pointIndex === -1 ? "Path Point" : `Point ${pointIndex + 1}`; + const pointLabel = + pointIndex === -1 ? "Path Point" : `Point ${pointIndex + 1}`; return `${pointLabel} selected (${getPathLabelById(selection.pathId, paths)})`; } case "entities": @@ -1555,7 +1564,9 @@ function formatRunnerAnimationHook( : "idle"; } -function formatWorldBackgroundLabel(background: WorldBackgroundSettings): string { +function formatWorldBackgroundLabel( + background: WorldBackgroundSettings +): string { if (background.mode === "solid") { return "Solid"; } @@ -1937,8 +1948,12 @@ export function App({ store, initialStatusMessage }: AppProps) { const [playerStartYawDraft, setPlayerStartYawDraft] = useState("0"); const [playerStartNavigationModeDraft, setPlayerStartNavigationModeDraft] = useState(DEFAULT_PLAYER_START_NAVIGATION_MODE); - const [playerStartMovementTemplateDraft, setPlayerStartMovementTemplateDraft] = - useState(createPlayerStartMovementTemplate()); + const [ + playerStartMovementTemplateDraft, + setPlayerStartMovementTemplateDraft + ] = useState( + createPlayerStartMovementTemplate() + ); const [ playerStartMovementTemplateNumberDraft, setPlayerStartMovementTemplateNumberDraft @@ -1961,8 +1976,10 @@ export function App({ store, initialStatusMessage }: AppProps) { ); const [playerStartInputBindingsDraft, setPlayerStartInputBindingsDraft] = useState(createPlayerStartInputBindings()); - const [playerStartKeyboardCaptureAction, setPlayerStartKeyboardCaptureAction] = - useState(null); + const [ + playerStartKeyboardCaptureAction, + setPlayerStartKeyboardCaptureAction + ] = useState(null); const [soundEmitterAudioAssetIdDraft, setSoundEmitterAudioAssetIdDraft] = useState(DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID ?? ""); const [soundEmitterVolumeDraft, setSoundEmitterVolumeDraft] = useState( @@ -2071,46 +2088,69 @@ export function App({ store, initialStatusMessage }: AppProps) { useState(String(editorState.projectDocument.time.startDayNumber)); const [projectTimeStartTimeOfDayDraft, setProjectTimeStartTimeOfDayDraft] = useState(String(editorState.projectDocument.time.startTimeOfDayHours)); - const [projectTimeDayLengthMinutesDraft, setProjectTimeDayLengthMinutesDraft] = - useState(String(editorState.projectDocument.time.dayLengthMinutes)); - const [projectTimeSunriseTimeOfDayDraft, setProjectTimeSunriseTimeOfDayDraft] = - useState(String(editorState.projectDocument.time.sunriseTimeOfDayHours)); + const [ + projectTimeDayLengthMinutesDraft, + setProjectTimeDayLengthMinutesDraft + ] = useState(String(editorState.projectDocument.time.dayLengthMinutes)); + const [ + projectTimeSunriseTimeOfDayDraft, + setProjectTimeSunriseTimeOfDayDraft + ] = useState(String(editorState.projectDocument.time.sunriseTimeOfDayHours)); const [projectTimeSunsetTimeOfDayDraft, setProjectTimeSunsetTimeOfDayDraft] = useState(String(editorState.projectDocument.time.sunsetTimeOfDayHours)); - const [projectTimeDawnDurationHoursDraft, setProjectTimeDawnDurationHoursDraft] = - useState(String(editorState.projectDocument.time.dawnDurationHours)); - const [projectTimeDuskDurationHoursDraft, setProjectTimeDuskDurationHoursDraft] = - useState(String(editorState.projectDocument.time.duskDurationHours)); + const [ + projectTimeDawnDurationHoursDraft, + setProjectTimeDawnDurationHoursDraft + ] = useState(String(editorState.projectDocument.time.dawnDurationHours)); + const [ + projectTimeDuskDurationHoursDraft, + setProjectTimeDuskDurationHoursDraft + ] = useState(String(editorState.projectDocument.time.duskDurationHours)); const [ worldDawnAmbientIntensityFactorDraft, setWorldDawnAmbientIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.dawn.ambientIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.dawn.ambientIntensityFactor) + ); const [ worldDawnLightIntensityFactorDraft, setWorldDawnLightIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.dawn.lightIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.dawn.lightIntensityFactor) + ); const [ worldDuskAmbientIntensityFactorDraft, setWorldDuskAmbientIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.dusk.ambientIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.dusk.ambientIntensityFactor) + ); const [ worldDuskLightIntensityFactorDraft, setWorldDuskLightIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.dusk.lightIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.dusk.lightIntensityFactor) + ); const [ worldNightAmbientIntensityFactorDraft, setWorldNightAmbientIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.night.ambientIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.night.ambientIntensityFactor) + ); const [ worldNightLightIntensityFactorDraft, setWorldNightLightIntensityFactorDraft - ] = useState(String(editorState.document.world.timeOfDay.night.lightIntensityFactor)); + ] = useState( + String(editorState.document.world.timeOfDay.night.lightIntensityFactor) + ); const [ worldNightBackgroundEnvironmentIntensityDraft, setWorldNightBackgroundEnvironmentIntensityDraft ] = useState( editorState.document.world.timeOfDay.night.background.mode === "image" - ? String(editorState.document.world.timeOfDay.night.background.environmentIntensity) + ? String( + editorState.document.world.timeOfDay.night.background + .environmentIntensity + ) : "0.5" ); const [ @@ -2285,7 +2325,9 @@ export function App({ store, initialStatusMessage }: AppProps) { const [viewportQuadResizeMode, setViewportQuadResizeMode] = useState(null); const documentValidation = validateSceneDocument(editorState.document); - const projectValidation = validateProjectDocument(editorState.projectDocument); + const projectValidation = validateProjectDocument( + editorState.projectDocument + ); const activeSceneProjectDiagnostics = projectValidation.diagnostics.filter( (diagnostic) => diagnostic.path?.startsWith(`scenes.${editorState.activeSceneId}.`) && @@ -2568,8 +2610,8 @@ export function App({ store, initialStatusMessage }: AppProps) { setSceneExitEnabledDraft(true); setSceneExitTargetSceneIdDraft(sceneTargetOptions[0]?.id ?? ""); setSceneExitTargetEntryIdDraft( - (sceneEntryOptionsBySceneId[sceneTargetOptions[0]?.id ?? ""]?.[0] - ?.entity.id ?? "") + sceneEntryOptionsBySceneId[sceneTargetOptions[0]?.id ?? ""]?.[0]?.entity + .id ?? "" ); return; } @@ -2622,7 +2664,9 @@ export function App({ store, initialStatusMessage }: AppProps) { setNpcActorIdDraft(selectedEntity.actorId); setNpcPresenceModeDraft(selectedEntity.presence.mode); if (selectedEntity.presence.mode === "timeWindow") { - setNpcPresenceStartHourDraft(String(selectedEntity.presence.startHour)); + setNpcPresenceStartHourDraft( + String(selectedEntity.presence.startHour) + ); setNpcPresenceEndHourDraft(String(selectedEntity.presence.endHour)); } else { setNpcPresenceStartHourDraft( @@ -2633,12 +2677,8 @@ export function App({ store, initialStatusMessage }: AppProps) { setNpcYawDraft(String(selectedEntity.yawDegrees)); setNpcColliderModeDraft(selectedEntity.collider.mode); setNpcEyeHeightDraft(String(selectedEntity.collider.eyeHeight)); - setNpcCapsuleRadiusDraft( - String(selectedEntity.collider.capsuleRadius) - ); - setNpcCapsuleHeightDraft( - String(selectedEntity.collider.capsuleHeight) - ); + setNpcCapsuleRadiusDraft(String(selectedEntity.collider.capsuleRadius)); + setNpcCapsuleHeightDraft(String(selectedEntity.collider.capsuleHeight)); setNpcBoxSizeDraft(createVec3Draft(selectedEntity.collider.boxSize)); setNpcModelAssetIdDraft(selectedEntity.modelAssetId ?? ""); break; @@ -3565,7 +3605,9 @@ export function App({ store, initialStatusMessage }: AppProps) { label: string, successMessage: string ) => { - if (areProjectTimeSettingsEqual(editorState.projectDocument.time, nextTime)) { + if ( + areProjectTimeSettingsEqual(editorState.projectDocument.time, nextTime) + ) { return; } @@ -3588,7 +3630,9 @@ export function App({ store, initialStatusMessage }: AppProps) { mutate: (time: ProjectTimeSettings) => void ) => { try { - const nextTime = cloneProjectTimeSettings(editorState.projectDocument.time); + const nextTime = cloneProjectTimeSettings( + editorState.projectDocument.time + ); mutate(nextTime); assertProjectTimeSettingsAreOrdered(nextTime); applyProjectTimeSettings(nextTime, label, successMessage); @@ -3616,7 +3660,10 @@ export function App({ store, initialStatusMessage }: AppProps) { `Project time will start at ${formatTimeOfDayHours(Number(projectTimeStartTimeOfDayDraft))}.`, (time) => { time.startTimeOfDayHours = normalizeTimeOfDayHours( - readFiniteNumberDraft(projectTimeStartTimeOfDayDraft, "Project start time") + readFiniteNumberDraft( + projectTimeStartTimeOfDayDraft, + "Project start time" + ) ); } ); @@ -3641,7 +3688,10 @@ export function App({ store, initialStatusMessage }: AppProps) { `Project sunrise will occur at ${formatTimeOfDayHours(Number(projectTimeSunriseTimeOfDayDraft))}.`, (time) => { time.sunriseTimeOfDayHours = normalizeTimeOfDayHours( - readFiniteNumberDraft(projectTimeSunriseTimeOfDayDraft, "Project sunrise") + readFiniteNumberDraft( + projectTimeSunriseTimeOfDayDraft, + "Project sunrise" + ) ); } ); @@ -3653,7 +3703,10 @@ export function App({ store, initialStatusMessage }: AppProps) { `Project sunset will occur at ${formatTimeOfDayHours(Number(projectTimeSunsetTimeOfDayDraft))}.`, (time) => { time.sunsetTimeOfDayHours = normalizeTimeOfDayHours( - readFiniteNumberDraft(projectTimeSunsetTimeOfDayDraft, "Project sunset") + readFiniteNumberDraft( + projectTimeSunsetTimeOfDayDraft, + "Project sunset" + ) ); } ); @@ -3761,7 +3814,8 @@ export function App({ store, initialStatusMessage }: AppProps) { mode: WorldBackgroundMode, imageAssetId?: string ) => { - const currentBackground = editorState.document.world.timeOfDay.night.background; + const currentBackground = + editorState.document.world.timeOfDay.night.background; if (mode === "image") { const currentBackgroundAssetId = @@ -3812,7 +3866,9 @@ export function App({ store, initialStatusMessage }: AppProps) { }; const applyNightBackgroundColor = (colorHex: string) => { - if (editorState.document.world.timeOfDay.night.background.mode !== "solid") { + if ( + editorState.document.world.timeOfDay.night.background.mode !== "solid" + ) { return; } @@ -3866,7 +3922,9 @@ export function App({ store, initialStatusMessage }: AppProps) { }; const applyNightBackgroundEnvironmentIntensity = () => { - if (editorState.document.world.timeOfDay.night.background.mode !== "image") { + if ( + editorState.document.world.timeOfDay.night.background.mode !== "image" + ) { return; } @@ -4894,7 +4952,8 @@ export function App({ store, initialStatusMessage }: AppProps) { } const sourceScene = editorState.projectDocument.scenes[runtimeSceneId]; - const targetScene = editorState.projectDocument.scenes[request.targetSceneId]; + const targetScene = + editorState.projectDocument.scenes[request.targetSceneId]; if (sourceScene === undefined) { setRuntimeMessage( @@ -4927,9 +4986,12 @@ export function App({ store, initialStatusMessage }: AppProps) { } try { - const nextRuntimeScene = buildRuntimeSceneForProjectScene(targetScene.id, { - sceneEntryId: targetEntry.id - }); + const nextRuntimeScene = buildRuntimeSceneForProjectScene( + targetScene.id, + { + sceneEntryId: targetEntry.id + } + ); applyRuntimeSceneSession(targetScene.id, nextRuntimeScene); setRuntimeMessage(null); @@ -5068,7 +5130,8 @@ export function App({ store, initialStatusMessage }: AppProps) { completeCreation("Placed Scene Entry."); return true; case "npc": { - const placedModelAssetId = creationPreview.target.modelAssetId ?? null; + const placedModelAssetId = + creationPreview.target.modelAssetId ?? null; store.executeCommand( createUpsertEntityCommand({ @@ -5655,7 +5718,11 @@ export function App({ store, initialStatusMessage }: AppProps) { yawDegrees: readYawDegreesDraft(sceneEntryYawDraft) }); - commitEntityChange(selectedSceneEntry, nextEntity, "Updated Scene Entry."); + commitEntityChange( + selectedSceneEntry, + nextEntity, + "Updated Scene Entry." + ); } catch (error) { setStatusMessage(getErrorMessage(error)); } @@ -5697,9 +5764,7 @@ export function App({ store, initialStatusMessage }: AppProps) { presence.mode === "timeWindow" && presence.startHour === presence.endHour ) { - throw new Error( - "NPC presence window start and end hours must differ." - ); + throw new Error("NPC presence window start and end hours must differ."); } const nextEntity = createNpcEntity({ @@ -5720,7 +5785,10 @@ export function App({ store, initialStatusMessage }: AppProps) { : trimmedModelAssetId, collider: { mode: colliderMode, - eyeHeight: readPositiveNumberDraft(npcEyeHeightDraft, "NPC eye height"), + eyeHeight: readPositiveNumberDraft( + npcEyeHeightDraft, + "NPC eye height" + ), capsuleRadius: readPositiveNumberDraft( npcCapsuleRadiusDraft, "NPC capsule radius" @@ -6326,10 +6394,7 @@ export function App({ store, initialStatusMessage }: AppProps) { } }; - const handleSetEntityVisible = ( - entity: EntityInstance, - visible: boolean - ) => { + const handleSetEntityVisible = (entity: EntityInstance, visible: boolean) => { try { store.executeCommand( createSetEntityAuthoredStateCommand({ @@ -6347,10 +6412,7 @@ export function App({ store, initialStatusMessage }: AppProps) { } }; - const handleSetEntityEnabled = ( - entity: EntityInstance, - enabled: boolean - ) => { + const handleSetEntityEnabled = (entity: EntityInstance, enabled: boolean) => { try { store.executeCommand( createSetEntityAuthoredStateCommand({ @@ -6451,7 +6513,9 @@ export function App({ store, initialStatusMessage }: AppProps) { try { store.executeCommand(createDeleteProjectAssetCommand(asset.id)); - setStatusMessage(`Deleted ${asset.sourceName} and cleaned up project references.`); + setStatusMessage( + `Deleted ${asset.sourceName} and cleaned up project references.` + ); return true; } catch (error) { setStatusMessage(getErrorMessage(error)); @@ -7356,7 +7420,9 @@ export function App({ store, initialStatusMessage }: AppProps) { @@ -7991,9 +8057,7 @@ export function App({ store, initialStatusMessage }: AppProps) { const applyAdvancedRenderingWhiteboxBevelEnabled = (enabled: boolean) => { applyAdvancedRenderingSettings( "Set whitebox bevel", - enabled - ? "Whitebox bevel enabled." - : "Whitebox bevel disabled.", + enabled ? "Whitebox bevel enabled." : "Whitebox bevel disabled.", (advancedRendering) => { advancedRendering.whiteboxBevel.enabled = enabled; } @@ -8006,10 +8070,11 @@ export function App({ store, initialStatusMessage }: AppProps) { "Set whitebox bevel edge width", "Updated the whitebox bevel edge width.", (advancedRendering) => { - advancedRendering.whiteboxBevel.edgeWidth = readNonNegativeNumberDraft( - advancedRenderingWhiteboxBevelEdgeWidthDraft, - "Whitebox bevel edge width" - ); + advancedRendering.whiteboxBevel.edgeWidth = + readNonNegativeNumberDraft( + advancedRenderingWhiteboxBevelEdgeWidthDraft, + "Whitebox bevel edge width" + ); } ); } catch (error) { @@ -9004,27 +9069,30 @@ export function App({ store, initialStatusMessage }: AppProps) { ? "Player Start" : runtimeScene.spawn.source === "sceneEntry" ? "Scene Entry" - : "Fallback"} + : "Fallback"}
Transitions
-
+
{runtimeGlobalState.transitionCount}
Project Time
- {formatTimeOfDayHours(runtimeGlobalState.clock.timeOfDayHours)} + {formatTimeOfDayHours( + runtimeGlobalState.clock.timeOfDayHours + )}
- Day {runtimeGlobalState.clock.dayCount + 1} · {Number.isInteger(runtimeGlobalState.clock.dayLengthMinutes) + Day {runtimeGlobalState.clock.dayCount + 1} ·{" "} + {Number.isInteger(runtimeGlobalState.clock.dayLengthMinutes) ? runtimeGlobalState.clock.dayLengthMinutes.toFixed(0) - : runtimeGlobalState.clock.dayLengthMinutes.toFixed(1)} min/day + : runtimeGlobalState.clock.dayLengthMinutes.toFixed( + 1 + )}{" "} + min/day
@@ -9142,7 +9210,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ? "Player Start" : runtimeScene.spawn.source === "sceneEntry" ? "Scene Entry" - : "Fallback"}{" "} + : "Fallback"}{" "} at {formatRunnerFeetPosition(runtimeScene.spawn.position)}
@@ -9167,7 +9235,8 @@ export function App({ store, initialStatusMessage }: AppProps) { )} {runtimeGlobalState.lastSceneTransition === null ? null : (
- Last transition: {runtimeGlobalState.lastSceneTransition.fromSceneName} to{" "} + Last transition:{" "} + {runtimeGlobalState.lastSceneTransition.fromSceneName} to{" "} {runtimeGlobalState.lastSceneTransition.toSceneName}
)} @@ -9197,7 +9266,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ? "Authored Player Start" : runtimeScene.spawn.source === "sceneEntry" ? "Scene Entry arrival" - : "Fallback runtime spawn"} + : "Fallback runtime spawn"} @@ -9345,9 +9414,8 @@ export function App({ store, initialStatusMessage }: AppProps) { {brushList.map((brush, brushIndex) => { const label = getBrushLabel(brush, brushIndex); const isSelected = selectedBrush?.id === brush.id; - const authoredStateSummary = formatAuthoredObjectStateSummary( - brush - ); + const authoredStateSummary = + formatAuthoredObjectStateSummary(brush); return (
Clock
- Day {editorState.projectDocument.time.startDayNumber} · {formatTimeOfDayHours( + Day {editorState.projectDocument.time.startDayNumber} ·{" "} + {formatTimeOfDayHours( editorState.projectDocument.time.startTimeOfDayHours )}
- Runner sessions begin on the authored start day and time, then keep advancing across scene transitions. + Runner sessions begin on the authored start day and time, + then keep advancing across scene transitions.
@@ -10239,12 +10307,15 @@ export function App({ store, initialStatusMessage }: AppProps) {
- Sunrise must stay earlier than sunset. Dawn and dusk durations define how broadly the twilight transition blends around each boundary. + Sunrise must stay earlier than sunset. Dawn and dusk + durations define how broadly the twilight transition blends + around each boundary.
- Environment authoring lives in World. Project Time now only defines the shared clock and daylight window. + Environment authoring lives in World. Project Time now only + defines the shared clock and daylight window.
@@ -10255,7 +10326,9 @@ export function App({ store, initialStatusMessage }: AppProps) { className="value" data-testid="world-background-mode-value" > - {formatWorldBackgroundLabel(editorState.document.world.background)} + {formatWorldBackgroundLabel( + editorState.document.world.background + )}
{editorState.document.world.projectTimeLightingEnabled @@ -10269,7 +10342,9 @@ export function App({ store, initialStatusMessage }: AppProps) { Follow Project Time applySceneProjectTimeLightingEnabled( event.currentTarget.checked @@ -10278,412 +10353,434 @@ export function App({ store, initialStatusMessage }: AppProps) { />
- Disable this when a scene should keep its authored world sky and lighting instead of the global sunrise, sunset, dawn, dusk, and night overrides. + Disable this when a scene should keep its authored world sky + and lighting instead of the global sunrise, sunset, dawn, + dusk, and night overrides.
-
-
- {editorState.document.world.background.mode === "solid" - ? editorState.document.world.background.colorHex - : editorState.document.world.background.mode === - "verticalGradient" - ? `${editorState.document.world.background.topColorHex} -> ${editorState.document.world.background.bottomColorHex}` - : (editorState.document.assets[ - editorState.document.world.background.assetId - ]?.sourceName ?? - editorState.document.world.background.assetId)} -
- {editorState.document.world.background.mode !== - "image" ? null : (
- Background Asset:{" "} - {editorState.document.assets[ - editorState.document.world.background.assetId - ]?.sourceName ?? - editorState.document.world.background.assetId} + className="world-background-preview" + data-testid="world-background-preview" + style={createWorldBackgroundStyle( + editorState.document.world.background, + editorState.document.world.background.mode === "image" + ? (loadedImageAssets[ + editorState.document.world.background.assetId + ]?.sourceUrl ?? null) + : null + )} + /> +
+ {editorState.document.world.background.mode === "solid" + ? editorState.document.world.background.colorHex + : editorState.document.world.background.mode === + "verticalGradient" + ? `${editorState.document.world.background.topColorHex} -> ${editorState.document.world.background.bottomColorHex}` + : (editorState.document.assets[ + editorState.document.world.background.assetId + ]?.sourceName ?? + editorState.document.world.background.assetId)}
- )} -
- -
-
Background Mode
-
- - - -
-
- - {editorState.document.world.background.mode === "image" && ( -
-
Image Background
- - -
- )} - - {editorState.document.world.background.mode !== "image" && ( -
-
Background Colors
- {editorState.document.world.background.mode === "solid" ? ( - - ) : ( -
- - + Background Asset:{" "} + {editorState.document.assets[ + editorState.document.world.background.assetId + ]?.sourceName ?? + editorState.document.world.background.assetId}
)}
- )} -
-
Ambient Light
-
-
+ {editorState.document.world.background.mode === "image" && ( +
+
Image Background
+ + +
+ )} + {editorState.document.world.background.mode !== "image" && ( +
+
Background Colors
+ {editorState.document.world.background.mode === + "solid" ? ( + + ) : ( +
+ + +
+ )} +
+ )} + +
+
Ambient Light
+
+ + +
+
+ +
+
Sun Light
+
+ + +
+ +
+ + + +
+
- {!editorState.document.world.projectTimeLightingEnabled ? null : ( + {!editorState.document.world + .projectTimeLightingEnabled ? null : ( <>
@@ -10695,7 +10792,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dawn", @@ -10712,7 +10812,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dawn", @@ -10729,7 +10832,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dawn", @@ -10771,7 +10877,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dawn", @@ -10821,7 +10930,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dusk", @@ -10838,7 +10950,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dusk", @@ -10855,7 +10970,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dusk", @@ -10897,7 +11015,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldTimePhaseColor( "dusk", @@ -10942,16 +11063,18 @@ export function App({ store, initialStatusMessage }: AppProps) {
Background
{formatWorldBackgroundLabel( - editorState.document.world.timeOfDay.night.background + editorState.document.world.timeOfDay.night + .background )}
{editorState.document.world.timeOfDay.night.background .mode === "solid" - ? editorState.document.world.timeOfDay.night.background - .colorHex - : editorState.document.world.timeOfDay.night.background - .mode === "verticalGradient" + ? editorState.document.world.timeOfDay.night + .background.colorHex + : editorState.document.world.timeOfDay.night + .background.mode === "verticalGradient" ? `${editorState.document.world.timeOfDay.night.background.topColorHex} -> ${editorState.document.world.timeOfDay.night.background.bottomColorHex}` : (editorState.document.assets[ editorState.document.world.timeOfDay.night @@ -11019,7 +11142,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyNightBackgroundColor( event.currentTarget.value @@ -11094,7 +11225,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyNightGradientColor( "top", @@ -11108,7 +11242,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyNightGradientColor( "bottom", @@ -11128,7 +11265,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldNightEnvironmentColor( "ambientColorHex", @@ -11168,7 +11308,10 @@ export function App({ store, initialStatusMessage }: AppProps) { applyWorldNightEnvironmentColor( "lightColorHex", @@ -11327,7 +11470,9 @@ export function App({ store, initialStatusMessage }: AppProps) { Enabled applyAdvancedRenderingAmbientOcclusionEnabled( event.currentTarget.checked @@ -11606,13 +11751,17 @@ export function App({ store, initialStatusMessage }: AppProps) { type="number" min="0.001" step="0.1" - value={advancedRenderingToneMappingExposureDraft} + value={ + advancedRenderingToneMappingExposureDraft + } onChange={(event) => setAdvancedRenderingToneMappingExposureDraft( event.currentTarget.value ) } - onBlur={applyAdvancedRenderingToneMappingExposure} + onBlur={ + applyAdvancedRenderingToneMappingExposure + } onKeyDown={(event) => handleDraftVectorKeyDown( event, @@ -11735,7 +11884,9 @@ export function App({ store, initialStatusMessage }: AppProps) { type="number" min="0.001" step="0.1" - value={advancedRenderingDepthOfFieldBokehScaleDraft} + value={ + advancedRenderingDepthOfFieldBokehScaleDraft + } onChange={(event) => setAdvancedRenderingDepthOfFieldBokehScaleDraft( event.currentTarget.value @@ -11788,7 +11939,9 @@ export function App({ store, initialStatusMessage }: AppProps) { type="number" min="0" step="0.01" - value={advancedRenderingWhiteboxBevelEdgeWidthDraft} + value={ + advancedRenderingWhiteboxBevelEdgeWidthDraft + } onChange={(event) => setAdvancedRenderingWhiteboxBevelEdgeWidthDraft( event.currentTarget.value @@ -11971,7 +12124,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
Authored State
- Hidden model instances stay authored and keep their runtime - collision behavior. Disabled instances are removed from the - editor viewport, picking, and runtime build. + Hidden model instances stay authored and keep their + runtime collision behavior. Disabled instances are removed + from the editor viewport, picking, and runtime build.
@@ -12529,8 +12684,8 @@ export function App({ store, initialStatusMessage }: AppProps) {
Hidden paths stay authored but disappear from the editor - viewport. Disabled paths are omitted from the runtime - path registry. + viewport. Disabled paths are omitted from the runtime path + registry.
@@ -12560,7 +12715,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
Loop
@@ -14348,7 +14536,9 @@ export function App({ store, initialStatusMessage }: AppProps) { handlePlayerStartGamepadCameraLookBindingChange( event.currentTarget @@ -14421,7 +14613,10 @@ export function App({ store, initialStatusMessage }: AppProps) { } onBlur={applySceneEntryChange} onKeyDown={(event) => - handleDraftVectorKeyDown(event, applySceneEntryChange) + handleDraftVectorKeyDown( + event, + applySceneEntryChange + ) } onKeyUp={(event) => handleNumberInputKeyUp(event, applySceneEntryChange) @@ -14500,8 +14695,8 @@ export function App({ store, initialStatusMessage }: AppProps) { className="select-input" value={npcPresenceModeDraft} onChange={(event) => { - const nextMode = - event.currentTarget.value as NpcPresenceMode; + const nextMode = event.currentTarget + .value as NpcPresenceMode; setNpcPresenceModeDraft(nextMode); scheduleDraftCommit(() => applyNpcChange()); }} @@ -14531,7 +14726,10 @@ export function App({ store, initialStatusMessage }: AppProps) { } onBlur={() => applyNpcChange()} onKeyDown={(event) => - handleDraftVectorKeyDown(event, applyNpcChange) + handleDraftVectorKeyDown( + event, + applyNpcChange + ) } onKeyUp={(event) => handleNumberInputKeyUp(event, applyNpcChange) @@ -14559,7 +14757,10 @@ export function App({ store, initialStatusMessage }: AppProps) { } onBlur={() => applyNpcChange()} onKeyDown={(event) => - handleDraftVectorKeyDown(event, applyNpcChange) + handleDraftVectorKeyDown( + event, + applyNpcChange + ) } onKeyUp={(event) => handleNumberInputKeyUp(event, applyNpcChange) @@ -14618,8 +14819,8 @@ export function App({ store, initialStatusMessage }: AppProps) { className="select-input" value={npcColliderModeDraft} onChange={(event) => { - const nextMode = - event.currentTarget.value as PlayerStartColliderMode; + const nextMode = event.currentTarget + .value as PlayerStartColliderMode; setNpcColliderModeDraft(nextMode); scheduleDraftCommit(() => applyNpcChange({ @@ -14685,10 +14886,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ) } onKeyUp={(event) => - handleNumberInputKeyUp( - event, - applyNpcChange - ) + handleNumberInputKeyUp(event, applyNpcChange) } onPointerUp={(event) => handleNumberInputPointerUp( @@ -14720,10 +14918,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ) } onKeyUp={(event) => - handleNumberInputKeyUp( - event, - applyNpcChange - ) + handleNumberInputKeyUp(event, applyNpcChange) } onPointerUp={(event) => handleNumberInputPointerUp( @@ -14762,10 +14957,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ) } onKeyUp={(event) => - handleNumberInputKeyUp( - event, - applyNpcChange - ) + handleNumberInputKeyUp(event, applyNpcChange) } onPointerUp={(event) => handleNumberInputPointerUp( @@ -14799,10 +14991,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ) } onKeyUp={(event) => - handleNumberInputKeyUp( - event, - applyNpcChange - ) + handleNumberInputKeyUp(event, applyNpcChange) } onPointerUp={(event) => handleNumberInputPointerUp( @@ -14836,10 +15025,7 @@ export function App({ store, initialStatusMessage }: AppProps) { ) } onKeyUp={(event) => - handleNumberInputKeyUp( - event, - applyNpcChange - ) + handleNumberInputKeyUp(event, applyNpcChange) } onPointerUp={(event) => handleNumberInputPointerUp( @@ -15458,9 +15644,7 @@ export function App({ store, initialStatusMessage }: AppProps) { type="text" value={sceneExitPromptDraft} onChange={(event) => - setSceneExitPromptDraft( - event.currentTarget.value - ) + setSceneExitPromptDraft(event.currentTarget.value) } onBlur={() => applySceneExitChange()} onKeyDown={(event) => { @@ -15557,7 +15741,9 @@ export function App({ store, initialStatusMessage }: AppProps) {
Authored State