Refactor elevator runtime into core

This commit is contained in:
sudhir
2026-05-13 01:56:06 +05:30
parent b782ce9cf2
commit 9838d2cd4f
14 changed files with 595 additions and 429 deletions
@@ -5,10 +5,23 @@ import {
type AnyNode,
type AnyNodeId,
type ElevatorNode,
type ElevatorDoorSide,
emitter,
getElevatorCabCenterZ,
getElevatorCabDepth,
getElevatorCabWidth,
getElevatorDoorLeafSides,
getElevatorDoorLeafWidth,
getElevatorDoorLeafX,
getElevatorShaftDepth,
getElevatorShaftWallThickness,
getElevatorShaftWidth,
getResolvedElevatorDoorStyle,
openElevatorDoor,
resolveElevatorBuildingLevels,
resolveElevatorDispatchTarget,
resolveElevatorServiceLevels,
requestElevatorLevel,
sceneRegistry,
useInteractive,
useScene,
@@ -62,7 +75,6 @@ const DOOR_LEAF_INTERACTION_DEPTH = 0.08
const ELEVATOR_RIDE_HORIZONTAL_PADDING = 0.18
const ELEVATOR_COLLIDER_HORIZONTAL_PADDING = 0.14
const ELEVATOR_COLLIDER_FLOOR_THICKNESS = 0.08
const ELEVATOR_COLLIDER_WALL_THICKNESS = 0.16
const ELEVATOR_COLLIDER_DOOR_DEPTH = 0.12
const ELEVATOR_ENTRY_DOOR_OPEN_THRESHOLD = 0.72
const DEFAULT_ELEVATOR_LEVEL_HEIGHT = 2.5
@@ -133,9 +145,6 @@ type ElevatorColliderUserData = {
side?: ElevatorDoorSide
}
type ElevatorDoorSide = 'left' | 'right'
type ElevatorDoorStyleValue = ElevatorNode['doorStyle']
type ElevatorColliderMesh = Mesh & {
userData: Mesh['userData'] & ElevatorColliderUserData
}
@@ -217,67 +226,6 @@ function getInteractableTargetKey(target: FirstPersonInteractableTarget | null)
: `${target.type}:${target.id}`
}
function getResolvedElevatorDoorStyle(
doorStyle: ElevatorDoorStyleValue | undefined,
): ElevatorDoorStyleValue {
return doorStyle ?? 'center-opening'
}
function getElevatorDoorLeafSides(
doorStyle: ElevatorDoorStyleValue | undefined,
): ElevatorDoorSide[] {
const resolvedDoorStyle = getResolvedElevatorDoorStyle(doorStyle)
if (resolvedDoorStyle === 'single-left') return ['left']
if (resolvedDoorStyle === 'single-right') return ['right']
return ['left', 'right']
}
function getElevatorDoorLeafWidth(width: number, doorStyle: ElevatorDoorStyleValue | undefined) {
return getResolvedElevatorDoorStyle(doorStyle) === 'center-opening'
? Math.max(width / 2 - 0.018, 0.12)
: Math.max(width - 0.018, 0.18)
}
function getElevatorDoorLeafX(
side: ElevatorDoorSide,
width: number,
doorOpen: number,
doorStyle: ElevatorDoorStyleValue | undefined,
) {
const resolvedDoorStyle = getResolvedElevatorDoorStyle(doorStyle)
if (resolvedDoorStyle === 'center-opening') {
const direction = side === 'left' ? -1 : 1
return direction * (width / 4 + doorOpen * width * 0.34)
}
const direction = resolvedDoorStyle === 'single-left' ? -1 : 1
return direction * doorOpen * width * 0.68
}
function getElevatorCabWidth(elevator: ElevatorNode) {
return Math.max(elevator.width, 0.8)
}
function getElevatorCabDepth(elevator: ElevatorNode) {
return Math.max(elevator.depth, 0.8)
}
function getElevatorShaftWallThickness(elevator: ElevatorNode) {
return Math.max(elevator.shaftWallThickness ?? ELEVATOR_COLLIDER_WALL_THICKNESS, 0.04)
}
function getElevatorShaftWidth(elevator: ElevatorNode, cabWidth = getElevatorCabWidth(elevator)) {
return Math.max(elevator.shaftWidth ?? cabWidth, cabWidth, 0.8)
}
function getElevatorShaftDepth(elevator: ElevatorNode, cabDepth = getElevatorCabDepth(elevator)) {
return Math.max(elevator.shaftDepth ?? cabDepth, cabDepth, 0.8)
}
function getElevatorCabCenterZ(elevator: ElevatorNode) {
return -getElevatorShaftDepth(elevator) / 2 + getElevatorCabDepth(elevator) / 2
}
function isDynamicElevatorCollider(kind: ElevatorColliderKind) {
return kind.startsWith('cab-') || kind.startsWith('landing-door')
}
@@ -836,7 +784,7 @@ export const FirstPersonControls = () => {
}
}
if (target.action === 'open-door') {
useInteractive.getState().openElevatorDoor(target.id)
openElevatorDoor(target.id)
return
}
if (target.levelId) {
@@ -849,7 +797,7 @@ export const FirstPersonControls = () => {
requestedElevatorId: target.id,
})
: target.id
useInteractive.getState().requestElevator(targetElevatorId, target.levelId)
requestElevatorLevel(targetElevatorId, target.levelId)
}
return
}
@@ -6,6 +6,7 @@ import {
type ElevatorNode,
ElevatorNode as ElevatorNodeSchema,
type LevelNode,
requestElevatorLevel,
useInteractive,
useLiveNodeOverrides,
useLiveTransforms,
@@ -337,7 +338,7 @@ export function ElevatorPanel() {
(levelId: LevelNode['id']) => {
if (!node) return
if ((node.disabledLevelIds ?? []).includes(levelId)) return
useInteractive.getState().requestElevator(node.id as AnyNodeId, levelId as AnyNodeId)
requestElevatorLevel(node.id as AnyNodeId, levelId as AnyNodeId)
},
[node],
)