@zylem/game-lib 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +9 -16
  3. package/dist/actions.d.ts +30 -21
  4. package/dist/actions.js +793 -146
  5. package/dist/actions.js.map +1 -1
  6. package/dist/behavior/jumper-2d.d.ts +114 -0
  7. package/dist/behavior/jumper-2d.js +711 -0
  8. package/dist/behavior/jumper-2d.js.map +1 -0
  9. package/dist/behavior/platformer-3d.d.ts +296 -0
  10. package/dist/behavior/platformer-3d.js +761 -0
  11. package/dist/behavior/platformer-3d.js.map +1 -0
  12. package/dist/behavior/ricochet-2d.d.ts +275 -0
  13. package/dist/behavior/ricochet-2d.js +425 -0
  14. package/dist/behavior/ricochet-2d.js.map +1 -0
  15. package/dist/behavior/ricochet-3d.d.ts +117 -0
  16. package/dist/behavior/ricochet-3d.js +443 -0
  17. package/dist/behavior/ricochet-3d.js.map +1 -0
  18. package/dist/behavior/screen-visibility.d.ts +79 -0
  19. package/dist/behavior/screen-visibility.js +358 -0
  20. package/dist/behavior/screen-visibility.js.map +1 -0
  21. package/dist/behavior/screen-wrap.d.ts +87 -0
  22. package/dist/behavior/screen-wrap.js +246 -0
  23. package/dist/behavior/screen-wrap.js.map +1 -0
  24. package/dist/behavior/shooter-2d.d.ts +79 -0
  25. package/dist/behavior/shooter-2d.js +180 -0
  26. package/dist/behavior/shooter-2d.js.map +1 -0
  27. package/dist/behavior/thruster.d.ts +11 -0
  28. package/dist/behavior/thruster.js +292 -0
  29. package/dist/behavior/thruster.js.map +1 -0
  30. package/dist/behavior/top-down-movement.d.ts +56 -0
  31. package/dist/behavior/top-down-movement.js +125 -0
  32. package/dist/behavior/top-down-movement.js.map +1 -0
  33. package/dist/behavior/world-boundary-2d.d.ts +142 -0
  34. package/dist/behavior/world-boundary-2d.js +235 -0
  35. package/dist/behavior/world-boundary-2d.js.map +1 -0
  36. package/dist/behavior/world-boundary-3d.d.ts +76 -0
  37. package/dist/behavior/world-boundary-3d.js +274 -0
  38. package/dist/behavior/world-boundary-3d.js.map +1 -0
  39. package/dist/behavior-descriptor-BXnVR8Ki.d.ts +159 -0
  40. package/dist/{blueprints-Cq3Ko6_G.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
  41. package/dist/camera-4XO5gbQH.d.ts +905 -0
  42. package/dist/camera.d.ts +3 -2
  43. package/dist/camera.js +1653 -377
  44. package/dist/camera.js.map +1 -1
  45. package/dist/composition-BASvMKrW.d.ts +218 -0
  46. package/dist/{core-bO8TzV7u.d.ts → core-CARRaS55.d.ts} +110 -69
  47. package/dist/core.d.ts +11 -6
  48. package/dist/core.js +10766 -5626
  49. package/dist/core.js.map +1 -1
  50. package/dist/{entities-DvByhMGU.d.ts → entities-ChFirVL9.d.ts} +133 -29
  51. package/dist/entities.d.ts +5 -3
  52. package/dist/entities.js +4679 -3202
  53. package/dist/entities.js.map +1 -1
  54. package/dist/entity-vj-HTjzU.d.ts +1169 -0
  55. package/dist/global-change-2JvMaz44.d.ts +25 -0
  56. package/dist/main.d.ts +1118 -16
  57. package/dist/main.js +17538 -8499
  58. package/dist/main.js.map +1 -1
  59. package/dist/physics-pose-DCc4oE44.d.ts +25 -0
  60. package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
  61. package/dist/physics-worker.d.ts +21 -0
  62. package/dist/physics-worker.js +306 -0
  63. package/dist/physics-worker.js.map +1 -0
  64. package/dist/physics.d.ts +205 -0
  65. package/dist/physics.js +577 -0
  66. package/dist/physics.js.map +1 -0
  67. package/dist/stage-types-C19IhuzA.d.ts +731 -0
  68. package/dist/stage.d.ts +11 -7
  69. package/dist/stage.js +8024 -3852
  70. package/dist/stage.js.map +1 -1
  71. package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
  72. package/dist/thruster-23lzoPZd.d.ts +180 -0
  73. package/dist/world-DfgxoNMt.d.ts +105 -0
  74. package/package.json +53 -13
  75. package/dist/behaviors.d.ts +0 -854
  76. package/dist/behaviors.js +0 -1209
  77. package/dist/behaviors.js.map +0 -1
  78. package/dist/camera-CeJPAgGg.d.ts +0 -116
  79. package/dist/moveable-B_vyA6cw.d.ts +0 -67
  80. package/dist/stage-types-Bd-KtcYT.d.ts +0 -375
  81. package/dist/transformable-CUhvyuYO.d.ts +0 -67
  82. package/dist/world-C8tQ7Plj.d.ts +0 -774
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/camera/camera.ts","../src/lib/camera/zylem-camera.ts","../src/lib/camera/perspective.ts","../src/lib/camera/third-person.ts","../src/lib/camera/fixed-2d.ts","../src/lib/graphics/render-pass.ts","../src/lib/graphics/shaders/vertex/object.shader.ts","../src/lib/graphics/shaders/standard.shader.ts","../src/lib/camera/camera-debug-delegate.ts"],"sourcesContent":["import { Vector2, Vector3 } from \"three\";\nimport { PerspectiveType } from \"./perspective\";\nimport { ZylemCamera } from \"./zylem-camera\";\n\nexport interface CameraOptions {\n\tperspective?: PerspectiveType;\n\tposition?: Vector3;\n\ttarget?: Vector3;\n\tzoom?: number;\n\tscreenResolution?: Vector2;\n}\n\nexport class CameraWrapper {\n\tcameraRef: ZylemCamera;\n\n\tconstructor(camera: ZylemCamera) {\n\t\tthis.cameraRef = camera;\n\t}\n}\n\nexport function createCamera(options: CameraOptions): CameraWrapper {\n\tconst screenResolution = options.screenResolution || new Vector2(window.innerWidth, window.innerHeight);\n\tlet frustumSize = 10;\n\tif (options.perspective === 'fixed-2d') {\n\t\tfrustumSize = options.zoom || 10;\n\t}\n\tconst zylemCamera = new ZylemCamera(options.perspective || 'third-person', screenResolution, frustumSize);\n\n\t// Set initial position and target\n\tzylemCamera.move(options.position || new Vector3(0, 0, 0));\n\tzylemCamera.camera.lookAt(options.target || new Vector3(0, 0, 0));\n\n\treturn new CameraWrapper(zylemCamera);\n}","import { Vector2, Camera, PerspectiveCamera, Vector3, Object3D, OrthographicCamera, WebGLRenderer, Scene } from 'three';\nimport { PerspectiveType, Perspectives } from './perspective';\nimport { ThirdPersonCamera } from './third-person';\nimport { Fixed2DCamera } from './fixed-2d';\nimport { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';\nimport RenderPass from '../graphics/render-pass';\nimport { StageEntity } from '../interfaces/entity';\nimport { CameraOrbitController, CameraDebugDelegate } from './camera-debug-delegate';\n\n// Re-export for backwards compatibility\nexport type { CameraDebugState, CameraDebugDelegate } from './camera-debug-delegate';\n\n/**\n * Interface for perspective-specific camera controllers\n */\nexport interface PerspectiveController {\n\tsetup(params: { screenResolution: Vector2; renderer: WebGLRenderer; scene: Scene; camera: ZylemCamera }): void;\n\tupdate(delta: number): void;\n\tresize(width: number, height: number): void;\n}\n\nexport class ZylemCamera {\n\tcameraRig: Object3D | null = null;\n\tcamera: Camera;\n\tscreenResolution: Vector2;\n\trenderer: WebGLRenderer;\n\tcomposer: EffectComposer;\n\t_perspective: PerspectiveType;\n\ttarget: StageEntity | null = null;\n\tsceneRef: Scene | null = null;\n\tfrustumSize = 10;\n\n\t// Perspective controller delegation\n\tperspectiveController: PerspectiveController | null = null;\n\n\t// Debug/orbit controls delegation\n\tprivate orbitController: CameraOrbitController | null = null;\n\n\tconstructor(perspective: PerspectiveType, screenResolution: Vector2, frustumSize: number = 10) {\n\t\tthis._perspective = perspective;\n\t\tthis.screenResolution = screenResolution;\n\t\tthis.frustumSize = frustumSize;\n\t\t// Initialize renderer\n\t\tthis.renderer = new WebGLRenderer({ antialias: false, alpha: true });\n\t\tthis.renderer.setSize(screenResolution.x, screenResolution.y);\n\t\tthis.renderer.shadowMap.enabled = true;\n\n\t\t// Initialize composer\n\t\tthis.composer = new EffectComposer(this.renderer);\n\n\t\t// Create camera based on perspective\n\t\tconst aspectRatio = screenResolution.x / screenResolution.y;\n\t\tthis.camera = this.createCameraForPerspective(aspectRatio);\n\n\t\t// Setup camera rig only for perspectives that need it (e.g., third-person following)\n\t\tif (this.needsRig()) {\n\t\t\tthis.cameraRig = new Object3D();\n\t\t\tthis.cameraRig.position.set(0, 3, 10);\n\t\t\tthis.cameraRig.add(this.camera);\n\t\t\tthis.camera.lookAt(new Vector3(0, 2, 0));\n\t\t} else {\n\t\t\t// Position camera directly for non-rig perspectives\n\t\t\tthis.camera.position.set(0, 0, 10);\n\t\t\tthis.camera.lookAt(new Vector3(0, 0, 0));\n\t\t}\n\n\t\t// Initialize perspective controller\n\t\tthis.initializePerspectiveController();\n\n\t\t// Initialize orbit controller (handles debug mode orbit controls)\n\t\tthis.orbitController = new CameraOrbitController(this.camera, this.renderer.domElement, this.cameraRig);\n\t}\n\n\t/**\n\t * Setup the camera with a scene\n\t */\n\tasync setup(scene: Scene) {\n\t\tthis.sceneRef = scene;\n\n\t\t// Setup render pass\n\t\tlet renderResolution = this.screenResolution.clone().divideScalar(2);\n\t\trenderResolution.x |= 0;\n\t\trenderResolution.y |= 0;\n\t\tconst pass = new RenderPass(renderResolution, scene, this.camera);\n\t\tthis.composer.addPass(pass);\n\n\t\t// Setup perspective controller\n\t\tif (this.perspectiveController) {\n\t\t\tthis.perspectiveController.setup({\n\t\t\t\tscreenResolution: this.screenResolution,\n\t\t\t\trenderer: this.renderer,\n\t\t\t\tscene: scene,\n\t\t\t\tcamera: this\n\t\t\t});\n\t\t}\n\n\t\t// Set scene reference for orbit controller (needed for camera rig detachment)\n\t\tthis.orbitController?.setScene(scene);\n\n\t\t// Start render loop\n\t\tthis.renderer.setAnimationLoop((delta) => {\n\t\t\tthis.update(delta || 0);\n\t\t});\n\t}\n\n\t/**\n\t * Update camera and render\n\t */\n\tupdate(delta: number) {\n\t\t// Update orbit controls (if debug mode is enabled)\n\t\tthis.orbitController?.update();\n\n\t\t// Skip perspective controller updates when in debug mode\n\t\t// This keeps the debug camera isolated from game camera logic\n\t\tif (this.perspectiveController && !this.isDebugModeActive()) {\n\t\t\tthis.perspectiveController.update(delta);\n\t\t}\n\n\t\t// Render the scene\n\t\tthis.composer.render(delta);\n\t}\n\n\t/**\n\t * Check if debug mode is active (orbit controls taking over camera)\n\t */\n\tisDebugModeActive(): boolean {\n\t\treturn this.orbitController?.isActive ?? false;\n\t}\n\n\t/**\n\t * Dispose renderer, composer, controls, and detach from scene\n\t */\n\tdestroy() {\n\t\ttry {\n\t\t\tthis.renderer.setAnimationLoop(null as any);\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\tthis.orbitController?.dispose();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\tthis.composer?.passes?.forEach((p: any) => p.dispose?.());\n\t\t\t// @ts-ignore dispose exists on EffectComposer but not typed here\n\t\t\tthis.composer?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\tthis.renderer.dispose();\n\t\t} catch { /* noop */ }\n\t\tthis.sceneRef = null;\n\t}\n\n\t/**\n\t * Attach a delegate to react to debug state changes.\n\t */\n\tsetDebugDelegate(delegate: CameraDebugDelegate | null) {\n\t\tthis.orbitController?.setDebugDelegate(delegate);\n\t}\n\n\t/**\n\t * Resize camera and renderer\n\t */\n\tresize(width: number, height: number) {\n\t\tthis.screenResolution.set(width, height);\n\t\tthis.renderer.setSize(width, height, false);\n\t\tthis.composer.setSize(width, height);\n\n\t\tif (this.camera instanceof PerspectiveCamera) {\n\t\t\tthis.camera.aspect = width / height;\n\t\t\tthis.camera.updateProjectionMatrix();\n\t\t}\n\n\t\tif (this.perspectiveController) {\n\t\t\tthis.perspectiveController.resize(width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Update renderer pixel ratio (DPR)\n\t */\n\tsetPixelRatio(dpr: number) {\n\t\tconst safe = Math.max(1, Number.isFinite(dpr) ? dpr : 1);\n\t\tthis.renderer.setPixelRatio(safe);\n\t}\n\n\t/**\n\t * Create camera based on perspective type\n\t */\n\tprivate createCameraForPerspective(aspectRatio: number): Camera {\n\t\tswitch (this._perspective) {\n\t\t\tcase Perspectives.ThirdPerson:\n\t\t\t\treturn this.createThirdPersonCamera(aspectRatio);\n\t\t\tcase Perspectives.FirstPerson:\n\t\t\t\treturn this.createFirstPersonCamera(aspectRatio);\n\t\t\tcase Perspectives.Isometric:\n\t\t\t\treturn this.createIsometricCamera(aspectRatio);\n\t\t\tcase Perspectives.Flat2D:\n\t\t\t\treturn this.createFlat2DCamera(aspectRatio);\n\t\t\tcase Perspectives.Fixed2D:\n\t\t\t\treturn this.createFixed2DCamera(aspectRatio);\n\t\t\tdefault:\n\t\t\t\treturn this.createThirdPersonCamera(aspectRatio);\n\t\t}\n\t}\n\n\t/**\n\t * Initialize perspective-specific controller\n\t */\n\tprivate initializePerspectiveController() {\n\t\tswitch (this._perspective) {\n\t\t\tcase Perspectives.ThirdPerson:\n\t\t\t\tthis.perspectiveController = new ThirdPersonCamera();\n\t\t\t\tbreak;\n\t\t\tcase Perspectives.Fixed2D:\n\t\t\t\tthis.perspectiveController = new Fixed2DCamera();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.perspectiveController = new ThirdPersonCamera();\n\t\t}\n\t}\n\n\tprivate createThirdPersonCamera(aspectRatio: number): PerspectiveCamera {\n\t\treturn new PerspectiveCamera(75, aspectRatio, 0.1, 1000);\n\t}\n\n\tprivate createFirstPersonCamera(aspectRatio: number): PerspectiveCamera {\n\t\treturn new PerspectiveCamera(75, aspectRatio, 0.1, 1000);\n\t}\n\n\tprivate createIsometricCamera(aspectRatio: number): OrthographicCamera {\n\t\treturn new OrthographicCamera(\n\t\t\tthis.frustumSize * aspectRatio / -2,\n\t\t\tthis.frustumSize * aspectRatio / 2,\n\t\t\tthis.frustumSize / 2,\n\t\t\tthis.frustumSize / -2,\n\t\t\t1,\n\t\t\t1000\n\t\t);\n\t}\n\n\tprivate createFlat2DCamera(aspectRatio: number): OrthographicCamera {\n\t\treturn new OrthographicCamera(\n\t\t\tthis.frustumSize * aspectRatio / -2,\n\t\t\tthis.frustumSize * aspectRatio / 2,\n\t\t\tthis.frustumSize / 2,\n\t\t\tthis.frustumSize / -2,\n\t\t\t1,\n\t\t\t1000\n\t\t);\n\t}\n\n\tprivate createFixed2DCamera(aspectRatio: number): OrthographicCamera {\n\t\treturn this.createFlat2DCamera(aspectRatio);\n\t}\n\n\t// Movement methods\n\tprivate moveCamera(position: Vector3) {\n\t\tif (this._perspective === Perspectives.Flat2D || this._perspective === Perspectives.Fixed2D) {\n\t\t\tthis.frustumSize = position.z;\n\t\t}\n\t\tif (this.cameraRig) {\n\t\t\tthis.cameraRig.position.set(position.x, position.y, position.z);\n\t\t} else {\n\t\t\tthis.camera.position.set(position.x, position.y, position.z);\n\t\t}\n\t}\n\n\tmove(position: Vector3) {\n\t\tthis.moveCamera(position);\n\t}\n\n\trotate(pitch: number, yaw: number, roll: number) {\n\t\tif (this.cameraRig) {\n\t\t\tthis.cameraRig.rotateX(pitch);\n\t\t\tthis.cameraRig.rotateY(yaw);\n\t\t\tthis.cameraRig.rotateZ(roll);\n\t\t} else {\n\t\t\t(this.camera as Object3D).rotateX(pitch);\n\t\t\t(this.camera as Object3D).rotateY(yaw);\n\t\t\t(this.camera as Object3D).rotateZ(roll);\n\t\t}\n\t}\n\n\t/**\n\t * Check if this perspective type needs a camera rig\n\t */\n\tprivate needsRig(): boolean {\n\t\treturn this._perspective === Perspectives.ThirdPerson;\n\t}\n\n\t/**\n\t * Get the DOM element for the renderer\n\t */\n\tgetDomElement(): HTMLCanvasElement {\n\t\treturn this.renderer.domElement;\n\t}\n}","export const Perspectives = {\n\tFirstPerson: 'first-person',\n\tThirdPerson: 'third-person',\n\tIsometric: 'isometric',\n\tFlat2D: 'flat-2d',\n\tFixed2D: 'fixed-2d',\n} as const;\n\nexport type PerspectiveType = (typeof Perspectives)[keyof typeof Perspectives];","import { Scene, Vector2, Vector3, WebGLRenderer } from 'three';\nimport { PerspectiveController, ZylemCamera } from './zylem-camera';\nimport { StageEntity } from '../interfaces/entity';\n\ninterface ThirdPersonCameraOptions {\n\ttarget: StageEntity;\n\tdistance: Vector3;\n\tscreenResolution: Vector2;\n\trenderer: WebGLRenderer;\n\tscene: Scene;\n}\n\nexport class ThirdPersonCamera implements PerspectiveController {\n\tdistance: Vector3;\n\tscreenResolution: Vector2 | null = null;\n\trenderer: WebGLRenderer | null = null;\n\tscene: Scene | null = null;\n\tcameraRef: ZylemCamera | null = null;\n\n\tconstructor() {\n\t\tthis.distance = new Vector3(0, 5, 8);\n\t}\n\n\t/**\n\t * Setup the third person camera controller\n\t */\n\tsetup(params: { screenResolution: Vector2; renderer: WebGLRenderer; scene: Scene; camera: ZylemCamera }) {\n\t\tconst { screenResolution, renderer, scene, camera } = params;\n\t\tthis.screenResolution = screenResolution;\n\t\tthis.renderer = renderer;\n\t\tthis.scene = scene;\n\t\tthis.cameraRef = camera;\n\t}\n\n\t/**\n\t * Update the third person camera\n\t */\n\tupdate(delta: number) {\n\t\tif (!this.cameraRef!.target) {\n\t\t\treturn;\n\t\t}\n\t\t// TODO: Implement third person camera following logic\n\t\tconst desiredCameraPosition = this.cameraRef!.target!.group.position.clone().add(this.distance);\n\t\tthis.cameraRef!.camera.position.lerp(desiredCameraPosition, 0.1);\n\t\tthis.cameraRef!.camera.lookAt(this.cameraRef!.target!.group.position);\n\t}\n\n\t/**\n\t * Handle resize events\n\t */\n\tresize(width: number, height: number) {\n\t\tif (this.screenResolution) {\n\t\t\tthis.screenResolution.set(width, height);\n\t\t}\n\t\t// TODO: Handle any third-person specific resize logic\n\t}\n\n\t/**\n\t * Set the distance from the target\n\t */\n\tsetDistance(distance: Vector3) {\n\t\tthis.distance = distance;\n\t}\n}","import { Scene, Vector2, WebGLRenderer } from 'three';\nimport { PerspectiveController, ZylemCamera } from './zylem-camera';\n\n/**\n * Fixed 2D Camera Controller\n * Maintains a static 2D camera view with no automatic following or movement\n */\nexport class Fixed2DCamera implements PerspectiveController {\n\tscreenResolution: Vector2 | null = null;\n\trenderer: WebGLRenderer | null = null;\n\tscene: Scene | null = null;\n\tcameraRef: ZylemCamera | null = null;\n\n\tconstructor() {\n\t\t// Fixed 2D camera doesn't need any initial setup parameters\n\t}\n\n\t/**\n\t * Setup the fixed 2D camera controller\n\t */\n\tsetup(params: { screenResolution: Vector2; renderer: WebGLRenderer; scene: Scene; camera: ZylemCamera }) {\n\t\tconst { screenResolution, renderer, scene, camera } = params;\n\t\tthis.screenResolution = screenResolution;\n\t\tthis.renderer = renderer;\n\t\tthis.scene = scene;\n\t\tthis.cameraRef = camera;\n\n\t\t// Position camera for 2D view (looking down the Z-axis)\n\t\tthis.cameraRef.camera.position.set(0, 0, 10);\n\t\tthis.cameraRef.camera.lookAt(0, 0, 0);\n\t}\n\n\t/**\n\t * Update the fixed 2D camera\n\t * Fixed cameras don't need to update position/rotation automatically\n\t */\n\tupdate(delta: number) {\n\t\t// Fixed 2D camera maintains its position and orientation\n\t\t// No automatic updates needed for a truly fixed camera\n\t}\n\n\t/**\n\t * Handle resize events for 2D camera\n\t */\n\tresize(width: number, height: number) {\n\t\tif (this.screenResolution) {\n\t\t\tthis.screenResolution.set(width, height);\n\t\t}\n\n\t\t// For orthographic cameras, we might need to adjust the frustum\n\t\t// This is handled in the main ZylemCamera resize method\n\t}\n}\n","import * as THREE from 'three';\nimport { standardShader } from './shaders/standard.shader';\nimport { WebGLRenderer, WebGLRenderTarget } from 'three';\nimport { Pass, FullScreenQuad } from 'three/addons/postprocessing/Pass.js';\n\nexport default class RenderPass extends Pass {\n\tfsQuad: FullScreenQuad;\n\tresolution: THREE.Vector2;\n\tscene: THREE.Scene;\n\tcamera: THREE.Camera;\n\trgbRenderTarget: WebGLRenderTarget;\n\tnormalRenderTarget: WebGLRenderTarget;\n\tnormalMaterial: THREE.Material;\n\n\tconstructor(resolution: THREE.Vector2, scene: THREE.Scene, camera: THREE.Camera) {\n\t\tsuper();\n\t\tthis.resolution = resolution;\n\t\tthis.fsQuad = new FullScreenQuad(this.material());\n\t\tthis.scene = scene;\n\t\tthis.camera = camera;\n\n\t\tthis.rgbRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);\n\t\tthis.normalRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);\n\n\t\tthis.normalMaterial = new THREE.MeshNormalMaterial();\n\t}\n\n\trender(\n\t\trenderer: WebGLRenderer,\n\t\twriteBuffer: WebGLRenderTarget\n\t) {\n\t\trenderer.setRenderTarget(this.rgbRenderTarget);\n\t\trenderer.render(this.scene, this.camera);\n\n\t\tconst overrideMaterial_old = this.scene.overrideMaterial;\n\t\trenderer.setRenderTarget(this.normalRenderTarget);\n\t\tthis.scene.overrideMaterial = this.normalMaterial;\n\t\trenderer.render(this.scene, this.camera);\n\t\tthis.scene.overrideMaterial = overrideMaterial_old;\n\n\t\t// @ts-ignore\n\t\tconst uniforms = this.fsQuad.material.uniforms;\n\t\tuniforms.tDiffuse.value = this.rgbRenderTarget.texture;\n\t\tuniforms.tDepth.value = this.rgbRenderTarget.depthTexture;\n\t\tuniforms.tNormal.value = this.normalRenderTarget.texture;\n\t\tuniforms.iTime.value += 0.01;\n\n\t\tif (this.renderToScreen) {\n\t\t\trenderer.setRenderTarget(null);\n\t\t} else {\n\t\t\trenderer.setRenderTarget(writeBuffer);\n\t\t}\n\t\tthis.fsQuad.render(renderer);\n\t}\n\n\tmaterial() {\n\t\treturn new THREE.ShaderMaterial({\n\t\t\tuniforms: {\n\t\t\t\tiTime: { value: 0 },\n\t\t\t\ttDiffuse: { value: null },\n\t\t\t\ttDepth: { value: null },\n\t\t\t\ttNormal: { value: null },\n\t\t\t\tresolution: {\n\t\t\t\t\tvalue: new THREE.Vector4(\n\t\t\t\t\t\tthis.resolution.x,\n\t\t\t\t\t\tthis.resolution.y,\n\t\t\t\t\t\t1 / this.resolution.x,\n\t\t\t\t\t\t1 / this.resolution.y,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t},\n\t\t\tvertexShader: standardShader.vertex,\n\t\t\tfragmentShader: standardShader.fragment\n\t\t});\n\t}\n\n\tdispose() {\n\t\ttry {\n\t\t\tthis.fsQuad?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\t(this.rgbRenderTarget as any)?.dispose?.();\n\t\t\t(this.normalRenderTarget as any)?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\t(this.normalMaterial as any)?.dispose?.();\n\t\t} catch { /* noop */ }\n\t}\n}\n","export const objectVertexShader = `\nuniform vec2 uvScale;\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n}\n`;\n","import { objectVertexShader } from './vertex/object.shader';\n\nconst fragment = `\nuniform sampler2D tDiffuse;\nvarying vec2 vUv;\n\nvoid main() {\n\tvec4 texel = texture2D( tDiffuse, vUv );\n\n\tgl_FragColor = texel;\n}\n`;\n\nexport const standardShader = {\n vertex: objectVertexShader,\n fragment\n};\n","import { Object3D, Vector3, Quaternion, Camera, Scene } from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\n\nexport interface CameraDebugState {\n\tenabled: boolean;\n\tselected: string[];\n}\n\nexport interface CameraDebugDelegate {\n\tsubscribe(listener: (state: CameraDebugState) => void): () => void;\n\tresolveTarget(uuid: string): Object3D | null;\n}\n\n/**\n * Manages orbit controls and debug state for a camera.\n * Orbit controls are only active when debug mode is enabled.\n */\nexport class CameraOrbitController {\n\tprivate camera: Camera;\n\tprivate domElement: HTMLElement;\n\tprivate cameraRig: Object3D | null = null;\n\tprivate sceneRef: Scene | null = null;\n\t\n\tprivate orbitControls: OrbitControls | null = null;\n\tprivate orbitTarget: Object3D | null = null;\n\tprivate orbitTargetWorldPos: Vector3 = new Vector3();\n\n\tprivate debugDelegate: CameraDebugDelegate | null = null;\n\tprivate debugUnsubscribe: (() => void) | null = null;\n\tprivate debugStateSnapshot: CameraDebugState = { enabled: false, selected: [] };\n\n\t// Saved camera state for restoration when exiting debug mode\n\tprivate savedCameraPosition: Vector3 | null = null;\n\tprivate savedCameraQuaternion: Quaternion | null = null;\n\tprivate savedCameraZoom: number | null = null;\n\tprivate savedCameraLocalPosition: Vector3 | null = null;\n\n\t// Saved debug camera state for restoration when re-entering debug mode\n\tprivate savedDebugCameraPosition: Vector3 | null = null;\n\tprivate savedDebugCameraQuaternion: Quaternion | null = null;\n\tprivate savedDebugCameraZoom: number | null = null;\n\tprivate savedDebugOrbitTarget: Vector3 | null = null;\n\n\tconstructor(camera: Camera, domElement: HTMLElement, cameraRig?: Object3D | null) {\n\t\tthis.camera = camera;\n\t\tthis.domElement = domElement;\n\t\tthis.cameraRig = cameraRig ?? null;\n\t}\n\n\t/**\n\t * Set the scene reference for adding/removing camera when detaching from rig.\n\t */\n\tsetScene(scene: Scene | null): void {\n\t\tthis.sceneRef = scene;\n\t}\n\n\t/**\n\t * Check if debug mode is currently active (orbit controls enabled).\n\t */\n\tget isActive(): boolean {\n\t\treturn this.debugStateSnapshot.enabled;\n\t}\n\n\t/**\n\t * Update orbit controls each frame.\n\t * Should be called from the camera's update loop.\n\t */\n\tupdate() {\n\t\tif (this.orbitControls && this.orbitTarget) {\n\t\t\tthis.orbitTarget.getWorldPosition(this.orbitTargetWorldPos);\n\t\t\tthis.orbitControls.target.copy(this.orbitTargetWorldPos);\n\t\t}\n\t\tthis.orbitControls?.update();\n\t}\n\n\t/**\n\t * Attach a delegate to react to debug state changes.\n\t */\n\tsetDebugDelegate(delegate: CameraDebugDelegate | null) {\n\t\tif (this.debugDelegate === delegate) {\n\t\t\treturn;\n\t\t}\n\t\tthis.detachDebugDelegate();\n\t\tthis.debugDelegate = delegate;\n\t\tif (!delegate) {\n\t\t\tthis.applyDebugState({ enabled: false, selected: [] });\n\t\t\treturn;\n\t\t}\n\t\tconst unsubscribe = delegate.subscribe((state) => {\n\t\t\tthis.applyDebugState(state);\n\t\t});\n\t\tthis.debugUnsubscribe = () => {\n\t\t\tunsubscribe?.();\n\t\t};\n\t}\n\n\t/**\n\t * Clean up resources.\n\t */\n\tdispose() {\n\t\tthis.disableOrbitControls();\n\t\tthis.detachDebugDelegate();\n\t}\n\n\t/**\n\t * Get the current debug state snapshot.\n\t */\n\tget debugState(): CameraDebugState {\n\t\treturn this.debugStateSnapshot;\n\t}\n\n\tprivate applyDebugState(state: CameraDebugState) {\n\t\tconst wasEnabled = this.debugStateSnapshot.enabled;\n\t\tthis.debugStateSnapshot = {\n\t\t\tenabled: state.enabled,\n\t\t\tselected: [...state.selected],\n\t\t};\n\t\tif (state.enabled && !wasEnabled) {\n\t\t\t// Entering debug mode: save game camera state, detach from rig, restore debug camera state if available\n\t\t\tthis.saveCameraState();\n\t\t\tthis.detachCameraFromRig();\n\t\t\tthis.enableOrbitControls();\n\t\t\tthis.restoreDebugCameraState();\n\t\t\tthis.updateOrbitTargetFromSelection(state.selected);\n\t\t} else if (!state.enabled && wasEnabled) {\n\t\t\t// Exiting debug mode: save debug camera state, then restore game camera state\n\t\t\tthis.saveDebugCameraState();\n\t\t\tthis.orbitTarget = null;\n\t\t\tthis.disableOrbitControls();\n\t\t\tthis.reattachCameraToRig();\n\t\t\tthis.restoreCameraState();\n\t\t} else if (state.enabled) {\n\t\t\t// Still in debug mode, just update target\n\t\t\tthis.updateOrbitTargetFromSelection(state.selected);\n\t\t}\n\t}\n\n\tprivate enableOrbitControls() {\n\t\tif (this.orbitControls) {\n\t\t\treturn;\n\t\t}\n\t\tthis.orbitControls = new OrbitControls(this.camera, this.domElement);\n\t\tthis.orbitControls.enableDamping = true;\n\t\tthis.orbitControls.dampingFactor = 0.05;\n\t\tthis.orbitControls.screenSpacePanning = false;\n\t\tthis.orbitControls.minDistance = 1;\n\t\tthis.orbitControls.maxDistance = 500;\n\t\tthis.orbitControls.maxPolarAngle = Math.PI / 2;\n\t\t// Default target to origin\n\t\tthis.orbitControls.target.set(0, 0, 0);\n\t}\n\n\tprivate disableOrbitControls() {\n\t\tif (!this.orbitControls) {\n\t\t\treturn;\n\t\t}\n\t\tthis.orbitControls.dispose();\n\t\tthis.orbitControls = null;\n\t}\n\n\tprivate updateOrbitTargetFromSelection(selected: string[]) {\n\t\t// Default to origin when no entity is selected\n\t\tif (!this.debugDelegate || selected.length === 0) {\n\t\t\tthis.orbitTarget = null;\n\t\t\tif (this.orbitControls) {\n\t\t\t\tthis.orbitControls.target.set(0, 0, 0);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = selected.length - 1; i >= 0; i -= 1) {\n\t\t\tconst uuid = selected[i];\n\t\t\tconst targetObject = this.debugDelegate.resolveTarget(uuid);\n\t\t\tif (targetObject) {\n\t\t\t\tthis.orbitTarget = targetObject;\n\t\t\t\tif (this.orbitControls) {\n\t\t\t\t\ttargetObject.getWorldPosition(this.orbitTargetWorldPos);\n\t\t\t\t\tthis.orbitControls.target.copy(this.orbitTargetWorldPos);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.orbitTarget = null;\n\t}\n\n\tprivate detachDebugDelegate() {\n\t\tif (this.debugUnsubscribe) {\n\t\t\ttry {\n\t\t\t\tthis.debugUnsubscribe();\n\t\t\t} catch { /* noop */ }\n\t\t}\n\t\tthis.debugUnsubscribe = null;\n\t\tthis.debugDelegate = null;\n\t}\n\n\t/**\n\t * Save camera position, rotation, and zoom before entering debug mode.\n\t */\n\tprivate saveCameraState() {\n\t\tthis.savedCameraPosition = this.camera.position.clone();\n\t\tthis.savedCameraQuaternion = this.camera.quaternion.clone();\n\t\t// Save zoom for orthographic/perspective cameras\n\t\tif ('zoom' in this.camera) {\n\t\t\tthis.savedCameraZoom = (this.camera as any).zoom as number;\n\t\t}\n\t}\n\n\t/**\n\t * Restore camera position, rotation, and zoom when exiting debug mode.\n\t */\n\tprivate restoreCameraState() {\n\t\tif (this.savedCameraPosition) {\n\t\t\tthis.camera.position.copy(this.savedCameraPosition);\n\t\t\tthis.savedCameraPosition = null;\n\t\t}\n\t\tif (this.savedCameraQuaternion) {\n\t\t\tthis.camera.quaternion.copy(this.savedCameraQuaternion);\n\t\t\tthis.savedCameraQuaternion = null;\n\t\t}\n\t\tif (this.savedCameraZoom !== null && 'zoom' in this.camera) {\n\t\t\tthis.camera.zoom = this.savedCameraZoom;\n\t\t\t(this.camera as any).updateProjectionMatrix?.();\n\t\t\tthis.savedCameraZoom = null;\n\t\t}\n\t}\n\n\t/**\n\t * Save debug camera state when exiting debug mode.\n\t */\n\tprivate saveDebugCameraState() {\n\t\tthis.savedDebugCameraPosition = this.camera.position.clone();\n\t\tthis.savedDebugCameraQuaternion = this.camera.quaternion.clone();\n\t\tif ('zoom' in this.camera) {\n\t\t\tthis.savedDebugCameraZoom = (this.camera as any).zoom as number;\n\t\t}\n\t\tif (this.orbitControls) {\n\t\t\tthis.savedDebugOrbitTarget = this.orbitControls.target.clone();\n\t\t}\n\t}\n\n\t/**\n\t * Restore debug camera state when re-entering debug mode.\n\t */\n\tprivate restoreDebugCameraState() {\n\t\tif (this.savedDebugCameraPosition) {\n\t\t\tthis.camera.position.copy(this.savedDebugCameraPosition);\n\t\t}\n\t\tif (this.savedDebugCameraQuaternion) {\n\t\t\tthis.camera.quaternion.copy(this.savedDebugCameraQuaternion);\n\t\t}\n\t\tif (this.savedDebugCameraZoom !== null && 'zoom' in this.camera) {\n\t\t\tthis.camera.zoom = this.savedDebugCameraZoom;\n\t\t\t(this.camera as any).updateProjectionMatrix?.();\n\t\t}\n\t\tif (this.savedDebugOrbitTarget && this.orbitControls) {\n\t\t\tthis.orbitControls.target.copy(this.savedDebugOrbitTarget);\n\t\t}\n\t}\n\n\t/**\n\t * Detach camera from its rig to allow free orbit movement in debug mode.\n\t * Preserves the camera's world position.\n\t */\n\tprivate detachCameraFromRig(): void {\n\t\tif (!this.cameraRig || this.camera.parent !== this.cameraRig) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Save the camera's local position for later restoration\n\t\tthis.savedCameraLocalPosition = this.camera.position.clone();\n\n\t\t// Get camera's world position before detaching\n\t\tconst worldPos = new Vector3();\n\t\tthis.camera.getWorldPosition(worldPos);\n\n\t\t// Remove camera from rig\n\t\tthis.cameraRig.remove(this.camera);\n\n\t\t// Add camera directly to scene if scene ref is available\n\t\tif (this.sceneRef) {\n\t\t\tthis.sceneRef.add(this.camera);\n\t\t}\n\n\t\t// Set camera's position to its previous world position\n\t\tthis.camera.position.copy(worldPos);\n\t}\n\n\t/**\n\t * Reattach camera to its rig when exiting debug mode.\n\t * Restores the camera's local position relative to the rig.\n\t */\n\tprivate reattachCameraToRig(): void {\n\t\tif (!this.cameraRig || this.camera.parent === this.cameraRig) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove camera from scene if it's there\n\t\tif (this.sceneRef && this.camera.parent === this.sceneRef) {\n\t\t\tthis.sceneRef.remove(this.camera);\n\t\t}\n\n\t\t// Add camera back to rig\n\t\tthis.cameraRig.add(this.camera);\n\n\t\t// Restore camera's local position\n\t\tif (this.savedCameraLocalPosition) {\n\t\t\tthis.camera.position.copy(this.savedCameraLocalPosition);\n\t\t\tthis.savedCameraLocalPosition = null;\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["Vector2","Vector3","Vector3","Object3D","WebGLRenderer","Vector3","WebGLRenderer","Object3D","Vector3","Vector2","Vector3"]}
1
+ {"version":3,"sources":["../src/lib/camera/camera.ts","../src/lib/camera/zylem-camera.ts","../src/lib/camera/perspective.ts","../src/lib/camera/camera-debug-delegate.ts","../src/lib/camera/renderer-manager.ts","../src/lib/graphics/render-pass.ts","../src/lib/graphics/shaders/vertex/object.shader.ts","../src/lib/graphics/shaders/standard.shader.ts","../src/lib/camera/smoothing.ts","../src/lib/camera/camera-pipeline.ts","../src/lib/camera/perspectives/third-person-perspective.ts","../src/lib/camera/perspectives/fixed-2d-perspective.ts","../src/lib/camera/perspectives/first-person-perspective.ts","../src/lib/camera/perspectives/index.ts","../src/lib/camera/camera-manager.ts"],"sourcesContent":["import { Vector2, Vector3, Texture } from \"three\";\nimport { PerspectiveType } from \"./perspective\";\nimport { ZylemCamera } from \"./zylem-camera\";\nimport { RendererType, Viewport, DEFAULT_VIEWPORT } from \"./renderer-manager\";\nimport { StageEntity } from \"../interfaces/entity\";\nimport type { CameraBehavior, CameraAction, CameraPerspective, CameraPipelineState } from \"./types\";\nimport { createPerspective } from \"./perspectives\";\nimport type { PerspectiveOptions } from \"./perspectives\";\n\nexport interface CameraOptions {\n\tperspective?: PerspectiveType;\n\tposition?: Vector3 | { x: number; y: number; z: number };\n\ttarget?: Vector3 | { x: number; y: number; z: number } | any;\n\tzoom?: number;\n\tscreenResolution?: Vector2;\n\t/**\n\t * Renderer type: 'auto' | 'webgpu' | 'webgl'\n\t * Use 'webgpu' for TSL shaders\n\t * @default 'webgl'\n\t */\n\trendererType?: RendererType;\n\t/**\n\t * Enable orbital controls for this camera.\n\t * Can be toggled at runtime via enableOrbitalControls() / disableOrbitalControls().\n\t * @default false\n\t */\n\tuseOrbitalControls?: boolean;\n\t/**\n\t * Viewport in normalized coordinates (0-1).\n\t * Defines where this camera renders on the canvas.\n\t * @default { x: 0, y: 0, width: 1, height: 1 } (fullscreen)\n\t */\n\tviewport?: Viewport;\n\t/**\n\t * Optional name for camera manager lookup.\n\t */\n\tname?: string;\n\t/**\n\t * Initial behaviors to attach to the camera pipeline.\n\t * Keys are used for idempotent add/remove.\n\t */\n\tbehaviors?: Record<string, CameraBehavior>;\n\t/**\n\t * Pipeline smoothing factor (0-1).\n\t * 1 = instant snap, 0 = no movement.\n\t * @default 0.15\n\t */\n\tdamping?: number;\n\t/**\n\t * When set, the camera renders to an offscreen texture instead of a\n\t * screen viewport. Use with setCameraFeed() to display the feed on\n\t * an in-scene mesh (jumbotron, security monitor, portal, etc.).\n\t *\n\t * @default undefined (renders to screen)\n\t */\n\trenderToTexture?: {\n\t\t/** Texture width in pixels. @default 512 */\n\t\twidth?: number;\n\t\t/** Texture height in pixels. @default 512 */\n\t\theight?: number;\n\t};\n\t/**\n\t * When true, this camera will not activate orbital controls in debug mode.\n\t * The pipeline (and its behaviors) will always run for this camera.\n\t * Use for cameras with custom behaviors (e.g. FPS mouse-look) that must\n\t * control the camera through the pipeline rather than debug orbit controls.\n\t * @default false\n\t */\n\tskipDebugOrbit?: boolean;\n}\n\n/**\n * CameraWrapper is the user-facing camera handle returned by createCamera().\n * It provides convenience methods for target management, orbital controls,\n * viewport configuration, and the camera pose pipeline.\n */\nexport class CameraWrapper {\n\tcameraRef: ZylemCamera;\n\n\tconstructor(camera: ZylemCamera) {\n\t\tthis.cameraRef = camera;\n\t}\n\n\t// ─── Target management ──────────────────────────────────────────────────\n\n\t/**\n\t * Add a target entity for the camera to follow/frame.\n\t * With multiple targets, the camera auto-frames to include all of them.\n\t */\n\taddTarget(entity: StageEntity): void {\n\t\tthis.cameraRef.addTarget(entity);\n\t}\n\n\t/**\n\t * Remove a target entity from the camera.\n\t */\n\tremoveTarget(entity: StageEntity): void {\n\t\tthis.cameraRef.removeTarget(entity);\n\t}\n\n\t/**\n\t * Clear all targets. Camera will look at world origin.\n\t */\n\tclearTargets(): void {\n\t\tthis.cameraRef.clearTargets();\n\t}\n\n\t// ─── Orbital controls ───────────────────────────────────────────────────\n\n\t/**\n\t * Enable orbital controls for this camera.\n\t * Allows the user to orbit, pan, and zoom the camera.\n\t */\n\tenableOrbitalControls(): void {\n\t\tthis.cameraRef.enableOrbitalControls();\n\t}\n\n\t/**\n\t * Disable orbital controls for this camera.\n\t */\n\tdisableOrbitalControls(): void {\n\t\tthis.cameraRef.disableOrbitalControls();\n\t}\n\n\t// ─── Viewport ───────────────────────────────────────────────────────────\n\n\t/**\n\t * Set the viewport for this camera (normalized 0-1 coordinates).\n\t * @param x Left edge (0 = left of canvas)\n\t * @param y Bottom edge (0 = bottom of canvas)\n\t * @param width Width as fraction of canvas\n\t * @param height Height as fraction of canvas\n\t */\n\tsetViewport(x: number, y: number, width: number, height: number): void {\n\t\tthis.cameraRef.setViewport(x, y, width, height);\n\t}\n\n\t// ─── Pipeline: Behaviors ────────────────────────────────────────────────\n\n\t/**\n\t * Add or replace a behavior by key (idempotent).\n\t * Behaviors modify the desired camera pose each frame.\n\t *\n\t * @param key Unique key for this behavior (used for replacement/removal).\n\t * @param behavior The CameraBehavior implementation.\n\t */\n\taddBehavior(key: string, behavior: CameraBehavior): void {\n\t\tthis.cameraRef.pipeline.addBehavior(key, behavior);\n\t}\n\n\t/**\n\t * Remove a behavior by key.\n\t */\n\tremoveBehavior(key: string): boolean {\n\t\treturn this.cameraRef.pipeline.removeBehavior(key);\n\t}\n\n\t// ─── Pipeline: Actions ──────────────────────────────────────────────────\n\n\t/**\n\t * Add a transient action (screenshake, recoil, etc.).\n\t * Actions apply additive deltas and self-expire when isDone() returns true.\n\t */\n\taddAction(action: CameraAction): void {\n\t\tthis.cameraRef.pipeline.addAction(action);\n\t}\n\n\t// ─── Pipeline: Perspective ──────────────────────────────────────────────\n\n\t/**\n\t * Switch the camera's active perspective at runtime.\n\t * The first frame after switching snaps to the new pose (no lerp).\n\t *\n\t * @param type Perspective type string (e.g. Perspectives.ThirdPerson).\n\t * @param options Perspective-specific options (distance, height, zoom, etc.).\n\t */\n\tsetPerspective(type: PerspectiveType, options?: PerspectiveOptions): void {\n\t\tthis.cameraRef.pipeline.setPerspective(createPerspective(type, options));\n\t}\n\n\t/**\n\t * Retrieve the active perspective instance, cast to the desired type.\n\t * Useful for calling perspective-specific methods (e.g. FirstPersonPerspective.look()).\n\t *\n\t * @example\n\t * const fps = camera.getPerspective<FirstPersonPerspective>();\n\t * fps.look(dx, dy);\n\t */\n\tgetPerspective<T extends CameraPerspective = CameraPerspective>(): T {\n\t\treturn this.cameraRef.pipeline.perspective as T;\n\t}\n\n\t// ─── Pipeline: Debug state ──────────────────────────────────────────────\n\n\t/**\n\t * Return a debug snapshot of the camera pipeline state.\n\t * Includes: active perspective, desired/final pose, behavior keys, action count.\n\t */\n\tgetState(): CameraPipelineState {\n\t\treturn this.cameraRef.pipeline.getState();\n\t}\n\n\t// ─── Render-to-texture ─────────────────────────────────────────────────\n\n\t/**\n\t * Get the offscreen render texture for this camera.\n\t * Returns null if the camera was not created with renderToTexture.\n\t * Use with setCameraFeed() or apply directly to a mesh material.\n\t */\n\tgetRenderTexture(): Texture | null {\n\t\treturn this.cameraRef.getRenderTexture();\n\t}\n}\n\n/**\n * Create a camera with the given options.\n * Returns a CameraWrapper for convenient access to camera features.\n */\nexport function createCamera(options: CameraOptions): CameraWrapper {\n\tconst screenResolution = options.screenResolution || new Vector2(window.innerWidth, window.innerHeight);\n\tlet frustumSize = 10;\n\tif (options.perspective === 'fixed-2d') {\n\t\tfrustumSize = options.zoom || 10;\n\t}\n\tconst zylemCamera = new ZylemCamera(\n\t\toptions.perspective || 'third-person',\n\t\tscreenResolution,\n\t\tfrustumSize,\n\t\toptions.rendererType || 'webgl'\n\t);\n\n\t// Set camera name if provided\n\tif (options.name) {\n\t\tzylemCamera.name = options.name;\n\t}\n\n\t// Set initial position and target\n\tconst position = options.position \n\t\t? (options.position instanceof Vector3 ? options.position : new Vector3(options.position.x, options.position.y, options.position.z))\n\t\t: new Vector3(0, 0, 0);\n\t\n\tconst target = options.target\n\t\t? (options.target instanceof Vector3 ? options.target : new Vector3(options.target.x, options.target.y, options.target.z))\n\t\t: new Vector3(0, 0, 0);\n\t\n\tzylemCamera.move(position);\n\tzylemCamera.camera.lookAt(target);\n\n\t// Reconfigure the perspective with user-specified options (position, zoom, etc.)\n\t// so the pipeline produces the correct base pose from the first frame.\n\tconst perspType = options.perspective || 'third-person';\n\tif (perspType === 'fixed-2d' || perspType === 'flat-2d') {\n\t\tzylemCamera.pipeline.setPerspective(\n\t\t\tcreatePerspective(perspType, { zoom: frustumSize })\n\t\t);\n\t} else {\n\t\tzylemCamera.pipeline.setPerspective(\n\t\t\tcreatePerspective(perspType, {\n\t\t\t\tinitialPosition: position.clone(),\n\t\t\t\tinitialLookAt: target.clone(),\n\t\t\t})\n\t\t);\n\t}\n\n\t// Set viewport if provided\n\tif (options.viewport) {\n\t\tzylemCamera.viewport = { ...options.viewport };\n\t}\n\n\t// Configure orbital controls\n\tif (options.useOrbitalControls) {\n\t\t(zylemCamera as any)._useOrbitalControls = true;\n\t}\n\n\t// Opt out of debug-mode orbital controls\n\tif (options.skipDebugOrbit) {\n\t\tzylemCamera._skipDebugOrbit = true;\n\t}\n\n\t// Configure pipeline damping\n\tif (options.damping != null) {\n\t\tzylemCamera.pipeline.damping = options.damping;\n\t}\n\n\t// Attach initial behaviors\n\tif (options.behaviors) {\n\t\tfor (const [key, behavior] of Object.entries(options.behaviors)) {\n\t\t\tzylemCamera.pipeline.addBehavior(key, behavior);\n\t\t}\n\t}\n\n\t// Create render target for RTT cameras\n\tif (options.renderToTexture) {\n\t\tconst { width = 512, height = 512 } = options.renderToTexture;\n\t\tzylemCamera.createRenderTarget(width, height);\n\t}\n\n\treturn new CameraWrapper(zylemCamera);\n}\n","import { Vector2, Camera, PerspectiveCamera, Vector3, Object3D, OrthographicCamera, Scene, WebGLRenderTarget, Texture, LinearFilter } from 'three';\nimport { PerspectiveType, Perspectives } from './perspective';\nimport { StageEntity } from '../interfaces/entity';\nimport { CameraOrbitController, CameraDebugDelegate } from './camera-debug-delegate';\nimport { RendererManager, DEFAULT_VIEWPORT } from './renderer-manager';\nimport type { ZylemRenderer, RendererType, Viewport } from './renderer-manager';\nimport { CameraPipeline } from './camera-pipeline';\nimport { createPerspective } from './perspectives';\nimport type { CameraContext, TransformLike, CameraPose } from './types';\n\n// Re-export for backwards compatibility\nexport type { CameraDebugState, CameraDebugDelegate } from './camera-debug-delegate';\nexport type { RendererType, ZylemRenderer } from './renderer-manager';\nexport { isWebGPUSupported } from './renderer-manager';\n\n/**\n * ZylemCamera is a lightweight camera wrapper that manages the Three.js camera,\n * the camera pose pipeline, and viewport configuration. Rendering is handled\n * by RendererManager.\n *\n * The pipeline runs: Perspective -> Behaviors -> Actions -> Smoothing -> Commit.\n * When orbit/debug controls are active, the pipeline is bypassed.\n */\nexport class ZylemCamera {\n\t/**\n\t * @deprecated No longer used. Kept as null for backward compatibility\n\t * with code that checks `camera.cameraRig` (e.g. scene graph insertion).\n\t */\n\tcameraRig: Object3D | null = null;\n\n\tcamera: Camera;\n\tscreenResolution: Vector2;\n\t_perspective: PerspectiveType;\n\tfrustumSize = 10;\n\trendererType: RendererType;\n\tsceneRef: Scene | null = null;\n\n\t/** Name for camera manager lookup. */\n\tname: string = '';\n\n\t/**\n\t * Viewport in normalized coordinates (0-1).\n\t * Default is fullscreen: { x: 0, y: 0, width: 1, height: 1 }\n\t */\n\tviewport: Viewport = { ...DEFAULT_VIEWPORT };\n\n\t/**\n\t * Multiple targets for the camera to follow/frame.\n\t */\n\ttargets: StageEntity[] = [];\n\n\t/**\n\t * The camera pose pipeline.\n\t * Exposed so CameraWrapper can delegate addBehavior/addAction/getState.\n\t */\n\tpipeline: CameraPipeline;\n\n\t/**\n\t * Offscreen render target for render-to-texture (RTT) cameras.\n\t * When set, the camera renders to this target instead of the screen viewport.\n\t * Created via createRenderTarget() or automatically by setCameraFeed().\n\t */\n\trenderTarget: WebGLRenderTarget | null = null;\n\n\t/**\n\t * @deprecated Use `targets` array instead. Kept for backward compatibility.\n\t */\n\tget target(): StageEntity | null {\n\t\treturn this.targets.length > 0 ? this.targets[0] : null;\n\t}\n\n\tset target(entity: StageEntity | null) {\n\t\tif (entity) {\n\t\t\tif (this.targets.length === 0) {\n\t\t\t\tthis.targets.push(entity);\n\t\t\t} else {\n\t\t\t\tthis.targets[0] = entity;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.targets = [];\n\t\t}\n\t}\n\n\t// Orbit controls\n\tprivate orbitController: CameraOrbitController | null = null;\n\tprivate _useOrbitalControls = false;\n\n\t/** When true, debug-mode orbital controls are not attached to this camera. */\n\t_skipDebugOrbit = false;\n\n\t/** Reference to the shared renderer manager (set during setup). */\n\tprivate _rendererManager: RendererManager | null = null;\n\n\t/** Elapsed time tracker for CameraContext. */\n\tprivate _elapsedTime = 0;\n\n\tconstructor(perspective: PerspectiveType, screenResolution: Vector2, frustumSize: number = 10, rendererType: RendererType = 'webgl') {\n\t\tthis._perspective = perspective;\n\t\tthis.screenResolution = screenResolution;\n\t\tthis.frustumSize = frustumSize;\n\t\tthis.rendererType = rendererType;\n\n\t\t// Create Three.js camera based on perspective\n\t\tconst aspectRatio = screenResolution.x / screenResolution.y;\n\t\tthis.camera = this.createCameraForPerspective(aspectRatio);\n\n\t\t// Position camera directly (no rig)\n\t\tthis.camera.position.set(0, 0, 10);\n\t\tthis.camera.lookAt(new Vector3(0, 0, 0));\n\n\t\t// Create pipeline with the appropriate perspective implementation\n\t\tconst perspectiveImpl = createPerspective(perspective);\n\t\tthis.pipeline = new CameraPipeline(perspectiveImpl);\n\t}\n\n\t/**\n\t * Setup the camera with a scene and renderer manager.\n\t */\n\tasync setup(scene: Scene, rendererManager?: RendererManager): Promise<void> {\n\t\tthis.sceneRef = scene;\n\n\t\tif (rendererManager) {\n\t\t\tthis._rendererManager = rendererManager;\n\t\t}\n\n\t\t// Ensure renderer manager is initialized\n\t\tif (this._rendererManager && !this._rendererManager.initialized) {\n\t\t\tawait this._rendererManager.initRenderer();\n\t\t}\n\n\t\t// Initialize orbit controller if renderer is available\n\t\tif (this._rendererManager) {\n\t\t\tthis.orbitController = new CameraOrbitController(\n\t\t\t\tthis.camera,\n\t\t\t\tthis._rendererManager.renderer.domElement,\n\t\t\t\tnull // no camera rig\n\t\t\t);\n\t\t\tthis.orbitController.setScene(scene);\n\n\t\t\t// If orbital controls were requested, enable them\n\t\t\tif (this._useOrbitalControls) {\n\t\t\t\tthis.orbitController.enableUserOrbitControls();\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Legacy setup method for backward compatibility.\n\t * Creates a temporary RendererManager internally.\n\t * @deprecated Use setup(scene, rendererManager) instead.\n\t */\n\tasync setupLegacy(scene: Scene): Promise<void> {\n\t\tif (!this._rendererManager) {\n\t\t\tthis._rendererManager = new RendererManager(this.screenResolution, this.rendererType);\n\t\t\tawait this._rendererManager.initRenderer();\n\n\t\t\t// Setup render pass for WebGL\n\t\t\tthis._rendererManager.setupRenderPass(scene, this.camera);\n\n\t\t\t// Start render loop\n\t\t\tthis._rendererManager.startRenderLoop((delta) => {\n\t\t\t\tthis.update(delta);\n\t\t\t\tif (this._rendererManager && this.sceneRef) {\n\t\t\t\t\tthis._rendererManager.render(this.sceneRef, this.camera);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tawait this.setup(scene, this._rendererManager);\n\t}\n\n\t/**\n\t * Update the camera each frame.\n\t *\n\t * When orbit/debug controls are active, the pipeline is skipped and\n\t * orbit controls manage the camera directly. Otherwise, the pipeline\n\t * runs: Perspective -> Behaviors -> Actions -> Smoothing -> Commit.\n\t */\n\tupdate(delta: number): void {\n\t\t// Update orbit controls (if debug mode or user orbital controls enabled)\n\t\tthis.orbitController?.update();\n\n\t\t// Skip pipeline when orbit controls are active\n\t\tif (this.isDebugModeActive() || this._useOrbitalControls) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Accumulate elapsed time\n\t\tthis._elapsedTime += delta;\n\n\t\t// Build context from current state\n\t\tconst ctx = this.buildContext(delta);\n\n\t\t// Run the pipeline\n\t\tconst finalPose = this.pipeline.run(ctx);\n\n\t\t// Commit the result to the Three.js camera\n\t\tthis.commitPose(finalPose);\n\t}\n\n\t/**\n\t * Check if debug mode is active (orbit controls taking over camera).\n\t */\n\tisDebugModeActive(): boolean {\n\t\treturn this.orbitController?.isActive ?? false;\n\t}\n\n\t/**\n\t * Enable user-configured orbital controls (not debug mode).\n\t */\n\tenableOrbitalControls(): void {\n\t\tthis._useOrbitalControls = true;\n\t\tthis.orbitController?.enableUserOrbitControls();\n\t}\n\n\t/**\n\t * Disable user-configured orbital controls.\n\t */\n\tdisableOrbitalControls(): void {\n\t\tthis._useOrbitalControls = false;\n\t\tthis.orbitController?.disableUserOrbitControls();\n\t}\n\n\t/**\n\t * Whether user orbital controls are enabled.\n\t */\n\tget useOrbitalControls(): boolean {\n\t\treturn this._useOrbitalControls;\n\t}\n\n\t// ─── Target management ──────────────────────────────────────────────────\n\n\t/**\n\t * Add a target entity for the camera to follow/frame.\n\t */\n\taddTarget(entity: StageEntity): void {\n\t\tif (!this.targets.includes(entity)) {\n\t\t\tthis.targets.push(entity);\n\t\t}\n\t}\n\n\t/**\n\t * Remove a target entity.\n\t */\n\tremoveTarget(entity: StageEntity): void {\n\t\tconst index = this.targets.indexOf(entity);\n\t\tif (index !== -1) {\n\t\t\tthis.targets.splice(index, 1);\n\t\t}\n\t}\n\n\t/**\n\t * Clear all targets.\n\t */\n\tclearTargets(): void {\n\t\tthis.targets = [];\n\t}\n\n\t// ─── Viewport & resize ──────────────────────────────────────────────────\n\n\t/**\n\t * Set the viewport for this camera (normalized 0-1 coordinates).\n\t */\n\tsetViewport(x: number, y: number, width: number, height: number): void {\n\t\tthis.viewport = { x, y, width, height };\n\t}\n\n\t/**\n\t * Resize camera projection.\n\t */\n\tresize(width: number, height: number): void {\n\t\tthis.screenResolution.set(width, height);\n\n\t\tif (this.camera instanceof PerspectiveCamera) {\n\t\t\tthis.camera.aspect = width / height;\n\t\t\tthis.camera.updateProjectionMatrix();\n\t\t}\n\n\t\tif (this.camera instanceof OrthographicCamera) {\n\t\t\tconst aspect = width / height;\n\t\t\tthis.camera.left = this.frustumSize * aspect / -2;\n\t\t\tthis.camera.right = this.frustumSize * aspect / 2;\n\t\t\tthis.camera.top = this.frustumSize / 2;\n\t\t\tthis.camera.bottom = this.frustumSize / -2;\n\t\t\tthis.camera.updateProjectionMatrix();\n\t\t}\n\t}\n\n\t// ─── Render-to-texture ─────────────────────────────────────────────────\n\n\t/**\n\t * Create an offscreen render target for this camera.\n\t * When a render target is present, CameraManager renders this camera\n\t * to the target instead of the screen viewport.\n\t *\n\t * @param width Texture width in pixels (default 512)\n\t * @param height Texture height in pixels (default 512)\n\t */\n\tcreateRenderTarget(width: number = 512, height: number = 512): WebGLRenderTarget {\n\t\tif (this.renderTarget) {\n\t\t\tthis.renderTarget.dispose();\n\t\t}\n\t\tthis.renderTarget = new WebGLRenderTarget(width, height, {\n\t\t\tminFilter: LinearFilter,\n\t\t\tmagFilter: LinearFilter,\n\t\t});\n\t\treturn this.renderTarget;\n\t}\n\n\t/**\n\t * Get the texture from the render target (for applying to a mesh material).\n\t * Returns null if no render target has been created.\n\t */\n\tgetRenderTexture(): Texture | null {\n\t\treturn this.renderTarget?.texture ?? null;\n\t}\n\n\t// ─── Lifecycle ──────────────────────────────────────────────────────────\n\n\t/**\n\t * Dispose camera resources.\n\t */\n\tdestroy(): void {\n\t\ttry {\n\t\t\tthis.orbitController?.dispose();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\tthis.renderTarget?.dispose();\n\t\t} catch { /* noop */ }\n\t\tthis.renderTarget = null;\n\t\tthis.sceneRef = null;\n\t\tthis.targets = [];\n\t\tthis._rendererManager = null;\n\t}\n\n\t// ─── Debug delegate ─────────────────────────────────────────────────────\n\n\t/**\n\t * Attach a delegate to react to debug state changes.\n\t * Skipped when _skipDebugOrbit is true so the pipeline always runs.\n\t */\n\tsetDebugDelegate(delegate: CameraDebugDelegate | null): void {\n\t\tif (this._skipDebugOrbit) return;\n\t\tthis.orbitController?.setDebugDelegate(delegate);\n\t}\n\n\t// ─── Movement helpers (backward compat) ─────────────────────────────────\n\n\t/**\n\t * Directly set the camera position.\n\t */\n\tmove(position: Vector3): void {\n\t\tif (this._perspective === Perspectives.Flat2D || this._perspective === Perspectives.Fixed2D) {\n\t\t\tthis.frustumSize = position.z;\n\t\t}\n\t\tthis.camera.position.set(position.x, position.y, position.z);\n\t}\n\n\t/**\n\t * Apply incremental rotation to the camera.\n\t */\n\trotate(pitch: number, yaw: number, roll: number): void {\n\t\t(this.camera as Object3D).rotateX(pitch);\n\t\t(this.camera as Object3D).rotateY(yaw);\n\t\t(this.camera as Object3D).rotateZ(roll);\n\t}\n\n\t// ─── Renderer manager access ────────────────────────────────────────────\n\n\t/**\n\t * Get the DOM element for the renderer.\n\t * @deprecated Access via RendererManager instead.\n\t */\n\tgetDomElement(): HTMLCanvasElement {\n\t\tif (this._rendererManager) {\n\t\t\treturn this._rendererManager.getDomElement();\n\t\t}\n\t\tthrow new Error('ZylemCamera: No renderer manager available. Call setup() first.');\n\t}\n\n\t/**\n\t * Get the renderer manager reference.\n\t */\n\tgetRendererManager(): RendererManager | null {\n\t\treturn this._rendererManager;\n\t}\n\n\t/**\n\t * Set the renderer manager reference (used by CameraManager during setup).\n\t */\n\tsetRendererManager(manager: RendererManager): void {\n\t\tthis._rendererManager = manager;\n\t}\n\n\t// ─── Legacy compatibility methods ────────────────────────────────────────\n\n\t/** @deprecated Renderer is now owned by RendererManager */\n\tget renderer(): any {\n\t\treturn this._rendererManager?.renderer;\n\t}\n\n\t/** @deprecated Composer is now owned by RendererManager */\n\tget composer(): any {\n\t\treturn this._rendererManager?.composer;\n\t}\n\n\t/** @deprecated Use RendererManager.setPixelRatio() instead */\n\tsetPixelRatio(dpr: number): void {\n\t\tthis._rendererManager?.setPixelRatio(dpr);\n\t}\n\n\t// ─── Private helpers ────────────────────────────────────────────────────\n\n\t/**\n\t * Build a CameraContext from current ZylemCamera state.\n\t * Converts StageEntity[] targets into Record<string, TransformLike>.\n\t */\n\tprivate buildContext(delta: number): CameraContext {\n\t\tconst targets: Record<string, TransformLike> = {};\n\n\t\tfor (let i = 0; i < this.targets.length; i++) {\n\t\t\tconst entity = this.targets[i];\n\t\t\tconst key = i === 0 ? 'primary' : `target_${i}`;\n\t\t\tif (entity.group) {\n\t\t\t\ttargets[key] = {\n\t\t\t\t\tposition: entity.group.position,\n\t\t\t\t\trotation: entity.group.quaternion,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tdt: delta,\n\t\t\ttime: this._elapsedTime,\n\t\t\tviewport: {\n\t\t\t\twidth: this.screenResolution.x,\n\t\t\t\theight: this.screenResolution.y,\n\t\t\t\taspect: this.screenResolution.x / this.screenResolution.y,\n\t\t\t},\n\t\t\ttargets,\n\t\t};\n\t}\n\n\t/**\n\t * Apply the final pipeline pose to the Three.js camera.\n\t */\n\tprivate commitPose(pose: CameraPose): void {\n\t\tthis.camera.position.copy(pose.position);\n\n\t\tif (pose.lookAt) {\n\t\t\tthis.camera.lookAt(pose.lookAt);\n\t\t} else {\n\t\t\tthis.camera.quaternion.copy(pose.rotation);\n\t\t}\n\n\t\tif (this.camera instanceof PerspectiveCamera) {\n\t\t\tif (pose.fov != null) this.camera.fov = pose.fov;\n\t\t\tif (pose.near != null) this.camera.near = pose.near;\n\t\t\tif (pose.far != null) this.camera.far = pose.far;\n\t\t\tthis.camera.updateProjectionMatrix();\n\t\t}\n\n\t\tif (this.camera instanceof OrthographicCamera) {\n\t\t\tif (pose.zoom != null) {\n\t\t\t\tconst aspect = this.screenResolution.x / this.screenResolution.y;\n\t\t\t\tconst size = pose.zoom;\n\t\t\t\tthis.camera.left = -size * aspect / 2;\n\t\t\t\tthis.camera.right = size * aspect / 2;\n\t\t\t\tthis.camera.top = size / 2;\n\t\t\t\tthis.camera.bottom = -size / 2;\n\t\t\t}\n\t\t\tif (pose.near != null) this.camera.near = pose.near;\n\t\t\tif (pose.far != null) this.camera.far = pose.far;\n\t\t\tthis.camera.updateProjectionMatrix();\n\t\t}\n\t}\n\n\t/**\n\t * Create a Three.js camera based on perspective type.\n\t */\n\tprivate createCameraForPerspective(aspectRatio: number): Camera {\n\t\tswitch (this._perspective) {\n\t\t\tcase Perspectives.ThirdPerson:\n\t\t\t\treturn new PerspectiveCamera(75, aspectRatio, 0.1, 1000);\n\t\t\tcase Perspectives.FirstPerson:\n\t\t\t\treturn new PerspectiveCamera(75, aspectRatio, 0.1, 1000);\n\t\t\tcase Perspectives.Isometric:\n\t\t\t\treturn new OrthographicCamera(\n\t\t\t\t\tthis.frustumSize * aspectRatio / -2,\n\t\t\t\t\tthis.frustumSize * aspectRatio / 2,\n\t\t\t\t\tthis.frustumSize / 2,\n\t\t\t\t\tthis.frustumSize / -2,\n\t\t\t\t\t1, 1000\n\t\t\t\t);\n\t\t\tcase Perspectives.Flat2D:\n\t\t\tcase Perspectives.Fixed2D:\n\t\t\t\treturn new OrthographicCamera(\n\t\t\t\t\tthis.frustumSize * aspectRatio / -2,\n\t\t\t\t\tthis.frustumSize * aspectRatio / 2,\n\t\t\t\t\tthis.frustumSize / 2,\n\t\t\t\t\tthis.frustumSize / -2,\n\t\t\t\t\t1, 1000\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\treturn new PerspectiveCamera(75, aspectRatio, 0.1, 1000);\n\t\t}\n\t}\n}\n","export const Perspectives = {\n\tFirstPerson: 'first-person',\n\tThirdPerson: 'third-person',\n\tIsometric: 'isometric',\n\tFlat2D: 'flat-2d',\n\tFixed2D: 'fixed-2d',\n\tTopDown: 'top-down',\n} as const;\n\nexport type PerspectiveType = (typeof Perspectives)[keyof typeof Perspectives];\n","import { Object3D, Vector3, Quaternion, Camera, Scene } from 'three';\nimport { OrbitControls } from 'three/addons/controls/OrbitControls.js';\n\nexport interface CameraDebugState {\n\tenabled: boolean;\n\tselected: string[];\n}\n\nexport interface CameraDebugDelegate {\n\tsubscribe(listener: (state: CameraDebugState) => void): () => void;\n\tresolveTarget(uuid: string): Object3D | null;\n}\n\n/**\n * Manages orbit controls for a camera.\n * Supports two modes:\n * 1. **Debug mode**: orbit controls activated by the debug system, with save/restore of camera state\n * 2. **User mode**: orbit controls enabled by the user via `useOrbitalControls` camera option\n *\n * These modes are independent -- debug mode takes precedence but user mode\n * keeps orbit controls active even outside debug.\n */\nexport class CameraOrbitController {\n\tprivate camera: Camera;\n\tprivate domElement: HTMLElement;\n\tprivate cameraRig: Object3D | null = null;\n\tprivate sceneRef: Scene | null = null;\n\t\n\tprivate orbitControls: OrbitControls | null = null;\n\tprivate orbitTarget: Object3D | null = null;\n\tprivate orbitTargetWorldPos: Vector3 = new Vector3();\n\n\tprivate debugDelegate: CameraDebugDelegate | null = null;\n\tprivate debugUnsubscribe: (() => void) | null = null;\n\tprivate debugStateSnapshot: CameraDebugState = { enabled: false, selected: [] };\n\n\t// Saved camera state for restoration when exiting debug mode\n\tprivate savedCameraPosition: Vector3 | null = null;\n\tprivate savedCameraQuaternion: Quaternion | null = null;\n\tprivate savedCameraZoom: number | null = null;\n\tprivate savedCameraLocalPosition: Vector3 | null = null;\n\n\t// Saved debug camera state for restoration when re-entering debug mode\n\tprivate savedDebugCameraPosition: Vector3 | null = null;\n\tprivate savedDebugCameraQuaternion: Quaternion | null = null;\n\tprivate savedDebugCameraZoom: number | null = null;\n\tprivate savedDebugOrbitTarget: Vector3 | null = null;\n\n\t/** Whether user-configured orbital controls are enabled (independent of debug) */\n\tprivate _userOrbitEnabled = false;\n\n\tconstructor(camera: Camera, domElement: HTMLElement, cameraRig?: Object3D | null) {\n\t\tthis.camera = camera;\n\t\tthis.domElement = domElement;\n\t\tthis.cameraRig = cameraRig ?? null;\n\t}\n\n\t/**\n\t * Set the scene reference for adding/removing camera when detaching from rig.\n\t */\n\tsetScene(scene: Scene | null): void {\n\t\tthis.sceneRef = scene;\n\t}\n\n\t/**\n\t * Check if debug mode is currently active (orbit controls enabled via debug system).\n\t */\n\tget isActive(): boolean {\n\t\treturn this.debugStateSnapshot.enabled;\n\t}\n\n\t/**\n\t * Check if any orbit controls are currently active (debug or user).\n\t */\n\tget isOrbitActive(): boolean {\n\t\treturn this.debugStateSnapshot.enabled || this._userOrbitEnabled;\n\t}\n\n\t/**\n\t * Update orbit controls each frame.\n\t * Should be called from the camera's update loop.\n\t */\n\tupdate() {\n\t\tif (this.orbitControls && this.orbitTarget) {\n\t\t\tthis.orbitTarget.getWorldPosition(this.orbitTargetWorldPos);\n\t\t\tthis.orbitControls.target.copy(this.orbitTargetWorldPos);\n\t\t}\n\t\tthis.orbitControls?.update();\n\t}\n\n\t/**\n\t * Enable user-configured orbital controls (not debug mode).\n\t * These orbit controls persist until explicitly disabled.\n\t */\n\tenableUserOrbitControls(): void {\n\t\tthis._userOrbitEnabled = true;\n\t\tif (!this.orbitControls) {\n\t\t\tthis.enableOrbitControls();\n\t\t}\n\t}\n\n\t/**\n\t * Disable user-configured orbital controls.\n\t * Will not disable orbit controls if debug mode is active.\n\t */\n\tdisableUserOrbitControls(): void {\n\t\tthis._userOrbitEnabled = false;\n\t\t// Only disable orbit controls if debug mode isn't also using them\n\t\tif (!this.debugStateSnapshot.enabled) {\n\t\t\tthis.disableOrbitControls();\n\t\t}\n\t}\n\n\t/**\n\t * Attach a delegate to react to debug state changes.\n\t */\n\tsetDebugDelegate(delegate: CameraDebugDelegate | null) {\n\t\tif (this.debugDelegate === delegate) {\n\t\t\treturn;\n\t\t}\n\t\tthis.detachDebugDelegate();\n\t\tthis.debugDelegate = delegate;\n\t\tif (!delegate) {\n\t\t\tthis.applyDebugState({ enabled: false, selected: [] });\n\t\t\treturn;\n\t\t}\n\t\tconst unsubscribe = delegate.subscribe((state) => {\n\t\t\tthis.applyDebugState(state);\n\t\t});\n\t\tthis.debugUnsubscribe = () => {\n\t\t\tunsubscribe?.();\n\t\t};\n\t}\n\n\t/**\n\t * Clean up resources.\n\t */\n\tdispose() {\n\t\tthis.disableOrbitControls();\n\t\tthis.detachDebugDelegate();\n\t}\n\n\t/**\n\t * Get the current debug state snapshot.\n\t */\n\tget debugState(): CameraDebugState {\n\t\treturn this.debugStateSnapshot;\n\t}\n\n\tprivate applyDebugState(state: CameraDebugState) {\n\t\tconst wasEnabled = this.debugStateSnapshot.enabled;\n\t\tthis.debugStateSnapshot = {\n\t\t\tenabled: state.enabled,\n\t\t\tselected: [...state.selected],\n\t\t};\n\t\tif (state.enabled && !wasEnabled) {\n\t\t\t// Entering debug mode: save game camera state, detach from rig, restore debug camera state if available\n\t\t\tthis.saveCameraState();\n\t\t\tthis.detachCameraFromRig();\n\t\t\tthis.enableOrbitControls();\n\t\t\tthis.restoreDebugCameraState();\n\t\t\tthis.updateOrbitTargetFromSelection(state.selected);\n\t\t} else if (!state.enabled && wasEnabled) {\n\t\t\t// Exiting debug mode: save debug camera state, then restore game camera state\n\t\t\tthis.saveDebugCameraState();\n\t\t\tthis.orbitTarget = null;\n\t\t\t// Only disable orbit controls if user mode isn't keeping them on\n\t\t\tif (!this._userOrbitEnabled) {\n\t\t\t\tthis.disableOrbitControls();\n\t\t\t}\n\t\t\tthis.reattachCameraToRig();\n\t\t\tthis.restoreCameraState();\n\t\t} else if (state.enabled) {\n\t\t\t// Still in debug mode, just update target\n\t\t\tthis.updateOrbitTargetFromSelection(state.selected);\n\t\t}\n\t}\n\n\tprivate enableOrbitControls() {\n\t\tif (this.orbitControls) {\n\t\t\treturn;\n\t\t}\n\t\tthis.orbitControls = new OrbitControls(this.camera, this.domElement);\n\t\tthis.orbitControls.enableDamping = true;\n\t\tthis.orbitControls.dampingFactor = 0.05;\n\t\tthis.orbitControls.screenSpacePanning = false;\n\t\tthis.orbitControls.minDistance = 1;\n\t\tthis.orbitControls.maxDistance = 500;\n\t\tthis.orbitControls.maxPolarAngle = Math.PI / 2;\n\t\t// Default target to origin\n\t\tthis.orbitControls.target.set(0, 0, 0);\n\t}\n\n\tprivate disableOrbitControls() {\n\t\tif (!this.orbitControls) {\n\t\t\treturn;\n\t\t}\n\t\tthis.orbitControls.dispose();\n\t\tthis.orbitControls = null;\n\t}\n\n\tprivate updateOrbitTargetFromSelection(selected: string[]) {\n\t\t// Default to origin when no entity is selected\n\t\tif (!this.debugDelegate || selected.length === 0) {\n\t\t\tthis.orbitTarget = null;\n\t\t\tif (this.orbitControls) {\n\t\t\t\tthis.orbitControls.target.set(0, 0, 0);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tfor (let i = selected.length - 1; i >= 0; i -= 1) {\n\t\t\tconst uuid = selected[i];\n\t\t\tconst targetObject = this.debugDelegate.resolveTarget(uuid);\n\t\t\tif (targetObject) {\n\t\t\t\tthis.orbitTarget = targetObject;\n\t\t\t\tif (this.orbitControls) {\n\t\t\t\t\ttargetObject.getWorldPosition(this.orbitTargetWorldPos);\n\t\t\t\t\tthis.orbitControls.target.copy(this.orbitTargetWorldPos);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\tthis.orbitTarget = null;\n\t}\n\n\tprivate detachDebugDelegate() {\n\t\tif (this.debugUnsubscribe) {\n\t\t\ttry {\n\t\t\t\tthis.debugUnsubscribe();\n\t\t\t} catch { /* noop */ }\n\t\t}\n\t\tthis.debugUnsubscribe = null;\n\t\tthis.debugDelegate = null;\n\t}\n\n\t/**\n\t * Save camera position, rotation, and zoom before entering debug mode.\n\t */\n\tprivate saveCameraState() {\n\t\tthis.savedCameraPosition = this.camera.position.clone();\n\t\tthis.savedCameraQuaternion = this.camera.quaternion.clone();\n\t\t// Save zoom for orthographic/perspective cameras\n\t\tif ('zoom' in this.camera) {\n\t\t\tthis.savedCameraZoom = (this.camera as any).zoom as number;\n\t\t}\n\t}\n\n\t/**\n\t * Restore camera position, rotation, and zoom when exiting debug mode.\n\t */\n\tprivate restoreCameraState() {\n\t\tif (this.savedCameraPosition) {\n\t\t\tthis.camera.position.copy(this.savedCameraPosition);\n\t\t\tthis.savedCameraPosition = null;\n\t\t}\n\t\tif (this.savedCameraQuaternion) {\n\t\t\tthis.camera.quaternion.copy(this.savedCameraQuaternion);\n\t\t\tthis.savedCameraQuaternion = null;\n\t\t}\n\t\tif (this.savedCameraZoom !== null && 'zoom' in this.camera) {\n\t\t\tthis.camera.zoom = this.savedCameraZoom;\n\t\t\t(this.camera as any).updateProjectionMatrix?.();\n\t\t\tthis.savedCameraZoom = null;\n\t\t}\n\t}\n\n\t/**\n\t * Save debug camera state when exiting debug mode.\n\t */\n\tprivate saveDebugCameraState() {\n\t\tthis.savedDebugCameraPosition = this.camera.position.clone();\n\t\tthis.savedDebugCameraQuaternion = this.camera.quaternion.clone();\n\t\tif ('zoom' in this.camera) {\n\t\t\tthis.savedDebugCameraZoom = (this.camera as any).zoom as number;\n\t\t}\n\t\tif (this.orbitControls) {\n\t\t\tthis.savedDebugOrbitTarget = this.orbitControls.target.clone();\n\t\t}\n\t}\n\n\t/**\n\t * Restore debug camera state when re-entering debug mode.\n\t */\n\tprivate restoreDebugCameraState() {\n\t\tif (this.savedDebugCameraPosition) {\n\t\t\tthis.camera.position.copy(this.savedDebugCameraPosition);\n\t\t}\n\t\tif (this.savedDebugCameraQuaternion) {\n\t\t\tthis.camera.quaternion.copy(this.savedDebugCameraQuaternion);\n\t\t}\n\t\tif (this.savedDebugCameraZoom !== null && 'zoom' in this.camera) {\n\t\t\tthis.camera.zoom = this.savedDebugCameraZoom;\n\t\t\t(this.camera as any).updateProjectionMatrix?.();\n\t\t}\n\t\tif (this.savedDebugOrbitTarget && this.orbitControls) {\n\t\t\tthis.orbitControls.target.copy(this.savedDebugOrbitTarget);\n\t\t}\n\t}\n\n\t/**\n\t * Detach camera from its rig to allow free orbit movement in debug mode.\n\t * Preserves the camera's world position.\n\t */\n\tprivate detachCameraFromRig(): void {\n\t\tif (!this.cameraRig || this.camera.parent !== this.cameraRig) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Save the camera's local position for later restoration\n\t\tthis.savedCameraLocalPosition = this.camera.position.clone();\n\n\t\t// Get camera's world position before detaching\n\t\tconst worldPos = new Vector3();\n\t\tthis.camera.getWorldPosition(worldPos);\n\n\t\t// Remove camera from rig\n\t\tthis.cameraRig.remove(this.camera);\n\n\t\t// Add camera directly to scene if scene ref is available\n\t\tif (this.sceneRef) {\n\t\t\tthis.sceneRef.add(this.camera);\n\t\t}\n\n\t\t// Set camera's position to its previous world position\n\t\tthis.camera.position.copy(worldPos);\n\t}\n\n\t/**\n\t * Reattach camera to its rig when exiting debug mode.\n\t * Restores the camera's local position relative to the rig.\n\t */\n\tprivate reattachCameraToRig(): void {\n\t\tif (!this.cameraRig || this.camera.parent === this.cameraRig) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remove camera from scene if it's there\n\t\tif (this.sceneRef && this.camera.parent === this.sceneRef) {\n\t\t\tthis.sceneRef.remove(this.camera);\n\t\t}\n\n\t\t// Add camera back to rig\n\t\tthis.cameraRig.add(this.camera);\n\n\t\t// Restore camera's local position\n\t\tif (this.savedCameraLocalPosition) {\n\t\t\tthis.camera.position.copy(this.savedCameraLocalPosition);\n\t\t\tthis.savedCameraLocalPosition = null;\n\t\t}\n\t}\n}\n","import { Vector2, WebGLRenderer, Scene, Camera, PerspectiveCamera } from 'three';\nimport { WebGPURenderer } from 'three/webgpu';\nimport { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';\nimport RenderPass from '../graphics/render-pass';\nimport type { ZylemCamera } from './zylem-camera';\n\n/**\n * Renderer type option for choosing rendering backend\n * - 'auto': Try WebGPU first, fall back to WebGL\n * - 'webgpu': Force WebGPU (error if not supported)\n * - 'webgl': Force WebGL\n */\nexport type RendererType = 'auto' | 'webgpu' | 'webgl';\n\n/**\n * Union type for renderer instances\n */\nexport type ZylemRenderer = WebGLRenderer | WebGPURenderer;\n\n/**\n * Viewport definition in normalized coordinates (0-1).\n * Represents a rectangular region of the canvas for camera rendering.\n */\nexport interface Viewport {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\n/** Default fullscreen viewport */\nexport const DEFAULT_VIEWPORT: Viewport = { x: 0, y: 0, width: 1, height: 1 };\n\n/**\n * Check if WebGPU is supported in the current browser\n */\nexport async function isWebGPUSupported(): Promise<boolean> {\n\tif (!('gpu' in navigator)) return false;\n\ttry {\n\t\tconst adapter = await (navigator as any).gpu.requestAdapter();\n\t\treturn adapter !== null;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * RendererManager owns the shared WebGL/WebGPU renderer, canvas element,\n * effect composer, and render loop. There is one RendererManager per game.\n *\n * It iterates active cameras and renders each with its configured viewport.\n */\nexport class RendererManager {\n\trenderer!: ZylemRenderer;\n\tcomposer!: EffectComposer;\n\tscreenResolution: Vector2;\n\trendererType: RendererType;\n\tprivate _isWebGPU = false;\n\tprivate _initialized = false;\n\tprivate _sceneRef: Scene | null = null;\n\tprivate _lastAnimationTimestamp: number | null = null;\n\n\tconstructor(screenResolution?: Vector2, rendererType: RendererType = 'webgl') {\n\t\tthis.screenResolution = screenResolution || new Vector2(window.innerWidth, window.innerHeight);\n\t\tthis.rendererType = rendererType;\n\t}\n\n\t/**\n\t * Check if the renderer has been initialized\n\t */\n\tget initialized(): boolean {\n\t\treturn this._initialized;\n\t}\n\n\t/**\n\t * Check if using WebGPU renderer\n\t */\n\tget isWebGPU(): boolean {\n\t\treturn this._isWebGPU;\n\t}\n\n\t/**\n\t * Initialize the renderer (must be called before rendering).\n\t * Async because WebGPU requires async initialization.\n\t */\n\tasync initRenderer(): Promise<void> {\n\t\tif (this._initialized) return;\n\n\t\tlet useWebGPU = false;\n\n\t\tif (this.rendererType === 'webgpu') {\n\t\t\tuseWebGPU = true;\n\t\t} else if (this.rendererType === 'auto') {\n\t\t\tuseWebGPU = await isWebGPUSupported();\n\t\t}\n\n\t\tif (useWebGPU) {\n\t\t\ttry {\n\t\t\t\tthis.renderer = new WebGPURenderer({ antialias: true });\n\t\t\t\tawait this.renderer.init();\n\t\t\t\tthis._isWebGPU = true;\n\t\t\t\tconsole.log('RendererManager: Using WebGPU renderer');\n\t\t\t} catch (e) {\n\t\t\t\tconsole.warn('RendererManager: WebGPU init failed, falling back to WebGL', e);\n\t\t\t\tthis.renderer = new WebGLRenderer({ antialias: false, alpha: true });\n\t\t\t\tthis._isWebGPU = false;\n\t\t\t}\n\t\t} else {\n\t\t\tthis.renderer = new WebGLRenderer({ antialias: false, alpha: true });\n\t\t\tthis._isWebGPU = false;\n\t\t\tconsole.log('RendererManager: Using WebGL renderer');\n\t\t}\n\n\t\tthis.renderer.setSize(this.screenResolution.x, this.screenResolution.y);\n\t\tif (this.renderer instanceof WebGLRenderer) {\n\t\t\tthis.renderer.shadowMap.enabled = true;\n\t\t}\n\n\t\t// Initialize composer (WebGPU uses different post-processing)\n\t\tif (!this._isWebGPU) {\n\t\t\tthis.composer = new EffectComposer(this.renderer as WebGLRenderer);\n\t\t}\n\n\t\tthis._initialized = true;\n\t}\n\n\t/**\n\t * Set the current scene reference for rendering.\n\t */\n\tsetScene(scene: Scene): void {\n\t\tthis._sceneRef = scene;\n\t}\n\n\t/**\n\t * Setup post-processing render pass for a camera (WebGL only).\n\t */\n\tsetupRenderPass(scene: Scene, camera: Camera): void {\n\t\tif (this._isWebGPU || !this.composer) return;\n\n\t\t// Dispose old passes before adding new ones (prevents GPU leak on stage transitions)\n\t\tif (this.composer.passes.length > 0) {\n\t\t\tthis.composer.passes.forEach((p: any) => { try { p.dispose?.(); } catch { /* noop */ } });\n\t\t\tthis.composer.passes.length = 0;\n\t\t}\n\n\t\tconst renderResolution = this.screenResolution.clone().divideScalar(2);\n\t\trenderResolution.x |= 0;\n\t\trenderResolution.y |= 0;\n\t\tconst pass = new RenderPass(renderResolution, scene, camera);\n\t\tthis.composer.addPass(pass);\n\t}\n\n\t/**\n\t * Start the render loop. Calls the provided callback each frame.\n\t */\n\tstartRenderLoop(onFrame: (delta: number) => void): void {\n\t\tthis._lastAnimationTimestamp = null;\n\t\tthis.renderer.setAnimationLoop((timestamp: number) => {\n\t\t\tconst deltaSeconds = this._lastAnimationTimestamp === null\n\t\t\t\t? 0\n\t\t\t\t: Math.max(0, (timestamp - this._lastAnimationTimestamp) / 1000);\n\t\t\tthis._lastAnimationTimestamp = timestamp;\n\t\t\tonFrame(deltaSeconds);\n\t\t});\n\t}\n\n\t/**\n\t * Stop the render loop.\n\t */\n\tstopRenderLoop(): void {\n\t\tthis._lastAnimationTimestamp = null;\n\t\ttry {\n\t\t\tthis.renderer.setAnimationLoop(null as any);\n\t\t} catch { /* noop */ }\n\t}\n\n\t/**\n\t * Render a scene from a single camera's perspective.\n\t * Sets the viewport based on the camera's viewport config.\n\t */\n\trenderCamera(scene: Scene, camera: ZylemCamera): void {\n\t\tconst vp = camera.viewport;\n\t\tconst w = this.screenResolution.x;\n\t\tconst h = this.screenResolution.y;\n\n\t\t// Set scissor and viewport for this camera\n\t\tconst pixelX = Math.floor(vp.x * w);\n\t\tconst pixelY = Math.floor(vp.y * h);\n\t\tconst pixelW = Math.floor(vp.width * w);\n\t\tconst pixelH = Math.floor(vp.height * h);\n\n\t\tif (this.renderer instanceof WebGLRenderer) {\n\t\t\tthis.renderer.setViewport(pixelX, pixelY, pixelW, pixelH);\n\t\t\tthis.renderer.setScissor(pixelX, pixelY, pixelW, pixelH);\n\t\t\tthis.renderer.setScissorTest(true);\n\t\t}\n\n\t\tif (this._isWebGPU) {\n\t\t\tthis.renderer.render(scene, camera.camera);\n\t\t} else if (this.composer) {\n\t\t\tthis.composer.render(0);\n\t\t}\n\t}\n\n\t/**\n\t * Render a camera to its offscreen render target (WebGL only).\n\t * Bypasses the EffectComposer since post-processing is not needed\n\t * for render-to-texture output.\n\t *\n\t * The camera must have a non-null renderTarget.\n\t */\n\trenderCameraToTarget(scene: Scene, camera: ZylemCamera): void {\n\t\tif (!camera.renderTarget) return;\n\n\t\tif (this.renderer instanceof WebGLRenderer) {\n\t\t\tconst prevTarget = this.renderer.getRenderTarget();\n\t\t\tthis.renderer.setRenderTarget(camera.renderTarget);\n\t\t\tthis.renderer.clear();\n\t\t\tthis.renderer.render(scene, camera.camera);\n\t\t\tthis.renderer.setRenderTarget(prevTarget);\n\t\t} else {\n\t\t\t// WebGPU RTT not yet supported\n\t\t\tconsole.warn('RendererManager: Render-to-texture is not yet supported for WebGPU');\n\t\t}\n\t}\n\n\t/**\n\t * Render a scene from multiple cameras, each with their own viewport.\n\t * Cameras are rendered in order (first = bottom layer, last = top layer).\n\t */\n\trenderCameras(scene: Scene, cameras: ZylemCamera[]): void {\n\t\tif (!scene || cameras.length === 0) return;\n\n\t\t// Clear the full canvas first\n\t\tif (this.renderer instanceof WebGLRenderer) {\n\t\t\tthis.renderer.setScissorTest(false);\n\t\t\tthis.renderer.clear();\n\t\t}\n\n\t\tfor (const cam of cameras) {\n\t\t\tthis.renderCamera(scene, cam);\n\t\t}\n\n\t\t// Restore scissor test state\n\t\tif (this.renderer instanceof WebGLRenderer) {\n\t\t\tthis.renderer.setScissorTest(false);\n\t\t}\n\t}\n\n\t/**\n\t * Simple single-camera render (backwards compatible).\n\t * Uses the full viewport for a single camera.\n\t */\n\trender(scene: Scene, camera: Camera): void {\n\t\tif (this._isWebGPU) {\n\t\t\tthis.renderer.render(scene, camera);\n\t\t} else if (this.composer) {\n\t\t\tthis.composer.render(0);\n\t\t}\n\t}\n\n\t/**\n\t * Resize the renderer and update resolution.\n\t */\n\tresize(width: number, height: number): void {\n\t\tthis.screenResolution.set(width, height);\n\t\tthis.renderer.setSize(width, height, false);\n\t\tif (this.composer) {\n\t\t\tthis.composer.setSize(width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Update renderer pixel ratio (DPR).\n\t */\n\tsetPixelRatio(dpr: number): void {\n\t\tconst safe = Math.max(1, Number.isFinite(dpr) ? dpr : 1);\n\t\tthis.renderer.setPixelRatio(safe);\n\t}\n\n\t/**\n\t * Get the DOM element for the renderer.\n\t */\n\tgetDomElement(): HTMLCanvasElement {\n\t\treturn this.renderer.domElement;\n\t}\n\n\t/**\n\t * Dispose renderer, composer, and related resources.\n\t */\n\tdispose(): void {\n\t\tthis.stopRenderLoop();\n\t\ttry {\n\t\t\tthis.composer?.passes?.forEach((p: any) => p.dispose?.());\n\t\t\t(this.composer as any)?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\tthis.renderer.dispose();\n\t\t} catch { /* noop */ }\n\t\tthis._sceneRef = null;\n\t\tthis._initialized = false;\n\t}\n}\n","import * as THREE from 'three';\nimport { standardShader } from './shaders/standard.shader';\nimport { WebGLRenderer, WebGLRenderTarget } from 'three';\nimport { Pass, FullScreenQuad } from 'three/addons/postprocessing/Pass.js';\n\nexport default class RenderPass extends Pass {\n\tfsQuad: FullScreenQuad;\n\tresolution: THREE.Vector2;\n\tscene: THREE.Scene;\n\tcamera: THREE.Camera;\n\trgbRenderTarget: WebGLRenderTarget;\n\tnormalRenderTarget: WebGLRenderTarget;\n\tnormalMaterial: THREE.Material;\n\n\tconstructor(resolution: THREE.Vector2, scene: THREE.Scene, camera: THREE.Camera) {\n\t\tsuper();\n\t\tthis.resolution = resolution;\n\t\tthis.fsQuad = new FullScreenQuad(this.material());\n\t\tthis.scene = scene;\n\t\tthis.camera = camera;\n\n\t\tthis.rgbRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);\n\t\tthis.normalRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);\n\n\t\tthis.normalMaterial = new THREE.MeshNormalMaterial();\n\t}\n\n\trender(\n\t\trenderer: WebGLRenderer,\n\t\twriteBuffer: WebGLRenderTarget\n\t) {\n\t\trenderer.setRenderTarget(this.rgbRenderTarget);\n\t\trenderer.render(this.scene, this.camera);\n\n\t\tconst overrideMaterial_old = this.scene.overrideMaterial;\n\t\trenderer.setRenderTarget(this.normalRenderTarget);\n\t\tthis.scene.overrideMaterial = this.normalMaterial;\n\t\trenderer.render(this.scene, this.camera);\n\t\tthis.scene.overrideMaterial = overrideMaterial_old;\n\n\t\t// @ts-ignore\n\t\tconst uniforms = this.fsQuad.material.uniforms;\n\t\tuniforms.tDiffuse.value = this.rgbRenderTarget.texture;\n\t\tuniforms.tDepth.value = this.rgbRenderTarget.depthTexture;\n\t\tuniforms.tNormal.value = this.normalRenderTarget.texture;\n\t\tuniforms.iTime.value += 0.01;\n\n\t\tif (this.renderToScreen) {\n\t\t\trenderer.setRenderTarget(null);\n\t\t} else {\n\t\t\trenderer.setRenderTarget(writeBuffer);\n\t\t}\n\t\tthis.fsQuad.render(renderer);\n\t}\n\n\tmaterial() {\n\t\treturn new THREE.ShaderMaterial({\n\t\t\tuniforms: {\n\t\t\t\tiTime: { value: 0 },\n\t\t\t\ttDiffuse: { value: null },\n\t\t\t\ttDepth: { value: null },\n\t\t\t\ttNormal: { value: null },\n\t\t\t\tresolution: {\n\t\t\t\t\tvalue: new THREE.Vector4(\n\t\t\t\t\t\tthis.resolution.x,\n\t\t\t\t\t\tthis.resolution.y,\n\t\t\t\t\t\t1 / this.resolution.x,\n\t\t\t\t\t\t1 / this.resolution.y,\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t},\n\t\t\tvertexShader: standardShader.vertex,\n\t\t\tfragmentShader: standardShader.fragment\n\t\t});\n\t}\n\n\tdispose() {\n\t\ttry {\n\t\t\tthis.fsQuad?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\t(this.rgbRenderTarget as any)?.dispose?.();\n\t\t\t(this.normalRenderTarget as any)?.dispose?.();\n\t\t} catch { /* noop */ }\n\t\ttry {\n\t\t\t(this.normalMaterial as any)?.dispose?.();\n\t\t} catch { /* noop */ }\n\t}\n}\n","export const objectVertexShader = `\nuniform vec2 uvScale;\nvarying vec2 vUv;\n\nvoid main() {\n\tvUv = uv;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n}\n`;\n","import { objectVertexShader } from './vertex/object.shader';\n\nconst fragment = `\nuniform sampler2D tDiffuse;\nvarying vec2 vUv;\n\nvoid main() {\n\tvec4 texel = texture2D( tDiffuse, vUv );\n\n\tgl_FragColor = texel;\n}\n`;\n\nexport const standardShader = {\n vertex: objectVertexShader,\n fragment\n};\n","import { Vector3, Quaternion, MathUtils } from 'three';\nimport type { CameraPose, PoseDelta } from './types';\n\n/**\n * Create a default camera pose at the origin facing forward.\n */\nexport function defaultPose(): CameraPose {\n\treturn {\n\t\tposition: new Vector3(0, 0, 10),\n\t\trotation: new Quaternion(),\n\t\tfov: 75,\n\t\tzoom: 1,\n\t\tnear: 0.1,\n\t\tfar: 1000,\n\t};\n}\n\n/**\n * Deep-clone a CameraPose so mutations don't leak between pipeline stages.\n */\nexport function clonePose(pose: CameraPose): CameraPose {\n\treturn {\n\t\tposition: pose.position.clone(),\n\t\trotation: pose.rotation.clone(),\n\t\tfov: pose.fov,\n\t\tzoom: pose.zoom,\n\t\tnear: pose.near,\n\t\tfar: pose.far,\n\t\tlookAt: pose.lookAt?.clone(),\n\t};\n}\n\n/**\n * Apply an additive PoseDelta on top of a CameraPose.\n * - Position: vector addition\n * - Rotation: quaternion multiplication (compose)\n * - FOV/Zoom: scalar addition\n *\n * Returns a new CameraPose (does not mutate the input).\n */\nexport function applyDelta(pose: CameraPose, delta: PoseDelta): CameraPose {\n\tconst result = clonePose(pose);\n\n\tif (delta.position) {\n\t\tresult.position.add(delta.position);\n\t}\n\tif (delta.rotation) {\n\t\tresult.rotation.multiply(delta.rotation);\n\t}\n\tif (delta.fov != null && result.fov != null) {\n\t\tresult.fov += delta.fov;\n\t}\n\tif (delta.zoom != null && result.zoom != null) {\n\t\tresult.zoom += delta.zoom;\n\t}\n\n\treturn result;\n}\n\n/**\n * Interpolate from `current` pose toward `target` pose using frame-rate-independent damping.\n *\n * @param current The current (smoothed) pose from the previous frame.\n * @param target The desired pose for this frame.\n * @param damping Smoothing factor in 0-1 range. 1 = instant snap, 0 = no movement.\n * @param dt Frame delta time in seconds.\n * @returns A new CameraPose interpolated between current and target.\n */\nexport function smoothPose(current: CameraPose, target: CameraPose, damping: number, dt: number): CameraPose {\n\tconst t = 1 - Math.pow(1 - MathUtils.clamp(damping, 0, 1), dt * 60);\n\n\tconst result = clonePose(current);\n\n\tresult.position.lerp(target.position, t);\n\tresult.rotation.slerp(target.rotation, t);\n\n\tif (target.fov != null && result.fov != null) {\n\t\tresult.fov = MathUtils.lerp(result.fov, target.fov, t);\n\t}\n\tif (target.zoom != null && result.zoom != null) {\n\t\tresult.zoom = MathUtils.lerp(result.zoom, target.zoom, t);\n\t}\n\tif (target.near != null) {\n\t\tresult.near = target.near;\n\t}\n\tif (target.far != null) {\n\t\tresult.far = target.far;\n\t}\n\n\t// Preserve lookAt from target (smoothing is on position/rotation, not lookAt)\n\tresult.lookAt = target.lookAt?.clone();\n\n\treturn result;\n}\n","import type {\n\tCameraPerspective,\n\tCameraBehavior,\n\tCameraAction,\n\tCameraContext,\n\tCameraPose,\n\tCameraPipelineState,\n} from './types';\nimport { defaultPose, clonePose, applyDelta, smoothPose } from './smoothing';\n\n/**\n * CameraPipeline runs a deterministic per-frame update:\n *\n * Perspective -> Behaviors (priority) -> Actions (deltas) -> Smoothing -> finalPose\n *\n * It separates \"desired pose\" from \"final pose\". Everything writes to desired;\n * only smoothing converts desired into the final committed pose.\n */\nexport class CameraPipeline {\n\t/** Active perspective (exactly one at a time). */\n\tperspective: CameraPerspective | null = null;\n\n\t/** Keyed behaviors, sorted by priority each frame. */\n\tprivate behaviors: Map<string, CameraBehavior> = new Map();\n\n\t/** Active transient actions. Expired actions are auto-removed. */\n\tprivate actions: CameraAction[] = [];\n\n\t/** The desired pose after perspective + behaviors + actions. */\n\tprivate _desiredPose: CameraPose = defaultPose();\n\n\t/** The smoothed final pose committed to the Three.js camera. */\n\tprivate _finalPose: CameraPose = defaultPose();\n\n\t/** Whether the pipeline has run at least once (prevents lerp from origin on first frame). */\n\tprivate _initialized = false;\n\n\t/** Smoothing factor: 0 = no movement, 1 = instant snap. */\n\tdamping = 0.15;\n\n\tconstructor(perspective?: CameraPerspective) {\n\t\tif (perspective) {\n\t\t\tthis.perspective = perspective;\n\t\t\tif (perspective.defaults?.damping != null) {\n\t\t\t\tthis.damping = perspective.defaults.damping;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Run the full pipeline for one frame.\n\t * Returns the final pose that should be committed to the Three.js camera.\n\t */\n\trun(ctx: CameraContext): CameraPose {\n\t\t// 1. Base pose from perspective\n\t\tlet pose: CameraPose = this.perspective\n\t\t\t? this.perspective.getBasePose(ctx)\n\t\t\t: defaultPose();\n\n\t\t// 2. Behaviors in priority order (low -> high)\n\t\tconst sorted = this.getSortedBehaviors();\n\t\tfor (const behavior of sorted) {\n\t\t\tif (behavior.enabled === false) continue;\n\t\t\tpose = behavior.update(ctx, pose);\n\t\t}\n\n\t\t// Store desired pose (before actions and smoothing)\n\t\tthis._desiredPose = clonePose(pose);\n\n\t\t// 3. Actions apply additive deltas; expired ones are removed\n\t\tfor (let i = this.actions.length - 1; i >= 0; i--) {\n\t\t\tconst action = this.actions[i];\n\t\t\tconst delta = action.update(ctx);\n\t\t\tpose = applyDelta(pose, delta);\n\t\t\tif (action.isDone(ctx)) {\n\t\t\t\tthis.actions.splice(i, 1);\n\t\t\t}\n\t\t}\n\n\t\t// 4. Smoothing: interpolate from previous final pose toward computed pose\n\t\tif (!this._initialized) {\n\t\t\tthis._finalPose = clonePose(pose);\n\t\t\tthis._initialized = true;\n\t\t} else {\n\t\t\tthis._finalPose = smoothPose(this._finalPose, pose, this.damping, ctx.dt);\n\t\t}\n\n\t\treturn this._finalPose;\n\t}\n\n\t// ─── Behavior management ───────────────────────────────────────────────\n\n\t/**\n\t * Add or replace a behavior by key (idempotent).\n\t * Calls onDetach on the old behavior and onAttach on the new one.\n\t */\n\taddBehavior(key: string, behavior: CameraBehavior, ctx?: CameraContext): void {\n\t\tconst existing = this.behaviors.get(key);\n\t\tif (existing?.onDetach && ctx) {\n\t\t\texisting.onDetach(ctx);\n\t\t}\n\t\tthis.behaviors.set(key, behavior);\n\t\tif (behavior.onAttach && ctx) {\n\t\t\tbehavior.onAttach(ctx);\n\t\t}\n\t}\n\n\t/**\n\t * Remove a behavior by key. Calls onDetach if a context is provided.\n\t */\n\tremoveBehavior(key: string, ctx?: CameraContext): boolean {\n\t\tconst existing = this.behaviors.get(key);\n\t\tif (!existing) return false;\n\t\tif (existing.onDetach && ctx) {\n\t\t\texisting.onDetach(ctx);\n\t\t}\n\t\treturn this.behaviors.delete(key);\n\t}\n\n\t/**\n\t * Check whether a behavior with the given key exists.\n\t */\n\thasBehavior(key: string): boolean {\n\t\treturn this.behaviors.has(key);\n\t}\n\n\t// ─── Action management ─────────────────────────────────────────────────\n\n\t/**\n\t * Add a transient action. Actions self-expire via isDone().\n\t */\n\taddAction(action: CameraAction): void {\n\t\tthis.actions.push(action);\n\t}\n\n\t// ─── State inspection ──────────────────────────────────────────────────\n\n\t/**\n\t * Return a debug snapshot of the pipeline state.\n\t */\n\tgetState(): CameraPipelineState {\n\t\treturn {\n\t\t\tperspectiveId: this.perspective?.id ?? null,\n\t\t\tdesiredPose: this._desiredPose ? clonePose(this._desiredPose) : null,\n\t\t\tfinalPose: this._finalPose ? clonePose(this._finalPose) : null,\n\t\t\tactiveBehaviors: Array.from(this.behaviors.keys()),\n\t\t\tactiveActionCount: this.actions.length,\n\t\t};\n\t}\n\n\t/**\n\t * Set a new perspective. Resets the pipeline initialization flag so the\n\t * first frame with the new perspective snaps instead of lerping from the old pose.\n\t */\n\tsetPerspective(perspective: CameraPerspective): void {\n\t\tthis.perspective = perspective;\n\t\tthis._initialized = false;\n\t\tif (perspective.defaults?.damping != null) {\n\t\t\tthis.damping = perspective.defaults.damping;\n\t\t}\n\t}\n\n\t// ─── Internal helpers ──────────────────────────────────────────────────\n\n\tprivate getSortedBehaviors(): CameraBehavior[] {\n\t\treturn Array.from(this.behaviors.values()).sort(\n\t\t\t(a, b) => (a.priority ?? 0) - (b.priority ?? 0)\n\t\t);\n\t}\n}\n","import { Vector3, Quaternion } from 'three';\nimport type { CameraPerspective, CameraContext, CameraPose } from '../types';\n\n/**\n * Configuration for the third-person perspective.\n */\nexport interface ThirdPersonOptions {\n\t/** Distance behind the target. Default 8. */\n\tdistance?: number;\n\t/** Height above the target. Default 5. */\n\theight?: number;\n\t/** Lateral offset from the target (shoulder cam). Default 0. */\n\tshoulderOffset?: number;\n\t/** Key in CameraContext.targets to follow. Default 'primary'. */\n\ttargetKey?: string;\n\t/** Perspective field of view. Default 75. */\n\tfov?: number;\n\t/** Padding multiplier when framing multiple targets. Default 1.5. */\n\tpaddingFactor?: number;\n\t/** Minimum camera distance when multi-framing. Default 5. */\n\tminDistance?: number;\n\t/** Fallback camera position when no targets exist (e.g. the user-specified initial position). */\n\tinitialPosition?: Vector3;\n\t/** Fallback lookAt point when no targets exist. */\n\tinitialLookAt?: Vector3;\n}\n\ninterface ThirdPersonBaseDefaults {\n\tdistance: number;\n\theight: number;\n\tshoulderOffset: number;\n\ttargetKey: string;\n\tfov: number;\n\tpaddingFactor: number;\n\tminDistance: number;\n}\n\nconst DEFAULTS: ThirdPersonBaseDefaults = {\n\tdistance: 8,\n\theight: 5,\n\tshoulderOffset: 0,\n\ttargetKey: 'primary',\n\tfov: 75,\n\tpaddingFactor: 1.5,\n\tminDistance: 5,\n};\n\n/**\n * Third-person 3D perspective.\n *\n * - 0 targets: returns a static pose behind the origin.\n * - 1 target: camera positioned behind and above the target, looking at it.\n * - 2+ targets: weighted-centroid framing with dynamic distance.\n */\nexport class ThirdPersonPerspective implements CameraPerspective {\n\treadonly id = 'third-person';\n\treadonly defaults = { damping: 0.15 };\n\n\tprivate opts: ThirdPersonBaseDefaults;\n\tprivate initialPosition?: Vector3;\n\tprivate initialLookAt?: Vector3;\n\n\tconstructor(options?: ThirdPersonOptions) {\n\t\tconst { initialPosition, initialLookAt, ...rest } = options ?? {};\n\t\tthis.opts = { ...DEFAULTS, ...rest };\n\t\tthis.initialPosition = initialPosition;\n\t\tthis.initialLookAt = initialLookAt;\n\t}\n\n\tgetBasePose(ctx: CameraContext): CameraPose {\n\t\tconst targetKeys = Object.keys(ctx.targets);\n\t\tconst primary = ctx.targets[this.opts.targetKey];\n\n\t\tif (targetKeys.length === 0 || !primary) {\n\t\t\treturn this.staticPose();\n\t\t}\n\n\t\tif (targetKeys.length === 1) {\n\t\t\treturn this.singleTargetPose(primary.position);\n\t\t}\n\n\t\treturn this.multiTargetPose(ctx);\n\t}\n\n\t/**\n\t * No targets: use the user-specified initial position if available,\n\t * otherwise fall back to a default pose behind the origin.\n\t */\n\tprivate staticPose(): CameraPose {\n\t\tif (this.initialPosition) {\n\t\t\treturn {\n\t\t\t\tposition: this.initialPosition.clone(),\n\t\t\t\trotation: new Quaternion(),\n\t\t\t\tfov: this.opts.fov,\n\t\t\t\tzoom: 1,\n\t\t\t\tnear: 0.1,\n\t\t\t\tfar: 1000,\n\t\t\t\tlookAt: this.initialLookAt?.clone() ?? new Vector3(0, 0, 0),\n\t\t\t};\n\t\t}\n\n\t\tconst position = new Vector3(\n\t\t\tthis.opts.shoulderOffset,\n\t\t\tthis.opts.height,\n\t\t\tthis.opts.distance\n\t\t);\n\t\treturn {\n\t\t\tposition,\n\t\t\trotation: new Quaternion(),\n\t\t\tfov: this.opts.fov,\n\t\t\tzoom: 1,\n\t\t\tnear: 0.1,\n\t\t\tfar: 1000,\n\t\t\tlookAt: new Vector3(0, 0, 0),\n\t\t};\n\t}\n\n\t/**\n\t * Single target: position = target + offset, lookAt = target.\n\t */\n\tprivate singleTargetPose(targetPos: Vector3): CameraPose {\n\t\tconst position = new Vector3(\n\t\t\ttargetPos.x + this.opts.shoulderOffset,\n\t\t\ttargetPos.y + this.opts.height,\n\t\t\ttargetPos.z + this.opts.distance\n\t\t);\n\t\treturn {\n\t\t\tposition,\n\t\t\trotation: new Quaternion(),\n\t\t\tfov: this.opts.fov,\n\t\t\tzoom: 1,\n\t\t\tnear: 0.1,\n\t\t\tfar: 1000,\n\t\t\tlookAt: targetPos.clone(),\n\t\t};\n\t}\n\n\t/**\n\t * Multi-target: compute centroid and adjust distance to frame all targets.\n\t */\n\tprivate multiTargetPose(ctx: CameraContext): CameraPose {\n\t\tconst targets = Object.values(ctx.targets);\n\n\t\t// Centroid\n\t\tconst centroid = new Vector3();\n\t\tfor (const t of targets) {\n\t\t\tcentroid.add(t.position);\n\t\t}\n\t\tcentroid.divideScalar(targets.length);\n\n\t\t// Max distance from centroid to any target\n\t\tlet maxDist = 0;\n\t\tfor (const t of targets) {\n\t\t\tconst d = centroid.distanceTo(t.position);\n\t\t\tif (d > maxDist) maxDist = d;\n\t\t}\n\n\t\tconst dynamicDistance = Math.max(\n\t\t\tmaxDist * this.opts.paddingFactor,\n\t\t\tthis.opts.minDistance\n\t\t);\n\n\t\t// Offset direction from the base offset\n\t\tconst baseOffset = new Vector3(\n\t\t\tthis.opts.shoulderOffset,\n\t\t\tthis.opts.height,\n\t\t\tthis.opts.distance\n\t\t);\n\t\tconst baseLen = baseOffset.length();\n\t\tconst dir = baseLen > 0 ? baseOffset.clone().normalize() : new Vector3(0, 0.5, 1).normalize();\n\n\t\tconst position = centroid.clone().add(dir.multiplyScalar(dynamicDistance));\n\n\t\t// Preserve vertical ratio\n\t\tif (baseLen > 0) {\n\t\t\tconst heightRatio = this.opts.height / baseLen;\n\t\t\tposition.y = centroid.y + dynamicDistance * heightRatio;\n\t\t}\n\n\t\treturn {\n\t\t\tposition,\n\t\t\trotation: new Quaternion(),\n\t\t\tfov: this.opts.fov,\n\t\t\tzoom: 1,\n\t\t\tnear: 0.1,\n\t\t\tfar: 1000,\n\t\t\tlookAt: centroid.clone(),\n\t\t};\n\t}\n}\n","import { Vector3, Quaternion } from 'three';\nimport type { CameraPerspective, CameraContext, CameraPose } from '../types';\n\n/**\n * Configuration for the fixed 2D perspective.\n */\nexport interface Fixed2DOptions {\n\t/** Fixed camera position. Default (0, 0, 10). */\n\tposition?: { x: number; y: number; z: number };\n\t/** Orthographic zoom (frustum size). Default 10. */\n\tzoom?: number;\n}\n\nconst DEFAULTS: Required<Fixed2DOptions> = {\n\tposition: { x: 0, y: 0, z: 10 },\n\tzoom: 10,\n};\n\n/**\n * Fixed 2D perspective.\n *\n * Returns a static orthographic pose looking down the Z-axis.\n * No target following -- the camera stays at the configured position.\n */\nexport class Fixed2DPerspective implements CameraPerspective {\n\treadonly id = 'fixed-2d';\n\treadonly defaults = { damping: 1 };\n\n\tprivate opts: Required<Fixed2DOptions>;\n\n\tconstructor(options?: Fixed2DOptions) {\n\t\tthis.opts = { ...DEFAULTS, ...options };\n\t}\n\n\tgetBasePose(_ctx: CameraContext): CameraPose {\n\t\treturn {\n\t\t\tposition: new Vector3(\n\t\t\t\tthis.opts.position.x,\n\t\t\t\tthis.opts.position.y,\n\t\t\t\tthis.opts.position.z\n\t\t\t),\n\t\t\trotation: new Quaternion(),\n\t\t\tzoom: this.opts.zoom,\n\t\t\tnear: 1,\n\t\t\tfar: 1000,\n\t\t\tlookAt: new Vector3(this.opts.position.x, this.opts.position.y, 0),\n\t\t};\n\t}\n}\n","import { Vector3, Quaternion, Euler, MathUtils } from 'three';\nimport type { CameraPerspective, CameraContext, CameraPose } from '../types';\n\n/**\n * Configuration for the first-person perspective.\n */\nexport interface FirstPersonOptions {\n\t/** Vertical offset above the target entity's position (eye height). @default 1.7 */\n\teyeHeight?: number;\n\t/** Default field of view in degrees. @default 75 */\n\tdefaultFov?: number;\n\t/** Maximum pitch angle in radians. @default Math.PI/2 - 0.01 */\n\tpitchLimit?: number;\n\t/** Lerp speed for smooth look-at transitions. @default 5 */\n\tlookAtLerpSpeed?: number;\n\t/** Lerp speed for FOV zoom transitions. @default 8 */\n\tfovLerpSpeed?: number;\n\t/** Key in CameraContext.targets to follow. @default 'primary' */\n\ttargetKey?: string;\n\t/** Fallback position when no target entity is attached. */\n\tinitialPosition?: Vector3;\n\t/** Fallback look-at point used to derive initial yaw/pitch when no target. */\n\tinitialLookAt?: Vector3;\n}\n\ninterface Defaults {\n\teyeHeight: number;\n\tdefaultFov: number;\n\tpitchLimit: number;\n\tlookAtLerpSpeed: number;\n\tfovLerpSpeed: number;\n\ttargetKey: string;\n}\n\nconst DEFAULTS: Defaults = {\n\teyeHeight: 1.7,\n\tdefaultFov: 75,\n\tpitchLimit: Math.PI / 2 - 0.01,\n\tlookAtLerpSpeed: 5,\n\tfovLerpSpeed: 8,\n\ttargetKey: 'primary',\n};\n\n/**\n * First-person camera perspective.\n *\n * Position is derived from the attached target entity (+ eye height).\n * Rotation is driven via `look()` / `setLook()` methods called by game code\n * or a future FPS behavior. Supports smooth FOV zoom and lerp'd look-at.\n */\nexport class FirstPersonPerspective implements CameraPerspective {\n\treadonly id = 'first-person';\n\treadonly defaults = { damping: 1 };\n\n\tprivate opts: Defaults;\n\t/** Fallback position when no target entity is attached. Mutate directly for manual movement. */\n\tinitialPosition?: Vector3;\n\tprivate initialLookAt?: Vector3;\n\n\t// --- Look state ---\n\tprivate _yaw = 0;\n\tprivate _pitch = 0;\n\n\t// --- FOV zoom state ---\n\tprivate _currentFov: number;\n\tprivate _targetFov: number;\n\n\t// --- Look-at target state ---\n\tprivate _lookAtTarget: Vector3 | null = null;\n\tprivate _lookAtLerpSpeed: number;\n\tprivate _currentRotation = new Quaternion();\n\tprivate _rotationInitialized = false;\n\n\tconstructor(options?: FirstPersonOptions) {\n\t\tconst { initialPosition, initialLookAt, ...rest } = options ?? {};\n\t\tthis.opts = { ...DEFAULTS, ...rest };\n\t\tthis.initialPosition = initialPosition;\n\t\tthis.initialLookAt = initialLookAt;\n\n\t\tthis._currentFov = this.opts.defaultFov;\n\t\tthis._targetFov = this.opts.defaultFov;\n\t\tthis._lookAtLerpSpeed = this.opts.lookAtLerpSpeed;\n\n\t\tif (initialPosition && initialLookAt) {\n\t\t\tthis.deriveYawPitchFromLookAt(initialPosition, initialLookAt);\n\t\t}\n\t}\n\n\t// --- Public API (called by game code / FPS behavior) ---\n\n\t/** Accumulate yaw and pitch deltas. Pitch is clamped to the configured limit. */\n\tlook(deltaYaw: number, deltaPitch: number): void {\n\t\tthis._yaw += deltaYaw;\n\t\tthis._pitch = MathUtils.clamp(\n\t\t\tthis._pitch + deltaPitch,\n\t\t\t-this.opts.pitchLimit,\n\t\t\tthis.opts.pitchLimit,\n\t\t);\n\t}\n\n\t/** Set absolute yaw and pitch. Pitch is clamped to the configured limit. */\n\tsetLook(yaw: number, pitch: number): void {\n\t\tthis._yaw = yaw;\n\t\tthis._pitch = MathUtils.clamp(pitch, -this.opts.pitchLimit, this.opts.pitchLimit);\n\t}\n\n\t/** Current yaw in radians. */\n\tget yaw(): number { return this._yaw; }\n\n\t/** Current pitch in radians. */\n\tget pitch(): number { return this._pitch; }\n\n\t/** Set the target FOV for a smooth zoom transition (e.g. sniper scope). */\n\tzoom(fov: number): void {\n\t\tthis._targetFov = fov;\n\t}\n\n\t/** Return to the default FOV. */\n\tresetZoom(): void {\n\t\tthis._targetFov = this.opts.defaultFov;\n\t}\n\n\t/** Current field of view. */\n\tget currentFov(): number { return this._currentFov; }\n\n\t/**\n\t * Enable smooth look-at toward a world position.\n\t * The camera will slerp from the current rotation toward the look-at direction.\n\t */\n\tlookAt(target: Vector3, lerpSpeed?: number): void {\n\t\tthis._lookAtTarget = target;\n\t\tif (lerpSpeed != null) {\n\t\t\tthis._lookAtLerpSpeed = lerpSpeed;\n\t\t}\n\t}\n\n\t/** Disable look-at and return to manual yaw/pitch control. */\n\tclearLookAt(): void {\n\t\tif (this._lookAtTarget) {\n\t\t\tthis.deriveYawPitchFromQuaternion(this._currentRotation);\n\t\t}\n\t\tthis._lookAtTarget = null;\n\t}\n\n\t// --- CameraPerspective interface ---\n\n\tgetBasePose(ctx: CameraContext): CameraPose {\n\t\tconst position = this.computePosition(ctx);\n\t\tconst rotation = this.computeRotation(position, ctx.dt);\n\t\tthis._currentFov = this.lerpFov(ctx.dt);\n\n\t\treturn {\n\t\t\tposition,\n\t\t\trotation,\n\t\t\tfov: this._currentFov,\n\t\t\tnear: 0.1,\n\t\t\tfar: 1000,\n\t\t};\n\t}\n\n\t// --- Private helpers ---\n\n\tprivate computePosition(ctx: CameraContext): Vector3 {\n\t\tconst target = ctx.targets[this.opts.targetKey];\n\t\tif (target) {\n\t\t\treturn new Vector3(\n\t\t\t\ttarget.position.x,\n\t\t\t\ttarget.position.y + this.opts.eyeHeight,\n\t\t\t\ttarget.position.z,\n\t\t\t);\n\t\t}\n\t\tif (this.initialPosition) {\n\t\t\treturn this.initialPosition.clone();\n\t\t}\n\t\treturn new Vector3(0, this.opts.eyeHeight, 0);\n\t}\n\n\tprivate computeRotation(eyePosition: Vector3, dt: number): Quaternion {\n\t\tconst yawPitchQuat = new Quaternion().setFromEuler(\n\t\t\tnew Euler(this._pitch, this._yaw, 0, 'YXZ'),\n\t\t);\n\n\t\tif (!this._rotationInitialized) {\n\t\t\tthis._currentRotation.copy(yawPitchQuat);\n\t\t\tthis._rotationInitialized = true;\n\t\t}\n\n\t\tif (this._lookAtTarget) {\n\t\t\tconst dir = _vec3.copy(this._lookAtTarget).sub(eyePosition);\n\t\t\tif (dir.lengthSq() > 0.0001) {\n\t\t\t\tdir.normalize();\n\t\t\t\tconst desiredYaw = Math.atan2(-dir.x, -dir.z);\n\t\t\t\tconst desiredPitch = Math.asin(MathUtils.clamp(dir.y, -1, 1));\n\t\t\t\tconst desiredQuat = _quat.setFromEuler(\n\t\t\t\t\t_euler.set(desiredPitch, desiredYaw, 0, 'YXZ'),\n\t\t\t\t);\n\n\t\t\t\tconst t = 1 - Math.pow(1 - Math.min(this._lookAtLerpSpeed * dt, 1), 1);\n\t\t\t\tthis._currentRotation.slerp(desiredQuat, MathUtils.clamp(t, 0, 1));\n\t\t\t\treturn this._currentRotation.clone();\n\t\t\t}\n\t\t}\n\n\t\tthis._currentRotation.copy(yawPitchQuat);\n\t\treturn yawPitchQuat;\n\t}\n\n\tprivate lerpFov(dt: number): number {\n\t\tif (Math.abs(this._currentFov - this._targetFov) < 0.01) {\n\t\t\treturn this._targetFov;\n\t\t}\n\t\tconst t = 1 - Math.pow(1 - Math.min(this.opts.fovLerpSpeed * dt, 1), 1);\n\t\treturn MathUtils.lerp(this._currentFov, this._targetFov, MathUtils.clamp(t, 0, 1));\n\t}\n\n\tprivate deriveYawPitchFromLookAt(from: Vector3, to: Vector3): void {\n\t\tconst dir = _vec3.copy(to).sub(from).normalize();\n\t\tthis._yaw = Math.atan2(-dir.x, -dir.z);\n\t\tthis._pitch = Math.asin(MathUtils.clamp(dir.y, -1, 1));\n\t}\n\n\tprivate deriveYawPitchFromQuaternion(q: Quaternion): void {\n\t\tconst euler = _euler.setFromQuaternion(q, 'YXZ');\n\t\tthis._yaw = euler.y;\n\t\tthis._pitch = MathUtils.clamp(euler.x, -this.opts.pitchLimit, this.opts.pitchLimit);\n\t}\n}\n\n// Reusable temporaries (avoid per-frame allocations)\nconst _vec3 = new Vector3();\nconst _quat = new Quaternion();\nconst _euler = new Euler();\n","import type { PerspectiveType } from '../perspective';\nimport type { CameraPerspective } from '../types';\nimport { ThirdPersonPerspective } from './third-person-perspective';\nimport type { ThirdPersonOptions } from './third-person-perspective';\nimport { Fixed2DPerspective } from './fixed-2d-perspective';\nimport type { Fixed2DOptions } from './fixed-2d-perspective';\nimport { FirstPersonPerspective } from './first-person-perspective';\nimport type { FirstPersonOptions } from './first-person-perspective';\n\nexport { ThirdPersonPerspective } from './third-person-perspective';\nexport type { ThirdPersonOptions } from './third-person-perspective';\nexport { Fixed2DPerspective } from './fixed-2d-perspective';\nexport type { Fixed2DOptions } from './fixed-2d-perspective';\nexport { FirstPersonPerspective } from './first-person-perspective';\nexport type { FirstPersonOptions } from './first-person-perspective';\n\n/**\n * Perspective-specific options union.\n * Extend as new perspective types are added.\n */\nexport type PerspectiveOptions = ThirdPersonOptions | Fixed2DOptions | FirstPersonOptions;\n\n/**\n * Factory: create a CameraPerspective from a PerspectiveType string.\n * Unrecognized types default to ThirdPersonPerspective.\n */\nexport function createPerspective(\n\ttype: PerspectiveType,\n\toptions?: PerspectiveOptions\n): CameraPerspective {\n\tswitch (type) {\n\t\tcase 'third-person':\n\t\t\treturn new ThirdPersonPerspective(options as ThirdPersonOptions);\n\t\tcase 'first-person':\n\t\t\treturn new FirstPersonPerspective(options as FirstPersonOptions);\n\t\tcase 'isometric':\n\t\t\t// Isometric placeholder -- fixed angle third-person\n\t\t\treturn new ThirdPersonPerspective({\n\t\t\t\tdistance: 10,\n\t\t\t\theight: 10,\n\t\t\t\t...(options as ThirdPersonOptions),\n\t\t\t});\n\t\tcase 'flat-2d':\n\t\t\treturn new Fixed2DPerspective(options as Fixed2DOptions);\n\t\tcase 'fixed-2d':\n\t\t\treturn new Fixed2DPerspective(options as Fixed2DOptions);\n\t\tdefault:\n\t\t\treturn new ThirdPersonPerspective(options as ThirdPersonOptions);\n\t}\n}\n","import { Vector2, Scene } from 'three';\nimport { ZylemCamera } from './zylem-camera';\nimport { RendererManager } from './renderer-manager';\nimport { Perspectives } from './perspective';\nimport { nanoid } from 'nanoid';\n\n/**\n * CameraManager orchestrates multiple cameras per stage.\n *\n * Responsibilities:\n * - Named camera registry (add/remove/get by name or reference)\n * - Active camera list management (determines which cameras render)\n * - Always-available debug camera with orbit controls\n * - Per-frame update of all active cameras' perspective controllers\n * - Coordinating rendering via RendererManager for all active viewports\n */\nexport class CameraManager {\n\t/** Named camera registry */\n\tprivate cameras: Map<string, ZylemCamera> = new Map();\n\n\t/** Currently active cameras, ordered by render layer (first = bottom) */\n\tprivate _activeCameras: ZylemCamera[] = [];\n\n\t/** Auto-created debug camera with orbit controls */\n\tprivate _debugCamera: ZylemCamera | null = null;\n\n\t/** Reference to the shared renderer manager */\n\tprivate _rendererManager: RendererManager | null = null;\n\n\t/** Scene reference */\n\tprivate _sceneRef: Scene | null = null;\n\n\t/** Counter for auto-generated camera names */\n\tprivate _autoNameCounter = 0;\n\n\tconstructor() {\n\t\t// Debug camera is created lazily during setup when we have screen resolution\n\t}\n\n\t/**\n\t * Get the list of currently active cameras.\n\t */\n\tget activeCameras(): ReadonlyArray<ZylemCamera> {\n\t\treturn this._activeCameras;\n\t}\n\n\t/**\n\t * Get the primary active camera (first in the active list).\n\t */\n\tget primaryCamera(): ZylemCamera | null {\n\t\treturn this._activeCameras.length > 0 ? this._activeCameras[0] : null;\n\t}\n\n\t/**\n\t * Get the debug camera.\n\t */\n\tget debugCamera(): ZylemCamera | null {\n\t\treturn this._debugCamera;\n\t}\n\n\t/**\n\t * Get all registered cameras.\n\t */\n\tget allCameras(): ReadonlyArray<ZylemCamera> {\n\t\treturn Array.from(this.cameras.values());\n\t}\n\n\t/**\n\t * Add a camera to the manager.\n\t * If no name is provided, one is auto-generated.\n\t * The first camera added becomes the active camera.\n\t *\n\t * @param camera The ZylemCamera instance to add\n\t * @param name Optional name for lookup\n\t * @returns The assigned name\n\t */\n\taddCamera(camera: ZylemCamera, name?: string): string {\n\t\tconst resolvedName = name || camera.name || `camera_${this._autoNameCounter++}`;\n\t\tcamera.name = resolvedName;\n\t\tthis.cameras.set(resolvedName, camera);\n\n\t\t// First camera added automatically becomes active\n\t\tif (this._activeCameras.length === 0) {\n\t\t\tthis._activeCameras.push(camera);\n\t\t}\n\n\t\treturn resolvedName;\n\t}\n\n\t/**\n\t * Remove a camera by name or reference.\n\t * Cannot remove the debug camera via this method.\n\t */\n\tremoveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\tlet name: string | undefined;\n\n\t\tif (typeof nameOrRef === 'string') {\n\t\t\tname = nameOrRef;\n\t\t} else {\n\t\t\t// Find by reference\n\t\t\tfor (const [key, cam] of this.cameras.entries()) {\n\t\t\t\tif (cam === nameOrRef) {\n\t\t\t\t\tname = key;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!name) return false;\n\n\t\tconst camera = this.cameras.get(name);\n\t\tif (!camera) return false;\n\n\t\t// Prevent removing the debug camera\n\t\tif (camera === this._debugCamera) {\n\t\t\tconsole.warn('CameraManager: Cannot remove the debug camera');\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.cameras.delete(name);\n\n\t\t// Remove from active cameras\n\t\tconst activeIndex = this._activeCameras.indexOf(camera);\n\t\tif (activeIndex !== -1) {\n\t\t\tthis._activeCameras.splice(activeIndex, 1);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Set a camera as the primary active camera (replaces all active cameras\n\t * except additional viewport cameras).\n\t *\n\t * @param nameOrRef Camera name or reference to activate\n\t */\n\tsetActiveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\tconst camera = this.resolveCamera(nameOrRef);\n\t\tif (!camera) {\n\t\t\tconsole.warn(`CameraManager: Camera not found: ${nameOrRef}`);\n\t\t\treturn false;\n\t\t}\n\n\t\t// Set as the sole active camera (keeping PiP cameras if any)\n\t\tconst pipCameras = this._activeCameras.filter(c => {\n\t\t\treturn c !== this._activeCameras[0] && c.viewport.width < 1;\n\t\t});\n\n\t\tthis._activeCameras = [camera, ...pipCameras];\n\t\treturn true;\n\t}\n\n\t/**\n\t * Add a camera as an additional active camera (for split-screen or PiP).\n\t */\n\taddActiveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\tconst camera = this.resolveCamera(nameOrRef);\n\t\tif (!camera) return false;\n\n\t\tif (!this._activeCameras.includes(camera)) {\n\t\t\tthis._activeCameras.push(camera);\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Remove a camera from the active render list (does not remove from registry).\n\t */\n\tdeactivateCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\tconst camera = this.resolveCamera(nameOrRef);\n\t\tif (!camera) return false;\n\n\t\tconst index = this._activeCameras.indexOf(camera);\n\t\tif (index !== -1) {\n\t\t\tthis._activeCameras.splice(index, 1);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get a camera by name.\n\t */\n\tgetCamera(name: string): ZylemCamera | null {\n\t\treturn this.cameras.get(name) ?? null;\n\t}\n\n\t/**\n\t * Setup all cameras with the given scene and renderer manager.\n\t * Also creates the debug camera.\n\t */\n\tasync setup(scene: Scene, rendererManager: RendererManager): Promise<void> {\n\t\tthis._sceneRef = scene;\n\t\tthis._rendererManager = rendererManager;\n\n\t\t// Create the debug camera\n\t\tthis.createDebugCamera(rendererManager.screenResolution);\n\n\t\t// Setup all registered cameras\n\t\tfor (const camera of this.cameras.values()) {\n\t\t\tcamera.setRendererManager(rendererManager);\n\t\t\tawait camera.setup(scene, rendererManager);\n\t\t}\n\n\t\t// Setup the debug camera\n\t\tif (this._debugCamera) {\n\t\t\tthis._debugCamera.setRendererManager(rendererManager);\n\t\t\tawait this._debugCamera.setup(scene, rendererManager);\n\t\t}\n\t}\n\n\t/**\n\t * Update all active cameras' controllers.\n\t */\n\tupdate(delta: number): void {\n\t\tfor (const camera of this._activeCameras) {\n\t\t\tcamera.update(delta);\n\t\t}\n\t}\n\n\t/**\n\t * Render all active cameras through the renderer manager.\n\t * RTT cameras (those with a renderTarget) are rendered first to their\n\t * offscreen textures, then viewport cameras are rendered to the screen.\n\t */\n\trender(scene: Scene): void {\n\t\tif (!this._rendererManager || this._activeCameras.length === 0) return;\n\n\t\tconst rttCameras: ZylemCamera[] = [];\n\t\tconst viewportCameras: ZylemCamera[] = [];\n\n\t\tfor (const cam of this._activeCameras) {\n\t\t\tif (cam.renderTarget) {\n\t\t\t\trttCameras.push(cam);\n\t\t\t} else {\n\t\t\t\tviewportCameras.push(cam);\n\t\t\t}\n\t\t}\n\n\t\t// RTT pass first so textures are ready for the viewport pass\n\t\tfor (const cam of rttCameras) {\n\t\t\tthis._rendererManager.renderCameraToTarget(scene, cam);\n\t\t}\n\n\t\t// Viewport pass renders to the screen canvas\n\t\tif (viewportCameras.length > 0) {\n\t\t\tthis._rendererManager.renderCameras(scene, viewportCameras);\n\t\t}\n\t}\n\n\t/**\n\t * Create a default third-person camera if no cameras have been added.\n\t */\n\tensureDefaultCamera(): ZylemCamera {\n\t\tif (this.cameras.size === 0 || this._activeCameras.length === 0) {\n\t\t\tconst screenRes = this._rendererManager?.screenResolution\n\t\t\t\t|| new Vector2(window.innerWidth, window.innerHeight);\n\t\t\tconst defaultCam = new ZylemCamera(Perspectives.ThirdPerson, screenRes);\n\t\t\tthis.addCamera(defaultCam, 'default');\n\t\t\treturn defaultCam;\n\t\t}\n\t\treturn this._activeCameras[0];\n\t}\n\n\t/**\n\t * Dispose all cameras and cleanup.\n\t */\n\tdispose(): void {\n\t\tfor (const camera of this.cameras.values()) {\n\t\t\tcamera.destroy();\n\t\t}\n\t\tthis._debugCamera?.destroy();\n\t\tthis.cameras.clear();\n\t\tthis._activeCameras = [];\n\t\tthis._debugCamera = null;\n\t\tthis._rendererManager = null;\n\t\tthis._sceneRef = null;\n\t}\n\n\t/**\n\t * Create the always-available debug camera with orbit controls.\n\t */\n\tprivate createDebugCamera(screenResolution: Vector2): void {\n\t\tthis._debugCamera = new ZylemCamera(Perspectives.ThirdPerson, screenResolution);\n\t\tthis._debugCamera.name = '__debug__';\n\t\tthis._debugCamera.enableOrbitalControls();\n\t\t// Debug camera is NOT added to the active cameras by default;\n\t\t// it's activated via the debug system\n\t}\n\n\t/**\n\t * Resolve a camera from a name or reference.\n\t */\n\tprivate resolveCamera(nameOrRef: string | ZylemCamera): ZylemCamera | null {\n\t\tif (typeof nameOrRef === 'string') {\n\t\t\treturn this.cameras.get(nameOrRef) ?? null;\n\t\t}\n\t\t// Check if the reference exists in our registry\n\t\tfor (const cam of this.cameras.values()) {\n\t\t\tif (cam === nameOrRef) return cam;\n\t\t}\n\t\treturn null;\n\t}\n}\n"],"mappings":"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","names":["Vector2","Vector3","PerspectiveCamera","Vector3","WebGLRenderTarget","WebGLRenderer","WebGLRenderer","Vector3","Quaternion","Vector3","Quaternion","Vector3","Quaternion","DEFAULTS","Vector3","Quaternion","MathUtils","DEFAULTS","Vector3","PerspectiveCamera","WebGLRenderTarget","Vector2","Vector3","Vector2","Vector2"]}
@@ -0,0 +1,218 @@
1
+ import { A as Action, I as GameEntity } from './entity-vj-HTjzU.js';
2
+
3
+ interface MoveByOptions {
4
+ /** X displacement (default: 0) */
5
+ x?: number;
6
+ /** Y displacement (default: 0) */
7
+ y?: number;
8
+ /** Z displacement (default: 0) */
9
+ z?: number;
10
+ /** Duration in milliseconds */
11
+ duration: number;
12
+ }
13
+ /**
14
+ * Move an entity by a displacement over a duration.
15
+ * Distributes the movement as velocity each frame so physics stays in sync.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * entity.runAction(moveBy({ x: 10, duration: 500 }));
20
+ * ```
21
+ */
22
+ declare function moveBy(opts: MoveByOptions): Action;
23
+ interface MoveToOptions {
24
+ /** Target X position */
25
+ x: number;
26
+ /** Target Y position */
27
+ y: number;
28
+ /** Target Z position */
29
+ z: number;
30
+ /** Duration in milliseconds */
31
+ duration: number;
32
+ }
33
+ /**
34
+ * Move an entity to an absolute position over a duration.
35
+ * Calculates displacement from the entity's position on the first tick.
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * entity.runAction(moveTo({ x: 0, y: 10, z: 0, duration: 2000 }));
40
+ * ```
41
+ */
42
+ declare function moveTo(opts: MoveToOptions): Action;
43
+ interface RotateByOptions {
44
+ /** X rotation in degrees (default: 0) */
45
+ x?: number;
46
+ /** Y rotation in degrees (default: 0) */
47
+ y?: number;
48
+ /** Z rotation in degrees (default: 0) */
49
+ z?: number;
50
+ /** Duration in milliseconds */
51
+ duration: number;
52
+ }
53
+ /**
54
+ * Rotate an entity by euler angles (degrees) over a duration.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * entity.runAction(rotateBy({ y: 360, duration: 2000 }));
59
+ * ```
60
+ */
61
+ declare function rotateBy(opts: RotateByOptions): Action;
62
+ /**
63
+ * Wait for a duration. Useful inside `sequence()`.
64
+ *
65
+ * @param ms Duration in milliseconds
66
+ * @example
67
+ * ```ts
68
+ * entity.runAction(sequence(moveBy({ x: 5, duration: 1000 }), delay(500), moveBy({ y: 3, duration: 1000 })));
69
+ * ```
70
+ */
71
+ declare function delay(ms: number): Action;
72
+ /**
73
+ * Call a function immediately. Completes in one frame.
74
+ * Useful inside `sequence()` for side effects.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * entity.runAction(sequence(moveBy({ x: 5, duration: 1000 }), callFunc(() => console.log('done'))));
79
+ * ```
80
+ */
81
+ declare function callFunc(fn: () => void): Action;
82
+
83
+ interface ThrottleOptions {
84
+ /** Interval in milliseconds between ready cycles */
85
+ duration: number;
86
+ }
87
+ /**
88
+ * A repeating timer that becomes ready every N milliseconds.
89
+ * Register with `entity.action(throttle(...))`.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * const t = entity.action(throttle({ duration: 500 }));
94
+ * entity.onUpdate(() => {
95
+ * if (t.ready) { t.consume(); // do something every 500ms }
96
+ * });
97
+ * ```
98
+ */
99
+ declare function throttle(opts: ThrottleOptions): ThrottleAction;
100
+ declare class ThrottleAction implements Action {
101
+ readonly duration: number;
102
+ done: boolean;
103
+ persistent: boolean;
104
+ ready: boolean;
105
+ private elapsed;
106
+ /** @param durationMs Duration in milliseconds */
107
+ constructor(durationMs: number);
108
+ tick(_entity: GameEntity<any>, delta: number): void;
109
+ /** Consume the ready state and reset the timer */
110
+ consume(): void;
111
+ reset(): void;
112
+ }
113
+ /**
114
+ * Detects the rising edge of a boolean signal (press).
115
+ * Call `.check(isPressed)` each frame in your onUpdate; `.triggered` is
116
+ * true for one frame on press.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * const press = entity.action(onPress());
121
+ * entity.onUpdate(({ inputs }) => {
122
+ * press.check(inputs.p1.buttons.A.pressed);
123
+ * if (press.triggered) { // do something once on press }
124
+ * });
125
+ * ```
126
+ */
127
+ declare function onPress(): OnPressAction;
128
+ declare class OnPressAction implements Action {
129
+ readonly duration: number;
130
+ done: boolean;
131
+ persistent: boolean;
132
+ triggered: boolean;
133
+ private wasPressed;
134
+ tick(): void;
135
+ /**
136
+ * Feed the current pressed state. Sets `.triggered = true` on the
137
+ * frame where `isPressed` transitions from false to true.
138
+ */
139
+ check(isPressed: boolean): void;
140
+ reset(): void;
141
+ }
142
+ /**
143
+ * Detects the falling edge of a boolean signal (release).
144
+ * Call `.check(isPressed)` each frame; `.triggered` is true for one frame
145
+ * on release.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * const release = entity.action(onRelease());
150
+ * entity.onUpdate(({ inputs }) => {
151
+ * release.check(inputs.p1.buttons.A.pressed);
152
+ * if (release.triggered) { // do something once on release }
153
+ * });
154
+ * ```
155
+ */
156
+ declare function onRelease(): OnReleaseAction;
157
+ declare class OnReleaseAction implements Action {
158
+ readonly duration: number;
159
+ done: boolean;
160
+ persistent: boolean;
161
+ triggered: boolean;
162
+ private wasPressed;
163
+ tick(): void;
164
+ /**
165
+ * Feed the current pressed state. Sets `.triggered = true` on the
166
+ * frame where `isPressed` transitions from true to false.
167
+ */
168
+ check(isPressed: boolean): void;
169
+ reset(): void;
170
+ }
171
+
172
+ /**
173
+ * Run actions in order, one after another.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * entity.runAction(sequence(
178
+ * moveBy({ x: 5, duration: 1000 }),
179
+ * delay(500),
180
+ * moveBy({ y: 3, duration: 1000 }),
181
+ * ));
182
+ * ```
183
+ */
184
+ declare function sequence(...actions: Action[]): Action;
185
+ /**
186
+ * Run all actions simultaneously. Done when all children are done.
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * entity.runAction(parallel(
191
+ * moveBy({ x: 5, duration: 1000 }),
192
+ * rotateBy({ y: 360, duration: 1000 }),
193
+ * ));
194
+ * ```
195
+ */
196
+ declare function parallel(...actions: Action[]): Action;
197
+ /**
198
+ * Repeat an action a fixed number of times.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * entity.runAction(repeat(moveBy({ x: 2, duration: 500 }), 5));
203
+ * ```
204
+ */
205
+ declare function repeat(action: Action, times: number): Action;
206
+ /**
207
+ * Repeat an action forever. Never completes.
208
+ *
209
+ * @example
210
+ * ```ts
211
+ * enemy.runAction(repeatForever(
212
+ * sequence(moveBy({ x: 3, duration: 2000 }), moveBy({ x: -3, duration: 2000 })),
213
+ * ));
214
+ * ```
215
+ */
216
+ declare function repeatForever(action: Action): Action;
217
+
218
+ export { moveTo as a, onRelease as b, callFunc as c, delay as d, repeat as e, repeatForever as f, moveBy as m, onPress as o, parallel as p, rotateBy as r, sequence as s, throttle as t };