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 {
areSceneLoadingScreenSettingsEqual,
cloneSceneLoadingScreenSettings,
createSceneDocumentFromProject,
type SceneLoadingScreenSettings
} from "../document/scene-document";
import {
formatSceneDiagnosticSummary,
validateProjectDocument,
validateSceneDocument
} from "../document/scene-document-validation";
import {
@@ -180,6 +182,9 @@ import {
DEFAULT_PLAYER_START_EYE_HEIGHT,
DEFAULT_SOUND_EMITTER_AUDIO_ASSET_ID,
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_MAX_DISTANCE,
DEFAULT_TELEPORT_TARGET_YAW_DEGREES,
@@ -194,6 +199,8 @@ import {
createInteractableEntity,
createPointLightEntity,
createPlayerStartEntity,
createSceneEntryEntity,
createSceneExitEntity,
createSoundEmitterEntity,
createSpotLightEntity,
createTeleportTargetEntity,
@@ -231,6 +238,8 @@ import {
import { RunnerCanvas } from "../runner-web/RunnerCanvas";
import type { FirstPersonTelemetry } from "../runtime-three/navigation-controller";
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 {
buildRuntimeSceneFromDocument,
type RuntimeNavigationMode,

View File

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