Add scene entry and exit entities with associated settings and validation

This commit is contained in:
2026-04-11 04:35:15 +02:00
parent c83ccbb8c1
commit ed76bda2e3
2 changed files with 55 additions and 0 deletions

View File

@@ -151,10 +151,12 @@ import {
import { import {
areSceneLoadingScreenSettingsEqual, areSceneLoadingScreenSettingsEqual,
cloneSceneLoadingScreenSettings, cloneSceneLoadingScreenSettings,
createSceneDocumentFromProject,
type SceneLoadingScreenSettings type SceneLoadingScreenSettings
} from "../document/scene-document"; } from "../document/scene-document";
import { import {
formatSceneDiagnosticSummary, formatSceneDiagnosticSummary,
validateProjectDocument,
validateSceneDocument validateSceneDocument
} from "../document/scene-document-validation"; } from "../document/scene-document-validation";
import { import {
@@ -180,6 +182,9 @@ import {
DEFAULT_PLAYER_START_EYE_HEIGHT, DEFAULT_PLAYER_START_EYE_HEIGHT,
DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID, DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
DEFAULT_SOUND_EMITTER_VOLUME, DEFAULT_SOUND_EMITTER_VOLUME,
DEFAULT_SCENE_ENTRY_YAW_DEGREES,
DEFAULT_SCENE_EXIT_PROMPT,
DEFAULT_SCENE_EXIT_RADIUS,
DEFAULT_SOUND_EMITTER_REF_DISTANCE, DEFAULT_SOUND_EMITTER_REF_DISTANCE,
DEFAULT_SOUND_EMITTER_MAX_DISTANCE, DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
DEFAULT_TELEPORT_TARGET_YAW_DEGREES, DEFAULT_TELEPORT_TARGET_YAW_DEGREES,
@@ -194,6 +199,8 @@ import {
createInteractableEntity, createInteractableEntity,
createPointLightEntity, createPointLightEntity,
createPlayerStartEntity, createPlayerStartEntity,
createSceneEntryEntity,
createSceneExitEntity,
createSoundEmitterEntity, createSoundEmitterEntity,
createSpotLightEntity, createSpotLightEntity,
createTeleportTargetEntity, createTeleportTargetEntity,
@@ -231,6 +238,8 @@ import {
import { RunnerCanvas } from "../runner-web/RunnerCanvas"; import { RunnerCanvas } from "../runner-web/RunnerCanvas";
import type { FirstPersonTelemetry } from "../runtime-three/navigation-controller"; import type { FirstPersonTelemetry } from "../runtime-three/navigation-controller";
import type { RuntimeInteractionPrompt } from "../runtime-three/runtime-interaction-system"; import type { RuntimeInteractionPrompt } from "../runtime-three/runtime-interaction-system";
import { createDefaultRuntimeGlobalState, type RuntimeGlobalState } from "../runtime-three/runtime-global-state";
import type { RuntimeSceneExitTransitionRequest } from "../runtime-three/runtime-host";
import { import {
buildRuntimeSceneFromDocument, buildRuntimeSceneFromDocument,
type RuntimeNavigationMode, type RuntimeNavigationMode,

View File

@@ -97,6 +97,8 @@ import {
DEFAULT_PLAYER_START_EYE_HEIGHT, DEFAULT_PLAYER_START_EYE_HEIGHT,
DEFAULT_PLAYER_START_YAW_DEGREES, DEFAULT_PLAYER_START_YAW_DEGREES,
DEFAULT_POINT_LIGHT_DISTANCE, DEFAULT_POINT_LIGHT_DISTANCE,
DEFAULT_SCENE_ENTRY_YAW_DEGREES,
DEFAULT_SCENE_EXIT_RADIUS,
DEFAULT_SOUND_EMITTER_MAX_DISTANCE, DEFAULT_SOUND_EMITTER_MAX_DISTANCE,
DEFAULT_SOUND_EMITTER_REF_DISTANCE, DEFAULT_SOUND_EMITTER_REF_DISTANCE,
DEFAULT_SPOT_LIGHT_ANGLE_DEGREES, DEFAULT_SPOT_LIGHT_ANGLE_DEGREES,
@@ -232,8 +234,12 @@ const TRIGGER_VOLUME_COLOR = 0x9f8cff;
const TRIGGER_VOLUME_SELECTED_COLOR = 0xf0b07f; const TRIGGER_VOLUME_SELECTED_COLOR = 0xf0b07f;
const TELEPORT_TARGET_COLOR = 0x7ee0ff; const TELEPORT_TARGET_COLOR = 0x7ee0ff;
const TELEPORT_TARGET_SELECTED_COLOR = 0xf6c48a; const TELEPORT_TARGET_SELECTED_COLOR = 0xf6c48a;
const SCENE_ENTRY_COLOR = 0x75f0d8;
const SCENE_ENTRY_SELECTED_COLOR = 0xf6c48a;
const INTERACTABLE_COLOR = 0x92de7e; const INTERACTABLE_COLOR = 0x92de7e;
const INTERACTABLE_SELECTED_COLOR = 0xf1cf7e; const INTERACTABLE_SELECTED_COLOR = 0xf1cf7e;
const SCENE_EXIT_COLOR = 0xff9c6d;
const SCENE_EXIT_SELECTED_COLOR = 0xf5dd88;
const BOX_CREATE_PREVIEW_FILL = 0x89b6ff; const BOX_CREATE_PREVIEW_FILL = 0x89b6ff;
const BOX_CREATE_PREVIEW_EDGE = 0xf3be8f; const BOX_CREATE_PREVIEW_EDGE = 0xf3be8f;
const PLACEMENT_PREVIEW_COLOR_HEX = "#89b6ff"; const PLACEMENT_PREVIEW_COLOR_HEX = "#89b6ff";
@@ -2959,6 +2965,7 @@ export class ViewportHost {
case "soundEmitter": case "soundEmitter":
case "triggerVolume": case "triggerVolume":
case "interactable": case "interactable":
case "sceneExit":
renderObjects.group.position.set( renderObjects.group.position.set(
entity.position.x, entity.position.x,
entity.position.y, entity.position.y,
@@ -2975,6 +2982,7 @@ export class ViewportHost {
); );
break; break;
case "playerStart": case "playerStart":
case "sceneEntry":
case "teleportTarget": case "teleportTarget":
renderObjects.group.position.set( renderObjects.group.position.set(
entity.position.x, entity.position.x,
@@ -3135,6 +3143,7 @@ export class ViewportHost {
case "soundEmitter": case "soundEmitter":
case "triggerVolume": case "triggerVolume":
case "interactable": case "interactable":
case "sceneExit":
this.applyEntityRenderObjectTransform({ this.applyEntityRenderObjectTransform({
...currentEntity, ...currentEntity,
position: this.currentTransformSession.preview.position position: this.currentTransformSession.preview.position
@@ -3165,6 +3174,7 @@ export class ViewportHost {
}); });
break; break;
case "playerStart": case "playerStart":
case "sceneEntry":
case "teleportTarget": case "teleportTarget":
this.applyEntityRenderObjectTransform({ this.applyEntityRenderObjectTransform({
...currentEntity, ...currentEntity,
@@ -3474,6 +3484,14 @@ export class ViewportHost {
entity.collider, entity.collider,
selected selected
); );
case "sceneEntry":
return this.createTeleportTargetRenderObjects(
entity.id,
entity.position,
entity.yawDegrees,
selected,
selected ? SCENE_ENTRY_SELECTED_COLOR : SCENE_ENTRY_COLOR
);
case "soundEmitter": case "soundEmitter":
return this.createSoundEmitterRenderObjects( return this.createSoundEmitterRenderObjects(
entity.id, entity.id,
@@ -3503,6 +3521,14 @@ export class ViewportHost {
entity.radius, entity.radius,
selected selected
); );
case "sceneExit":
return this.createInteractableRenderObjects(
entity.id,
entity.position,
entity.radius,
selected,
selected ? SCENE_EXIT_SELECTED_COLOR : SCENE_EXIT_COLOR
);
} }
} }
@@ -5507,9 +5533,11 @@ export class ViewportHost {
); );
case "pointLight": case "pointLight":
case "playerStart": case "playerStart":
case "sceneEntry":
case "soundEmitter": case "soundEmitter":
case "teleportTarget": case "teleportTarget":
case "interactable": case "interactable":
case "sceneExit":
case "spotLight": case "spotLight":
return this.getPlanarCreationAnchor(event); return this.getPlanarCreationAnchor(event);
} }
@@ -5699,6 +5727,15 @@ export class ViewportHost {
false false
).group; ).group;
break; break;
case "sceneEntry":
previewGroup = this.createTeleportTargetRenderObjects(
"creation-preview",
previewPosition,
DEFAULT_SCENE_ENTRY_YAW_DEGREES,
false,
BOX_CREATE_PREVIEW_FILL
).group;
break;
case "soundEmitter": case "soundEmitter":
previewGroup = this.createSoundEmitterRenderObjects( previewGroup = this.createSoundEmitterRenderObjects(
"creation-preview", "creation-preview",
@@ -5736,6 +5773,15 @@ export class ViewportHost {
BOX_CREATE_PREVIEW_FILL BOX_CREATE_PREVIEW_FILL
).group; ).group;
break; break;
case "sceneExit":
previewGroup = this.createInteractableRenderObjects(
"creation-preview",
previewPosition,
DEFAULT_SCENE_EXIT_RADIUS,
false,
BOX_CREATE_PREVIEW_FILL
).group;
break;
} }
if (this.displayMode === "wireframe") { if (this.displayMode === "wireframe") {
this.applyWireframePresentation(previewGroup); this.applyWireframePresentation(previewGroup);