Add spawn node support and refine stair and door cutouts
This commit is contained in:
@@ -13,6 +13,7 @@ import { RoofSegmentRenderer } from './roof-segment/roof-segment-renderer'
|
||||
import { ScanRenderer } from './scan/scan-renderer'
|
||||
import { SiteRenderer } from './site/site-renderer'
|
||||
import { SlabRenderer } from './slab/slab-renderer'
|
||||
import { SpawnRenderer } from './spawn/spawn-renderer'
|
||||
import { StairRenderer } from './stair/stair-renderer'
|
||||
import { StairSegmentRenderer } from './stair-segment/stair-segment-renderer'
|
||||
import { WallRenderer } from './wall/wall-renderer'
|
||||
@@ -32,6 +33,7 @@ export const NodeRenderer = ({ nodeId }: { nodeId: AnyNode['id'] }) => {
|
||||
{node.type === 'level' && <LevelRenderer node={node} />}
|
||||
{node.type === 'item' && <ItemRenderer node={node} />}
|
||||
{node.type === 'slab' && <SlabRenderer node={node} />}
|
||||
{node.type === 'spawn' && <SpawnRenderer node={node} />}
|
||||
{node.type === 'wall' && <WallRenderer node={node} />}
|
||||
{node.type === 'fence' && <FenceRenderer node={node} />}
|
||||
{node.type === 'door' && <DoorRenderer node={node} />}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { type SpawnNode, useLiveTransforms, useRegistry } from '@pascal-app/core'
|
||||
import { useMemo, useRef } from 'react'
|
||||
import type { Group } from 'three'
|
||||
import { Color, Shape } from 'three'
|
||||
import { useNodeEvents } from '../../../hooks/use-node-events'
|
||||
import useViewer from '../../../store/use-viewer'
|
||||
|
||||
// Mirrors the current first-person controller capsule in the editor package:
|
||||
// colliderCapsuleArgs={[0.25, 0.8, 4, 8]} with the controller center 0.8m above the floor.
|
||||
const PLAYER_CAPSULE_RADIUS = 0.25
|
||||
const PLAYER_CAPSULE_LENGTH = 0.8
|
||||
const PLAYER_CAPSULE_CENTER_Y = 0.8
|
||||
|
||||
const SPAWN_COLOR = new Color('#22c55e')
|
||||
|
||||
export const SpawnRenderer = ({ node }: { node: SpawnNode }) => {
|
||||
const ref = useRef<Group>(null!)
|
||||
const handlers = useNodeEvents(node, 'spawn')
|
||||
const liveTransform = useLiveTransforms((state) => state.get(node.id))
|
||||
const walkthroughMode = useViewer((state) => state.walkthroughMode)
|
||||
|
||||
useRegistry(node.id, 'spawn', ref)
|
||||
|
||||
const materialProps = useMemo(
|
||||
() => ({
|
||||
color: SPAWN_COLOR,
|
||||
emissive: SPAWN_COLOR,
|
||||
emissiveIntensity: 0.08,
|
||||
metalness: 0.03,
|
||||
roughness: 0.42,
|
||||
}),
|
||||
[],
|
||||
)
|
||||
|
||||
const arrowShape = useMemo(() => {
|
||||
const shape = new Shape()
|
||||
// Positive local Y becomes negative world Z after the -90deg X rotation below,
|
||||
// so this tip points "forward" for the player/spawn direction.
|
||||
shape.moveTo(0, 0.24)
|
||||
shape.lineTo(-0.18, -0.14)
|
||||
shape.lineTo(0.18, -0.14)
|
||||
shape.closePath()
|
||||
return shape
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<group
|
||||
position={liveTransform?.position ?? node.position}
|
||||
ref={ref}
|
||||
rotation={[0, liveTransform?.rotation ?? node.rotation, 0]}
|
||||
visible={!walkthroughMode}
|
||||
>
|
||||
<mesh position={[0, 0.09, 0]} rotation={[-Math.PI / 2, 0, 0]} {...handlers}>
|
||||
<ringGeometry args={[0.34, 0.48, 48]} />
|
||||
<meshStandardMaterial {...materialProps} />
|
||||
</mesh>
|
||||
|
||||
<mesh
|
||||
position={[0, 0.1, -0.52]}
|
||||
rotation={[-Math.PI / 2, 0, ( Math.PI) / 180]}
|
||||
{...handlers}
|
||||
>
|
||||
<shapeGeometry args={[arrowShape]} />
|
||||
<meshStandardMaterial {...materialProps} />
|
||||
</mesh>
|
||||
|
||||
<group position={[0, 0.09, 0]}>
|
||||
<mesh position={[0, 0.48, 0]} {...handlers}>
|
||||
<boxGeometry args={[0.4, 0.82, 0.28]} />
|
||||
<meshStandardMaterial {...materialProps} />
|
||||
</mesh>
|
||||
|
||||
<mesh position={[0, 1.08, 0]} {...handlers}>
|
||||
<boxGeometry args={[0.24, 0.24, 0.24]} />
|
||||
<meshStandardMaterial {...materialProps} />
|
||||
</mesh>
|
||||
</group>
|
||||
</group>
|
||||
)
|
||||
}
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
type SiteNode,
|
||||
type SlabEvent,
|
||||
type SlabNode,
|
||||
type SpawnEvent,
|
||||
type SpawnNode,
|
||||
type StairEvent,
|
||||
type StairNode,
|
||||
type StairSegmentEvent,
|
||||
@@ -44,6 +46,7 @@ type NodeConfig = {
|
||||
level: { node: LevelNode; event: LevelEvent }
|
||||
zone: { node: ZoneNode; event: ZoneEvent }
|
||||
slab: { node: SlabNode; event: SlabEvent }
|
||||
spawn: { node: SpawnNode; event: SpawnEvent }
|
||||
ceiling: { node: CeilingNode; event: CeilingEvent }
|
||||
roof: { node: RoofNode; event: RoofEvent }
|
||||
'roof-segment': { node: RoofSegmentNode; event: RoofSegmentEvent }
|
||||
|
||||
Reference in New Issue
Block a user