@zylem/game-lib 0.6.3 → 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 (74) hide show
  1. package/dist/actions.d.ts +5 -5
  2. package/dist/actions.js +196 -32
  3. package/dist/actions.js.map +1 -1
  4. package/dist/behavior/jumper-2d.d.ts +114 -0
  5. package/dist/behavior/jumper-2d.js +711 -0
  6. package/dist/behavior/jumper-2d.js.map +1 -0
  7. package/dist/behavior/platformer-3d.d.ts +14 -14
  8. package/dist/behavior/platformer-3d.js +347 -104
  9. package/dist/behavior/platformer-3d.js.map +1 -1
  10. package/dist/behavior/ricochet-2d.d.ts +4 -3
  11. package/dist/behavior/ricochet-2d.js +53 -22
  12. package/dist/behavior/ricochet-2d.js.map +1 -1
  13. package/dist/behavior/ricochet-3d.d.ts +117 -0
  14. package/dist/behavior/ricochet-3d.js +443 -0
  15. package/dist/behavior/ricochet-3d.js.map +1 -0
  16. package/dist/behavior/screen-visibility.d.ts +79 -0
  17. package/dist/behavior/screen-visibility.js +358 -0
  18. package/dist/behavior/screen-visibility.js.map +1 -0
  19. package/dist/behavior/screen-wrap.d.ts +4 -3
  20. package/dist/behavior/screen-wrap.js +100 -49
  21. package/dist/behavior/screen-wrap.js.map +1 -1
  22. package/dist/behavior/shooter-2d.d.ts +79 -0
  23. package/dist/behavior/shooter-2d.js +180 -0
  24. package/dist/behavior/shooter-2d.js.map +1 -0
  25. package/dist/behavior/thruster.d.ts +5 -4
  26. package/dist/behavior/thruster.js +133 -75
  27. package/dist/behavior/thruster.js.map +1 -1
  28. package/dist/behavior/top-down-movement.d.ts +56 -0
  29. package/dist/behavior/top-down-movement.js +125 -0
  30. package/dist/behavior/top-down-movement.js.map +1 -0
  31. package/dist/behavior/world-boundary-2d.d.ts +4 -3
  32. package/dist/behavior/world-boundary-2d.js +90 -36
  33. package/dist/behavior/world-boundary-2d.js.map +1 -1
  34. package/dist/behavior/world-boundary-3d.d.ts +76 -0
  35. package/dist/behavior/world-boundary-3d.js +274 -0
  36. package/dist/behavior/world-boundary-3d.js.map +1 -0
  37. package/dist/{behavior-descriptor-BWNWmIjv.d.ts → behavior-descriptor-BXnVR8Ki.d.ts} +22 -5
  38. package/dist/{blueprints-BWGz8fII.d.ts → blueprints-DmbK2dki.d.ts} +2 -2
  39. package/dist/camera-4XO5gbQH.d.ts +905 -0
  40. package/dist/camera.d.ts +1 -1
  41. package/dist/camera.js +876 -289
  42. package/dist/camera.js.map +1 -1
  43. package/dist/{composition-DrzFrbqI.d.ts → composition-BASvMKrW.d.ts} +1 -1
  44. package/dist/{core-DAkskq6Y.d.ts → core-CARRaS55.d.ts} +57 -14
  45. package/dist/core.d.ts +9 -8
  46. package/dist/core.js +4519 -1255
  47. package/dist/core.js.map +1 -1
  48. package/dist/{entities-DC9ce_vx.d.ts → entities-ChFirVL9.d.ts} +22 -28
  49. package/dist/entities.d.ts +4 -4
  50. package/dist/entities.js +1231 -314
  51. package/dist/entities.js.map +1 -1
  52. package/dist/{entity-BpbZqg19.d.ts → entity-vj-HTjzU.d.ts} +80 -11
  53. package/dist/{global-change-Dc8uCKi2.d.ts → global-change-2JvMaz44.d.ts} +1 -1
  54. package/dist/main.d.ts +718 -19
  55. package/dist/main.js +12129 -5959
  56. package/dist/main.js.map +1 -1
  57. package/dist/physics-pose-DCc4oE44.d.ts +25 -0
  58. package/dist/physics-protocol-BDD3P5W2.d.ts +200 -0
  59. package/dist/physics-worker.d.ts +21 -0
  60. package/dist/physics-worker.js +306 -0
  61. package/dist/physics-worker.js.map +1 -0
  62. package/dist/physics.d.ts +205 -0
  63. package/dist/physics.js +577 -0
  64. package/dist/physics.js.map +1 -0
  65. package/dist/{stage-types-BFsm3qsZ.d.ts → stage-types-C19IhuzA.d.ts} +253 -89
  66. package/dist/stage.d.ts +9 -8
  67. package/dist/stage.js +3782 -1041
  68. package/dist/stage.js.map +1 -1
  69. package/dist/sync-state-machine-CZyspBpj.d.ts +16 -0
  70. package/dist/{thruster-DhRaJnoL.d.ts → thruster-23lzoPZd.d.ts} +16 -8
  71. package/dist/world-DfgxoNMt.d.ts +105 -0
  72. package/package.json +25 -1
  73. package/dist/camera-B5e4c78l.d.ts +0 -468
  74. package/dist/world-Be5m1XC1.d.ts +0 -31
package/dist/stage.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/stage/zylem-stage.ts","../src/lib/collision/world.ts","../src/lib/game/game-state.ts","../src/lib/game/game-event-bus.ts","../src/lib/entities/actor.ts","../src/lib/entities/entity.ts","../src/lib/systems/transformable.system.ts","../src/lib/core/flags.ts","../src/lib/core/base-node.ts","../../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/src/index.ts","../src/lib/events/event-emitter-delegate.ts","../src/lib/events/zylem-events.ts","../src/lib/actions/capabilities/transform-store.ts","../src/lib/actions/capabilities/moveable.ts","../src/lib/actions/capabilities/rotatable.ts","../src/lib/actions/capabilities/transformable.ts","../src/lib/entities/parts/collision-factories.ts","../src/lib/entities/common.ts","../src/lib/graphics/shaders/vertex/object.shader.ts","../src/lib/graphics/shaders/standard.shader.ts","../src/lib/core/asset-manager.ts","../src/lib/core/loaders/texture-loader.ts","../src/lib/core/loaders/gltf-loader.ts","../src/lib/core/loaders/fbx-loader.ts","../src/lib/core/loaders/obj-loader.ts","../src/lib/core/loaders/audio-loader.ts","../src/lib/core/loaders/file-loader.ts","../src/lib/core/entity-asset-loader.ts","../src/lib/entities/delegates/animation.ts","../src/lib/graphics/material.ts","../src/lib/core/utility/strings.ts","../src/lib/graphics/zylem-scene.ts","../src/lib/debug/debug-state.ts","../src/lib/graphics/instance-manager.ts","../src/lib/stage/stage-state.ts","../src/lib/core/utility/vector.ts","../src/lib/core/lifecycle-base.ts","../src/lib/stage/stage-debug-delegate.ts","../src/lib/stage/debug-entity-cursor.ts","../src/lib/stage/stage-camera-debug-delegate.ts","../src/lib/stage/stage-camera-delegate.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/camera/camera-debug-delegate.ts","../src/lib/camera/renderer-manager.ts","../src/lib/graphics/render-pass.ts","../src/lib/camera/camera-manager.ts","../src/lib/stage/stage-loading-delegate.ts","../src/lib/stage/stage-entity-model-delegate.ts","../src/lib/stage/stage-config.ts","../src/lib/core/utility/options-parser.ts","../src/lib/actions/capabilities/apply-transform.ts","../src/lib/core/vessel.ts","../src/lib/camera/camera.ts","../src/lib/stage/stage-default.ts","../src/lib/input/input-presets.ts","../src/lib/stage/stage.ts","../src/lib/stage/entity-spawner.ts","../src/lib/stage/stage-events.ts"],"sourcesContent":["import { addEntity, createWorld as createECS, removeEntity } from 'bitecs';\nimport { Color, Vector3, Vector2 } from 'three';\n\nimport { ZylemWorld } from '../collision/world';\nimport { ZylemScene } from '../graphics/zylem-scene';\nimport { InstanceManager } from '../graphics/instance-manager';\nimport { resetStageVariables, setStageBackgroundColor, setStageBackgroundImage, setStageVariables, clearVariables, initialStageState } from './stage-state';\n\nimport { GameEntityInterface } from '../types/entity-types';\nimport { debugState } from '../debug/debug-state';\nimport { subscribe } from 'valtio/vanilla';\nimport { getGlobals } from \"../game/game-state\";\n\nimport { SetupContext, UpdateContext, DestroyContext } from '../core/base-node-life-cycle';\nimport { LifeCycleBase } from '../core/lifecycle-base';\nimport createTransformSystem, { StageSystem } from '../systems/transformable.system';\nimport { BaseNode } from '../core/base-node';\nimport { nanoid } from 'nanoid';\nimport { Stage } from './stage';\nimport { CameraWrapper } from '../camera/camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { StageDebugDelegate } from './stage-debug-delegate';\nimport { StageCameraDebugDelegate } from './stage-camera-debug-delegate';\nimport { StageCameraDelegate } from './stage-camera-delegate';\nimport { StageLoadingDelegate } from './stage-loading-delegate';\nimport { StageEntityModelDelegate } from './stage-entity-model-delegate';\nimport { GameEntity } from '../entities/entity';\nimport { BaseEntityInterface } from '../types/entity-types';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { LoadingEvent } from '../core/interfaces';\nimport { parseStageOptions } from './stage-config';\nimport { isBaseNode, isThenable } from '../core/utility/options-parser';\nimport type { BehaviorSystem, BehaviorSystemFactory } from '../behaviors/behavior-system';\nimport { applyTransformChanges } from '../actions/capabilities/apply-transform';\nimport { Vessel } from '../core/vessel';\nexport type { LoadingEvent };\n\nexport interface ZylemStageConfig {\n\tinputs: Record<string, string[]>;\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader: any | null;\n\tgravity: Vector3;\n\tvariables: Record<string, any>;\n\tstageRef?: Stage;\n}\n\ntype NodeLike = { create: Function };\nexport type StageEntityInput = NodeLike | Promise<any> | (() => NodeLike | Promise<any>);\n\nexport type StageOptionItem = Partial<ZylemStageConfig> | CameraWrapper | StageEntityInput;\nexport type StageOptions = [] | [Partial<ZylemStageConfig>, ...StageOptionItem[]];\n\nexport type StageState = ZylemStageConfig & { entities: GameEntityInterface[] };\n\nconst STAGE_TYPE = 'Stage';\n\n/**\n * ZylemStage orchestrates scene, physics world, entities, and lifecycle.\n *\n * Responsibilities:\n * - Manage stage configuration (background, inputs, gravity, variables)\n * - Initialize and own `ZylemScene` and `ZylemWorld`\n * - Spawn, track, and remove entities; emit entity-added events\n * - Drive per-frame updates and transform system\n */\nexport class ZylemStage extends LifeCycleBase<ZylemStage> {\n\tpublic type = STAGE_TYPE;\n\n\tstate: StageState = { ...initialStageState };\n\tgravity: Vector3;\n\n\tworld: ZylemWorld | null;\n\tscene: ZylemScene | null;\n\tinstanceManager: InstanceManager | null = null;\n\n\tchildren: Array<BaseNode> = [];\n\t_childrenMap: Map<number, BaseNode> = new Map();\n\t_removalMap: Map<number, BaseNode> = new Map();\n\n\tprivate pendingEntities: StageEntityInput[] = [];\n\tprivate pendingPromises: Promise<BaseNode>[] = [];\n\tprivate isLoaded: boolean = false;\n\n\t_debugMap: Map<string, BaseNode> = new Map();\n\n\tprivate entityAddedHandlers: Array<(entity: BaseNode) => void> = [];\n\n\tecs = createECS();\n\ttestSystem: any = null;\n\ttransformSystem: ReturnType<typeof createTransformSystem> | null = null;\n\tprivate behaviorSystems: BehaviorSystem[] = [];\n\tprivate registeredSystemKeys: Set<symbol> = new Set();\n\tdebugDelegate: StageDebugDelegate | null = null;\n\tcameraDebugDelegate: StageCameraDebugDelegate | null = null;\n\tprivate debugStateUnsubscribe: (() => void) | null = null;\n\n\tuuid: string;\n\twrapperRef: Stage | null = null;\n\tcamera?: CameraWrapper;\n\tcameras: CameraWrapper[] = [];\n\tcameraRef?: ZylemCamera | null = null;\n\t/** Camera manager for multi-camera support */\n\tcameraManagerRef: CameraManager | null = null;\n\t/** Shared renderer manager (injected by the game) */\n\trendererManager: RendererManager | null = null;\n\n\t// Delegates\n\tprivate cameraDelegate: StageCameraDelegate;\n\tprivate loadingDelegate: StageLoadingDelegate;\n\tprivate entityModelDelegate: StageEntityModelDelegate;\n\n\t/**\n\t * Create a new stage.\n\t * @param options Stage options: partial config, camera, and initial entities or factories\n\t */\n\tconstructor(options: StageOptions = []) {\n\t\tsuper();\n\t\tthis.world = null;\n\t\tthis.scene = null;\n\t\tthis.uuid = nanoid();\n\n\t\t// Initialize delegates\n\t\tthis.cameraDelegate = new StageCameraDelegate(this);\n\t\tthis.loadingDelegate = new StageLoadingDelegate();\n\t\tthis.entityModelDelegate = new StageEntityModelDelegate();\n\n\t\t// Parse the options array using the stage-config module\n\t\tconst parsed = parseStageOptions(options);\n\t\tthis.camera = parsed.camera;\n\t\tthis.cameras = parsed.cameras;\n\t\tthis.children = parsed.entities;\n\t\tthis.pendingEntities = parsed.asyncEntities;\n\t\t\n\t\t// Update state with resolved config\n\t\tthis.saveState({\n\t\t\t...this.state,\n\t\t\tinputs: parsed.config.inputs,\n\t\t\tbackgroundColor: parsed.config.backgroundColor,\n\t\t\tbackgroundImage: parsed.config.backgroundImage,\n\t\t\tbackgroundShader: parsed.config.backgroundShader,\n\t\t\tgravity: parsed.config.gravity,\n\t\t\tvariables: parsed.config.variables,\n\t\t\tentities: [],\n\t\t});\n\n\t\tthis.gravity = parsed.config.gravity ?? new Vector3(0, 0, 0);\n\t}\n\n\tprivate handleEntityImmediatelyOrQueue(entity: BaseNode): void {\n\t\tif (this.isLoaded) {\n\t\t\tthis.spawnEntity(entity);\n\t\t} else {\n\t\t\tthis.children.push(entity);\n\t\t}\n\t}\n\n\tprivate handlePromiseWithSpawnOnResolve(promise: Promise<any>): void {\n\t\tif (this.isLoaded) {\n\t\t\tpromise\n\t\t\t\t.then((entity) => this.spawnEntity(entity))\n\t\t\t\t.catch((e) => console.error('Failed to build async entity', e));\n\t\t} else {\n\t\t\tthis.pendingPromises.push(promise as Promise<BaseNode>);\n\t\t}\n\t}\n\n\tprivate saveState(state: StageState) {\n\t\tthis.state = state;\n\t}\n\n\tprivate setState() {\n\t\tconst { backgroundColor, backgroundImage } = this.state;\n\t\tconst color = backgroundColor instanceof Color ? backgroundColor : new Color(backgroundColor);\n\t\tsetStageBackgroundColor(color);\n\t\tsetStageBackgroundImage(backgroundImage);\n\t\t// Initialize reactive stage variables on load\n\t\tsetStageVariables(this.state.variables ?? {});\n\t}\n\n\t/**\n\t * Load and initialize the stage's scene and world.\n\t * Uses generator pattern to yield control to event loop for real-time progress.\n\t * @param id DOM element id for the renderer container\n\t * @param camera Optional camera override\n\t */\n\tasync load(id: string, camera?: ZylemCamera | null, rendererManager?: RendererManager | null) {\n\t\tthis.setState();\n\n\t\tif (rendererManager) {\n\t\t\tthis.rendererManager = rendererManager;\n\t\t}\n\n\t\t// Build camera manager first so we can use its primary camera as the\n\t\t// canonical camera reference. This avoids creating two separate default\n\t\t// camera instances (one for the scene and a different one in the manager).\n\t\tif (this.rendererManager) {\n\t\t\tthis.cameraManagerRef = this.cameraDelegate.buildCameraManager(\n\t\t\t\tcamera,\n\t\t\t\t...this.cameras\n\t\t\t);\n\t\t}\n\n\t\t// Derive the resolved camera from the camera manager's primary camera\n\t\t// (when available), otherwise fall back to the legacy single-camera path.\n\t\tconst zylemCamera = this.cameraManagerRef?.primaryCamera\n\t\t\t?? this.cameraDelegate.resolveCamera(camera, this.camera);\n\t\tthis.cameraRef = zylemCamera;\n\t\tthis.scene = new ZylemScene(id, zylemCamera, this.state);\n\n\t\tconst physicsWorld = await ZylemWorld.loadPhysics(this.gravity ?? new Vector3(0, 0, 0));\n\t\tthis.world = new ZylemWorld(physicsWorld);\n\n\t\t// Setup scene (lighting, etc.)\n\t\tthis.scene.setup();\n\n\t\t// Setup cameras: prefer camera manager, fall back to legacy single camera\n\t\tif (this.cameraManagerRef && this.rendererManager) {\n\t\t\tawait this.scene.setupCameraManager(this.scene.scene, this.cameraManagerRef, this.rendererManager);\n\t\t\t// Setup render pass for the primary camera (WebGL post-processing)\n\t\t\tconst primaryCam = this.cameraManagerRef.primaryCamera;\n\t\t\tif (primaryCam) {\n\t\t\t\tthis.rendererManager.setupRenderPass(this.scene.scene, primaryCam.camera);\n\t\t\t}\n\t\t\t// Start the render loop via the renderer manager\n\t\t\tthis.rendererManager.startRenderLoop((delta) => {\n\t\t\t\tthis.cameraManagerRef?.update(delta);\n\t\t\t\tthis.cameraManagerRef?.render(this.scene!.scene);\n\t\t\t});\n\t\t} else {\n\t\t\t// Legacy path: single camera manages its own renderer\n\t\t\tthis.scene.setupCamera(this.scene.scene, zylemCamera);\n\t\t}\n\n\t\tthis.entityModelDelegate.attach(this.scene);\n\n\t\t// Initialize instance manager for mesh batching\n\t\tthis.instanceManager = new InstanceManager();\n\t\tthis.instanceManager.setScene(this.scene.scene);\n\n\t\tthis.loadingDelegate.emitStart();\n\n\t\t// Run entity loading with generator pattern for real-time progress\n\t\tawait this.runEntityLoadGenerator();\n\n\t\tthis.transformSystem = createTransformSystem(this as unknown as StageSystem);\n\t\tthis.isLoaded = true;\n\t\tthis.loadingDelegate.emitComplete();\n\t}\n\n\t/**\n\t * Generator that yields between entity loads for real-time progress updates.\n\t */\n\tprivate *entityLoadGenerator(): Generator<{ current: number; total: number; name: string }> {\n\t\tconst total = this.children.length + this.pendingEntities.length + this.pendingPromises.length;\n\t\tlet current = 0;\n\n\t\tfor (const child of this.children) {\n\t\t\tthis.spawnEntity(child);\n\t\t\tcurrent++;\n\t\t\tyield { current, total, name: child.name || 'unknown' };\n\t\t}\n\n\t\tif (this.pendingEntities.length) {\n\t\t\tthis.enqueue(...this.pendingEntities);\n\t\t\tcurrent += this.pendingEntities.length;\n\t\t\tthis.pendingEntities = [];\n\t\t\tyield { current, total, name: 'pending entities' };\n\t\t}\n\n\t\tif (this.pendingPromises.length) {\n\t\t\tfor (const promise of this.pendingPromises) {\n\t\t\t\tpromise.then((entity) => {\n\t\t\t\t\tthis.spawnEntity(entity);\n\t\t\t\t}).catch((e) => console.error('Failed to resolve pending stage entity', e));\n\t\t\t}\n\t\t\tcurrent += this.pendingPromises.length;\n\t\t\tthis.pendingPromises = [];\n\t\t\tyield { current, total, name: 'async entities' };\n\t\t}\n\t}\n\n\t/**\n\t * Runs the entity load generator, yielding to the event loop between loads.\n\t * This allows the browser to process events and update the UI in real-time.\n\t */\n\tprivate runEntityLoadGenerator(): void {\n\t\tconst gen = this.entityLoadGenerator();\n\t\tfor (const progress of gen) {\n\t\t\tthis.loadingDelegate.emitProgress(`Loaded ${progress.name}`, progress.current, progress.total);\n\t\t\t// Yield to event loop so browser can process events and update UI\n\t\t\t// Use setTimeout(0) for more reliable async behavior than RAF\n\t\t\tnew Promise<void>(resolve => setTimeout(resolve, 0));\n\t\t}\n\t}\n\n\n\tprotected _setup(params: SetupContext<ZylemStage>): void {\n\t\tif (!this.scene || !this.world) {\n\t\t\tthis.logMissingEntities();\n\t\t\treturn;\n\t\t}\n\t\t// Setup debug delegate based on current state\n\t\tthis.updateDebugDelegate();\n\n\t\t// Subscribe to debugState changes for runtime toggle\n\t\tthis.debugStateUnsubscribe = subscribe(debugState, () => {\n\t\t\tthis.updateDebugDelegate();\n\t\t});\n\t}\n\n\tprivate updateDebugDelegate(): void {\n\t\tif (debugState.enabled && !this.debugDelegate && this.scene && this.world) {\n\t\t\t// Create debug delegate when debug is enabled\n\t\t\tthis.debugDelegate = new StageDebugDelegate(this);\n\t\t\t\n\t\t\t// Create and attach camera debug delegate for orbit controls\n\t\t\tif (this.cameraRef && !this.cameraDebugDelegate) {\n\t\t\t\tthis.cameraDebugDelegate = new StageCameraDebugDelegate(this);\n\t\t\t\tthis.cameraRef.setDebugDelegate(this.cameraDebugDelegate);\n\t\t\t}\n\t\t} else if (!debugState.enabled && this.debugDelegate) {\n\t\t\t// Dispose debug delegate when debug is disabled\n\t\t\tthis.debugDelegate.dispose();\n\t\t\tthis.debugDelegate = null;\n\t\t\t\n\t\t\t// Detach camera debug delegate\n\t\t\tif (this.cameraRef) {\n\t\t\t\tthis.cameraRef.setDebugDelegate(null);\n\t\t\t}\n\t\t\tthis.cameraDebugDelegate = null;\n\t\t}\n\t}\n\n\tprotected _update(params: UpdateContext<ZylemStage>): void {\n\t\tconst { delta } = params;\n\t\tif (!this.scene || !this.world) {\n\t\t\tthis.logMissingEntities();\n\t\t\treturn;\n\t\t}\n\t\tthis.world.update(params);\n\t\t// Run registered ECS behavior systems\n\t\tfor (const system of this.behaviorSystems) {\n\t\t\tsystem.update(this.ecs, delta);\n\t\t}\n\t\tthis._childrenMap.forEach((child, eid) => {\n\t\t\tchild.nodeUpdate({\n\t\t\t\t...params,\n\t\t\t\tme: child,\n\t\t\t});\n\t\t\t\n\t\t\t// Apply pending transformations after update callbacks\n\t\t\tif ((child as any).transformStore) {\n\t\t\t\tapplyTransformChanges(child as any, (child as any).transformStore);\n\t\t\t}\n\t\t\t\n\t\t\tif (child.markedForRemoval) {\n\t\t\t\tthis.removeEntityByUuid(child.uuid);\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Sync physics to rendering AFTER transforms are applied\n\t\tthis.transformSystem?.system(this.ecs);\n\t\t\n\t\t// Sync instanced mesh transforms\n\t\tthis.instanceManager?.update();\n\t\tthis.scene.update({ delta });\n\t\tthis.scene.updateSkybox(delta);\n\t}\n\n\tpublic outOfLoop() {\n\t\tthis.debugUpdate();\n\t}\n\n\t/** Update debug overlays and helpers if enabled. */\n\tpublic debugUpdate() {\n\t\tif (debugState.enabled) {\n\t\t\tthis.debugDelegate?.update();\n\t\t}\n\t}\n\n\t/** Cleanup owned resources when the stage is destroyed. */\n\tprotected _destroy(params: DestroyContext<ZylemStage>): void {\n\t\t// Cleanup behavior systems\n\t\tfor (const system of this.behaviorSystems) {\n\t\t\tsystem.destroy?.(this.ecs);\n\t\t}\n\t\tthis.behaviorSystems = [];\n\t\tthis.registeredSystemKeys.clear();\n\t\tthis._childrenMap.forEach((child) => {\n\t\t\ttry { child.nodeDestroy({ me: child, globals: getGlobals() }); } catch { /* noop */ }\n\t\t\t// Clear entity-scoped variable proxy store entries\n\t\t\tclearVariables(child);\n\t\t});\n\t\tthis._childrenMap.clear();\n\t\tthis._removalMap.clear();\n\t\tthis._debugMap.clear();\n\n\t\tthis.world?.destroy();\n\t\tthis.scene?.destroy();\n\n\t\t// Cleanup debug state subscription\n\t\tif (this.debugStateUnsubscribe) {\n\t\t\tthis.debugStateUnsubscribe();\n\t\t\tthis.debugStateUnsubscribe = null;\n\t\t}\n\n\t\tthis.debugDelegate?.dispose();\n\t\tthis.debugDelegate = null;\n\t\tthis.cameraRef?.setDebugDelegate(null);\n\t\tthis.cameraDebugDelegate = null;\n\n\t\tthis.entityModelDelegate.dispose();\n\n\t\t// Dispose instance manager\n\t\tthis.instanceManager?.dispose();\n\t\tthis.instanceManager = null;\n\n\t\t// Stop renderer render loop if using renderer manager\n\t\tif (this.rendererManager) {\n\t\t\tthis.rendererManager.stopRenderLoop();\n\t\t}\n\n\t\tthis.isLoaded = false;\n\t\tthis.world = null as any;\n\t\tthis.scene = null as any;\n\t\tthis.cameraRef = null;\n\t\tthis.cameraManagerRef = null;\n\t\t// Cleanup transform system\n\t\tthis.transformSystem?.destroy(this.ecs);\n\t\tthis.transformSystem = null;\n\n\t\t// Clear reactive stage variables on unload\n\t\tresetStageVariables();\n\t\t// Clear object-scoped variables for this stage\n\t\tclearVariables(this);\n\t}\n\n\t/**\n\t * Create, register, and add an entity to the scene/world.\n\t * Safe to call only after `load` when scene/world exist.\n\t */\n\tasync spawnEntity(child: BaseNode) {\n\t\tif (!this.scene || !this.world) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the child is a Vessel, spawn each of its children individually\n\t\t// then register the Vessel itself so it participates in the update loop.\n\t\tif (child instanceof Vessel) {\n\t\t\tchild.create();\n\t\t\tfor (const childEntity of child.getChildren()) {\n\t\t\t\tif (childEntity instanceof BaseNode) {\n\t\t\t\t\tawait this.spawnEntity(childEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Assign an ECS eid so the Vessel can be tracked in _childrenMap\n\t\t\tconst vesselEid = addEntity(this.ecs);\n\t\t\tchild.eid = vesselEid;\n\n\t\t\t// Run vessel lifecycle after children are spawned\n\t\t\tchild.nodeSetup({\n\t\t\t\tme: child,\n\t\t\t\tglobals: getGlobals(),\n\t\t\t\tcamera: this.scene.zylemCamera,\n\t\t\t});\n\n\t\t\tthis.addEntityToStage(child);\n\t\t\treturn;\n\t\t}\n\n\t\tconst entity = child.create();\n\t\tconst eid = addEntity(this.ecs);\n\t\tentity.eid = eid;\n\t\tthis.scene.addEntity(entity);\n\n\t\t// Auto-register behavior systems from entity refs\n\t\tif (typeof entity.getBehaviorRefs === 'function') {\n\t\t\tfor (const ref of entity.getBehaviorRefs()) {\n\t\t\t\tconst key = ref.descriptor.key;\n\t\t\t\tif (!this.registeredSystemKeys.has(key)) {\n\t\t\t\t\tconst system = ref.descriptor.systemFactory({ world: this.world, ecs: this.ecs, scene: this.scene });\n\t\t\t\t\tthis.behaviorSystems.push(system);\n\t\t\t\t\tthis.registeredSystemKeys.add(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (entity.colliderDesc) {\n\t\t\tthis.world.addEntity(entity);\n\t\t}\n\n\t\t// Recursively spawn any BaseNode children (for nested entities)\n\t\tfor (const childNode of child.getChildren()) {\n\t\t\tif (childNode instanceof BaseNode) {\n\t\t\t\tawait this.spawnEntity(childNode);\n\t\t\t}\n\t\t}\n\n\t\tchild.nodeSetup({\n\t\t\tme: child,\n\t\t\tglobals: getGlobals(),\n\t\t\tcamera: this.scene.zylemCamera,\n\t\t});\n\n\t\t// Register for instanced rendering if opted in\n\t\tthis.tryRegisterInstance(entity);\n\n\t\tthis.addEntityToStage(entity);\n\t\tthis.entityModelDelegate.observe(entity);\n\t}\n\n\t/**\n\t * Try to register an entity for instanced rendering.\n\t * Batching is enabled by default unless explicitly disabled with batched: false.\n\t */\n\tprivate tryRegisterInstance(entity: GameEntity<any>): void {\n\t\tif (!this.instanceManager) return;\n\n\t\t// Batching is disabled by default, must be explicitly enabled\n\t\tconst options = entity.options as any;\n\t\tif (options?.batched !== true) return;\n\n\t\t// Need mesh with geometry and material\n\t\tif (!entity.mesh?.geometry || !entity.materials?.length) return;\n\n\t\tconst geometry = entity.mesh.geometry;\n\t\tconst material = entity.materials[0];\n\n\t\t// Generate batch key based on entity type and options\n\t\tconst entityType = (entity.constructor as any).type?.description || 'unknown';\n\t\tconst size = options.size || { x: 1, y: 1, z: 1 };\n\t\tconst matOptions = options.material || {};\n\n\t\tconst batchKey = InstanceManager.generateBatchKey({\n\t\t\tgeometryType: entityType,\n\t\t\tdimensions: { x: size.x, y: size.y, z: size.z },\n\t\t\tmaterialPath: matOptions.path || null,\n\t\t\tshaderType: matOptions.shader ? 'custom' : 'standard',\n\t\t\tcolorHex: matOptions.color?.getHex?.() || 0xffffff,\n\t\t});\n\n\t\t// Register with instance manager\n\t\tconst instanceId = this.instanceManager.register(entity, geometry, material, batchKey);\n\n\t\tif (instanceId >= 0) {\n\t\t\tentity.batchKey = batchKey;\n\t\t\tentity.instanceId = instanceId;\n\t\t\tentity.isInstanced = true;\n\n\t\t\t// Hide the individual mesh since it's now part of an instanced batch\n\t\t\tif (entity.mesh) {\n\t\t\t\tentity.mesh.visible = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tbuildEntityState(child: BaseNode): Partial<BaseEntityInterface> {\n\t\tif (child instanceof GameEntity) {\n\t\t\treturn { ...child.buildInfo() } as Partial<BaseEntityInterface>;\n\t\t}\n\t\treturn {\n\t\t\tuuid: child.uuid,\n\t\t\tname: child.name,\n\t\t\teid: child.eid,\n\t\t} as Partial<BaseEntityInterface>;\n\t}\n\n\t/** Add the entity to internal maps and notify listeners. */\n\taddEntityToStage(entity: BaseNode) {\n\t\tthis._childrenMap.set(entity.eid, entity);\n\t\tif (debugState.enabled) {\n\t\t\tthis._debugMap.set(entity.uuid, entity);\n\t\t}\n\t\tfor (const handler of this.entityAddedHandlers) {\n\t\t\ttry {\n\t\t\t\thandler(entity);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('onEntityAdded handler failed', e);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Subscribe to entity-added events.\n\t * @param callback Invoked for each entity when added\n\t * @param options.replayExisting If true and stage already loaded, replays existing entities\n\t * @returns Unsubscribe function\n\t */\n\tonEntityAdded(callback: (entity: BaseNode) => void, options?: { replayExisting?: boolean }) {\n\t\tthis.entityAddedHandlers.push(callback);\n\t\tif (options?.replayExisting && this.isLoaded) {\n\t\t\tthis._childrenMap.forEach((entity) => {\n\t\t\t\ttry { callback(entity); } catch (e) { console.error('onEntityAdded replay failed', e); }\n\t\t\t});\n\t\t}\n\t\treturn () => {\n\t\t\tthis.entityAddedHandlers = this.entityAddedHandlers.filter((h) => h !== callback);\n\t\t};\n\t}\n\n\tonLoading(callback: (event: LoadingEvent) => void) {\n\t\treturn this.loadingDelegate.onLoading(callback);\n\t}\n\n\t/**\n\t * Register an ECS behavior system to run each frame.\n\t * @param systemOrFactory A BehaviorSystem instance or factory function\n\t * @returns this for chaining\n\t */\n\tregisterSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): this {\n\t\tlet system: BehaviorSystem;\n\t\tif (typeof systemOrFactory === 'function') {\n\t\tsystem = systemOrFactory({ world: this.world, ecs: this.ecs, scene: this.scene });\n\t\t} else {\n\t\t\tsystem = systemOrFactory;\n\t\t}\n\t\tthis.behaviorSystems.push(system);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Remove an entity and its resources by its UUID.\n\t * @returns true if removed, false if not found or stage not ready\n\t */\n\tremoveEntityByUuid(uuid: string): boolean {\n\t\tif (!this.scene || !this.world) return false;\n\t\t// Try mapping via world collision map first for physics-backed entities\n\t\t// @ts-ignore - collisionMap is public Map<string, GameEntity<any>>\n\t\tconst mapEntity = this.world.collisionMap.get(uuid) as any | undefined;\n\t\tconst entity: any = mapEntity ?? this._debugMap.get(uuid);\n\t\tif (!entity) return false;\n\n\t\tthis.entityModelDelegate.unobserve(uuid);\n\n\t\t// Unregister from instance manager if instanced\n\t\tif (entity.isInstanced && this.instanceManager) {\n\t\t\tthis.instanceManager.unregister(entity);\n\t\t}\n\n\t\tthis.world.destroyEntity(entity);\n\n\t\tif (entity.group) {\n\t\t\tthis.scene.scene.remove(entity.group);\n\t\t} else if (entity.mesh) {\n\t\t\tthis.scene.scene.remove(entity.mesh);\n\t\t}\n\n\t\tremoveEntity(this.ecs, entity.eid);\n\n\t\tlet foundKey: number | null = null;\n\t\tthis._childrenMap.forEach((value, key) => {\n\t\t\tif ((value as any).uuid === uuid) {\n\t\t\t\tfoundKey = key;\n\t\t\t}\n\t\t});\n\t\tif (foundKey !== null) {\n\t\t\tthis._childrenMap.delete(foundKey);\n\t\t}\n\t\tthis._debugMap.delete(uuid);\n\t\treturn true;\n\t}\n\n\t/** Get an entity by its name; returns null if not found. */\n\tgetEntityByName(name: string) {\n\t\tconst arr = Object.entries(Object.fromEntries(this._childrenMap)).map((entry) => entry[1]);\n\t\tconst entity = arr.find((child) => child.name === name);\n\t\tif (!entity) {\n\t\t\tconsole.warn(`Entity ${name} not found`);\n\t\t}\n\t\treturn entity ?? null;\n\t}\n\n\tlogMissingEntities() {\n\t\tconsole.warn('Zylem world or scene is null');\n\t}\n\n\t// ─── Camera management forwarding ─────────────────────────────────────\n\n\t/**\n\t * Add a camera to this stage's camera manager.\n\t */\n\taddCamera(camera: ZylemCamera, name?: string): string | null {\n\t\tif (!this.cameraManagerRef) {\n\t\t\tconsole.warn('ZylemStage: CameraManager not available. Ensure stage is loaded with a RendererManager.');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.cameraManagerRef.addCamera(camera, name);\n\t}\n\n\t/**\n\t * Remove a camera from this stage's camera manager.\n\t */\n\tremoveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\treturn this.cameraManagerRef?.removeCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Set the active camera by name or reference.\n\t */\n\tsetActiveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\treturn this.cameraManagerRef?.setActiveCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Get a camera by name from the camera manager.\n\t */\n\tgetCamera(name: string): ZylemCamera | null {\n\t\treturn this.cameraManagerRef?.getCamera(name) ?? null;\n\t}\n\n\t/** Resize renderer viewport. */\n\tresize(width: number, height: number) {\n\t\tif (this.scene) {\n\t\t\tthis.scene.updateRenderer(width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Enqueue items to be spawned. Items can be:\n\t * - BaseNode instances (immediate or deferred until load)\n\t * - Factory functions returning BaseNode or Promise<BaseNode>\n\t * - Promises resolving to BaseNode\n\t */\n\tenqueue(...items: StageEntityInput[]) {\n\t\tfor (const item of items) {\n\t\t\tif (!item) continue;\n\t\t\tif (isBaseNode(item)) {\n\t\t\t\tthis.handleEntityImmediatelyOrQueue(item);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof item === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = (item as (() => BaseNode | Promise<any>))();\n\t\t\t\t\tif (isBaseNode(result)) {\n\t\t\t\t\t\tthis.handleEntityImmediatelyOrQueue(result);\n\t\t\t\t\t} else if (isThenable(result)) {\n\t\t\t\t\t\tthis.handlePromiseWithSpawnOnResolve(result as Promise<any>);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('Error executing entity factory', error);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isThenable(item)) {\n\t\t\t\tthis.handlePromiseWithSpawnOnResolve(item as Promise<any>);\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Vector3 } from 'three';\nimport RAPIER, { World } from '@dimforge/rapier3d-compat';\n\nimport { Entity } from '../interfaces/entity';\nimport { state } from '../game/game-state';\nimport { UpdateContext } from '../core/base-node-life-cycle';\nimport { ZylemActor } from '../entities/actor';\nimport { GameEntity } from '../entities/entity';\n\n/**\n * Interface for entities that handle collision events.\n */\nexport interface CollisionHandlerDelegate {\n\thandlePostCollision(params: any): boolean;\n\thandleIntersectionEvent(params: any): void;\n}\n\n/**\n * Type guard to check if an object implements CollisionHandlerDelegate.\n */\nexport function isCollisionHandlerDelegate(obj: any): obj is CollisionHandlerDelegate {\n\treturn typeof obj?.handlePostCollision === \"function\" && typeof obj?.handleIntersectionEvent === \"function\";\n}\n\nexport class ZylemWorld implements Entity<ZylemWorld> {\n\ttype = 'World';\n\tworld: World;\n\tcollisionMap: Map<string, GameEntity<any>> = new Map();\n\tcollisionBehaviorMap: Map<string, GameEntity<any>> = new Map();\n\t_removalMap: Map<string, GameEntity<any>> = new Map();\n\n\tstatic async loadPhysics(gravity: Vector3) {\n\t\tawait RAPIER.init();\n\t\tconst physicsWorld = new RAPIER.World(gravity);\n\t\treturn physicsWorld;\n\t}\n\n\tconstructor(world: World) {\n\t\tthis.world = world;\n\t}\n\n\taddEntity(entity: any) {\n\t\tconst rigidBody = this.world.createRigidBody(entity.bodyDesc);\n\t\tentity.body = rigidBody;\n\t\t// TODO: consider passing in more specific data\n\t\tentity.body.userData = { uuid: entity.uuid, ref: entity };\n\t\tif (this.world.gravity.x === 0 && this.world.gravity.y === 0 && this.world.gravity.z === 0) {\n\t\t\tentity.body.lockTranslations(true, true);\n\t\t\tentity.body.lockRotations(true, true);\n\t\t}\n\n\t\t// Create primary collider\n\t\tconst collider = this.world.createCollider(entity.colliderDesc, entity.body);\n\t\tentity.collider = collider;\n\t\tentity.colliders = [collider];\n\n\t\t// Create additional compound colliders (if any)\n\t\tif (entity.colliderDescs?.length > 1) {\n\t\t\tfor (let i = 1; i < entity.colliderDescs.length; i++) {\n\t\t\t\tconst additionalCollider = this.world.createCollider(entity.colliderDescs[i], entity.body);\n\t\t\t\tentity.colliders.push(additionalCollider);\n\t\t\t}\n\t\t}\n\n\t\tif (entity.controlledRotation || entity instanceof ZylemActor) {\n\t\t\tentity.body.lockRotations(true, true);\n\t\t\tentity.characterController = this.world.createCharacterController(0.01);\n\t\t\tentity.characterController.setMaxSlopeClimbAngle(45 * Math.PI / 180);\n\t\t\tentity.characterController.setMinSlopeSlideAngle(30 * Math.PI / 180);\n\t\t\tentity.characterController.enableSnapToGround(0.01);\n\t\t\tentity.characterController.setSlideEnabled(true);\n\t\t\tentity.characterController.setApplyImpulsesToDynamicBodies(true);\n\t\t\tentity.characterController.setCharacterMass(1);\n\t\t}\n\t\tthis.collisionMap.set(entity.uuid, entity);\n\t}\n\n\tsetForRemoval(entity: any) {\n\t\tif (entity.body) {\n\t\t\tthis._removalMap.set(entity.uuid, entity);\n\t\t}\n\t}\n\n\tdestroyEntity(entity: GameEntity<any>) {\n\t\t// Free character controller WASM resource if present\n\t\tif ((entity as any).characterController) {\n\t\t\ttry { (entity as any).characterController.free(); } catch { /* noop */ }\n\t\t\t(entity as any).characterController = null;\n\t\t}\n\t\t// Remove all colliders (compound support)\n\t\tif (entity.colliders?.length) {\n\t\t\tfor (const collider of entity.colliders) {\n\t\t\t\tthis.world.removeCollider(collider, true);\n\t\t\t}\n\t\t} else if (entity.collider) {\n\t\t\tthis.world.removeCollider(entity.collider, true);\n\t\t}\n\t\tif (entity.body) {\n\t\t\tthis.world.removeRigidBody(entity.body);\n\t\t\tthis.collisionMap.delete(entity.uuid);\n\t\t\tthis._removalMap.delete(entity.uuid);\n\t\t}\n\t}\n\n\tsetup() { }\n\n\tupdate(params: UpdateContext<any>) {\n\t\tconst { delta } = params;\n\t\tif (!this.world) {\n\t\t\treturn;\n\t\t}\n\t\tthis.updateColliders(delta);\n\t\tthis.updatePostCollisionBehaviors(delta);\n\t\tthis.world.step();\n\t}\n\n\tupdatePostCollisionBehaviors(delta: number) {\n\t\tconst dictionaryRef = this.collisionBehaviorMap;\n\t\tfor (let [id, collider] of dictionaryRef) {\n\t\t\tconst gameEntity = collider as any;\n\t\t\tif (!isCollisionHandlerDelegate(gameEntity)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst active = gameEntity.handlePostCollision({ entity: gameEntity, delta });\n\t\t\tif (!active) {\n\t\t\t\tthis.collisionBehaviorMap.delete(id);\n\t\t\t}\n\t\t}\n\t}\n\n\tupdateColliders(delta: number) {\n\t\tconst dictionaryRef = this.collisionMap;\n\t\tfor (let [id, collider] of dictionaryRef) {\n\t\t\tconst gameEntity = collider as GameEntity<any>;\n\t\t\tif (!gameEntity.body) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (this._removalMap.get(gameEntity.uuid)) {\n\t\t\t\tthis.destroyEntity(gameEntity);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\tthis.world.contactsWith(gameEntity.body.collider(0), (otherCollider) => {\n\t\t\tif (!otherCollider) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// @ts-ignore\n\t\t\tconst uuid = otherCollider._parent.userData.uuid;\n\t\t\tconst entity = dictionaryRef.get(uuid);\n\t\t\tif (!entity) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (gameEntity._collision) {\n\t\t\t\tgameEntity._collision(entity, state.globals);\n\t\t\t}\n\t\t});\n\t\t// Body may have been invalidated by a destroy() call inside a collision callback\n\t\tif (!gameEntity.body || gameEntity.markedForRemoval) {\n\t\t\tcontinue;\n\t\t}\n\t\tthis.world.intersectionsWith(gameEntity.body.collider(0), (otherCollider) => {\n\t\t\t\tif (!otherCollider) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// @ts-ignore\n\t\t\t\tconst uuid = otherCollider._parent.userData.uuid;\n\t\t\t\tconst entity = dictionaryRef.get(uuid);\n\t\t\t\tif (!entity) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (gameEntity._collision) {\n\t\t\t\t\tgameEntity._collision(entity, state.globals);\n\t\t\t\t}\n\t\t\t\tif (isCollisionHandlerDelegate(entity)) {\n\t\t\t\t\tentity.handleIntersectionEvent({ entity, other: gameEntity, delta });\n\t\t\t\t\tthis.collisionBehaviorMap.set(uuid, entity);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tdestroy() {\n\t\ttry {\n\t\t\tfor (const [, entity] of this.collisionMap) {\n\t\t\t\ttry { this.destroyEntity(entity); } catch { /* noop */ }\n\t\t\t}\n\t\t\tthis.collisionMap.clear();\n\t\t\tthis.collisionBehaviorMap.clear();\n\t\t\tthis._removalMap.clear();\n\t\t\t// Free WASM-backed Rapier world before dropping the reference\n\t\t\ttry { this.world?.free(); } catch { /* noop */ }\n\t\t\t// @ts-ignore\n\t\t\tthis.world = undefined as any;\n\t\t} catch { /* noop */ }\n\t}\n\n}","import { proxy, subscribe } from 'valtio/vanilla';\nimport { getByPath, setByPath } from '../core/utility/path-utils';\nimport { gameEventBus } from './game-event-bus';\n\n/**\n * Internal game state store using valtio proxy for reactivity.\n */\nconst state = proxy({\n\tid: '',\n\tglobals: {} as Record<string, unknown>,\n\ttime: 0,\n});\n\n/**\n * Track active subscriptions for cleanup on game dispose.\n */\nconst activeSubscriptions: Set<() => void> = new Set();\n\n/**\n * Set a global value by path.\n * Emits a 'game:state:updated' event when the value changes.\n * @example setGlobal('score', 100)\n * @example setGlobal('player.health', 50)\n */\nexport function setGlobal(path: string, value: unknown): void {\n\tconst previousValue = getByPath(state.globals, path);\n\tsetByPath(state.globals, path, value);\n\n\tgameEventBus.emit('game:state:updated', {\n\t\tpath,\n\t\tvalue,\n\t\tpreviousValue,\n\t});\n}\n\n/**\n * Create/initialize a global with a default value.\n * Only sets the value if it doesn't already exist.\n * Use this to ensure globals have initial values before game starts.\n * @example createGlobal('score', 0)\n * @example createGlobal('player.health', 100)\n */\nexport function createGlobal<T>(path: string, defaultValue: T): T {\n\tconst existing = getByPath<T>(state.globals, path);\n\tif (existing === undefined) {\n\t\tsetByPath(state.globals, path, defaultValue);\n\t\treturn defaultValue;\n\t}\n\treturn existing;\n}\n\n/**\n * Get a global value by path.\n * @example getGlobal('score') // 100\n * @example getGlobal<number>('player.health') // 50\n */\nexport function getGlobal<T = unknown>(path: string): T | undefined {\n\treturn getByPath<T>(state.globals, path);\n}\n\n/**\n * Subscribe to changes on a global value at a specific path.\n * Returns an unsubscribe function. Subscriptions are automatically\n * cleaned up when the game is disposed.\n * @example const unsub = onGlobalChange('score', (val) => console.log(val));\n */\nexport function onGlobalChange<T = unknown>(\n\tpath: string,\n\tcallback: (value: T) => void\n): () => void {\n\tlet previous = getByPath<T>(state.globals, path);\n\tconst unsub = subscribe(state.globals, () => {\n\t\tconst current = getByPath<T>(state.globals, path);\n\t\tif (current !== previous) {\n\t\t\tprevious = current;\n\t\t\tcallback(current as T);\n\t\t}\n\t});\n\tactiveSubscriptions.add(unsub);\n\treturn () => {\n\t\tunsub();\n\t\tactiveSubscriptions.delete(unsub);\n\t};\n}\n\n/**\n * Subscribe to changes on multiple global paths.\n * Callback fires when any of the paths change, receiving all current values.\n * Subscriptions are automatically cleaned up when the game is disposed.\n * @example const unsub = onGlobalChanges(['score', 'lives'], ([score, lives]) => console.log(score, lives));\n */\nexport function onGlobalChanges<T extends unknown[] = unknown[]>(\n\tpaths: string[],\n\tcallback: (values: T) => void\n): () => void {\n\tlet previousValues = paths.map(p => getByPath(state.globals, p));\n\tconst unsub = subscribe(state.globals, () => {\n\t\tconst currentValues = paths.map(p => getByPath(state.globals, p));\n\t\tconst hasChange = currentValues.some((val, i) => val !== previousValues[i]);\n\t\tif (hasChange) {\n\t\t\tpreviousValues = currentValues;\n\t\t\tcallback(currentValues as T);\n\t\t}\n\t});\n\tactiveSubscriptions.add(unsub);\n\treturn () => {\n\t\tunsub();\n\t\tactiveSubscriptions.delete(unsub);\n\t};\n}\n\n/**\n * Get the entire globals object (read-only snapshot).\n */\nexport function getGlobals<T = Record<string, unknown>>(): T {\n\treturn state.globals as T;\n}\n\n/**\n * Initialize globals from an object. Used internally during game setup.\n */\nexport function initGlobals(globals: Record<string, unknown>): void {\n\tfor (const [key, value] of Object.entries(globals)) {\n\t\tsetByPath(state.globals, key, value);\n\t}\n}\n\n/**\n * Reset all globals. Used internally on game dispose.\n */\nexport function resetGlobals(): void {\n\tstate.globals = {};\n}\n\n/**\n * Unsubscribe all active global subscriptions.\n * Used internally on game dispose to prevent old callbacks from firing.\n */\nexport function clearGlobalSubscriptions(): void {\n\tfor (const unsub of activeSubscriptions) {\n\t\tunsub();\n\t}\n\tactiveSubscriptions.clear();\n}\n\nexport { state };","import { LoadingEvent } from '../core/interfaces';\n\n/**\n * Event types for the game event bus.\n */\nexport type GameEventType = \n\t| 'stage:loading:start'\n\t| 'stage:loading:progress'\n\t| 'stage:loading:complete'\n\t| 'game:state:updated';\n\n/**\n * Payload for stage loading events.\n */\nexport interface StageLoadingPayload extends LoadingEvent {\n\tstageName?: string;\n\tstageIndex?: number;\n}\n\n/**\n * Payload for game state update events.\n */\nexport interface GameStateUpdatedPayload {\n\tpath: string;\n\tvalue: unknown;\n\tpreviousValue?: unknown;\n}\n\n/**\n * Event map for typed event handling.\n */\nexport interface GameEventMap {\n\t'stage:loading:start': StageLoadingPayload;\n\t'stage:loading:progress': StageLoadingPayload;\n\t'stage:loading:complete': StageLoadingPayload;\n\t'game:state:updated': GameStateUpdatedPayload;\n}\n\ntype EventCallback<T> = (payload: T) => void;\n\n/**\n * Simple event bus for game-stage communication.\n * Used to decouple stage loading events from direct coupling.\n */\nexport class GameEventBus {\n\tprivate listeners: Map<GameEventType, Set<EventCallback<any>>> = new Map();\n\n\t/**\n\t * Subscribe to an event type.\n\t */\n\ton<K extends GameEventType>(event: K, callback: EventCallback<GameEventMap[K]>): () => void {\n\t\tif (!this.listeners.has(event)) {\n\t\t\tthis.listeners.set(event, new Set());\n\t\t}\n\t\tthis.listeners.get(event)!.add(callback);\n\t\treturn () => this.off(event, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from an event type.\n\t */\n\toff<K extends GameEventType>(event: K, callback: EventCallback<GameEventMap[K]>): void {\n\t\tthis.listeners.get(event)?.delete(callback);\n\t}\n\n\t/**\n\t * Emit an event to all subscribers.\n\t */\n\temit<K extends GameEventType>(event: K, payload: GameEventMap[K]): void {\n\t\tconst callbacks = this.listeners.get(event);\n\t\tif (!callbacks) return;\n\t\tfor (const cb of callbacks) {\n\t\t\ttry {\n\t\t\t\tcb(payload);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(`Error in event handler for ${event}`, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear all listeners.\n\t */\n\tdispose(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n\n/**\n * Singleton event bus instance for global game events.\n */\nexport const gameEventBus = new GameEventBus();\n","import { ActiveCollisionTypes, ColliderDesc } from '@dimforge/rapier3d-compat';\nimport { BufferGeometry, Object3D, SkinnedMesh, Mesh, MeshStandardMaterial, Group, Vector3 } from 'three';\nimport { BaseNode } from '../core/base-node';\nimport { GameEntityOptions, GameEntity } from './entity';\nimport { createEntity } from './create';\nimport { UpdateContext, UpdateFunction } from '../core/base-node-life-cycle';\nimport { EntityAssetLoader } from '../core/entity-asset-loader';\nimport { EntityLoaderDelegate } from './delegates/loader';\nimport { Vec3 } from '../core/vector';\nimport { AnimationDelegate, AnimationOptions } from './delegates/animation';\nimport { MaterialOptions } from '../graphics/material';\nimport { DebugInfoProvider } from './delegates/debug';\nimport { EntityBuilder } from './builder';\nimport { EntityCollisionBuilder } from './builder';\nimport { commonDefaults } from './common';\nimport { standardShader } from '../graphics/shaders/standard.shader';\n\ntype AnimationObject = {\n\tkey?: string;\n\tpath: string;\n};\n\nexport type CollisionShapeType = 'capsule' | 'model';\n\ntype ZylemActorOptions = GameEntityOptions & {\n\tstatic?: boolean;\n\tanimations?: AnimationObject[];\n\tmodels?: string[];\n\tscale?: Vec3;\n\tmaterial?: MaterialOptions;\n\tcollisionShape?: CollisionShapeType;\n};\n\nconst actorDefaults: ZylemActorOptions = {\n\t...commonDefaults,\n\tcollision: {\n\t\tstatic: false,\n\t\tsize: new Vector3(0.5, 0.5, 0.5),\n\t\tposition: new Vector3(0, 0, 0),\n\t},\n\tmaterial: {\n\t\tshader: standardShader\n\t},\n\tanimations: [],\n\tmodels: [],\n\tcollisionShape: 'capsule',\n};\n\nclass ActorCollisionBuilder extends EntityCollisionBuilder {\n\tprivate objectModel: Group | null = null;\n\tprivate collisionShape: CollisionShapeType = 'capsule';\n\n\tconstructor(data: any) {\n\t\tsuper();\n\t\tthis.objectModel = data.objectModel;\n\t\tthis.collisionShape = data.collisionShape ?? 'capsule';\n\t}\n\n\tcollider(options: ZylemActorOptions): ColliderDesc {\n\t\tif (this.collisionShape === 'model') {\n\t\t\treturn this.createColliderFromModel(this.objectModel, options);\n\t\t}\n\t\treturn this.createCapsuleCollider(options);\n\t}\n\n\t/**\n\t * Create a capsule collider based on size options (character controller style).\n\t */\n\tprivate createCapsuleCollider(options: ZylemActorOptions): ColliderDesc {\n\t\tconst size = options.collision?.size ?? options.size ?? { x: 0.5, y: 1, z: 0.5 };\n\t\tconst halfHeight = ((size as any).y || 1);\n\t\tconst radius = Math.max((size as any).x || 0.5, (size as any).z || 0.5);\n\t\tlet colliderDesc = ColliderDesc.capsule(halfHeight, radius);\n\t\tcolliderDesc.setSensor(false);\n\t\tcolliderDesc.setTranslation(0, halfHeight + radius, 0);\n\t\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\t\treturn colliderDesc;\n\t}\n\n\t/**\n\t * Create a collider based on model geometry (works with Mesh and SkinnedMesh).\n\t * If collision.size and collision.position are provided, use those instead of computing from geometry.\n\t */\n\tprivate createColliderFromModel(objectModel: Group | null, options: ZylemActorOptions): ColliderDesc {\n\t\tconst collisionSize = options.collision?.size;\n\t\tconst collisionPosition = options.collision?.position;\n\n\t\t// If user provided explicit size, use that instead of computing from model\n\t\tif (collisionSize) {\n\t\t\tconst halfWidth = (collisionSize as any).x / 2;\n\t\t\tconst halfHeight = (collisionSize as any).y / 2;\n\t\t\tconst halfDepth = (collisionSize as any).z / 2;\n\n\t\t\tlet colliderDesc = ColliderDesc.cuboid(halfWidth, halfHeight, halfDepth);\n\t\t\tcolliderDesc.setSensor(false);\n\n\t\t\t// Use user-provided position or default to center\n\t\t\tconst posX = collisionPosition ? (collisionPosition as any).x : 0;\n\t\t\tconst posY = collisionPosition ? (collisionPosition as any).y : halfHeight;\n\t\t\tconst posZ = collisionPosition ? (collisionPosition as any).z : 0;\n\t\t\tcolliderDesc.setTranslation(posX, posY, posZ);\n\t\t\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\t\t\treturn colliderDesc;\n\t\t}\n\n\t\t// Fall back to computing from model geometry\n\t\tif (!objectModel) return this.createCapsuleCollider(options);\n\n\t\t// Find first Mesh (SkinnedMesh or regular Mesh)\n\t\tlet foundGeometry: BufferGeometry | null = null;\n\t\tobjectModel.traverse((child) => {\n\t\t\tif (!foundGeometry && (child as any).isMesh) {\n\t\t\t\tfoundGeometry = (child as Mesh).geometry as BufferGeometry;\n\t\t\t}\n\t\t});\n\n\t\tif (!foundGeometry) return this.createCapsuleCollider(options);\n\n\t\tconst geometry: BufferGeometry = foundGeometry;\n\t\tgeometry.computeBoundingBox();\n\t\tconst box = geometry.boundingBox;\n\t\tif (!box) return this.createCapsuleCollider(options);\n\n\t\tconst height = box.max.y - box.min.y;\n\t\tconst width = box.max.x - box.min.x;\n\t\tconst depth = box.max.z - box.min.z;\n\n\t\t// Create box collider based on mesh bounds\n\t\tlet colliderDesc = ColliderDesc.cuboid(width / 2, height / 2, depth / 2);\n\t\tcolliderDesc.setSensor(false);\n\t\t// Position collider at center of model\n\t\tconst centerY = (box.max.y + box.min.y) / 2;\n\t\tcolliderDesc.setTranslation(0, centerY, 0);\n\t\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\t\treturn colliderDesc;\n\t}\n}\n\nclass ActorBuilder extends EntityBuilder<ZylemActor, ZylemActorOptions> {\n\tprotected createEntity(options: Partial<ZylemActorOptions>): ZylemActor {\n\t\treturn new ZylemActor(options);\n\t}\n}\n\nexport const ACTOR_TYPE = Symbol('Actor');\n\nexport class ZylemActor extends GameEntity<ZylemActorOptions> implements EntityLoaderDelegate, DebugInfoProvider {\n\tstatic type = ACTOR_TYPE;\n\n\tprivate _object: Object3D | null = null;\n\tprivate _animationDelegate: AnimationDelegate | null = null;\n\tprivate _modelFileNames: string[] = [];\n\tprivate _assetLoader: EntityAssetLoader = new EntityAssetLoader();\n\n\tcontrolledRotation: boolean = false;\n\n\tconstructor(options?: ZylemActorOptions) {\n\t\tsuper();\n\t\tthis.options = { ...actorDefaults, ...options };\n\t\t// Add actor-specific update to the lifecycle callbacks\n\t\tthis.prependUpdate(this.actorUpdate.bind(this) as UpdateFunction<this>);\n\t\tthis.controlledRotation = true;\n\t}\n\n\t/**\n\t * Initiates model and animation loading in background (deferred).\n\t * Call returns immediately; assets will be ready on subsequent updates.\n\t */\n\tload(): void {\n\t\tthis._modelFileNames = this.options.models || [];\n\t\t// Start async loading in background\n\t\tthis.loadModelsDeferred();\n\t}\n\n\t/**\n\t * Returns current data synchronously.\n\t * May return null values if loading is still in progress.\n\t */\n\tdata(): any {\n\t\treturn {\n\t\t\tanimations: this._animationDelegate?.animations,\n\t\t\tobjectModel: this._object,\n\t\t\tcollisionShape: this.options.collisionShape,\n\t\t};\n\t}\n\n\tactorUpdate(params: UpdateContext<ZylemActorOptions>): void {\n\t\tthis._animationDelegate?.update(params.delta);\n\t}\n\n\t/**\n\t * Clean up actor resources including animations, models, and groups\n\t */\n\tactorDestroy(): void {\n\t\t// Stop and dispose animation delegate\n\t\tif (this._animationDelegate) {\n\t\t\tthis._animationDelegate.dispose();\n\t\t\tthis._animationDelegate = null;\n\t\t}\n\n\t\t// Dispose geometries and materials from loaded object\n\t\tif (this._object) {\n\t\t\tthis._object.traverse((child) => {\n\t\t\t\tif ((child as any).isMesh) {\n\t\t\t\t\tconst mesh = child as SkinnedMesh;\n\t\t\t\t\tmesh.geometry?.dispose();\n\t\t\t\t\tif (Array.isArray(mesh.material)) {\n\t\t\t\t\t\tmesh.material.forEach(m => m.dispose());\n\t\t\t\t\t} else if (mesh.material) {\n\t\t\t\t\t\tmesh.material.dispose();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tthis._object = null;\n\t\t}\n\n\t\t// Clear group reference\n\t\tif (this.group) {\n\t\t\tthis.group.clear();\n\t\t\tthis.group = null as any;\n\t\t}\n\n\t\t// Clear file name references\n\t\tthis._modelFileNames = [];\n\t}\n\n\t/**\n\t * Deferred loading - starts async load and updates entity when complete.\n\t * Called by synchronous load() method.\n\t */\n\tprivate loadModelsDeferred(): void {\n\t\tif (this._modelFileNames.length === 0) return;\n\n\t\t// Emit loading started event\n\t\tthis.dispatch('entity:model:loading', {\n\t\t\tentityId: this.uuid,\n\t\t\tfiles: this._modelFileNames\n\t\t});\n\n\t\tconst promises = this._modelFileNames.map(file => this._assetLoader.loadFile(file));\n\t\tPromise.all(promises).then(results => {\n\t\t\tif (results[0]?.object) {\n\t\t\t\tthis._object = results[0].object;\n\t\t\t}\n\t\t\t// Count meshes for the loaded event\n\t\t\tlet meshCount = 0;\n\t\t\tif (this._object) {\n\t\t\t\tthis._object.traverse((child) => {\n\t\t\t\t\tif ((child as any).isMesh) meshCount++;\n\t\t\t\t});\n\t\t\t\tthis.group = new Group();\n\t\t\t\tthis.group.attach(this._object);\n\t\t\t\tthis.group.scale.set(\n\t\t\t\t\tthis.options.scale?.x || 1,\n\t\t\t\t\tthis.options.scale?.y || 1,\n\t\t\t\t\tthis.options.scale?.z || 1\n\t\t\t\t);\n\n\t\t\t\t// Apply material overrides if specified\n\t\t\t\tthis.applyMaterialOverrides();\n\n\t\t\t\t// Load animations after model is ready\n\t\t\t\tthis._animationDelegate = new AnimationDelegate(this._object);\n\t\t\t\tthis._animationDelegate.loadAnimations(this.options.animations || []).then(() => {\n\t\t\t\t\tthis.dispatch('entity:animation:loaded', {\n\t\t\t\t\t\tentityId: this.uuid,\n\t\t\t\t\t\tanimationCount: this.options.animations?.length || 0\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Emit model loaded event\n\t\t\tthis.dispatch('entity:model:loaded', {\n\t\t\t\tentityId: this.uuid,\n\t\t\t\tsuccess: !!this._object,\n\t\t\t\tmeshCount\n\t\t\t});\n\t\t});\n\t}\n\n\tplayAnimation(animationOptions: AnimationOptions) {\n\t\tthis._animationDelegate?.playAnimation(animationOptions);\n\t}\n\n\t/**\n\t * Apply material overrides from options to all meshes in the loaded model.\n\t * Only applies if material options are explicitly specified (not just defaults).\n\t */\n\tprivate applyMaterialOverrides(): void {\n\t\tconst materialOptions = this.options.material;\n\t\t// Only apply if user specified material options beyond defaults\n\t\tif (!materialOptions || (!materialOptions.color && !materialOptions.path)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this._object) return;\n\n\t\tthis._object.traverse((child) => {\n\t\t\tif ((child as any).isMesh) {\n\t\t\t\tconst mesh = child as Mesh;\n\t\t\t\tif (materialOptions.color) {\n\t\t\t\t\t// Create new material with the specified color\n\t\t\t\t\tconst newMaterial = new MeshStandardMaterial({\n\t\t\t\t\t\tcolor: materialOptions.color,\n\t\t\t\t\t\temissiveIntensity: 0.5,\n\t\t\t\t\t\tlightMapIntensity: 0.5,\n\t\t\t\t\t\tfog: true,\n\t\t\t\t\t});\n\t\t\t\t\tmesh.castShadow = true;\n\t\t\t\t\tmesh.receiveShadow = true;\n\t\t\t\t\tmesh.material = newMaterial;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tget object(): Object3D | null {\n\t\treturn this._object;\n\t}\n\n\t/**\n\t * Provide custom debug information for the actor\n\t * This will be merged with the default debug information\n\t */\n\tgetDebugInfo(): Record<string, any> {\n\t\tconst debugInfo: Record<string, any> = {\n\t\t\ttype: 'Actor',\n\t\t\tmodels: this._modelFileNames.length > 0 ? this._modelFileNames : 'none',\n\t\t\tmodelLoaded: !!this._object,\n\t\t\tscale: this.options.scale ?\n\t\t\t\t`${this.options.scale.x}, ${this.options.scale.y}, ${this.options.scale.z}` :\n\t\t\t\t'1, 1, 1',\n\t\t};\n\n\t\t// Add animation info if available\n\t\tif (this._animationDelegate) {\n\t\t\tdebugInfo.currentAnimation = this._animationDelegate.currentAnimationKey || 'none';\n\t\t\tdebugInfo.animationsCount = this.options.animations?.length || 0;\n\t\t}\n\n\t\t// Add mesh info if model is loaded\n\t\tif (this._object) {\n\t\t\tlet meshCount = 0;\n\t\t\tlet vertexCount = 0;\n\t\t\tthis._object.traverse((child) => {\n\t\t\t\tif ((child as any).isMesh) {\n\t\t\t\t\tmeshCount++;\n\t\t\t\t\tconst geometry = (child as SkinnedMesh).geometry;\n\t\t\t\t\tif (geometry && geometry.attributes.position) {\n\t\t\t\t\t\tvertexCount += geometry.attributes.position.count;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tdebugInfo.meshCount = meshCount;\n\t\t\tdebugInfo.vertexCount = vertexCount;\n\t\t}\n\n\t\treturn debugInfo;\n\t}\n}\n\ntype ActorOptions = BaseNode | ZylemActorOptions;\n\nexport function createActor(...args: Array<ActorOptions>): ZylemActor {\n\treturn createEntity<ZylemActor, ZylemActorOptions>({\n\t\targs,\n\t\tdefaultConfig: actorDefaults,\n\t\tEntityClass: ZylemActor,\n\t\tBuilderClass: ActorBuilder,\n\t\tCollisionBuilderClass: ActorCollisionBuilder,\n\t\tentityType: ZylemActor.type\n\t});\n}","import { Mesh, Material, ShaderMaterial, Group, Color, Vector3 } from 'three';\nimport {\n\tCollider,\n\tColliderDesc,\n\tRigidBody,\n\tRigidBodyDesc,\n\tVector,\n} from '@dimforge/rapier3d-compat';\nimport { position, rotation, scale } from '../systems/transformable.system';\nimport { Vec3 } from '../core/vector';\nimport { MaterialBuilder, MaterialOptions } from '../graphics/material';\nimport { CollisionOptions } from '../collision/collision-builder';\nimport { BaseNode } from '../core/base-node';\nimport {\n\tDestroyContext,\n\tSetupContext,\n\tUpdateContext,\n\tLoadedContext,\n\tCleanupContext,\n} from '../core/base-node-life-cycle';\nimport type { EntityMeshBuilder, EntityCollisionBuilder } from './builder';\nimport { Behavior } from '../behaviors/behavior';\nimport {\n\tEventEmitterDelegate,\n\tzylemEventBus,\n\ttype EntityEvents,\n} from '../events';\nimport type {\n\tBehaviorDescriptor,\n\tBehaviorRef,\n\tBehaviorHandle,\n} from '../behaviors/behavior-descriptor';\nimport type { TransformState } from '../actions/capabilities/transform-store';\nimport { createTransformStore } from '../actions/capabilities/transform-store';\nimport { makeTransformable } from '../actions/capabilities/transformable';\nimport type { MoveableEntity } from '../actions/capabilities/moveable';\nimport type { RotatableEntityAPI } from '../actions/capabilities/rotatable';\nimport { isCollisionComponent, type CollisionComponent } from './parts/collision-factories';\nimport type { NodeInterface } from '../core/node-interface';\nimport { commonDefaults } from './common';\nimport type { Action } from '../actions/action';\n\nexport interface CollisionContext<\n\tT,\n\tO extends GameEntityOptions,\n\tTGlobals extends Record<string, unknown> = any,\n> {\n\tentity: T;\n\t// Use 'any' for other's options type to break recursive type variance issues\n\tother: GameEntity<O | any>;\n\tglobals: TGlobals;\n}\n\nexport interface CollisionDelegate<T, O extends GameEntityOptions> {\n\t// Use 'any' for entity and options types to avoid contravariance issues\n\t// with function parameters. Type safety is still enforced at the call site via onCollision()\n\tcollision?: ((params: CollisionContext<any, any>) => void)[];\n}\n\nexport type IBuilder<BuilderOptions = any> = {\n\tpreBuild: (options: BuilderOptions) => BuilderOptions;\n\tbuild: (options: BuilderOptions) => BuilderOptions;\n\tpostBuild: (options: BuilderOptions) => BuilderOptions;\n};\n\nexport type GameEntityOptions = {\n\tname?: string;\n\tcolor?: Color;\n\tsize?: Vec3;\n\tposition?: Vec3;\n\tbatched?: boolean;\n\tcollision?: Partial<CollisionOptions>;\n\tmaterial?: Partial<MaterialOptions>;\n\tcustom?: { [key: string]: any };\n\tcollisionType?: string;\n\tcollisionGroup?: string;\n\tcollisionFilter?: string[];\n\t_builders?: {\n\t\tmeshBuilder?: IBuilder | EntityMeshBuilder | null;\n\t\tcollisionBuilder?: IBuilder | EntityCollisionBuilder | null;\n\t\tmaterialBuilder?: MaterialBuilder | null;\n\t};\n};\n\nexport abstract class GameEntityLifeCycle {\n\tabstract _setup(params: SetupContext<this>): void;\n\tabstract _update(params: UpdateContext<this>): void;\n\tabstract _destroy(params: DestroyContext<this>): void;\n}\n\nexport interface EntityDebugInfo {\n\tbuildInfo: () => Record<string, string>;\n}\n\nexport class GameEntity<O extends GameEntityOptions>\n\textends BaseNode<O>\n\timplements GameEntityLifeCycle, EntityDebugInfo, MoveableEntity, RotatableEntityAPI {\n\tpublic behaviors: Behavior[] = [];\n\tpublic group: Group | undefined;\n\tpublic mesh: Mesh | undefined;\n\tpublic materials: Material[] | undefined;\n\tpublic bodyDesc: RigidBodyDesc | null = null;\n\tpublic body: RigidBody | null = null;\n\tpublic colliderDesc: ColliderDesc | undefined;\n\tpublic collider: Collider | undefined;\n\tpublic custom: Record<string, any> = {};\n\n\t// Compound entity support: multiple colliders and meshes\n\t/** All collider descriptions for this entity (including primary) */\n\tpublic colliderDescs: ColliderDesc[] = [];\n\t/** All colliders attached to this entity's rigid body */\n\tpublic colliders: Collider[] = [];\n\t/** Additional meshes for compound visual entities (added via add()) */\n\tpublic compoundMeshes: Mesh[] = [];\n\n\tpublic debugInfo: Record<string, any> = {};\n\tpublic debugMaterial: ShaderMaterial | undefined;\n\n\tpublic collisionDelegate: CollisionDelegate<this, O> = {\n\t\tcollision: [],\n\t};\n\tpublic collisionType?: string;\n\n\t// Instancing support\n\t/** Batch key for instanced rendering (null if not instanced) */\n\tpublic batchKey: string | null = null;\n\t/** Index within the instanced mesh batch */\n\tpublic instanceId: number = -1;\n\t/** Whether this entity uses instanced rendering */\n\tpublic isInstanced: boolean = false;\n\n\t// Event delegate for dispatch/listen API\n\tprotected eventDelegate = new EventEmitterDelegate<EntityEvents>();\n\n\t// Behavior references (new ECS pattern)\n\tprivate behaviorRefs: BehaviorRef[] = [];\n\n\t// Transform store for batched physics updates (auto-created in create())\n\tpublic transformStore: TransformState;\n\n\t// Movement & rotation methods are assigned at runtime by makeTransformable.\n\t// The `implements` clause above ensures the type contract; declarations below\n\t// satisfy the compiler while the constructor fills them in.\n\tmoveX!: (delta: number) => void;\n\tmoveY!: (delta: number) => void;\n\tmoveZ!: (delta: number) => void;\n\tmoveXY!: (deltaX: number, deltaY: number) => void;\n\tmoveXZ!: (deltaX: number, deltaZ: number) => void;\n\tmove!: (vector: Vector3) => void;\n\tresetVelocity!: () => void;\n\tmoveForwardXY!: (delta: number, rotation2DAngle: number) => void;\n\tgetPosition!: () => Vector | null;\n\tgetVelocity!: () => Vector | null;\n\tsetPosition!: (x: number, y: number, z: number) => void;\n\tsetPositionX!: (x: number) => void;\n\tsetPositionY!: (y: number) => void;\n\tsetPositionZ!: (z: number) => void;\n\twrapAroundXY!: (boundsX: number, boundsY: number) => void;\n\twrapAround3D!: (boundsX: number, boundsY: number, boundsZ: number) => void;\n\trotateInDirection!: (moveVector: Vector3) => void;\n\trotateYEuler!: (amount: number) => void;\n\trotateEuler!: (eulerRotation: Vector3) => void;\n\trotateX!: (delta: number) => void;\n\trotateY!: (delta: number) => void;\n\trotateZ!: (delta: number) => void;\n\tsetRotationY!: (y: number) => void;\n\tsetRotationX!: (x: number) => void;\n\tsetRotationZ!: (z: number) => void;\n\tsetRotationDegrees!: (x: number, y: number, z: number) => void;\n\tsetRotationDegreesY!: (y: number) => void;\n\tsetRotationDegreesX!: (x: number) => void;\n\tsetRotationDegreesZ!: (z: number) => void;\n\tsetRotation!: (x: number, y: number, z: number) => void;\n\tgetRotation!: () => any;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.transformStore = createTransformStore();\n\t\tmakeTransformable(this);\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Composable add() - accepts Mesh, CollisionComponent, or child entities\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add meshes, collision components, or child entities to this entity.\n\t * Supports fluent chaining: `entity.add(boxMesh()).add(boxCollision())`.\n\t *\n\t * - `Mesh`: First mesh becomes the primary mesh; subsequent meshes are\n\t * compound meshes grouped together.\n\t * - `CollisionComponent`: First sets bodyDesc + colliderDesc; subsequent\n\t * add extra colliders to the same rigid body.\n\t * - `NodeInterface`: Added as a child entity (delegates to BaseNode.add).\n\t */\n\tpublic add(...components: Array<NodeInterface | Mesh | CollisionComponent>): this {\n\t\tfor (const component of components) {\n\t\t\tif (component instanceof Mesh) {\n\t\t\t\tthis.addMeshComponent(component);\n\t\t\t} else if (isCollisionComponent(component)) {\n\t\t\t\tthis.addCollisionComponent(component);\n\t\t\t} else {\n\t\t\t\tsuper.add(component as NodeInterface);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tprivate addMeshComponent(mesh: Mesh): void {\n\t\tif (!this.mesh) {\n\t\t\t// First mesh becomes the primary mesh\n\t\t\tthis.mesh = mesh;\n\t\t\tif (!this.materials) {\n\t\t\t\tthis.materials = [];\n\t\t\t}\n\t\t\tif (mesh.material) {\n\t\t\t\tconst mat = mesh.material;\n\t\t\t\tif (Array.isArray(mat)) {\n\t\t\t\t\tthis.materials.push(...mat);\n\t\t\t\t} else {\n\t\t\t\t\tthis.materials.push(mat);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Subsequent meshes are compound meshes\n\t\t\tthis.compoundMeshes.push(mesh);\n\t\t\t// Ensure the entity has a group so all meshes are parented together\n\t\t\tif (!this.group) {\n\t\t\t\tthis.group = new Group();\n\t\t\t\tthis.group.add(this.mesh);\n\t\t\t}\n\t\t\tthis.group.add(mesh);\n\t\t}\n\t}\n\n\tprivate addCollisionComponent(collision: CollisionComponent): void {\n\t\tif (!this.bodyDesc) {\n\t\t\t// First collision sets the body description and primary collider\n\t\t\tthis.bodyDesc = collision.bodyDesc;\n\t\t\tthis.colliderDesc = collision.colliderDesc;\n\t\t\tthis.colliderDescs.push(collision.colliderDesc);\n\t\t\t// Apply entity position to the body\n\t\t\tconst pos = this.options?.position ?? { x: 0, y: 0, z: 0 };\n\t\t\tthis.bodyDesc.setTranslation(pos.x, pos.y, pos.z);\n\t\t} else {\n\t\t\t// Subsequent collisions add extra colliders to the same body\n\t\t\tthis.colliderDescs.push(collision.colliderDesc);\n\t\t}\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Actions API -- entity-scoped, self-contained stateful actions\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tprivate _actions: Action[] = [];\n\n\t/**\n\t * Run a fire-and-forget action. Auto-removed when done.\n\t * @example `me.runAction(moveBy({ x: 10, duration: 0.3 }))`\n\t */\n\tpublic runAction<A extends Action>(action: A): A {\n\t\tthis._actions.push(action);\n\t\treturn action;\n\t}\n\n\t/**\n\t * Register a persistent action (throttle, onPress). Not removed when done.\n\t * @example `const press = entity.action(onPress())`\n\t */\n\tpublic action<A extends Action>(action: A): A {\n\t\taction.persistent = true;\n\t\tthis._actions.push(action);\n\t\treturn action;\n\t}\n\n\t/**\n\t * Tick all registered actions. Called automatically before user onUpdate callbacks.\n\t *\n\t * Resets velocity/angularVelocity accumulation before ticking so that\n\t * actions can compose via `+=` without cross-frame build-up.\n\t * (The existing move helpers like `moveXY` use `=` which doesn't accumulate,\n\t * but action composition needs additive writes on a clean slate each frame.)\n\t */\n\tpublic _tickActions(delta: number): void {\n\t\tif (this._actions.length === 0) return;\n\n\t\t// Clear accumulation from the previous frame so that\n\t\t// actions can compose via `+=` on a clean slate each frame.\n\t\tconst store = this.transformStore;\n\t\tstore.velocity.x = 0;\n\t\tstore.velocity.y = 0;\n\t\tstore.velocity.z = 0;\n\t\tstore.dirty.velocity = false;\n\t\tstore.angularVelocity.x = 0;\n\t\tstore.angularVelocity.y = 0;\n\t\tstore.angularVelocity.z = 0;\n\t\tstore.dirty.angularVelocity = false;\n\n\t\tfor (let i = this._actions.length - 1; i >= 0; i--) {\n\t\t\tconst act = this._actions[i];\n\t\t\tact.tick(this, delta);\n\t\t\tif (act.done && !act.persistent) {\n\t\t\t\tthis._actions.splice(i, 1);\n\t\t\t}\n\t\t}\n\n\t\t// If every non-persistent action finished this frame, zero out\n\t\t// any velocity they wrote so the entity doesn't drift.\n\t\tif (this._actions.length === 0) {\n\t\t\tstore.velocity.x = 0;\n\t\t\tstore.velocity.y = 0;\n\t\t\tstore.velocity.z = 0;\n\t\t\tstore.dirty.velocity = false;\n\t\t\tstore.angularVelocity.x = 0;\n\t\t\tstore.angularVelocity.y = 0;\n\t\t\tstore.angularVelocity.z = 0;\n\t\t\tstore.dirty.angularVelocity = false;\n\t\t}\n\t}\n\n\tpublic create(): this {\n\t\tconst { position: setupPosition } = this.options;\n\t\tconst { x, y, z } = setupPosition || { x: 0, y: 0, z: 0 };\n\t\tthis.behaviors = [\n\t\t\t{ component: position, values: { x, y, z } },\n\t\t\t{ component: scale, values: { x: 0, y: 0, z: 0 } },\n\t\t\t{ component: rotation, values: { x: 0, y: 0, z: 0, w: 0 } },\n\t\t];\n\t\tthis.name = this.options.name || '';\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add collision callbacks\n\t */\n\tpublic onCollision(\n\t\t...callbacks: ((params: CollisionContext<this, O>) => void)[]\n\t): this {\n\t\tconst existing = this.collisionDelegate.collision ?? [];\n\t\tthis.collisionDelegate.collision = [...existing, ...callbacks];\n\t\treturn this;\n\t}\n\n\t/**\n\t * Use a behavior on this entity via typed descriptor.\n\t * Behaviors will be auto-registered as systems when the entity is spawned.\n\t * @param descriptor The behavior descriptor (import from behaviors module)\n\t * @param options Optional overrides for the behavior's default options\n\t * @returns BehaviorHandle with behavior-specific methods for lazy FSM access\n\t */\n\tpublic use<\n\t\tO extends Record<string, any>,\n\t\tH extends Record<string, any> = Record<string, never>,\n\t>(\n\t\tdescriptor: BehaviorDescriptor<O, H>,\n\t\toptions?: Partial<O>,\n\t): BehaviorHandle<O, H> {\n\t\tconst behaviorRef: BehaviorRef<O> = {\n\t\t\tdescriptor: descriptor as BehaviorDescriptor<O, any>,\n\t\t\toptions: { ...descriptor.defaultOptions, ...options } as O,\n\t\t};\n\t\tthis.behaviorRefs.push(behaviorRef as BehaviorRef<any>);\n\n\t\t// Create base handle\n\t\tconst baseHandle = {\n\t\t\tgetFSM: () => behaviorRef.fsm ?? null,\n\t\t\tgetOptions: () => behaviorRef.options,\n\t\t\tref: behaviorRef,\n\t\t};\n\n\t\t// Merge behavior-specific methods if createHandle is provided\n\t\tconst customMethods = descriptor.createHandle?.(behaviorRef) ?? ({} as H);\n\n\t\treturn {\n\t\t\t...baseHandle,\n\t\t\t...customMethods,\n\t\t} as BehaviorHandle<O, H>;\n\t}\n\n\t/**\n\t * Get all behavior references attached to this entity.\n\t * Used by the stage to auto-register required systems.\n\t */\n\tpublic getBehaviorRefs(): BehaviorRef[] {\n\t\treturn this.behaviorRefs;\n\t}\n\n\t/**\n\t * Entity-specific setup - resets actions for a fresh stage session.\n\t * (User callbacks are handled by BaseNode's lifecycleCallbacks.setup)\n\t */\n\tpublic _setup(params: SetupContext<this>): void {\n\t\t// Reset actions for the new stage session.\n\t\t// Remove completed fire-and-forget actions; reset all others\n\t\t// so they replay from the beginning.\n\t\tfor (let i = this._actions.length - 1; i >= 0; i--) {\n\t\t\tconst act = this._actions[i];\n\t\t\tif (act.done && !act.persistent) {\n\t\t\t\tthis._actions.splice(i, 1);\n\t\t\t} else {\n\t\t\t\tact.reset();\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected async _loaded(_params: LoadedContext<this>): Promise<void> { }\n\n\t/**\n\t * Entity-specific update - updates materials.\n\t * Transform changes are applied by the stage after all update callbacks complete.\n\t * (User callbacks are handled by BaseNode's lifecycleCallbacks.update)\n\t */\n\tpublic _update(params: UpdateContext<this>): void {\n\t\tthis.updateMaterials(params);\n\t}\n\n\t/**\n\t * Entity-specific destroy -- reserved for consumer game logic.\n\t * Engine-internal resource disposal runs in _cleanup() instead.\n\t */\n\tpublic _destroy(params: DestroyContext<this>): void { }\n\n\t/**\n\t * Engine-internal resource cleanup -- runs automatically after destroy.\n\t * Disposes GPU/DOM resources (meshes, materials, debug material).\n\t *\n\t * Note: actions, collision callbacks, and behavior refs are intentionally\n\t * NOT cleared here -- they are registered by consumer code at module level\n\t * and must persist across stage reloads. Actions are reset in _setup().\n\t */\n\tprotected _cleanup(_params: CleanupContext<this>): void {\n\t\t// Dispose entity event emitter & subscriptions\n\t\tthis.disposeEvents();\n\n\t\t// Dispose compound meshes\n\t\tfor (const m of this.compoundMeshes) {\n\t\t\tm.geometry?.dispose();\n\t\t\tif (Array.isArray(m.material)) {\n\t\t\t\tm.material.forEach(mat => mat.dispose());\n\t\t\t} else {\n\t\t\t\tm.material?.dispose();\n\t\t\t}\n\t\t}\n\t\tthis.compoundMeshes.length = 0;\n\n\t\t// Dispose debug material\n\t\tthis.debugMaterial?.dispose();\n\t\tthis.debugMaterial = undefined;\n\n\t\t// Remove group from parent (camera or scene)\n\t\tthis.group?.removeFromParent();\n\n\t\t// Note: physics references (body, collider, colliders) are intentionally\n\t\t// NOT nulled here. They are needed by removeEntityByUuid() → world.destroyEntity()\n\t\t// which runs later when the stage processes markedForRemoval entities.\n\t}\n\n\tpublic _collision(other: GameEntity<O>, globals?: any): void {\n\t\tif (this.collisionDelegate.collision?.length) {\n\t\t\tconst callbacks = this.collisionDelegate.collision;\n\t\t\tcallbacks.forEach((callback) => {\n\t\t\t\tcallback({ entity: this, other, globals });\n\t\t\t});\n\t\t}\n\t}\n\n\tprotected updateMaterials(params: any) {\n\t\tif (!this.materials?.length) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const material of this.materials) {\n\t\t\tif (material instanceof ShaderMaterial) {\n\t\t\t\tif (material.uniforms) {\n\t\t\t\t\tmaterial.uniforms.iTime &&\n\t\t\t\t\t\t(material.uniforms.iTime.value += params.delta);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic buildInfo(): Record<string, string> {\n\t\tconst info: Record<string, string> = {};\n\t\tinfo.name = this.name;\n\t\tinfo.uuid = this.uuid;\n\t\tinfo.eid = this.eid.toString();\n\t\treturn info;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Events API\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Dispatch an event from this entity.\n\t * Events are emitted both locally and to the global event bus.\n\t */\n\tdispatch<K extends keyof EntityEvents>(\n\t\tevent: K,\n\t\tpayload: EntityEvents[K],\n\t): void {\n\t\tthis.eventDelegate.dispatch(event, payload);\n\t\t(zylemEventBus as any).emit(event, payload);\n\t}\n\n\t/**\n\t * Listen for events on this entity instance.\n\t * @returns Unsubscribe function\n\t */\n\tlisten<K extends keyof EntityEvents>(\n\t\tevent: K,\n\t\thandler: (payload: EntityEvents[K]) => void,\n\t): () => void {\n\t\treturn this.eventDelegate.listen(event, handler);\n\t}\n\n\t/**\n\t * Clean up entity event subscriptions.\n\t */\n\tdisposeEvents(): void {\n\t\tthis.eventDelegate.dispose();\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bare entity factory\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Create a bare entity with no mesh or collision.\n * Use `.add(boxMesh(), boxCollision())` to compose its shape.\n *\n * @example\n * ```ts\n * const box = create({ position: { x: 0, y: 5, z: 0 } })\n * .add(boxMesh({ size: { x: 2, y: 2, z: 2 } }))\n * .add(boxCollision({ size: { x: 2, y: 2, z: 2 } }));\n * ```\n */\nexport function create(options?: Partial<GameEntityOptions>): GameEntity<GameEntityOptions> {\n\tconst entity = new (GameEntity as any)() as GameEntity<GameEntityOptions>;\n\tentity.options = { ...commonDefaults, ...options } as GameEntityOptions;\n\treturn entity;\n}\n","import {\n\tdefineSystem,\n\tdefineQuery,\n\tdefineComponent,\n\tTypes,\n\tremoveQuery,\n\ttype IWorld,\n} from 'bitecs';\nimport { Quaternion } from 'three';\nimport { StageEntity } from '../interfaces/entity';\nimport RAPIER from '@dimforge/rapier3d-compat';\n\nexport type StageSystem = {\n\t_childrenMap: Map<number, StageEntity & { body: RAPIER.RigidBody }>;\n}\n\nexport const position = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32\n});\n\nexport const rotation = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32,\n\tw: Types.f32\n});\n\nexport const scale = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32\n});\n\n// Reusable quaternion to avoid allocations per frame\nconst _tempQuaternion = new Quaternion();\n\nexport type TransformSystemResult = {\n\tsystem: ReturnType<typeof defineSystem>;\n\tdestroy: (world: IWorld) => void;\n};\n\nexport default function createTransformSystem(stage: StageSystem): TransformSystemResult {\n\tconst queryTerms = [position, rotation];\n\tconst transformQuery = defineQuery(queryTerms);\n\tconst stageEntities = stage._childrenMap;\n\n\tconst system = defineSystem((world) => {\n\t\tconst entities = transformQuery(world);\n\t\tif (stageEntities === undefined) {\n\t\t\treturn world;\n\t\t}\n\n\t\tfor (const [key, stageEntity] of stageEntities) {\n\t\t\t// Early bailout - combine conditions\n\t\t\tif (!stageEntity?.body || stageEntity.markedForRemoval) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst id = entities[key];\n\t\t\tconst body = stageEntity.body;\n\t\t\tconst target = stageEntity.group ?? stageEntity.mesh;\n\n\t\t\t// Position sync\n\t\t\tconst translation = body.translation();\n\t\t\tposition.x[id] = translation.x;\n\t\t\tposition.y[id] = translation.y;\n\t\t\tposition.z[id] = translation.z;\n\n\t\t\tif (target) {\n\t\t\t\ttarget.position.set(translation.x, translation.y, translation.z);\n\t\t\t}\n\n\t\t\t// Skip rotation if controlled externally\n\t\t\tif (stageEntity.controlledRotation) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Rotation sync - reuse quaternion\n\t\t\tconst rot = body.rotation();\n\t\t\trotation.x[id] = rot.x;\n\t\t\trotation.y[id] = rot.y;\n\t\t\trotation.z[id] = rot.z;\n\t\t\trotation.w[id] = rot.w;\n\n\t\t\tif (target) {\n\t\t\t\t_tempQuaternion.set(rot.x, rot.y, rot.z, rot.w);\n\t\t\t\ttarget.setRotationFromQuaternion(_tempQuaternion);\n\t\t\t}\n\t\t}\n\n\t\treturn world;\n\t});\n\n\tconst destroy = (world: IWorld) => {\n\t\t// Remove the query from bitecs world tracking\n\t\tremoveQuery(world, transformQuery);\n\t};\n\n\treturn { system, destroy };\n}","/** Vite build flags */\nexport const DEBUG_FLAG = import.meta.env.VITE_DEBUG_FLAG === 'true';","import {\n\tCleanupContext,\n\tCleanupFunction,\n\tDestroyContext,\n\tDestroyFunction,\n\tLoadedContext,\n\tLoadedFunction,\n\tSetupContext,\n\tSetupFunction,\n\tUpdateContext,\n\tUpdateFunction,\n} from \"./base-node-life-cycle\";\nimport { DEBUG_FLAG } from \"./flags\";\nimport { nanoid } from \"nanoid\";\nimport { NodeInterface } from \"./node-interface\";\n\nexport type BaseNodeOptions<T = any> = BaseNode | Partial<T>;\n\n/**\n * Lifecycle callback arrays - each lifecycle event can have multiple callbacks\n * that execute in order.\n */\nexport interface LifecycleCallbacks<T> {\n\tsetup: Array<SetupFunction<T>>;\n\tloaded: Array<LoadedFunction<T>>;\n\tupdate: Array<UpdateFunction<T>>;\n\tdestroy: Array<DestroyFunction<T>>;\n\tcleanup: Array<CleanupFunction<T>>;\n}\n\nexport abstract class BaseNode<Options = any, T = any> implements NodeInterface {\n\tprotected parent: NodeInterface | null = null;\n\tprotected children: NodeInterface[] = [];\n\tpublic options: Options;\n\tpublic eid: number = 0;\n\tpublic uuid: string = '';\n\tpublic name: string = '';\n\tpublic markedForRemoval: boolean = false;\n\n\t/**\n\t * Lifecycle callback arrays - use onSetup(), onUpdate(), etc. to add callbacks\n\t * Uses `any` for the type parameter to avoid invariance issues when subclasses\n\t * are assigned to BaseNode references. Type safety is enforced by the public\n\t * onSetup/onUpdate/etc. methods which are typed with `this`.\n\t */\n\tprotected lifecycleCallbacks: LifecycleCallbacks<any> = {\n\t\tsetup: [],\n\t\tloaded: [],\n\t\tupdate: [],\n\t\tdestroy: [],\n\t\tcleanup: [],\n\t};\n\n\tconstructor(args: BaseNodeOptions[] = []) {\n\t\tconst options = args\n\t\t\t.filter(arg => !(arg instanceof BaseNode))\n\t\t\t.reduce((acc, opt) => ({ ...acc, ...opt }), {});\n\t\tthis.options = options as Options;\n\t\tthis.uuid = nanoid();\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Fluent API for adding lifecycle callbacks\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add setup callbacks to be executed in order during nodeSetup\n\t */\n\tpublic onSetup(...callbacks: Array<SetupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.setup.push(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add loaded callbacks to be executed in order during nodeLoaded\n\t */\n\tpublic onLoaded(...callbacks: Array<LoadedFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.loaded.push(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add update callbacks to be executed in order during nodeUpdate\n\t */\n\tpublic onUpdate(...callbacks: Array<UpdateFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.update.push(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add destroy callbacks to be executed in order during nodeDestroy\n\t */\n\tpublic onDestroy(...callbacks: Array<DestroyFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.destroy.push(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add cleanup callbacks to be executed in order during nodeCleanup\n\t */\n\tpublic onCleanup(...callbacks: Array<CleanupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.cleanup.push(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Prepend setup callbacks (run before existing ones)\n\t */\n\tpublic prependSetup(...callbacks: Array<SetupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.setup.unshift(...callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Prepend update callbacks (run before existing ones)\n\t */\n\tpublic prependUpdate(...callbacks: Array<UpdateFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.update.unshift(...callbacks);\n\t\treturn this;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Tree structure\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic setParent(parent: NodeInterface | null): void {\n\t\tthis.parent = parent;\n\t}\n\n\tpublic getParent(): NodeInterface | null {\n\t\treturn this.parent;\n\t}\n\n\tpublic add(baseNode: NodeInterface): void {\n\t\tthis.children.push(baseNode);\n\t\tbaseNode.setParent(this);\n\t}\n\n\tpublic remove(baseNode: NodeInterface): void {\n\t\tconst index = this.children.indexOf(baseNode);\n\t\tif (index !== -1) {\n\t\t\tthis.children.splice(index, 1);\n\t\t\tbaseNode.setParent(null);\n\t\t}\n\t}\n\n\tpublic getChildren(): NodeInterface[] {\n\t\treturn this.children;\n\t}\n\n\tpublic isComposite(): boolean {\n\t\treturn this.children.length > 0;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Abstract methods for subclass implementation\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic abstract create(): T;\n\n\tprotected abstract _setup(params: SetupContext<this>): void;\n\n\tprotected abstract _loaded(params: LoadedContext<this>): Promise<void>;\n\n\tprotected abstract _update(params: UpdateContext<this>): void;\n\n\tprotected abstract _destroy(params: DestroyContext<this>): void;\n\n\tprotected abstract _cleanup(params: CleanupContext<this>): void;\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Node lifecycle execution - runs internal + callback arrays\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic nodeSetup(params: SetupContext<this>) {\n\t\tif (DEBUG_FLAG) { /** */ }\n\t\tthis.markedForRemoval = false;\n\t\tif (typeof this._setup === 'function') {\n\t\t\tthis._setup(params);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.setup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tthis.children.forEach(child => child.nodeSetup(params));\n\t}\n\n\tpublic nodeUpdate(params: UpdateContext<this>): void {\n\t\tif (this.markedForRemoval) {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof this._update === 'function') {\n\t\t\tthis._update(params);\n\t\t}\n\t\t// Tick entity actions before user callbacks so state is fresh\n\t\tif (typeof (this as any)._tickActions === 'function') {\n\t\t\t(this as any)._tickActions(params.delta);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.update) {\n\t\t\tcallback(params);\n\t\t}\n\t\tthis.children.forEach(child => child.nodeUpdate(params));\n\t}\n\n\tpublic nodeDestroy(params: DestroyContext<this>): void {\n\t\t// Guard against re-entry (e.g. destroy called twice during collision loop)\n\t\tif (this.markedForRemoval) return;\n\n\t\tthis.children.forEach(child => child.nodeDestroy(params));\n\n\t\t// Destroy phase -- consumer game logic (onDestroy callbacks + _destroy override)\n\t\tfor (const callback of this.lifecycleCallbacks.destroy) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._destroy === 'function') {\n\t\t\tthis._destroy(params);\n\t\t}\n\t\tthis.markedForRemoval = true;\n\n\t\t// Cleanup phase -- engine-internal resource disposal (onCleanup callbacks + _cleanup override)\n\t\tfor (const callback of this.lifecycleCallbacks.cleanup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._cleanup === 'function') {\n\t\t\tthis._cleanup(params);\n\t\t}\n\t}\n\n\tpublic async nodeLoaded(params: LoadedContext<this>): Promise<void> {\n\t\tif (typeof this._loaded === 'function') {\n\t\t\tawait this._loaded(params);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.loaded) {\n\t\t\tcallback(params);\n\t\t}\n\t}\n\n\tpublic nodeCleanup(params: CleanupContext<this>): void {\n\t\tthis.children.forEach(child => (child as any).nodeCleanup?.(params));\n\t\tfor (const callback of this.lifecycleCallbacks.cleanup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._cleanup === 'function') {\n\t\t\tthis._cleanup(params);\n\t\t}\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Options\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic getOptions(): Options {\n\t\treturn this.options;\n\t}\n\n\tpublic setOptions(options: Partial<Options>): void {\n\t\tthis.options = { ...this.options, ...options };\n\t}\n}","export type EventType = string | symbol;\n\n// An event handler can take an optional event argument\n// and should not return a value\nexport type Handler<T = unknown> = (event: T) => void;\nexport type WildcardHandler<T = Record<string, unknown>> = (\n\ttype: keyof T,\n\tevent: T[keyof T]\n) => void;\n\n// An array of all currently registered event handlers for a type\nexport type EventHandlerList<T = unknown> = Array<Handler<T>>;\nexport type WildCardEventHandlerList<T = Record<string, unknown>> = Array<\n\tWildcardHandler<T>\n>;\n\n// A map of event types and their corresponding event handlers.\nexport type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<\n\tkeyof Events | '*',\n\tEventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>\n>;\n\nexport interface Emitter<Events extends Record<EventType, unknown>> {\n\tall: EventHandlerMap<Events>;\n\n\ton<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;\n\ton(type: '*', handler: WildcardHandler<Events>): void;\n\n\toff<Key extends keyof Events>(\n\t\ttype: Key,\n\t\thandler?: Handler<Events[Key]>\n\t): void;\n\toff(type: '*', handler: WildcardHandler<Events>): void;\n\n\temit<Key extends keyof Events>(type: Key, event: Events[Key]): void;\n\temit<Key extends keyof Events>(\n\t\ttype: undefined extends Events[Key] ? Key : never\n\t): void;\n}\n\n/**\n * Mitt: Tiny (~200b) functional event emitter / pubsub.\n * @name mitt\n * @returns {Mitt}\n */\nexport default function mitt<Events extends Record<EventType, unknown>>(\n\tall?: EventHandlerMap<Events>\n): Emitter<Events> {\n\ttype GenericEventHandler =\n\t\t| Handler<Events[keyof Events]>\n\t\t| WildcardHandler<Events>;\n\tall = all || new Map();\n\n\treturn {\n\t\t/**\n\t\t * A Map of event names to registered handler functions.\n\t\t */\n\t\tall,\n\n\t\t/**\n\t\t * Register an event handler for the given type.\n\t\t * @param {string|symbol} type Type of event to listen for, or `'*'` for all events\n\t\t * @param {Function} handler Function to call in response to given event\n\t\t * @memberOf mitt\n\t\t */\n\t\ton<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\thandlers.push(handler);\n\t\t\t} else {\n\t\t\t\tall!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove an event handler for the given type.\n\t\t * If `handler` is omitted, all handlers of the given type are removed.\n\t\t * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)\n\t\t * @param {Function} [handler] Handler function to remove\n\t\t * @memberOf mitt\n\t\t */\n\t\toff<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\tif (handler) {\n\t\t\t\t\thandlers.splice(handlers.indexOf(handler) >>> 0, 1);\n\t\t\t\t} else {\n\t\t\t\t\tall!.set(type, []);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Invoke all handlers for the given type.\n\t\t * If present, `'*'` handlers are invoked after type-matched handlers.\n\t\t *\n\t\t * Note: Manually firing '*' handlers is not supported.\n\t\t *\n\t\t * @param {string|symbol} type The event type to invoke\n\t\t * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler\n\t\t * @memberOf mitt\n\t\t */\n\t\temit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {\n\t\t\tlet handlers = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as EventHandlerList<Events[keyof Events]>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(evt!);\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\thandlers = all!.get('*');\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as WildCardEventHandlerList<Events>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(type, evt!);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n","import mitt, { Emitter } from 'mitt';\n\n/**\n * Event scope identifier for routing events.\n */\nexport type EventScope = 'game' | 'stage' | 'entity';\n\n/**\n * Reusable delegate for event emission and subscription.\n * Use via composition in Game, Stage, and Entity classes.\n * \n * @example\n * class Game {\n * private eventDelegate = new EventEmitterDelegate<GameEvents>();\n * \n * dispatch<K extends keyof GameEvents>(event: K, payload: GameEvents[K]) {\n * this.eventDelegate.dispatch(event, payload);\n * }\n * }\n */\nexport class EventEmitterDelegate<TEvents extends Record<string, unknown>> {\n\tprivate emitter: Emitter<TEvents>;\n\tprivate unsubscribes: (() => void)[] = [];\n\n\tconstructor() {\n\t\tthis.emitter = mitt<TEvents>();\n\t}\n\n\t/**\n\t * Dispatch an event to all listeners.\n\t */\n\tdispatch<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n\t\tthis.emitter.emit(event, payload);\n\t}\n\n\t/**\n\t * Subscribe to an event. Returns an unsubscribe function.\n\t */\n\tlisten<K extends keyof TEvents>(\n\t\tevent: K,\n\t\thandler: (payload: TEvents[K]) => void\n\t): () => void {\n\t\tthis.emitter.on(event, handler);\n\t\tconst unsub = () => this.emitter.off(event, handler);\n\t\tthis.unsubscribes.push(unsub);\n\t\treturn unsub;\n\t}\n\n\t/**\n\t * Subscribe to all events.\n\t */\n\tlistenAll(handler: (type: keyof TEvents, payload: TEvents[keyof TEvents]) => void): () => void {\n\t\tthis.emitter.on('*', handler as any);\n\t\tconst unsub = () => this.emitter.off('*', handler as any);\n\t\tthis.unsubscribes.push(unsub);\n\t\treturn unsub;\n\t}\n\n\t/**\n\t * Clean up all subscriptions.\n\t */\n\tdispose(): void {\n\t\tthis.unsubscribes.forEach(fn => fn());\n\t\tthis.unsubscribes = [];\n\t\tthis.emitter.all.clear();\n\t}\n}\n","import mitt from 'mitt';\nimport type { LoadingEvent } from '../core/interfaces';\n\n/**\n * Payload for game loading events with stage context.\n */\nexport interface GameLoadingPayload extends LoadingEvent {\n\tstageName?: string;\n\tstageIndex?: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Game Events\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Payload for stage configuration sent to editor. */\nexport interface StageConfigPayload {\n\tid: string;\n\tbackgroundColor: string;\n\tbackgroundImage: string | null;\n\tgravity: { x: number; y: number; z: number };\n\tinputs: Record<string, string[]>;\n\tvariables: Record<string, unknown>;\n}\n\n/** Payload for entity configuration sent to editor. */\nexport interface EntityConfigPayload {\n\tuuid: string;\n\tname: string;\n\ttype: string;\n\tposition: { x: number; y: number; z: number };\n\trotation: { x: number; y: number; z: number };\n\tscale: { x: number; y: number; z: number };\n}\n\n/** Payload for state dispatch events from game to editor. */\nexport interface StateDispatchPayload {\n\tscope: 'game' | 'stage' | 'entity';\n\tpath: string;\n\tvalue: unknown;\n\tpreviousValue?: unknown;\n\tconfig?: {\n\t\tid: string;\n\t\taspectRatio: number;\n\t\tfullscreen: boolean;\n\t\tbodyBackground: string | undefined;\n\t\tinternalResolution: { width: number; height: number } | undefined;\n\t\tdebug: boolean;\n\t} | null;\n\tstageConfig?: StageConfigPayload | null;\n\tentities?: EntityConfigPayload[] | null;\n}\n\nexport type GameEvents = {\n\t'loading:start': GameLoadingPayload;\n\t'loading:progress': GameLoadingPayload;\n\t'loading:complete': GameLoadingPayload;\n\t'paused': { paused: boolean };\n\t'debug': { enabled: boolean };\n\t'state:dispatch': StateDispatchPayload;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stage Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type StageEvents = {\n\t'stage:loaded': { stageId: string };\n\t'stage:unloaded': { stageId: string };\n\t'stage:variable:changed': { key: string; value: unknown };\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Entity Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type EntityEvents = {\n\t'entity:spawned': { entityId: string; name: string };\n\t'entity:destroyed': { entityId: string };\n\t'entity:collision': { entityId: string; otherId: string };\n\t'entity:model:loading': { entityId: string; files: string[] };\n\t'entity:model:loaded': { entityId: string; success: boolean; meshCount?: number };\n\t'entity:animation:loaded': { entityId: string; animationCount: number };\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Combined Event Map\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type ZylemEvents = GameEvents & StageEvents & EntityEvents;\n\n/**\n * Global event bus for cross-package communication.\n * \n * Usage:\n * ```ts\n * import { zylemEventBus } from '@zylem/game-lib';\n * \n * // Subscribe\n * const unsub = zylemEventBus.on('loading:progress', (e) => console.log(e));\n * \n * // Emit\n * zylemEventBus.emit('loading:progress', { type: 'progress', progress: 0.5 });\n * \n * // Cleanup\n * unsub();\n * ```\n */\nexport const zylemEventBus = mitt<ZylemEvents>();\n","import { proxy } from 'valtio';\n\n/**\n * Transform state managed by Valtio for batched physics updates.\n * \n * This store accumulates transformation intents during the frame,\n * then applies them all at once after onUpdate() callbacks complete.\n * \n * Design decisions:\n * - Position: Accumulated deltas (additive)\n * - Rotation: Last value wins (replacement)\n * - Velocity: Accumulated deltas (additive)\n * - Angular velocity: Accumulated deltas (additive)\n */\nexport interface TransformState {\n\t/** Position deltas to be applied (accumulated) */\n\tposition: { x: number; y: number; z: number };\n\t\n\t/** Rotation quaternion (last value wins) */\n\trotation: { x: number; y: number; z: number; w: number };\n\t\n\t/** Linear velocity (accumulated) */\n\tvelocity: { x: number; y: number; z: number };\n\t\n\t/** Angular velocity (accumulated) */\n\tangularVelocity: { x: number; y: number; z: number };\n\t\n\t/** Dirty flags to track what needs to be applied */\n\tdirty: {\n\t\tposition: boolean;\n\t\trotation: boolean;\n\t\tvelocity: boolean;\n\t\tangularVelocity: boolean;\n\t};\n}\n\n/**\n * Create a new transform store with optional initial values.\n * The store is a Valtio proxy, making it reactive for debugging/visualization.\n * \n * @param initial Optional initial state values\n * @returns Reactive transform state\n */\nexport function createTransformStore(initial?: Partial<TransformState>): TransformState {\n\tconst defaultState: TransformState = {\n\t\tposition: { x: 0, y: 0, z: 0 },\n\t\trotation: { x: 0, y: 0, z: 0, w: 1 },\n\t\tvelocity: { x: 0, y: 0, z: 0 },\n\t\tangularVelocity: { x: 0, y: 0, z: 0 },\n\t\tdirty: {\n\t\t\tposition: false,\n\t\t\trotation: false,\n\t\t\tvelocity: false,\n\t\t\tangularVelocity: false,\n\t\t},\n\t};\n\n\treturn proxy({\n\t\t...defaultState,\n\t\t...initial,\n\t\t// Ensure dirty flags are properly initialized even if partial initial state\n\t\tdirty: {\n\t\t\t...defaultState.dirty,\n\t\t\t...initial?.dirty,\n\t\t},\n\t});\n}\n\n/**\n * Reset a transform store to its initial clean state.\n * Called after applying changes to prepare for the next frame.\n * \n * @param store The transform store to reset\n */\nexport function resetTransformStore(store: TransformState): void {\n\t// Reset position deltas\n\tstore.position.x = 0;\n\tstore.position.y = 0;\n\tstore.position.z = 0;\n\n\t// Reset rotation to identity quaternion\n\tstore.rotation.x = 0;\n\tstore.rotation.y = 0;\n\tstore.rotation.z = 0;\n\tstore.rotation.w = 1;\n\n\t// Reset velocity\n\tstore.velocity.x = 0;\n\tstore.velocity.y = 0;\n\tstore.velocity.z = 0;\n\n\t// Reset angular velocity\n\tstore.angularVelocity.x = 0;\n\tstore.angularVelocity.y = 0;\n\tstore.angularVelocity.z = 0;\n\n\t// Clear all dirty flags\n\tstore.dirty.position = false;\n\tstore.dirty.rotation = false;\n\tstore.dirty.velocity = false;\n\tstore.dirty.angularVelocity = false;\n}\n","import { Vector3 } from 'three';\nimport { RigidBody, Vector } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\n\nexport interface EntityWithBody {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Move an entity along the X axis, preserving other velocities.\n */\nexport function moveX(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the Y axis, preserving other velocities.\n */\nexport function moveY(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.y = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the Z axis, preserving other velocities.\n */\nexport function moveZ(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.z = delta;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the X and Y axis, preserving Z velocity.\n */\nexport function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = deltaX;\n\tentity.transformStore.velocity.y = deltaY;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move an entity along the X and Z axis, preserving Y velocity.\n */\nexport function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x = deltaX;\n\tentity.transformStore.velocity.z = deltaZ;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Move entity based on a vector, adding to existing velocities.\n */\nexport function move(entity: EntityWithBody, vector: Vector3): void {\n\tif (!entity.transformStore) return;\n\tentity.transformStore.velocity.x += vector.x;\n\tentity.transformStore.velocity.y += vector.y;\n\tentity.transformStore.velocity.z += vector.z;\n\tentity.transformStore.dirty.velocity = true;\n}\n\n/**\n * Reset entity velocity\n */\nexport function resetVelocity(entity: EntityWithBody): void {\n\tif (!entity.body) return;\n\tentity.body.setLinvel(new Vector3(0, 0, 0), true);\n\tentity.body.setLinearDamping(5);\n}\n\n/**\n * Move entity forward in 2D space, preserving Z velocity\n */\nexport function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void {\n\tconst deltaX = Math.sin(-rotation2DAngle) * delta;\n\tconst deltaY = Math.cos(-rotation2DAngle) * delta;\n\tmoveXY(entity, deltaX, deltaY);\n}\n\n/**\n * Get entity position\n */\nexport function getPosition(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.translation();\n}\n\n/**\n * Get entity velocity\n */\nexport function getVelocity(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.linvel();\n}\n\n/**\n * Set entity position\n */\nexport function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity X position\n */\nexport function setPositionX(entity: EntityWithBody, x: number): void {\n\tif (!entity.body) return;\n\tconst { y, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Y position\n */\nexport function setPositionY(entity: EntityWithBody, y: number): void {\n\tif (!entity.body) return;\n\tconst { x, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Z position\n */\nexport function setPositionZ(entity: EntityWithBody, z: number): void {\n\tif (!entity.body) return;\n\tconst { x, y } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Wrap entity around 2D bounds\n */\nexport function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\n\tif (newX !== x || newY !== y) {\n\t\tsetPosition(entity, newX, newY, 0);\n\t}\n}\n\n/**\n * Wrap entity around 3D bounds\n */\nexport function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y, z } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\tconst newZ = z > boundsZ ? -boundsZ : (z < -boundsZ ? boundsZ : z);\n\n\tif (newX !== x || newY !== y || newZ !== z) {\n\t\tsetPosition(entity, newX, newY, newZ);\n\t}\n}\n\n/**\n * Enhanced moveable entity with bound methods\n */\nexport interface MoveableEntity extends EntityWithBody {\n\tmoveX(delta: number): void;\n\tmoveY(delta: number): void;\n\tmoveZ(delta: number): void;\n\tmoveXY(deltaX: number, deltaY: number): void;\n\tmoveXZ(deltaX: number, deltaZ: number): void;\n\tmove(vector: Vector3): void;\n\tresetVelocity(): void;\n\tmoveForwardXY(delta: number, rotation2DAngle: number): void;\n\tgetPosition(): Vector | null;\n\tgetVelocity(): Vector | null;\n\tsetPosition(x: number, y: number, z: number): void;\n\tsetPositionX(x: number): void;\n\tsetPositionY(y: number): void;\n\tsetPositionZ(z: number): void;\n\twrapAroundXY(boundsX: number, boundsY: number): void;\n\twrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;\n}\n\n/**\n * Enhance an entity with additive movement methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeMoveable<T extends EntityWithBody>(entity: T): T & MoveableEntity {\n\tconst moveable = entity as T & MoveableEntity;\n\n\t// Create transform store if it doesn't exist\n\tif (!moveable.transformStore) {\n\t\tmoveable.transformStore = createTransformStore();\n\t}\n\n\tmoveable.moveX = (delta: number) => moveX(entity, delta);\n\tmoveable.moveY = (delta: number) => moveY(entity, delta);\n\tmoveable.moveZ = (delta: number) => moveZ(entity, delta);\n\tmoveable.moveXY = (deltaX: number, deltaY: number) => moveXY(entity, deltaX, deltaY);\n\tmoveable.moveXZ = (deltaX: number, deltaZ: number) => moveXZ(entity, deltaX, deltaZ);\n\tmoveable.move = (vector: Vector3) => move(entity, vector);\n\tmoveable.resetVelocity = () => resetVelocity(entity);\n\tmoveable.moveForwardXY = (delta: number, rotation2DAngle: number) => moveForwardXY(entity, delta, rotation2DAngle);\n\tmoveable.getPosition = () => getPosition(entity);\n\tmoveable.getVelocity = () => getVelocity(entity);\n\tmoveable.setPosition = (x: number, y: number, z: number) => setPosition(entity, x, y, z);\n\tmoveable.setPositionX = (x: number) => setPositionX(entity, x);\n\tmoveable.setPositionY = (y: number) => setPositionY(entity, y);\n\tmoveable.setPositionZ = (z: number) => setPositionZ(entity, z);\n\tmoveable.wrapAroundXY = (boundsX: number, boundsY: number) => wrapAroundXY(entity, boundsX, boundsY);\n\tmoveable.wrapAround3D = (boundsX: number, boundsY: number, boundsZ: number) => wrapAround3D(entity, boundsX, boundsY, boundsZ);\n\n\treturn moveable;\n}","import { Euler, Vector3, MathUtils, Quaternion } from 'three';\nimport { RigidBody } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\n\nexport interface RotatableEntity {\n\tbody: RigidBody | null;\n\tgroup: any;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Rotate an entity in the direction of a movement vector\n */\nexport function rotateInDirection(entity: RotatableEntity, moveVector: Vector3): void {\n\tif (!entity.body) return;\n\tconst rotate = Math.atan2(-moveVector.x, moveVector.z);\n\trotateYEuler(entity, rotate);\n}\n\n/**\n * Rotate an entity around the Y axis using Euler angles\n */\nexport function rotateYEuler(entity: RotatableEntity, amount: number): void {\n\trotateEuler(entity, new Vector3(0, -amount, 0));\n}\n\n/**\n * Rotate an entity using Euler angles\n */\nexport function rotateEuler(entity: RotatableEntity, rotation: Vector3): void {\n\tif (!entity.group) return;\n\tconst euler = new Euler(rotation.x, rotation.y, rotation.z);\n\tentity.group.setRotationFromEuler(euler);\n}\n\n/**\n * Rotate an entity around the Y axis.\n */\nexport function rotateY(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaY = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Y-axis rotation: q_delta = (0, deltaY, 0, deltaW)\n\tconst newW = q.w * deltaW - q.y * deltaY;\n\tconst newX = q.x * deltaW + q.z * deltaY;\n\tconst newY = q.y * deltaW + q.w * deltaY;\n\tconst newZ = q.z * deltaW - q.x * deltaY;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Rotate an entity around the X axis.\n */\nexport function rotateX(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaX = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For X-axis rotation: q_delta = (deltaX, 0, 0, deltaW)\n\tconst newW = q.w * deltaW - q.x * deltaX;\n\tconst newX = q.x * deltaW + q.w * deltaX;\n\tconst newY = q.y * deltaW + q.z * deltaX;\n\tconst newZ = q.z * deltaW - q.y * deltaX;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Rotate an entity around the Z axis.\n */\nexport function rotateZ(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaZ = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Z-axis rotation: q_delta = (0, 0, deltaZ, deltaW)\n\tconst newW = q.w * deltaW - q.z * deltaZ;\n\tconst newX = q.x * deltaW - q.y * deltaZ;\n\tconst newY = q.y * deltaW + q.x * deltaZ;\n\tconst newZ = q.z * deltaW + q.w * deltaZ;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Y axis.\n */\nexport function setRotationY(entity: RotatableEntity, y: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = y / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst yComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = yComponent;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Y axis\n */\nexport function setRotationDegreesY(entity: RotatableEntity, y: number): void {\n\tif (!entity.body) return;\n\tsetRotationY(entity, MathUtils.degToRad(y));\n}\n\n/**\n * Set rotation around X axis.\n */\nexport function setRotationX(entity: RotatableEntity, x: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = x / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst xComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = xComponent;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around X axis\n */\nexport function setRotationDegreesX(entity: RotatableEntity, x: number): void {\n\tif (!entity.body) return;\n\tsetRotationX(entity, MathUtils.degToRad(x));\n}\n\n/**\n * Set rotation around Z axis.\n */\nexport function setRotationZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = z / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst zComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = zComponent;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation around Z axis\n */\nexport function setRotationDegreesZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.body) return;\n\tsetRotationZ(entity, MathUtils.degToRad(z));\n}\n\n/**\n * Set rotation for all axes.\n */\nexport function setRotation(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst quat = new Quaternion().setFromEuler(new Euler(x, y, z));\n\tentity.transformStore.rotation.w = quat.w;\n\tentity.transformStore.rotation.x = quat.x;\n\tentity.transformStore.rotation.y = quat.y;\n\tentity.transformStore.rotation.z = quat.z;\n\tentity.transformStore.dirty.rotation = true;\n}\n\n/**\n * Set rotation for all axes\n */\nexport function setRotationDegrees(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tsetRotation(entity, MathUtils.degToRad(x), MathUtils.degToRad(y), MathUtils.degToRad(z));\n}\n\n/**\n * Get current rotation\n */\nexport function getRotation(entity: RotatableEntity): any {\n\tif (!entity.body) return null;\n\treturn entity.body.rotation();\n}\n\n/**\n * Rotatable entity API with bound methods\n */\nexport interface RotatableEntityAPI extends RotatableEntity {\n\trotateInDirection(moveVector: Vector3): void;\n\trotateYEuler(amount: number): void;\n\trotateEuler(rotation: Vector3): void;\n\trotateY(delta: number): void;\n\trotateX(delta: number): void;\n\trotateZ(delta: number): void;\n\tsetRotationY(y: number): void;\n\tsetRotationX(x: number): void;\n\tsetRotationZ(z: number): void;\n\tsetRotationDegrees(x: number, y: number, z: number): void;\n\tsetRotationDegreesY(y: number): void;\n\tsetRotationDegreesX(x: number): void;\n\tsetRotationDegreesZ(z: number): void;\n\tsetRotation(x: number, y: number, z: number): void;\n\tgetRotation(): any;\n}\n\n/**\n * Enhance an entity instance with rotatable methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeRotatable<T extends RotatableEntity>(entity: T): T & RotatableEntityAPI {\n\tconst rotatableEntity = entity as T & RotatableEntityAPI;\n\n\t// Create transform store if it doesn't exist\n\tif (!rotatableEntity.transformStore) {\n\t\trotatableEntity.transformStore = createTransformStore();\n\t}\n\n\trotatableEntity.rotateInDirection = (moveVector: Vector3) => rotateInDirection(entity, moveVector);\n\trotatableEntity.rotateYEuler = (amount: number) => rotateYEuler(entity, amount);\n\trotatableEntity.rotateEuler = (rotation: Vector3) => rotateEuler(entity, rotation);\n\trotatableEntity.rotateX = (delta: number) => rotateX(entity, delta);\n\trotatableEntity.rotateY = (delta: number) => rotateY(entity, delta);\n\trotatableEntity.rotateZ = (delta: number) => rotateZ(entity, delta);\n\trotatableEntity.setRotationY = (y: number) => setRotationY(entity, y);\n\trotatableEntity.setRotationX = (x: number) => setRotationX(entity, x);\n\trotatableEntity.setRotationZ = (z: number) => setRotationZ(entity, z);\n\trotatableEntity.setRotationDegreesY = (y: number) => setRotationDegreesY(entity, y);\n\trotatableEntity.setRotationDegreesX = (x: number) => setRotationDegreesX(entity, x);\n\trotatableEntity.setRotationDegreesZ = (z: number) => setRotationDegreesZ(entity, z);\n\trotatableEntity.setRotationDegrees = (x: number, y: number, z: number) => setRotationDegrees(entity, x, y, z);\n\trotatableEntity.setRotation = (x: number, y: number, z: number) => setRotation(entity, x, y, z);\n\trotatableEntity.getRotation = () => getRotation(entity);\n\n\treturn rotatableEntity;\n}","import { makeMoveable, EntityWithBody, MoveableEntity } from './moveable';\nimport { makeRotatable, RotatableEntity, RotatableEntityAPI } from './rotatable';\n\n/**\n * Enhance an entity with both movement and rotation capabilities.\n * Transform store is automatically created by makeMoveable and makeRotatable.\n */\nexport function makeTransformable<\n\tT extends RotatableEntity & EntityWithBody\n>(entity: T): T & MoveableEntity & RotatableEntityAPI {\n\tconst withMovement = makeMoveable(entity);\n\tconst withRotation = makeRotatable(withMovement);\n\treturn withRotation;\n}\n\n","import {\n\tActiveCollisionTypes,\n\tColliderDesc,\n\tRigidBodyDesc,\n\tRigidBodyType,\n} from '@dimforge/rapier3d-compat';\nimport { Vector3 } from 'three';\nimport type { Vec3 } from '../../core/vector';\nimport {\n\tgetOrCreateCollisionGroupId,\n\tcreateCollisionFilter,\n\ttype CollisionOptions,\n} from '../../collision/collision-builder';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CollisionComponent type returned by all collision factories\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * A built collision component containing a rigid body description and collider description.\n * Returned by collision factory functions (boxCollision, sphereCollision, etc.)\n * and consumed by GameEntity.add().\n */\nexport interface CollisionComponent {\n\t__kind: 'collision';\n\tbodyDesc: RigidBodyDesc;\n\tcolliderDesc: ColliderDesc;\n}\n\n/**\n * Type guard for CollisionComponent.\n */\nexport function isCollisionComponent(obj: any): obj is CollisionComponent {\n\treturn obj && obj.__kind === 'collision';\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Shared helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface BaseCollisionOptions {\n\t/** Whether the body is static (fixed) or dynamic */\n\tstatic?: boolean;\n\t/** Whether this collider is a sensor */\n\tsensor?: boolean;\n\t/** Position offset relative to the entity origin */\n\toffset?: Vec3;\n\t/** Collision type string for group filtering */\n\tcollisionType?: string;\n\t/** Allowed collision types for filtering */\n\tcollisionFilter?: string[];\n}\n\nfunction buildBodyDesc(isStatic: boolean): RigidBodyDesc {\n\tconst type = isStatic ? RigidBodyType.Fixed : RigidBodyType.Dynamic;\n\treturn new RigidBodyDesc(type)\n\t\t.setTranslation(0, 0, 0)\n\t\t.setGravityScale(1.0)\n\t\t.setCanSleep(false)\n\t\t.setCcdEnabled(true);\n}\n\nfunction applyCollisionOptions(\n\tcolliderDesc: ColliderDesc,\n\topts: BaseCollisionOptions,\n): void {\n\tif (opts.offset) {\n\t\tcolliderDesc.setTranslation(opts.offset.x, opts.offset.y, opts.offset.z);\n\t}\n\tif (opts.sensor) {\n\t\tcolliderDesc.setSensor(true);\n\t\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.KINEMATIC_FIXED;\n\t}\n\tif (opts.collisionType) {\n\t\tconst groupId = getOrCreateCollisionGroupId(opts.collisionType);\n\t\tlet filter = 0b1111111111111111;\n\t\tif (opts.collisionFilter) {\n\t\t\tfilter = createCollisionFilter(opts.collisionFilter);\n\t\t}\n\t\tcolliderDesc.setCollisionGroups((groupId << 16) | filter);\n\t}\n}\n\nfunction makeComponent(\n\tcolliderDesc: ColliderDesc,\n\topts: BaseCollisionOptions,\n): CollisionComponent {\n\tapplyCollisionOptions(colliderDesc, opts);\n\treturn {\n\t\t__kind: 'collision',\n\t\tbodyDesc: buildBodyDesc(opts.static ?? false),\n\t\tcolliderDesc,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Box\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface BoxCollisionOptions extends BaseCollisionOptions {\n\t/** Box dimensions (default: 1x1x1) */\n\tsize?: Vec3;\n}\n\n/**\n * Create a box (cuboid) collision component.\n */\nexport function boxCollision(opts: BoxCollisionOptions = {}): CollisionComponent {\n\tconst size = opts.size ?? { x: 1, y: 1, z: 1 };\n\tconst desc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Sphere\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface SphereCollisionOptions extends BaseCollisionOptions {\n\t/** Sphere radius (default: 1) */\n\tradius?: number;\n}\n\n/**\n * Create a sphere (ball) collision component.\n */\nexport function sphereCollision(opts: SphereCollisionOptions = {}): CollisionComponent {\n\tconst desc = ColliderDesc.ball(opts.radius ?? 1);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cone\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ConeCollisionOptions extends BaseCollisionOptions {\n\t/** Base radius (default: 1) */\n\tradius?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a cone collision component.\n */\nexport function coneCollision(opts: ConeCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 1;\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cone(height / 2, radius);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Pyramid (cone collider with 4-sided visual approximation)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PyramidCollisionOptions extends BaseCollisionOptions {\n\t/** Base radius (default: 1) */\n\tradius?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a pyramid collision component (approximated as a cone).\n */\nexport function pyramidCollision(opts: PyramidCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 1;\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cone(height / 2, radius);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cylinder\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface CylinderCollisionOptions extends BaseCollisionOptions {\n\t/** Top radius (default: 1) */\n\tradiusTop?: number;\n\t/** Bottom radius (default: 1) */\n\tradiusBottom?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a cylinder collision component.\n */\nexport function cylinderCollision(opts: CylinderCollisionOptions = {}): CollisionComponent {\n\tconst radius = Math.max(opts.radiusTop ?? 1, opts.radiusBottom ?? 1);\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cylinder(height / 2, radius);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Pill (capsule)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PillCollisionOptions extends BaseCollisionOptions {\n\t/** Capsule hemisphere radius (default: 0.5) */\n\tradius?: number;\n\t/** Cylindrical section length (default: 1) */\n\tlength?: number;\n}\n\n/**\n * Create a pill (capsule) collision component.\n */\nexport function pillCollision(opts: PillCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 0.5;\n\tconst length = opts.length ?? 1;\n\tconst desc = ColliderDesc.capsule(length / 2, radius);\n\treturn makeComponent(desc, opts);\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plane (heightfield)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PlaneCollisionOptions extends BaseCollisionOptions {\n\t/** Tile dimensions (default: 10x10) */\n\ttile?: { x: number; y: number };\n\t/** Number of subdivisions per axis (default: 10) */\n\tsubdivisions?: number;\n\t/** Pre-computed height data for the heightfield */\n\theightData?: Float32Array;\n}\n\n/**\n * Create a plane (heightfield) collision component.\n * For flat planes, pass no heightData — a zeroed heightfield is used.\n */\nexport function planeCollision(opts: PlaneCollisionOptions = {}): CollisionComponent {\n\tconst tile = opts.tile ?? { x: 10, y: 10 };\n\tconst subdivisions = opts.subdivisions ?? 10;\n\tconst size = new Vector3(tile.x, 1, tile.y);\n\n\tconst totalVerts = (subdivisions + 1) * (subdivisions + 1);\n\tconst heightData = opts.heightData ?? new Float32Array(totalVerts);\n\n\tconst desc = ColliderDesc.heightfield(\n\t\tsubdivisions,\n\t\tsubdivisions,\n\t\theightData,\n\t\tsize,\n\t);\n\n\treturn makeComponent(desc, { ...opts, static: opts.static ?? true });\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Zone (sensor cuboid)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ZoneCollisionOptions extends BaseCollisionOptions {\n\t/** Zone dimensions (default: 1x1x1) */\n\tsize?: Vec3;\n}\n\n/**\n * Create a zone (sensor cuboid) collision component.\n * Always a sensor; static by default.\n */\nexport function zoneCollision(opts: ZoneCollisionOptions = {}): CollisionComponent {\n\tconst size = opts.size ?? { x: 1, y: 1, z: 1 };\n\tconst desc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2);\n\tdesc.setSensor(true);\n\tdesc.activeCollisionTypes = ActiveCollisionTypes.KINEMATIC_FIXED;\n\treturn makeComponent(desc, { ...opts, static: opts.static ?? true, sensor: true });\n}\n","import { Color, Vector3 } from 'three';\nimport { standardShader } from '../graphics/shaders/standard.shader';\nimport { GameEntityOptions } from './entity';\nimport { BaseNode } from '../core/base-node';\n\nexport const commonDefaults: Partial<GameEntityOptions> = {\n position: new Vector3(0, 0, 0),\n material: {\n color: new Color('#ffffff'),\n shader: standardShader\n },\n collision: {\n static: false,\n },\n};\n\n/**\n * Merge a variadic args array (BaseNode children + options object) with defaults.\n * Returns the merged options. This replaces the createEntity() arg parsing logic.\n */\nexport function mergeArgs<T extends GameEntityOptions>(\n args: Array<BaseNode | Partial<T>>,\n defaults: Partial<T>,\n): T {\n const configArgs = args.filter(\n (arg): arg is Partial<T> => !(arg instanceof BaseNode),\n );\n let merged: Partial<T> = { ...defaults };\n for (const opt of configArgs) {\n merged = { ...merged, ...opt };\n }\n return merged as 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","/**\n * Centralized Asset Manager for Zylem\n * \n * Provides caching, parallel loading, and unified access to all asset types.\n * All asset loading should funnel through this manager.\n */\n\nimport { Texture, Object3D, LoadingManager, Cache } from 'three';\nimport { GLTF } from 'three/addons/loaders/GLTFLoader.js';\nimport mitt, { Emitter } from 'mitt';\n\nimport {\n\tAssetType,\n\tAssetLoadOptions,\n\tAssetManagerEvents,\n\tBatchLoadItem,\n\tModelLoadResult\n} from './asset-types';\n\nimport {\n\tTextureLoaderAdapter,\n\tGLTFLoaderAdapter,\n\tFBXLoaderAdapter,\n\tOBJLoaderAdapter,\n\tAudioLoaderAdapter,\n\tFileLoaderAdapter,\n\tJsonLoaderAdapter,\n\tTextureOptions,\n\tGLTFLoadOptions,\n\tFBXLoadOptions,\n\tOBJLoadOptions,\n\tFileLoadOptions\n} from './loaders';\n\n/**\n * Asset cache entry\n */\ninterface CacheEntry<T> {\n\tpromise: Promise<T>;\n\tresult?: T;\n\tloadedAt: number;\n}\n\n/**\n * AssetManager - Singleton for all asset loading\n * \n * Features:\n * - URL-based caching with deduplication\n * - Typed load methods for each asset type\n * - Batch loading with Promise.all() for parallelism\n * - Progress events via LoadingManager\n * - Clone support for shared assets (textures, models)\n */\nexport class AssetManager {\n\tprivate static instance: AssetManager | null = null;\n\n\t// Caches for different asset types\n\tprivate textureCache: Map<string, CacheEntry<Texture>> = new Map();\n\tprivate modelCache: Map<string, CacheEntry<ModelLoadResult>> = new Map();\n\tprivate audioCache: Map<string, CacheEntry<AudioBuffer>> = new Map();\n\tprivate fileCache: Map<string, CacheEntry<string | ArrayBuffer>> = new Map();\n\tprivate jsonCache: Map<string, CacheEntry<unknown>> = new Map();\n\n\t// Loaders\n\tprivate textureLoader: TextureLoaderAdapter;\n\tprivate gltfLoader: GLTFLoaderAdapter;\n\tprivate fbxLoader: FBXLoaderAdapter;\n\tprivate objLoader: OBJLoaderAdapter;\n\tprivate audioLoader: AudioLoaderAdapter;\n\tprivate fileLoader: FileLoaderAdapter;\n\tprivate jsonLoader: JsonLoaderAdapter;\n\n\t// Loading manager for progress tracking\n\tprivate loadingManager: LoadingManager;\n\n\t// Event emitter\n\tprivate events: Emitter<AssetManagerEvents>;\n\n\t// Stats\n\tprivate stats = {\n\t\ttexturesLoaded: 0,\n\t\tmodelsLoaded: 0,\n\t\taudioLoaded: 0,\n\t\tfilesLoaded: 0,\n\t\tcacheHits: 0,\n\t\tcacheMisses: 0\n\t};\n\n\tprivate constructor() {\n\t\t// Initialize loaders\n\t\tthis.textureLoader = new TextureLoaderAdapter();\n\t\tthis.gltfLoader = new GLTFLoaderAdapter();\n\t\tthis.fbxLoader = new FBXLoaderAdapter();\n\t\tthis.objLoader = new OBJLoaderAdapter();\n\t\tthis.audioLoader = new AudioLoaderAdapter();\n\t\tthis.fileLoader = new FileLoaderAdapter();\n\t\tthis.jsonLoader = new JsonLoaderAdapter();\n\n\t\t// Initialize loading manager\n\t\tthis.loadingManager = new LoadingManager();\n\t\tthis.loadingManager.onProgress = (url, loaded, total) => {\n\t\t\tthis.events.emit('batch:progress', { loaded, total });\n\t\t};\n\n\t\t// Initialize event emitter\n\t\tthis.events = mitt<AssetManagerEvents>();\n\n\t\t// Enable Three.js built-in cache\n\t\tCache.enabled = true;\n\t}\n\n\t/**\n\t * Get the singleton instance\n\t */\n\tstatic getInstance(): AssetManager {\n\t\tif (!AssetManager.instance) {\n\t\t\tAssetManager.instance = new AssetManager();\n\t\t}\n\t\treturn AssetManager.instance;\n\t}\n\n\t/**\n\t * Reset the singleton (useful for testing)\n\t */\n\tstatic resetInstance(): void {\n\t\tif (AssetManager.instance) {\n\t\t\tAssetManager.instance.clearCache();\n\t\t\tAssetManager.instance = null;\n\t\t}\n\t}\n\n\t// ==================== TEXTURE LOADING ====================\n\n\t/**\n\t * Load a texture with caching\n\t */\n\tasync loadTexture(url: string, options?: TextureOptions): Promise<Texture> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.TEXTURE,\n\t\t\tthis.textureCache,\n\t\t\t() => this.textureLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(texture) => {\n\t\t\t\tif (!options?.clone) return texture;\n\t\t\t\tconst cloned = this.textureLoader.clone(texture);\n\t\t\t\t// Re-apply per-instance texture options to the clone so that\n\t\t\t\t// different callers sharing the same cached base texture can\n\t\t\t\t// use independent repeat / wrap values.\n\t\t\t\tif (options.repeat) {\n\t\t\t\t\tcloned.repeat.copy(options.repeat);\n\t\t\t\t}\n\t\t\t\tif (options.wrapS !== undefined) {\n\t\t\t\t\tcloned.wrapS = options.wrapS;\n\t\t\t\t}\n\t\t\t\tif (options.wrapT !== undefined) {\n\t\t\t\t\tcloned.wrapT = options.wrapT;\n\t\t\t\t}\n\t\t\t\treturn cloned;\n\t\t\t}\n\t\t);\n\t}\n\n\t// ==================== MODEL LOADING ====================\n\n\t/**\n\t * Load a GLTF/GLB model with caching\n\t */\n\tasync loadGLTF(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.GLTF,\n\t\t\tthis.modelCache,\n\t\t\t() => this.gltfLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.gltfLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Load an FBX model with caching\n\t */\n\tasync loadFBX(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.FBX,\n\t\t\tthis.modelCache,\n\t\t\t() => this.fbxLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.fbxLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Load an OBJ model with caching\n\t */\n\tasync loadOBJ(url: string, options?: OBJLoadOptions): Promise<ModelLoadResult> {\n\t\t// Include mtlPath in cache key for OBJ files\n\t\tconst cacheKey = options?.mtlPath ? `${url}:${options.mtlPath}` : url;\n\t\treturn this.loadWithCache(\n\t\t\tcacheKey,\n\t\t\tAssetType.OBJ,\n\t\t\tthis.modelCache,\n\t\t\t() => this.objLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.objLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Auto-detect model type and load\n\t */\n\tasync loadModel(url: string, options?: AssetLoadOptions): Promise<ModelLoadResult> {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\t\n\t\tswitch (ext) {\n\t\t\tcase 'gltf':\n\t\t\tcase 'glb':\n\t\t\t\treturn this.loadGLTF(url, options);\n\t\t\tcase 'fbx':\n\t\t\t\treturn this.loadFBX(url, options);\n\t\t\tcase 'obj':\n\t\t\t\treturn this.loadOBJ(url, options);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported model format: ${ext}`);\n\t\t}\n\t}\n\n\t// ==================== AUDIO LOADING ====================\n\n\t/**\n\t * Load an audio buffer with caching\n\t */\n\tasync loadAudio(url: string, options?: AssetLoadOptions): Promise<AudioBuffer> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.AUDIO,\n\t\t\tthis.audioCache,\n\t\t\t() => this.audioLoader.load(url, options),\n\t\t\toptions\n\t\t);\n\t}\n\n\t// ==================== FILE LOADING ====================\n\n\t/**\n\t * Load a raw file with caching\n\t */\n\tasync loadFile(url: string, options?: FileLoadOptions): Promise<string | ArrayBuffer> {\n\t\tconst cacheKey = options?.responseType ? `${url}:${options.responseType}` : url;\n\t\treturn this.loadWithCache(\n\t\t\tcacheKey,\n\t\t\tAssetType.FILE,\n\t\t\tthis.fileCache,\n\t\t\t() => this.fileLoader.load(url, options),\n\t\t\toptions\n\t\t);\n\t}\n\n\t/**\n\t * Load a JSON file with caching\n\t */\n\tasync loadJSON<T = unknown>(url: string, options?: AssetLoadOptions): Promise<T> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.JSON,\n\t\t\tthis.jsonCache,\n\t\t\t() => this.jsonLoader.load<T>(url, options),\n\t\t\toptions\n\t\t) as Promise<T>;\n\t}\n\n\t// ==================== BATCH LOADING ====================\n\n\t/**\n\t * Load multiple assets in parallel\n\t */\n\tasync loadBatch(items: BatchLoadItem[]): Promise<Map<string, any>> {\n\t\tconst results = new Map<string, any>();\n\t\t\n\t\tconst promises = items.map(async (item) => {\n\t\t\ttry {\n\t\t\t\tlet result: any;\n\t\t\t\t\n\t\t\t\tswitch (item.type) {\n\t\t\t\t\tcase AssetType.TEXTURE:\n\t\t\t\t\t\tresult = await this.loadTexture(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.GLTF:\n\t\t\t\t\t\tresult = await this.loadGLTF(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.FBX:\n\t\t\t\t\t\tresult = await this.loadFBX(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.OBJ:\n\t\t\t\t\t\tresult = await this.loadOBJ(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.AUDIO:\n\t\t\t\t\t\tresult = await this.loadAudio(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.FILE:\n\t\t\t\t\t\tresult = await this.loadFile(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.JSON:\n\t\t\t\t\t\tresult = await this.loadJSON(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(`Unknown asset type: ${item.type}`);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tresults.set(item.url, result);\n\t\t\t} catch (error) {\n\t\t\t\tthis.events.emit('asset:error', {\n\t\t\t\t\turl: item.url,\n\t\t\t\t\ttype: item.type,\n\t\t\t\t\terror: error as Error\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\n\t\tawait Promise.all(promises);\n\t\t\n\t\tthis.events.emit('batch:complete', { urls: items.map(i => i.url) });\n\t\t\n\t\treturn results;\n\t}\n\n\t/**\n\t * Preload assets without returning results\n\t */\n\tasync preload(items: BatchLoadItem[]): Promise<void> {\n\t\tawait this.loadBatch(items);\n\t}\n\n\t// ==================== CACHE MANAGEMENT ====================\n\n\t/**\n\t * Check if an asset is cached\n\t */\n\tisCached(url: string): boolean {\n\t\treturn this.textureCache.has(url) ||\n\t\t\tthis.modelCache.has(url) ||\n\t\t\tthis.audioCache.has(url) ||\n\t\t\tthis.fileCache.has(url) ||\n\t\t\tthis.jsonCache.has(url);\n\t}\n\n\t/**\n\t * Clear all caches or a specific URL\n\t */\n\tclearCache(url?: string): void {\n\t\tif (url) {\n\t\t\tthis.textureCache.delete(url);\n\t\t\tthis.modelCache.delete(url);\n\t\t\tthis.audioCache.delete(url);\n\t\t\tthis.fileCache.delete(url);\n\t\t\tthis.jsonCache.delete(url);\n\t\t} else {\n\t\t\tthis.textureCache.clear();\n\t\t\tthis.modelCache.clear();\n\t\t\tthis.audioCache.clear();\n\t\t\tthis.fileCache.clear();\n\t\t\tthis.jsonCache.clear();\n\t\t\tCache.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Get cache statistics\n\t */\n\tgetStats(): typeof this.stats {\n\t\treturn { ...this.stats };\n\t}\n\n\t// ==================== EVENTS ====================\n\n\t/**\n\t * Subscribe to asset manager events\n\t */\n\ton<K extends keyof AssetManagerEvents>(\n\t\tevent: K,\n\t\thandler: (payload: AssetManagerEvents[K]) => void\n\t): void {\n\t\tthis.events.on(event, handler);\n\t}\n\n\t/**\n\t * Unsubscribe from asset manager events\n\t */\n\toff<K extends keyof AssetManagerEvents>(\n\t\tevent: K,\n\t\thandler: (payload: AssetManagerEvents[K]) => void\n\t): void {\n\t\tthis.events.off(event, handler);\n\t}\n\n\t// ==================== PRIVATE HELPERS ====================\n\n\t/**\n\t * Generic cache wrapper for loading assets\n\t */\n\tprivate async loadWithCache<T>(\n\t\turl: string,\n\t\ttype: AssetType,\n\t\tcache: Map<string, CacheEntry<T>>,\n\t\tloader: () => Promise<T>,\n\t\toptions?: AssetLoadOptions,\n\t\tcloner?: (result: T) => T\n\t): Promise<T> {\n\t\t// Check for force reload\n\t\tif (options?.forceReload) {\n\t\t\tcache.delete(url);\n\t\t}\n\n\t\t// Check cache\n\t\tconst cached = cache.get(url);\n\t\tif (cached) {\n\t\t\tthis.stats.cacheHits++;\n\t\t\tthis.events.emit('asset:loaded', { url, type, fromCache: true });\n\t\t\t\n\t\t\tconst result = await cached.promise;\n\t\t\treturn cloner ? cloner(result) : result;\n\t\t}\n\n\t\t// Cache miss - start loading\n\t\tthis.stats.cacheMisses++;\n\t\tthis.events.emit('asset:loading', { url, type });\n\n\t\tconst promise = loader();\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tpromise,\n\t\t\tloadedAt: Date.now()\n\t\t};\n\t\tcache.set(url, entry);\n\n\t\ttry {\n\t\t\tconst result = await promise;\n\t\t\tentry.result = result;\n\t\t\t\n\t\t\t// Update stats\n\t\t\tthis.updateStats(type);\n\t\t\t\n\t\t\tthis.events.emit('asset:loaded', { url, type, fromCache: false });\n\t\t\t\n\t\t\treturn cloner ? cloner(result) : result;\n\t\t} catch (error) {\n\t\t\t// Remove failed entry from cache\n\t\t\tcache.delete(url);\n\t\t\tthis.events.emit('asset:error', { url, type, error: error as Error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate updateStats(type: AssetType): void {\n\t\tswitch (type) {\n\t\t\tcase AssetType.TEXTURE:\n\t\t\t\tthis.stats.texturesLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.GLTF:\n\t\t\tcase AssetType.FBX:\n\t\t\tcase AssetType.OBJ:\n\t\t\t\tthis.stats.modelsLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.AUDIO:\n\t\t\t\tthis.stats.audioLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.FILE:\n\t\t\tcase AssetType.JSON:\n\t\t\t\tthis.stats.filesLoaded++;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Singleton instance export for convenience\n */\nexport const assetManager = AssetManager.getInstance();","/**\n * Texture loader adapter for the Asset Manager\n */\n\nimport { TextureLoader, Texture, RepeatWrapping, Vector2, Wrapping } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport interface TextureOptions extends AssetLoadOptions {\n\trepeat?: Vector2;\n\twrapS?: Wrapping;\n\twrapT?: Wrapping;\n}\n\nexport class TextureLoaderAdapter implements LoaderAdapter<Texture> {\n\tprivate loader: TextureLoader;\n\n\tconstructor() {\n\t\tthis.loader = new TextureLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'tga'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: TextureOptions): Promise<Texture> {\n\t\tconst texture = await this.loader.loadAsync(url, (event) => {\n\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t}\n\t\t});\n\n\t\t// Apply texture options\n\t\tif (options?.repeat) {\n\t\t\ttexture.repeat.copy(options.repeat);\n\t\t}\n\t\ttexture.wrapS = options?.wrapS ?? RepeatWrapping;\n\t\ttexture.wrapT = options?.wrapT ?? RepeatWrapping;\n\n\t\treturn texture;\n\t}\n\n\t/**\n\t * Clone a texture for independent usage\n\t */\n\tclone(texture: Texture): Texture {\n\t\tconst cloned = texture.clone();\n\t\tcloned.needsUpdate = true;\n\t\treturn cloned;\n\t}\n}\n","/**\n * GLTF loader adapter for the Asset Manager\n * Uses native fetch (already async/non-blocking in browsers) + parseAsync\n */\n\nimport { GLTF, GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\n\nexport interface GLTFLoadOptions extends AssetLoadOptions {\n\t/** \n\t * Use async fetch + parseAsync pattern instead of loader.load()\n\t * Note: fetch() is already non-blocking in browsers, so this mainly\n\t * provides a cleaner async/await pattern rather than performance gains\n\t */\n\tuseAsyncFetch?: boolean;\n}\n\nexport class GLTFLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: GLTFLoader;\n\n\tconstructor() {\n\t\tthis.loader = new GLTFLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['gltf', 'glb'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\tif (options?.useAsyncFetch) {\n\t\t\treturn this.loadWithAsyncFetch(url, options);\n\t\t}\n\t\treturn this.loadMainThread(url, options);\n\t}\n\n\t/**\n\t * Load using native fetch + parseAsync\n\t * Both fetch and parsing are async, keeping the main thread responsive\n\t */\n\tprivate async loadWithAsyncFetch(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\ttry {\n\t\t\tconst response = await fetch(url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n\t\t\t}\n\t\t\tconst buffer = await response.arrayBuffer();\n\n\t\t\t// Parse on main thread using GLTFLoader.parseAsync\n\t\t\t// The url is passed as the path for resolving relative resources\n\t\t\tconst gltf = await this.loader.parseAsync(buffer, url);\n\n\t\t\treturn {\n\t\t\t\tobject: gltf.scene,\n\t\t\t\tanimations: gltf.animations,\n\t\t\t\tgltf\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Async fetch GLTF load failed for ${url}, falling back to loader.load():`, error);\n\t\t\treturn this.loadMainThread(url, options);\n\t\t}\n\t}\n\n\tprivate async loadMainThread(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(gltf: GLTF) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject: gltf.scene,\n\t\t\t\t\t\tanimations: gltf.animations,\n\t\t\t\t\t\tgltf\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded GLTF scene for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: result.object.clone(),\n\t\t\tanimations: result.animations?.map(anim => anim.clone()),\n\t\t\tgltf: result.gltf\n\t\t};\n\t}\n}\n","/**\n * FBX loader adapter for the Asset Manager\n * Uses native fetch (already async/non-blocking in browsers) + parse\n */\n\nimport { Object3D } from 'three';\nimport { FBXLoader } from 'three/addons/loaders/FBXLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\n\nexport interface FBXLoadOptions extends AssetLoadOptions {\n\t/** \n\t * Use async fetch + parse pattern instead of loader.load()\n\t * Note: fetch() is already non-blocking in browsers\n\t */\n\tuseAsyncFetch?: boolean;\n}\n\nexport class FBXLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: FBXLoader;\n\n\tconstructor() {\n\t\tthis.loader = new FBXLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'fbx';\n\t}\n\n\tasync load(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\tif (options?.useAsyncFetch) {\n\t\t\treturn this.loadWithAsyncFetch(url, options);\n\t\t}\n\t\treturn this.loadMainThread(url, options);\n\t}\n\n\t/**\n\t * Load using native fetch + parse\n\t */\n\tprivate async loadWithAsyncFetch(url: string, _options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\ttry {\n\t\t\tconst response = await fetch(url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n\t\t\t}\n\t\t\tconst buffer = await response.arrayBuffer();\n\n\t\t\t// Parse on main thread using FBXLoader.parse\n\t\t\tconst object = this.loader.parse(buffer, url);\n\n\t\t\treturn {\n\t\t\t\tobject,\n\t\t\t\tanimations: (object as any).animations || []\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Async fetch FBX load failed for ${url}, falling back to loader.load():`, error);\n\t\t\treturn this.loadMainThread(url, _options);\n\t\t}\n\t}\n\n\tprivate async loadMainThread(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(object: Object3D) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tanimations: (object as any).animations || []\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded FBX object for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: result.object.clone(),\n\t\t\tanimations: result.animations?.map(anim => anim.clone())\n\t\t};\n\t}\n}\n","/**\n * OBJ loader adapter for the Asset Manager\n * Supports optional MTL (material) file loading\n */\n\nimport { Object3D, Group } from 'three';\nimport { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\nimport { MTLLoader } from 'three/addons/loaders/MTLLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\n\nexport interface OBJLoadOptions extends AssetLoadOptions {\n\t/** Path to MTL material file */\n\tmtlPath?: string;\n}\n\nexport class OBJLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: OBJLoader;\n\tprivate mtlLoader: MTLLoader;\n\n\tconstructor() {\n\t\tthis.loader = new OBJLoader();\n\t\tthis.mtlLoader = new MTLLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'obj';\n\t}\n\n\tasync load(url: string, options?: OBJLoadOptions): Promise<ModelLoadResult> {\n\t\t// Load MTL first if provided\n\t\tif (options?.mtlPath) {\n\t\t\tawait this.loadMTL(options.mtlPath);\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(object: Group) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tanimations: []\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async loadMTL(url: string): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.mtlLoader.load(\n\t\t\t\turl,\n\t\t\t\t(materials) => {\n\t\t\t\t\tmaterials.preload();\n\t\t\t\t\tthis.loader.setMaterials(materials);\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded OBJ object for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: result.object.clone(),\n\t\t\tanimations: []\n\t\t};\n\t}\n}\n","/**\n * Audio loader adapter for the Asset Manager\n */\n\nimport { AudioLoader } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport class AudioLoaderAdapter implements LoaderAdapter<AudioBuffer> {\n\tprivate loader: AudioLoader;\n\n\tconstructor() {\n\t\tthis.loader = new AudioLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['mp3', 'ogg', 'wav', 'flac', 'aac', 'm4a'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: AssetLoadOptions): Promise<AudioBuffer> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(buffer) => resolve(buffer),\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n}\n","/**\n * File loader adapter for the Asset Manager\n */\n\nimport { FileLoader } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport interface FileLoadOptions extends AssetLoadOptions {\n\tresponseType?: 'text' | 'arraybuffer' | 'blob' | 'json';\n}\n\nexport class FileLoaderAdapter implements LoaderAdapter<string | ArrayBuffer> {\n\tprivate loader: FileLoader;\n\n\tconstructor() {\n\t\tthis.loader = new FileLoader();\n\t}\n\n\tisSupported(_url: string): boolean {\n\t\t// FileLoader can handle any file type\n\t\treturn true;\n\t}\n\n\tasync load(url: string, options?: FileLoadOptions): Promise<string | ArrayBuffer> {\n\t\tconst responseType = options?.responseType ?? 'text';\n\t\tthis.loader.setResponseType(responseType as any);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(data) => resolve(data as string | ArrayBuffer),\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n}\n\n/**\n * JSON loader using FileLoader\n */\nexport class JsonLoaderAdapter implements LoaderAdapter<unknown> {\n\tprivate fileLoader: FileLoaderAdapter;\n\n\tconstructor() {\n\t\tthis.fileLoader = new FileLoaderAdapter();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'json';\n\t}\n\n\tasync load<T = unknown>(url: string, options?: AssetLoadOptions): Promise<T> {\n\t\tconst data = await this.fileLoader.load(url, { ...options, responseType: 'json' });\n\t\treturn data as T;\n\t}\n}\n","/**\n * Entity Asset Loader - Refactored to use AssetManager\n * \n * This module provides a compatibility layer for existing code that uses EntityAssetLoader.\n * All loading now goes through the centralized AssetManager for caching.\n */\n\nimport { AnimationClip, Object3D } from 'three';\nimport { GLTF } from 'three/addons/loaders/GLTFLoader.js';\nimport { assetManager } from './asset-manager';\n\nexport interface AssetLoaderResult {\n\tobject?: Object3D;\n\tanimation?: AnimationClip;\n\tgltf?: GLTF;\n}\n\n/**\n * EntityAssetLoader - Uses AssetManager for all model loading\n * \n * This class is now a thin wrapper around AssetManager, providing backward\n * compatibility for existing code while benefiting from centralized caching.\n */\nexport class EntityAssetLoader {\n\t/**\n\t * Load a model file (FBX, GLTF, GLB, OBJ) using the asset manager\n\t */\n\tasync loadFile(file: string): Promise<AssetLoaderResult> {\n\t\tconst ext = file.split('.').pop()?.toLowerCase();\n\n\t\tswitch (ext) {\n\t\t\tcase 'fbx': {\n\t\t\t\tconst result = await assetManager.loadFBX(file);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object,\n\t\t\t\t\tanimation: result.animations?.[0]\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase 'gltf':\n\t\t\tcase 'glb': {\n\t\t\t\tconst result = await assetManager.loadGLTF(file);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object,\n\t\t\t\t\tgltf: result.gltf\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase 'obj': {\n\t\t\t\tconst result = await assetManager.loadOBJ(file);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object\n\t\t\t\t};\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported file type: ${file}`);\n\t\t}\n\t}\n}\n","import {\n\tAnimationAction,\n\tAnimationClip,\n\tAnimationMixer,\n\tLoopOnce,\n\tLoopRepeat,\n\tObject3D,\n} from 'three';\nimport { EntityAssetLoader, AssetLoaderResult } from '../../core/entity-asset-loader';\n\nexport type AnimationOptions = {\n\tkey: string;\n\tpauseAtEnd?: boolean;\n\tpauseAtPercentage?: number;\n\tfadeToKey?: string;\n\tfadeDuration?: number;\n};\n\ntype AnimationObject = {\n\tkey?: string;\n\tpath: string;\n};\n\nexport class AnimationDelegate {\n\tprivate _mixer: AnimationMixer | null = null;\n\tprivate _actions: Record<string, AnimationAction> = {};\n\tprivate _animations: AnimationClip[] = [];\n\tprivate _currentAction: AnimationAction | null = null;\n\n\tprivate _pauseAtPercentage = 0;\n\tprivate _isPaused = false;\n\tprivate _queuedKey: string | null = null;\n\tprivate _fadeDuration = 0.5;\n\n\tprivate _currentKey: string = '';\n\tprivate _assetLoader = new EntityAssetLoader();\n\n\tconstructor(private target: Object3D) { }\n\n\tasync loadAnimations(animations: AnimationObject[]): Promise<void> {\n\t\tif (!animations.length) return;\n\n\t\tconst results = await Promise.all(animations.map(a => this._assetLoader.loadFile(a.path)));\n\t\t\n\t\t// Build animations list while preserving original key mapping\n\t\t// Filter to only successful loads and pair with their original keys\n\t\tconst loadedAnimations: { key: string; clip: AnimationClip }[] = [];\n\t\tresults.forEach((result, i) => {\n\t\t\tif (result.animation) {\n\t\t\t\tloadedAnimations.push({\n\t\t\t\t\tkey: animations[i].key || i.toString(),\n\t\t\t\t\tclip: result.animation\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tif (!loadedAnimations.length) return;\n\n\t\tthis._animations = loadedAnimations.map(a => a.clip);\n\t\tthis._mixer = new AnimationMixer(this.target);\n\t\t\n\t\t// Create actions with correct key mapping\n\t\tloadedAnimations.forEach(({ key, clip }) => {\n\t\t\tthis._actions[key] = this._mixer!.clipAction(clip);\n\t\t});\n\n\t\tthis.playAnimation({ key: loadedAnimations[0].key });\n\t}\n\n\tupdate(delta: number): void {\n\t\tif (!this._mixer || !this._currentAction) return;\n\n\t\tthis._mixer.update(delta);\n\n\t\tconst pauseAtTime = this._currentAction.getClip().duration * (this._pauseAtPercentage / 100);\n\t\tif (\n\t\t\t!this._isPaused &&\n\t\t\tthis._pauseAtPercentage > 0 &&\n\t\t\tthis._currentAction.time >= pauseAtTime\n\t\t) {\n\t\t\tthis._currentAction.time = pauseAtTime;\n\t\t\tthis._currentAction.paused = true;\n\t\t\tthis._isPaused = true;\n\n\t\t\tif (this._queuedKey !== null) {\n\t\t\t\tconst next = this._actions[this._queuedKey];\n\t\t\t\tnext.reset().play();\n\t\t\t\tthis._currentAction.crossFadeTo(next, this._fadeDuration, false);\n\t\t\t\tthis._currentAction = next;\n\t\t\t\tthis._currentKey = this._queuedKey;\n\t\t\t\tthis._queuedKey = null;\n\t\t\t}\n\t\t}\n\t}\n\n\tplayAnimation(opts: AnimationOptions): void {\n\t\tif (!this._mixer) return;\n\t\tconst { key, pauseAtPercentage = 0, pauseAtEnd = false, fadeToKey, fadeDuration = 0.5 } = opts;\n\t\tif (key === this._currentKey) return;\n\n\t\t// Check if the new action exists BEFORE stopping the current animation\n\t\t// This prevents T-posing when an animation key doesn't exist\n\t\tconst action = this._actions[key];\n\t\tif (!action) return;\n\n\t\tthis._queuedKey = fadeToKey || null;\n\t\tthis._fadeDuration = fadeDuration;\n\n\t\tthis._pauseAtPercentage = pauseAtEnd ? 100 : pauseAtPercentage;\n\t\tthis._isPaused = false;\n\n\t\tconst prev = this._currentAction;\n\t\t// Don't stop prev here - crossFadeTo needs it playing for smooth transition\n\n\t\tif (this._pauseAtPercentage > 0) {\n\t\t\taction.setLoop(LoopOnce, Infinity);\n\t\t\taction.clampWhenFinished = true;\n\t\t} else {\n\t\t\taction.setLoop(LoopRepeat, Infinity);\n\t\t\taction.clampWhenFinished = false;\n\t\t}\n\n\t\t// Start the new action\n\t\taction.reset().play();\n\n\t\t// Crossfade from previous if it exists\n\t\tif (prev) {\n\t\t\tprev.crossFadeTo(action, fadeDuration, false);\n\t\t}\n\n\t\tthis._currentAction = action;\n\t\tthis._currentKey = key;\n\t}\n\n\t/**\n\t * Dispose of all animation resources\n\t */\n\tdispose(): void {\n\t\t// Stop all actions\n\t\tObject.values(this._actions).forEach(action => {\n\t\t\taction.stop();\n\t\t});\n\n\t\t// Stop and uncache mixer\n\t\tif (this._mixer) {\n\t\t\tthis._mixer.stopAllAction();\n\t\t\tthis._mixer.uncacheRoot(this.target);\n\t\t\tthis._mixer = null;\n\t\t}\n\n\t\t// Clear references\n\t\tthis._actions = {};\n\t\tthis._animations = [];\n\t\tthis._currentAction = null;\n\t\tthis._currentKey = '';\n\t}\n\n\tget currentAnimationKey() { return this._currentKey; }\n\tget animations() { return this._animations; }\n}\n","import { Color, Material, Vector2, Vector3 } from 'three';\nimport {\n\tMeshPhongMaterial,\n\tMeshStandardMaterial,\n\tRepeatWrapping,\n\tShaderMaterial,\n} from 'three';\nimport {\n\tMeshBasicNodeMaterial,\n\tMeshStandardNodeMaterial,\n} from 'three/webgpu';\nimport { shortHash, sortedStringify } from '../core/utility/strings';\nimport { standardShader } from './shaders/standard.shader';\nimport { assetManager } from '../core/asset-manager';\n\n/**\n * GLSL shader object (traditional approach for WebGL)\n */\nexport type ZylemShaderObject = { fragment: string; vertex: string };\n\n/**\n * TSL shader type (for WebGPU)\n * colorNode should be a TSL node that returns the fragment color\n */\nexport type ZylemTSLShader = {\n\tcolorNode: any; // TSL node - use any since Three.js types are still evolving\n\ttransparent?: boolean;\n};\n\n/**\n * Combined shader type supporting both GLSL and TSL\n */\nexport type ZylemShader = ZylemShaderObject | ZylemTSLShader;\n\n/**\n * Check if a shader is a TSL shader\n */\nexport function isTSLShader(shader: ZylemShader): shader is ZylemTSLShader {\n\treturn 'colorNode' in shader;\n}\n\n/**\n * Check if a shader is a GLSL shader\n */\nexport function isGLSLShader(shader: ZylemShader): shader is ZylemShaderObject {\n\treturn 'fragment' in shader && 'vertex' in shader;\n}\n\nexport interface MaterialOptions {\n\tpath?: string;\n\tnormalMap?: string;\n\trepeat?: Vector2;\n\tshader?: ZylemShader;\n\tcolor?: Color;\n\t/**\n\t * When true, prefer TSL/NodeMaterial (for WebGPU)\n\t * When false, prefer GLSL/ShaderMaterial (for WebGL)\n\t */\n\tuseTSL?: boolean;\n}\n\ntype BatchGeometryMap = Map<symbol, number>;\n\ninterface BatchMaterialMapObject {\n\tgeometryMap: BatchGeometryMap;\n\tmaterial: Material;\n}\n\ntype BatchKey = ReturnType<typeof shortHash>;\n\nexport type TexturePath = string | null;\n\nexport class MaterialBuilder {\n\tstatic batchMaterialMap: Map<BatchKey, BatchMaterialMapObject> = new Map();\n\n\tmaterials: Material[] = [];\n\n\t/** Whether to use TSL/NodeMaterial (for WebGPU compatibility) */\n\tprivate useTSL: boolean;\n\n\tconstructor(useTSL: boolean = false) {\n\t\tthis.useTSL = useTSL;\n\t}\n\n\tbatchMaterial(options: Partial<MaterialOptions>, entityType: symbol) {\n\t\tconst batchKey = shortHash(sortedStringify(options));\n\t\tconst mappedObject = MaterialBuilder.batchMaterialMap.get(batchKey);\n\t\tif (mappedObject) {\n\t\t\tconst count = mappedObject.geometryMap.get(entityType);\n\t\t\tif (count) {\n\t\t\t\tmappedObject.geometryMap.set(entityType, count + 1);\n\t\t\t} else {\n\t\t\t\tmappedObject.geometryMap.set(entityType, 1);\n\t\t\t}\n\t\t} else {\n\t\t\tMaterialBuilder.batchMaterialMap.set(batchKey, {\n\t\t\t\tgeometryMap: new Map([[entityType, 1]]),\n\t\t\t\tmaterial: this.materials[0],\n\t\t\t});\n\t\t}\n\t}\n\n\tbuild(options: Partial<MaterialOptions>, entityType: symbol): void {\n\t\tconst { path, normalMap, repeat, color, shader, useTSL } = options;\n\t\t\n\t\t// Override TSL preference if specified in options\n\t\tconst shouldUseTSL = useTSL ?? this.useTSL;\n\n\t\t// If shader is provided, use it\n\t\tif (shader) {\n\t\t\tif (isTSLShader(shader)) {\n\t\t\t\t// TSL shader provided directly\n\t\t\t\tthis.setTSLShader(shader);\n\t\t\t} else if (isGLSLShader(shader)) {\n\t\t\t\t// GLSL shader provided\n\t\t\t\tif (shouldUseTSL) {\n\t\t\t\t\tconsole.warn('MaterialBuilder: GLSL shader provided but TSL mode requested. Using GLSL.');\n\t\t\t\t}\n\t\t\t\tthis.setShader(shader);\n\t\t\t}\n\t\t} else if (path) {\n\t\t\t// Texture path provided\n\t\t\tthis.setTexture(path, repeat, shouldUseTSL);\n\t\t}\n\n\t\tif (color) {\n\t\t\tthis.withColor(color, shouldUseTSL);\n\t\t}\n\n\t\tif (this.materials.length === 0) {\n\t\t\tthis.setColor(new Color('#ffffff'), shouldUseTSL);\n\t\t}\n\n\t\t// Apply normal map if present (to the last added material)\n\t\tif (normalMap && this.materials.length > 0) {\n\t\t\tthis.setNormalMap(normalMap, repeat);\n\t\t}\n\n\t\tthis.batchMaterial(options, entityType);\n\t}\n\n\twithColor(color: Color, useTSL: boolean = false): this {\n\t\tthis.setColor(color, useTSL);\n\t\treturn this;\n\t}\n\n\twithShader(shader: ZylemShaderObject): this {\n\t\tthis.setShader(shader);\n\t\treturn this;\n\t}\n\n\twithTSLShader(shader: ZylemTSLShader): this {\n\t\tthis.setTSLShader(shader);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Set texture - loads in background (deferred).\n\t * Material is created immediately with null map, texture applies when loaded.\n\t */\n\tsetTexture(texturePath: TexturePath = null, repeat: Vector2 = new Vector2(1, 1), useTSL: boolean = false): void {\n\t\tif (!texturePath) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (useTSL) {\n\t\t\t// For TSL/WebGPU, use NodeMaterial\n\t\t\tconst material = new MeshStandardNodeMaterial();\n\t\t\tthis.materials.push(material);\n\n\t\t\t// Load texture in background and apply when ready\n\t\t\tassetManager.loadTexture(texturePath as string, {\n\t\t\t\tclone: true,\n\t\t\t\trepeat,\n\t\t\t}).then((texture) => {\n\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\tmaterial.map = texture;\n\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t});\n\t\t} else {\n\t\t\t// For WebGL, use traditional material\n\t\t\tconst material = new MeshPhongMaterial({\n\t\t\t\tmap: null,\n\t\t\t});\n\t\t\tthis.materials.push(material);\n\n\t\t\t// Load texture in background and apply when ready\n\t\t\tassetManager\n\t\t\t\t.loadTexture(texturePath as string, {\n\t\t\t\t\tclone: true,\n\t\t\t\t\trepeat,\n\t\t\t\t})\n\t\t\t\t.then((texture) => {\n\t\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\t\tmaterial.map = texture;\n\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Set normal map for the current material\n\t */\n\tsetNormalMap(normalMapPath: string, repeat: Vector2 = new Vector2(1, 1)): void {\n\t\tconst material = this.materials[this.materials.length - 1];\n\t\tif (!material) return;\n\n\t\tassetManager\n\t\t\t.loadTexture(normalMapPath, {\n\t\t\t\tclone: true,\n\t\t\t\trepeat,\n\t\t\t})\n\t\t\t.then((texture) => {\n\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\t\n\t\t\t\tif (material instanceof MeshStandardMaterial \n\t\t\t\t\t|| material instanceof MeshPhongMaterial\n\t\t\t\t\t|| material instanceof MeshStandardNodeMaterial) {\n\t\t\t\t\tmaterial.normalMap = texture;\n\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t} else if (material instanceof ShaderMaterial) {\n\t\t\t\t\t// Support for custom shaders if they have tNormal or normalMap uniform\n\t\t\t\t\tif (material.uniforms.tNormal) {\n\t\t\t\t\t\tmaterial.uniforms.tNormal.value = texture;\n\t\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (material.uniforms.normalMap) {\n\t\t\t\t\t\tmaterial.uniforms.normalMap.value = texture;\n\t\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tsetColor(color: Color, useTSL: boolean = false) {\n\t\tif (useTSL) {\n\t\t\t// TSL/WebGPU compatible material\n\t\t\tconst material = new MeshStandardNodeMaterial();\n\t\t\tmaterial.color = color;\n\t\t\tthis.materials.push(material);\n\t\t} else {\n\t\t\t// WebGL compatible material\n\t\t\tconst material = new MeshStandardMaterial({\n\t\t\t\tcolor: color,\n\t\t\t\temissiveIntensity: 0.5,\n\t\t\t\tlightMapIntensity: 0.5,\n\t\t\t\tfog: true,\n\t\t\t});\n\t\t\tthis.materials.push(material);\n\t\t}\n\t}\n\n\t/**\n\t * Set GLSL shader (WebGL only)\n\t */\n\tsetShader(customShader: ZylemShaderObject) {\n\t\tconst { fragment, vertex } = customShader ?? standardShader;\n\n\t\tconst shader = new ShaderMaterial({\n\t\t\tuniforms: {\n\t\t\t\tiResolution: { value: new Vector3(1, 1, 1) },\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\tnormalMap: { value: null },\n\t\t\t\tlightDir: { value: new Vector3(1, 1, 1) },\n\t\t\t\tnormalStrength: { value: 1.0 },\n\t\t\t},\n\t\t\tvertexShader: vertex,\n\t\t\tfragmentShader: fragment,\n\t\t\ttransparent: true,\n\t\t});\n\t\tthis.materials.push(shader);\n\t}\n\n\t/**\n\t * Set TSL shader (WebGPU compatible)\n\t */\n\tsetTSLShader(tslShader: ZylemTSLShader) {\n\t\tconst material = new MeshBasicNodeMaterial();\n\t\tmaterial.colorNode = tslShader.colorNode;\n\t\tif (tslShader.transparent) {\n\t\t\tmaterial.transparent = true;\n\t\t}\n\t\tthis.materials.push(material);\n\t}\n}\n\n// Re-export TSL utilities for shader authoring\nexport {\n\tuniform,\n\tuv,\n\ttime,\n\tvec3,\n\tvec4,\n\tfloat,\n\tFn,\n} from 'three/tsl';\n","export function sortedStringify(obj: Record<string, any>) {\n\tconst sortedObj = Object.keys(obj)\n\t\t.sort()\n\t\t.reduce((acc: Record<string, any>, key: string) => {\n\t\t\tacc[key] = obj[key];\n\t\t\treturn acc;\n\t\t}, {} as Record<string, any>);\n\n\treturn JSON.stringify(sortedObj);\n}\n\nexport function shortHash(objString: string) {\n\tlet hash = 0;\n\tfor (let i = 0; i < objString.length; i++) {\n\t\thash = Math.imul(31, hash) + objString.charCodeAt(i) | 0;\n\t}\n\treturn hash.toString(36);\n}","import {\n\tScene,\n\tColor,\n\tAmbientLight,\n\tDirectionalLight,\n\tObject3D,\n\tVector3,\n\tGridHelper,\n\tBoxGeometry,\n\tShaderMaterial,\n\tMesh,\n\tBackSide,\n\tMaterial,\n\tTexture,\n\tLight,\n} from 'three';\nimport { MeshBasicNodeMaterial } from 'three/webgpu';\nimport { Entity, LifecycleFunction } from '../interfaces/entity';\nimport { GameEntity } from '../entities/entity';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { debugState } from '../debug/debug-state';\nimport { SetupFunction } from '../core/base-node-life-cycle';\nimport { getGlobals } from '../game/game-state';\nimport { assetManager } from '../core/asset-manager';\nimport { ZylemShader, isTSLShader, isGLSLShader } from './material';\n\ninterface SceneState {\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader?: ZylemShader | null;\n}\n\nexport class ZylemScene implements Entity<ZylemScene> {\n\tpublic type = 'Scene';\n\n\t_setup?: SetupFunction<ZylemScene>;\n\tscene!: Scene;\n\t/** @deprecated Use cameraManager instead */\n\tzylemCamera!: ZylemCamera;\n\tcameraManager: CameraManager | null = null;\n\tcontainerElement: HTMLElement | null = null;\n\tupdate: LifecycleFunction<ZylemScene> = () => { };\n\t_collision?: ((entity: any, other: any, globals?: any) => void) | undefined;\n\t_destroy?: ((globals?: any) => void) | undefined;\n\tname?: string | undefined;\n\ttag?: Set<string> | undefined;\n\n\t// Skybox for background shaders (supports both GLSL ShaderMaterial and TSL MeshBasicNodeMaterial)\n\tprivate skyboxMaterial: Material | null = null;\n\n\tconstructor(id: string, camera: ZylemCamera, state: SceneState) {\n\t\tconst scene = new Scene();\n\t\tconst isColor = state.backgroundColor instanceof Color;\n\t\tconst backgroundColor = (isColor) ? state.backgroundColor : new Color(state.backgroundColor);\n\t\tscene.background = backgroundColor as Color;\n\t\t\n\t\tconsole.log('ZylemScene state.backgroundShader:', state.backgroundShader);\n\t\t\n\t\tif (state.backgroundShader) {\n\t\t\tthis.setupBackgroundShader(scene, state.backgroundShader);\n\t\t} else if (state.backgroundImage) {\n\t\t\t// Load background image asynchronously via asset manager\n\t\t\tassetManager.loadTexture(state.backgroundImage).then(texture => {\n\t\t\t\tscene.background = texture;\n\t\t\t});\n\t\t}\n\n\t\tthis.scene = scene;\n\t\tthis.zylemCamera = camera;\n\n\t\tthis.setupLighting(scene);\n\t\tif (debugState.enabled) {\n\t\t\tthis.debugScene();\n\t\t}\n\t}\n\n\t/**\n\t * Create a large inverted box with the shader for skybox effect\n\t * Supports both GLSL (ShaderMaterial) and TSL (MeshBasicNodeMaterial) shaders\n\t */\n\tprivate setupBackgroundShader(scene: Scene, shader: ZylemShader) {\n\t\t// Clear the solid color background\n\t\tscene.background = null;\n\n\t\tif (isTSLShader(shader)) {\n\t\t\t// TSL shader - use MeshBasicNodeMaterial for WebGPU\n\t\t\tthis.skyboxMaterial = new MeshBasicNodeMaterial();\n\t\t\t(this.skyboxMaterial as MeshBasicNodeMaterial).colorNode = shader.colorNode;\n\t\t\tif (shader.transparent) {\n\t\t\t\tthis.skyboxMaterial.transparent = true;\n\t\t\t}\n\t\t\tthis.skyboxMaterial.side = BackSide;\n\t\t\tthis.skyboxMaterial.depthWrite = false;\n\t\t\tconsole.log('Skybox created with TSL shader');\n\t\t} else if (isGLSLShader(shader)) {\n\t\t\t// GLSL shader - use ShaderMaterial for WebGL\n\t\t\t// Skybox vertex shader with depth trick (pos.xyww ensures depth = 1.0)\n\t\t\tconst skyboxVertexShader = `\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec3 vWorldPosition;\n\t\t\t\t\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvec4 worldPosition = modelMatrix * vec4(position, 1.0);\n\t\t\t\t\tvWorldPosition = worldPosition.xyz;\n\t\t\t\t\tvec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n\t\t\t\t\tgl_Position = pos.xyww; // Ensures depth is always 1.0 (farthest)\n\t\t\t\t}\n\t\t\t`;\n\n\t\t\t// Create shader material with skybox-specific settings\n\t\t\tthis.skyboxMaterial = new ShaderMaterial({\n\t\t\t\tvertexShader: skyboxVertexShader,\n\t\t\t\tfragmentShader: shader.fragment,\n\t\t\t\tuniforms: {\n\t\t\t\t\tiTime: { value: 0.0 },\n\t\t\t\t},\n\t\t\t\tside: BackSide, // Render on inside of geometry\n\t\t\t\tdepthWrite: false, // Don't write to depth buffer\n\t\t\t\tdepthTest: true, // But do test depth\n\t\t\t});\n\t\t\tconsole.log('Skybox created with GLSL shader');\n\t\t}\n\n\t\t// Use BoxGeometry for skybox\n\t\tconst geometry = new BoxGeometry(1, 1, 1);\n\t\tconst skybox = new Mesh(geometry, this.skyboxMaterial!);\n\t\tskybox.scale.setScalar(100000); // Scale up significantly\n\t\tskybox.frustumCulled = false; // Always render\n\t\tscene.add(skybox);\n\t}\n\n\tsetup() {\n\t\tif (this._setup) {\n\t\t\tthis._setup({ me: this, camera: this.zylemCamera, globals: getGlobals() });\n\t\t}\n\t}\n\n\tdestroy() {\n\t\t// Destroy via camera manager if available, otherwise legacy single camera\n\t\tif (this.cameraManager) {\n\t\t\tthis.cameraManager.dispose();\n\t\t\tthis.cameraManager = null;\n\t\t} else if (this.zylemCamera && (this.zylemCamera as any).destroy) {\n\t\t\t(this.zylemCamera as any).destroy();\n\t\t}\n\t\tif (this.skyboxMaterial) {\n\t\t\tthis.skyboxMaterial.dispose();\n\t\t}\n\t\tif (this.scene) {\n\t\t\t// Dispose background texture if present\n\t\t\tif (this.scene.background instanceof Texture) {\n\t\t\t\tthis.scene.background.dispose();\n\t\t\t\tthis.scene.background = null;\n\t\t\t}\n\n\t\t\tthis.scene.traverse((obj: any) => {\n\t\t\t\tif (obj.geometry) {\n\t\t\t\t\tobj.geometry.dispose?.();\n\t\t\t\t}\n\t\t\t\tif (obj.material) {\n\t\t\t\t\tconst materials = Array.isArray(obj.material) ? obj.material : [obj.material];\n\t\t\t\t\tfor (const mat of materials) {\n\t\t\t\t\t\t// Dispose all texture maps on the material\n\t\t\t\t\t\tif (mat.map) mat.map.dispose?.();\n\t\t\t\t\t\tif (mat.normalMap) mat.normalMap.dispose?.();\n\t\t\t\t\t\tif (mat.aoMap) mat.aoMap.dispose?.();\n\t\t\t\t\t\tif (mat.emissiveMap) mat.emissiveMap.dispose?.();\n\t\t\t\t\t\tif (mat.roughnessMap) mat.roughnessMap.dispose?.();\n\t\t\t\t\t\tif (mat.metalnessMap) mat.metalnessMap.dispose?.();\n\t\t\t\t\t\tif (mat.envMap) mat.envMap.dispose?.();\n\t\t\t\t\t\tif (mat.lightMap) mat.lightMap.dispose?.();\n\t\t\t\t\t\tif (mat.bumpMap) mat.bumpMap.dispose?.();\n\t\t\t\t\t\tif (mat.displacementMap) mat.displacementMap.dispose?.();\n\t\t\t\t\t\tif (mat.alphaMap) mat.alphaMap.dispose?.();\n\t\t\t\t\t\tmat.dispose?.();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Dispose shadow map render targets on lights\n\t\t\t\tif ((obj as Light).isLight && (obj as any).shadow?.map) {\n\t\t\t\t\t(obj as any).shadow.map.dispose();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.scene.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Setup camera with the scene.\n\t * Supports both legacy single camera and CameraManager modes.\n\t */\n\tsetupCamera(scene: Scene, camera: ZylemCamera, rendererManager?: RendererManager) {\n\t\t// Add camera rig or camera directly to scene\n\t\tthis.addCameraToScene(scene, camera);\n\n\t\tif (rendererManager) {\n\t\t\t// New path: camera setup with shared renderer manager\n\t\t\tcamera.setup(scene, rendererManager);\n\t\t} else {\n\t\t\t// Legacy path: camera handles its own renderer\n\t\t\tcamera.setupLegacy(scene);\n\t\t}\n\t}\n\n\t/**\n\t * Setup with a CameraManager (multi-camera support).\n\t */\n\tasync setupCameraManager(scene: Scene, cameraManager: CameraManager, rendererManager: RendererManager): Promise<void> {\n\t\tthis.cameraManager = cameraManager;\n\n\t\t// Add all active cameras to the scene\n\t\tfor (const camera of cameraManager.activeCameras) {\n\t\t\tthis.addCameraToScene(scene, camera);\n\t\t}\n\n\t\t// Setup the camera manager (initializes all cameras)\n\t\tawait cameraManager.setup(scene, rendererManager);\n\t}\n\n\t/**\n\t * Add a camera (rig or direct) to the scene graph.\n\t */\n\tprivate addCameraToScene(scene: Scene, camera: ZylemCamera): void {\n\t\tif (camera.cameraRig) {\n\t\t\tscene.add(camera.cameraRig);\n\t\t} else {\n\t\t\tscene.add(camera.camera as Object3D);\n\t\t}\n\t}\n\n\t/**\n\t * Setup scene lighting\n\t */\n\tsetupLighting(scene: Scene) {\n\t\tconst ambientLight = new AmbientLight(0xffffff, 2);\n\t\tscene.add(ambientLight);\n\n\t\tconst directionalLight = new DirectionalLight(0xffffff, 2);\n\t\tdirectionalLight.name = 'Light';\n\t\tdirectionalLight.position.set(0, 100, 0);\n\t\tdirectionalLight.castShadow = true;\n\t\tdirectionalLight.shadow.camera.near = 0.1;\n\t\tdirectionalLight.shadow.camera.far = 2000;\n\t\tdirectionalLight.shadow.camera.left = -100;\n\t\tdirectionalLight.shadow.camera.right = 100;\n\t\tdirectionalLight.shadow.camera.top = 100;\n\t\tdirectionalLight.shadow.camera.bottom = -100;\n\t\tdirectionalLight.shadow.mapSize.width = 2048;\n\t\tdirectionalLight.shadow.mapSize.height = 2048;\n\t\tscene.add(directionalLight);\n\t}\n\n\t/**\n\t * Update renderer size - delegates to camera manager or camera\n\t */\n\tupdateRenderer(width: number, height: number) {\n\t\tif (this.cameraManager) {\n\t\t\t// Resize all cameras\n\t\t\tfor (const camera of this.cameraManager.allCameras) {\n\t\t\t\tcamera.resize(width, height);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.zylemCamera.resize(width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Add object to scene\n\t */\n\tadd(object: Object3D, position: Vector3 = new Vector3(0, 0, 0)) {\n\t\tobject.position.set(position.x, position.y, position.z);\n\t\tthis.scene.add(object);\n\t}\n\n\t/**\n\t * Add game entity to scene\n\t */\n\taddEntity(entity: GameEntity<any>) {\n\t\tif (entity.group) {\n\t\t\tthis.add(entity.group, entity.options.position);\n\t\t} else if (entity.mesh) {\n\t\t\tthis.add(entity.mesh, entity.options.position);\n\t\t}\n\t}\n\n\t/**\n\t * Add an entity's group or mesh to the scene (for late-loaded models).\n\t * Uses entity's current body position if physics is active.\n\t */\n\taddEntityGroup(entity: GameEntity<any>): void {\n\t\tconst position = entity.body\n\t\t\t? new Vector3(\n\t\t\t\tentity.body.translation().x,\n\t\t\t\tentity.body.translation().y,\n\t\t\t\tentity.body.translation().z\n\t\t\t )\n\t\t\t: entity.options.position;\n\n\t\tif (entity.group) {\n\t\t\tthis.add(entity.group, position);\n\t\t} else if (entity.mesh) {\n\t\t\tthis.add(entity.mesh, position);\n\t\t}\n\t}\n\n\t/**\n\t * Add debug helpers to scene\n\t */\n\tdebugScene() {\n\t\tconst size = 1000;\n\t\tconst divisions = 100;\n\n\t\tconst gridHelper = new GridHelper(size, divisions);\n\t\tthis.scene.add(gridHelper);\n\t}\n\n\t/**\n\t * Update skybox shader uniforms (only applies to GLSL ShaderMaterial)\n\t * TSL shaders use the time node which auto-updates\n\t */\n\tupdateSkybox(delta: number) {\n\t\tif (this.skyboxMaterial && this.skyboxMaterial instanceof ShaderMaterial) {\n\t\t\tif (this.skyboxMaterial.uniforms?.iTime) {\n\t\t\t\tthis.skyboxMaterial.uniforms.iTime.value += delta;\n\t\t\t}\n\t\t}\n\t}\n}\n","import { proxy } from 'valtio';\nimport type { GameEntity } from '../entities/entity';\n\nexport type DebugTools = 'select' | 'translate' | 'rotate' | 'scale' | 'delete' | 'none';\n\nexport interface DebugState {\n\tenabled: boolean;\n\tpaused: boolean;\n\ttool: DebugTools;\n\tselectedEntity: GameEntity<any> | null;\n\thoveredEntity: GameEntity<any> | null;\n\tflags: Set<string>;\n}\n\nexport const debugState = proxy<DebugState>({\n\tenabled: false,\n\tpaused: false,\n\ttool: 'none',\n\tselectedEntity: null,\n\thoveredEntity: null,\n\tflags: new Set(),\n});\n\nexport function isPaused(): boolean {\n\treturn debugState.paused;\n}\n\nexport function setPaused(paused: boolean): void {\n\tdebugState.paused = paused;\n}\n\nexport function setDebugFlag(flag: string, value: boolean): void {\n\tif (value) {\n\t\tdebugState.flags.add(flag);\n\t} else {\n\t\tdebugState.flags.delete(flag);\n\t}\n}\n\nexport function getDebugTool(): DebugTools {\n\treturn debugState.tool;\n}\n\nexport function setDebugTool(tool: DebugTools): void {\n\tdebugState.tool = tool;\n}\n\nexport function getSelectedEntity(): GameEntity<any> | null {\n\treturn debugState.selectedEntity;\n}\n\nexport function setSelectedEntity(entity: GameEntity<any> | null): void {\n\tdebugState.selectedEntity = entity;\n}\n\nexport function getHoveredEntity(): GameEntity<any> | null {\n\treturn debugState.hoveredEntity;\n}\n\nexport function setHoveredEntity(entity: GameEntity<any> | null): void {\n\tdebugState.hoveredEntity = entity;\n}\n\nexport function resetHoveredEntity(): void {\n\tdebugState.hoveredEntity = null;\n}\n","import { BufferGeometry, InstancedMesh, Material, Matrix4, Object3D, Vector3, Quaternion } from 'three';\nimport type { GameEntity, GameEntityOptions } from '../entities/entity';\nimport { shortHash, sortedStringify } from '../core/utility/strings';\n\n/**\n * Represents a batch of entities sharing the same geometry and material\n */\nexport interface BatchGroup {\n\t/** Unique key identifying this batch */\n\tkey: string;\n\t/** The instanced mesh for rendering */\n\tinstancedMesh: InstancedMesh;\n\t/** Original geometry */\n\tgeometry: BufferGeometry;\n\t/** Original material */\n\tmaterial: Material;\n\t/** Map of entity UUID to instance index */\n\tentityMap: Map<string, number>;\n\t/** List of entities in this batch (by their index) */\n\tentities: (GameEntity<any> | null)[];\n\t/** Indices that have been freed and can be reused */\n\tfreeIndices: number[];\n\t/** Active indices for fast iteration */\n\tactiveIndices: number[];\n\t/** Dirty flags for transforms that need syncing */\n\tdirtyIndices: Set<number>;\n\t/** Maximum capacity */\n\tcapacity: number;\n}\n\n/**\n * Configuration for batch key generation\n */\nexport interface BatchKeyConfig {\n\tgeometryType: string;\n\tdimensions: Record<string, number>;\n\tmaterialPath?: string | null;\n\tshaderType?: 'standard' | 'custom';\n\tcolorHex?: number;\n}\n\n/**\n * Manages instanced mesh batching for entities\n */\nexport class InstanceManager {\n\tprivate batches: Map<string, BatchGroup> = new Map();\n\tprivate entityToBatch: Map<string, string> = new Map(); // entity UUID -> batch key\n\tprivate scene: Object3D | null = null;\n\n\t/** Default initial capacity for new batches */\n\tstatic DEFAULT_CAPACITY = 128;\n\t/** Factor to grow batch when full */\n\tstatic GROWTH_FACTOR = 2;\n\n\t/**\n\t * Set the scene to add instanced meshes to\n\t */\n\tsetScene(scene: Object3D): void {\n\t\tthis.scene = scene;\n\t}\n\n\t/**\n\t * Generate a batch key from configuration\n\t */\n\tstatic generateBatchKey(config: BatchKeyConfig): string {\n\t\tconst keyData = {\n\t\t\tgeo: `${config.geometryType}:${sortedStringify(config.dimensions)}`,\n\t\t\tmat: config.materialPath || 'none',\n\t\t\tshader: config.shaderType || 'standard',\n\t\t\tcolor: config.colorHex ?? 0xffffff,\n\t\t};\n\t\treturn shortHash(sortedStringify(keyData));\n\t}\n\n\t/**\n\t * Register an entity with the instance manager\n\t * @returns The instance index, or -1 if registration failed\n\t */\n\tregister(\n\t\tentity: GameEntity<any>,\n\t\tgeometry: BufferGeometry,\n\t\tmaterial: Material,\n\t\tbatchKey: string\n\t): number {\n\t\tlet batch = this.batches.get(batchKey);\n\n\t\tif (!batch) {\n\t\t\tbatch = this.createBatch(batchKey, geometry, material);\n\t\t}\n\n\t\t// Get an index for this entity\n\t\tlet index: number;\n\t\tif (batch.freeIndices.length > 0) {\n\t\t\tindex = batch.freeIndices.pop()!;\n\t\t} else {\n\t\t\tindex = batch.entities.length;\n\t\t\tif (index >= batch.capacity) {\n\t\t\t\tthis.growBatch(batch);\n\t\t\t}\n\t\t\tbatch.entities.push(null);\n\t\t}\n\n\t\t// Store entity reference\n\t\tbatch.entities[index] = entity;\n\t\tbatch.entityMap.set(entity.uuid, index);\n\t\tthis.entityToBatch.set(entity.uuid, batchKey);\n\n\t\t// Update visible instance count\n\t\tbatch.instancedMesh.count = Math.max(batch.instancedMesh.count, index + 1);\n\n\t\t// Add to active list\n\t\tbatch.activeIndices.push(index);\n\n\t\t// Mark dirty for initial transform sync\n\t\tbatch.dirtyIndices.add(index);\n\n\t\treturn index;\n\t}\n\n\t/**\n\t * Unregister an entity from the instance manager\n\t */\n\tunregister(entity: GameEntity<any>): void {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return;\n\n\t\tconst index = batch.entityMap.get(entity.uuid);\n\t\tif (index === undefined) return;\n\n\t\t// Clear the entity slot\n\t\tbatch.entities[index] = null;\n\t\tbatch.entityMap.delete(entity.uuid);\n\t\tthis.entityToBatch.delete(entity.uuid);\n\t\tbatch.freeIndices.push(index);\n\t\t// Remove from active list (swap and pop for O(1))\n\t\tconst idxInActive = batch.activeIndices.indexOf(index);\n\t\tif (idxInActive !== -1) {\n\t\t\tconst last = batch.activeIndices.pop()!;\n\t\t\tif (idxInActive < batch.activeIndices.length) {\n\t\t\t\tbatch.activeIndices[idxInActive] = last;\n\t\t\t}\n\t\t}\n\t\tbatch.dirtyIndices.delete(index);\n\n\t\t// Hide the instance by scaling to zero\n\t\tconst matrix = new Matrix4();\n\t\tmatrix.makeScale(0, 0, 0);\n\t\tbatch.instancedMesh.setMatrixAt(index, matrix);\n\t\tbatch.instancedMesh.instanceMatrix.needsUpdate = true;\n\t}\n\n\t/**\n\t * Mark an entity's transform as dirty (needs syncing)\n\t */\n\tmarkDirty(entity: GameEntity<any>): void {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return;\n\n\t\tconst index = batch.entityMap.get(entity.uuid);\n\t\tif (index !== undefined) {\n\t\t\tbatch.dirtyIndices.add(index);\n\t\t}\n\t}\n\n\t/**\n\t * Update all dirty instance transforms\n\t * Call this once per frame\n\t */\n\t/**\n\t * Update all active instance transforms\n\t * Call this once per frame\n\t */\n\tupdate(): void {\n\t\tconst matrix = new Matrix4();\n\t\tconst pos = new Vector3();\n\t\tconst quat = new Quaternion();\n\t\tconst scale = new Vector3(1, 1, 1);\n\n\t\tfor (const batch of this.batches.values()) {\n\t\t\tif (batch.activeIndices.length === 0) continue;\n\n\t\t\tlet needsUpdate = false;\n\t\t\t// Check if we have explicit dirty updates\n\t\t\tif (batch.dirtyIndices.size > 0) {\n\t\t\t\tfor (const index of batch.dirtyIndices) {\n\t\t\t\t\tthis.updateInstanceMatrix(batch, index, matrix, pos, quat, scale);\n\t\t\t\t}\n\t\t\t\tbatch.dirtyIndices.clear();\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\n\t\t\t// Also update all active dynamic entities (assumed dynamic if they have a body)\n\t\t\tfor (const index of batch.activeIndices) {\n\t\t\t\tconst entity = batch.entities[index];\n\t\t\t\t// Optimization: Only update if it has a physics body (dynamic)\n\t\t\t\tif (entity && entity.body) {\n\t\t\t\t\tthis.updateInstanceMatrix(batch, index, matrix, pos, quat, scale);\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (needsUpdate) {\n\t\t\t\tbatch.instancedMesh.instanceMatrix.needsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateInstanceMatrix(batch: BatchGroup, index: number, matrix: Matrix4, pos: Vector3, quat: Quaternion, scale: Vector3) {\n\t\tconst entity = batch.entities[index];\n\t\tif (!entity) return;\n\n\t\tif (entity.body) {\n\t\t\tconst translation = entity.body.translation();\n\t\t\tconst rotation = entity.body.rotation();\n\t\t\tpos.set(translation.x, translation.y, translation.z);\n\t\t\tquat.set(rotation.x, rotation.y, rotation.z, rotation.w);\n\t\t\tmatrix.compose(pos, quat, scale);\n\t\t} else if (entity.mesh) {\n\t\t\tentity.mesh.updateMatrix();\n\t\t\tmatrix.copy(entity.mesh.matrix);\n\t\t} else if (entity.group) {\n\t\t\tentity.group.updateMatrix();\n\t\t\tmatrix.copy(entity.group.matrix);\n\t\t}\n\n\t\tbatch.instancedMesh.setMatrixAt(index, matrix);\n\t}\n\n\t/**\n\t * Get batch info for an entity\n\t */\n\tgetBatchInfo(entity: GameEntity<any>): { batchKey: string; instanceId: number } | null {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return null;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return null;\n\n\t\tconst instanceId = batch.entityMap.get(entity.uuid);\n\t\tif (instanceId === undefined) return null;\n\n\t\treturn { batchKey, instanceId };\n\t}\n\n\t/**\n\t * Get statistics about current batching\n\t */\n\tgetStats(): { batchCount: number; totalInstances: number; batches: { key: string; count: number; capacity: number }[] } {\n\t\tlet totalInstances = 0;\n\t\tconst batches: { key: string; count: number; capacity: number }[] = [];\n\n\t\tfor (const [key, batch] of this.batches) {\n\t\t\tconst count = batch.entityMap.size;\n\t\t\ttotalInstances += count;\n\t\t\tbatches.push({ key, count, capacity: batch.capacity });\n\t\t}\n\n\t\treturn { batchCount: this.batches.size, totalInstances, batches };\n\t}\n\n\t/**\n\t * Dispose all batches and release resources\n\t */\n\tdispose(): void {\n\t\tfor (const batch of this.batches.values()) {\n\t\t\tif (this.scene) {\n\t\t\t\tthis.scene.remove(batch.instancedMesh);\n\t\t\t}\n\t\t\tbatch.instancedMesh.dispose();\n\t\t\tbatch.geometry.dispose();\n\t\t}\n\t\tthis.batches.clear();\n\t\tthis.entityToBatch.clear();\n\t}\n\n\t/**\n\t * Create a new batch group\n\t */\n\tprivate createBatch(key: string, geometry: BufferGeometry, material: Material): BatchGroup {\n\t\tconst capacity = InstanceManager.DEFAULT_CAPACITY;\n\t\tconst instancedMesh = new InstancedMesh(geometry, material, capacity);\n\t\tinstancedMesh.count = 0; // Start with zero visible instances\n\t\tinstancedMesh.frustumCulled = false; // Let individual instances handle culling\n\n\t\t// Initialize all matrices to hidden (zero scale)\n\t\tconst hiddenMatrix = new Matrix4().makeScale(0, 0, 0);\n\t\tfor (let i = 0; i < capacity; i++) {\n\t\t\tinstancedMesh.setMatrixAt(i, hiddenMatrix);\n\t\t}\n\t\tinstancedMesh.instanceMatrix.needsUpdate = true;\n\n\t\tconst batch: BatchGroup = {\n\t\t\tkey,\n\t\t\tinstancedMesh,\n\t\t\tgeometry,\n\t\t\tmaterial,\n\t\t\tentityMap: new Map(),\n\t\t\tentities: [],\n\t\t\tfreeIndices: [],\n\t\t\tactiveIndices: [],\n\t\t\tdirtyIndices: new Set(),\n\t\t\tcapacity,\n\t\t};\n\n\t\tthis.batches.set(key, batch);\n\n\t\tif (this.scene) {\n\t\t\tthis.scene.add(instancedMesh);\n\t\t}\n\n\t\treturn batch;\n\t}\n\n\t/**\n\t * Grow a batch's capacity\n\t */\n\tprivate growBatch(batch: BatchGroup): void {\n\t\tconst newCapacity = batch.capacity * InstanceManager.GROWTH_FACTOR;\n\n\t\t// Create new instanced mesh with larger capacity\n\t\tconst newInstancedMesh = new InstancedMesh(batch.geometry, batch.material, newCapacity);\n\t\tnewInstancedMesh.count = batch.instancedMesh.count;\n\t\tnewInstancedMesh.frustumCulled = false;\n\n\t\t// Copy existing matrices\n\t\tconst matrix = new Matrix4();\n\t\tfor (let i = 0; i < batch.capacity; i++) {\n\t\t\tbatch.instancedMesh.getMatrixAt(i, matrix);\n\t\t\tnewInstancedMesh.setMatrixAt(i, matrix);\n\t\t}\n\n\t\t// Initialize new slots as hidden\n\t\tconst hiddenMatrix = new Matrix4().makeScale(0, 0, 0);\n\t\tfor (let i = batch.capacity; i < newCapacity; i++) {\n\t\t\tnewInstancedMesh.setMatrixAt(i, hiddenMatrix);\n\t\t}\n\t\tnewInstancedMesh.instanceMatrix.needsUpdate = true;\n\n\t\t// Swap meshes\n\t\tif (this.scene) {\n\t\t\tthis.scene.remove(batch.instancedMesh);\n\t\t\tthis.scene.add(newInstancedMesh);\n\t\t}\n\t\tbatch.instancedMesh.dispose();\n\t\tbatch.instancedMesh = newInstancedMesh;\n\t\tbatch.capacity = newCapacity;\n\t}\n}\n","import { Color, Vector3 } from 'three';\nimport { proxy, subscribe } from 'valtio/vanilla';\nimport { BaseEntityInterface, GameEntityInterface } from '../types/entity-types';\nimport { StageStateInterface } from '../types/stage-types';\nimport { getByPath, setByPath } from '../core/utility/path-utils';\nimport { ZylemBlueColor } from '../core/utility/vector';\n\n/**\n * Initial stage state with default values.\n * Exported for use in ZylemStage construction.\n */\nexport const initialStageState = {\n\tbackgroundColor: ZylemBlueColor,\n\tbackgroundImage: null,\n\tbackgroundShader: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard'],\n\t\tp2: ['gamepad-2', 'keyboard'],\n\t},\n\tgravity: new Vector3(0, 0, 0),\n\tvariables: {},\n\tentities: [] as GameEntityInterface[],\n};\n\n/**\n * Stage state proxy for reactive updates.\n */\nconst stageState = proxy({\n\tbackgroundColor: new Color(Color.NAMES.cornflowerblue),\n\tbackgroundImage: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard-1'],\n\t\tp2: ['gamepad-2', 'keyboard-2'],\n\t},\n\tvariables: {},\n\tgravity: new Vector3(0, 0, 0),\n\tentities: [],\n} as StageStateInterface);\n\n// ============================================================\n// Stage state setters (internal use)\n// ============================================================\n\nconst setStageBackgroundColor = (value: Color) => {\n\tstageState.backgroundColor = value;\n};\n\nconst setStageBackgroundImage = (value: string | null) => {\n\tstageState.backgroundImage = value;\n};\n\nconst setEntitiesToStage = (entities: Partial<BaseEntityInterface>[]) => {\n\tstageState.entities = entities;\n};\n\n/** Replace the entire stage variables object (used on stage load). */\nconst setStageVariables = (variables: Record<string, any>) => {\n\tstageState.variables = { ...variables };\n};\n\n/** Reset all stage variables (used on stage unload). */\nconst resetStageVariables = () => {\n\tstageState.variables = {};\n};\n\nconst stageStateToString = (state: StageStateInterface) => {\n\tlet string = `\\n`;\n\tfor (const key in state) {\n\t\tconst value = state[key as keyof StageStateInterface];\n\t\tstring += `${key}:\\n`;\n\t\tif (key === 'entities') {\n\t\t\tfor (const entity of state.entities) {\n\t\t\t\tstring += ` ${entity.uuid}: ${entity.name}\\n`;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === 'object' && value !== null) {\n\t\t\tfor (const subKey in value as Record<string, any>) {\n\t\t\t\tconst subValue = value?.[subKey as keyof typeof value];\n\t\t\t\tif (subValue) {\n\t\t\t\t\tstring += ` ${subKey}: ${subValue}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (typeof value === 'string') {\n\t\t\tstring += ` ${key}: ${value}\\n`;\n\t\t}\n\t}\n\treturn string;\n};\n\n// ============================================================\n// Object-scoped variable storage (WeakMap-based)\n// ============================================================\n\n/**\n * WeakMap to store variables keyed by object reference.\n * Variables are automatically garbage collected when the target is collected.\n */\nconst variableStore = new WeakMap<object, Record<string, unknown>>();\n\n/**\n * Separate proxy store for reactivity. We need a regular Map for subscriptions\n * since WeakMap doesn't support iteration/subscriptions.\n */\nconst variableProxyStore = new Map<object, ReturnType<typeof proxy>>();\n\nfunction getOrCreateVariableProxy(target: object): Record<string, unknown> {\n\tlet store = variableProxyStore.get(target) as Record<string, unknown> | undefined;\n\tif (!store) {\n\t\tstore = proxy({});\n\t\tvariableProxyStore.set(target, store);\n\t}\n\treturn store;\n}\n\n/**\n * Set a variable on an object by path.\n * @example setVariable(stage1, 'totalAngle', 0.5)\n * @example setVariable(entity, 'enemy.count', 10)\n */\nexport function setVariable(target: object, path: string, value: unknown): void {\n\tconst store = getOrCreateVariableProxy(target);\n\tsetByPath(store, path, value);\n}\n\n/**\n * Create/initialize a variable with a default value on a target object.\n * Only sets the value if it doesn't already exist.\n * @example createVariable(stage1, 'totalAngle', 0)\n * @example createVariable(entity, 'enemy.count', 10)\n */\nexport function createVariable<T>(target: object, path: string, defaultValue: T): T {\n\tconst store = getOrCreateVariableProxy(target);\n\tconst existing = getByPath<T>(store, path);\n\tif (existing === undefined) {\n\t\tsetByPath(store, path, defaultValue);\n\t\treturn defaultValue;\n\t}\n\treturn existing;\n}\n\n/**\n * Get a variable from an object by path.\n * @example getVariable(stage1, 'totalAngle') // 0.5\n * @example getVariable<number>(entity, 'enemy.count') // 10\n */\nexport function getVariable<T = unknown>(target: object, path: string): T | undefined {\n\tconst store = variableProxyStore.get(target);\n\tif (!store) return undefined;\n\treturn getByPath<T>(store, path);\n}\n\n/**\n * Subscribe to changes on a variable at a specific path for a target object.\n * Returns an unsubscribe function.\n * @example const unsub = onVariableChange(stage1, 'score', (val) => console.log(val));\n */\nexport function onVariableChange<T = unknown>(\n\ttarget: object,\n\tpath: string,\n\tcallback: (value: T) => void\n): () => void {\n\tconst store = getOrCreateVariableProxy(target);\n\tlet previous = getByPath<T>(store, path);\n\treturn subscribe(store, () => {\n\t\tconst current = getByPath<T>(store, path);\n\t\tif (current !== previous) {\n\t\t\tprevious = current;\n\t\t\tcallback(current as T);\n\t\t}\n\t});\n}\n\n/**\n * Subscribe to changes on multiple variable paths for a target object.\n * Callback fires when any of the paths change, receiving all current values.\n * Returns an unsubscribe function.\n * @example const unsub = onVariableChanges(stage1, ['count', 'total'], ([count, total]) => console.log(count, total));\n */\nexport function onVariableChanges<T extends unknown[] = unknown[]>(\n\ttarget: object,\n\tpaths: string[],\n\tcallback: (values: T) => void\n): () => void {\n\tconst store = getOrCreateVariableProxy(target);\n\tlet previousValues = paths.map(p => getByPath(store, p));\n\treturn subscribe(store, () => {\n\t\tconst currentValues = paths.map(p => getByPath(store, p));\n\t\tconst hasChange = currentValues.some((val, i) => val !== previousValues[i]);\n\t\tif (hasChange) {\n\t\t\tpreviousValues = currentValues;\n\t\t\tcallback(currentValues as T);\n\t\t}\n\t});\n}\n\n/**\n * Clear all variables for a target object. Used on stage/entity dispose.\n */\nexport function clearVariables(target: object): void {\n\tvariableProxyStore.delete(target);\n}\n\n// ============================================================\n// Legacy stage variable functions (internal, for stage defaults)\n// ============================================================\n\nconst setStageVariable = (key: string, value: any) => {\n\tstageState.variables[key] = value;\n};\n\nconst getStageVariable = (key: string) => {\n\tif (stageState.variables.hasOwnProperty(key)) {\n\t\treturn stageState.variables[key];\n\t} else {\n\t\tconsole.warn(`Stage variable ${key} not found`);\n\t}\n};\n\nexport {\n\tstageState,\n\t\n\tsetStageBackgroundColor,\n\tsetStageBackgroundImage,\n\t\n\tstageStateToString,\n\tsetStageVariable,\n\tgetStageVariable,\n\tsetStageVariables,\n\tresetStageVariables,\n};","import { Color, Vector3 as ThreeVector3 } from 'three';\nimport { Vector3 } from '@dimforge/rapier3d-compat';\n\n// TODO: needs implementations\n/**\n * @deprecated This type is deprecated.\n */\nexport type Vect3 = ThreeVector3 | Vector3;\n\nexport const ZylemBlueColor = new Color('#0333EC');\nexport const ZylemBlue = '#0333EC';\nexport const ZylemBlueTransparent = '#0333ECA0';\nexport const ZylemGoldText = '#DAA420';\n\nexport const Vec0 = new Vector3(0, 0, 0);\nexport const Vec1 = new Vector3(1, 1, 1);","import { DestroyContext, DestroyFunction, SetupContext, SetupFunction, UpdateContext, UpdateFunction } from './base-node-life-cycle';\n\n/**\n * Provides BaseNode-like lifecycle without ECS/children. Consumers implement\n * the protected hooks and may assign public setup/update/destroy callbacks.\n */\nexport abstract class LifeCycleBase<TSelf> {\n\tupdate: UpdateFunction<TSelf> = () => { };\n\tsetup: SetupFunction<TSelf> = () => { };\n\tdestroy: DestroyFunction<TSelf> = () => { };\n\n\tprotected abstract _setup(context: SetupContext<TSelf>): void;\n\tprotected abstract _update(context: UpdateContext<TSelf>): void;\n\tprotected abstract _destroy(context: DestroyContext<TSelf>): void;\n\n\tnodeSetup(context: SetupContext<TSelf>) {\n\t\tif (typeof (this as any)._setup === 'function') {\n\t\t\tthis._setup(context);\n\t\t}\n\t\tif (this.setup) {\n\t\t\tthis.setup(context);\n\t\t}\n\t}\n\n\tnodeUpdate(context: UpdateContext<TSelf>) {\n\t\tif (typeof (this as any)._update === 'function') {\n\t\t\tthis._update(context);\n\t\t}\n\t\tif (this.update) {\n\t\t\tthis.update(context);\n\t\t}\n\t}\n\n\tnodeDestroy(context: DestroyContext<TSelf>) {\n\t\tif (this.destroy) {\n\t\t\tthis.destroy(context);\n\t\t}\n\t\tif (typeof (this as any)._destroy === 'function') {\n\t\t\tthis._destroy(context);\n\t\t}\n\t}\n}\n\n\n","import { Ray, RayColliderToi } from '@dimforge/rapier3d-compat';\nimport { BufferAttribute, BufferGeometry, LineBasicMaterial, LineSegments, Raycaster, Vector2, Vector3 } from 'three';\nimport { ZylemStage } from './zylem-stage';\nimport { debugState, DebugTools, getDebugTool, getHoveredEntity, resetHoveredEntity, setHoveredEntity, setSelectedEntity } from '../debug/debug-state';\nimport { DebugEntityCursor } from './debug-entity-cursor';\n\nexport type AddEntityFactory = (params: { position: Vector3; normal?: Vector3 }) => Promise<any> | any;\n\nexport interface StageDebugDelegateOptions {\n\tmaxRayDistance?: number;\n\taddEntityFactory?: AddEntityFactory | null;\n}\n\nconst SELECT_TOOL_COLOR = 0x22ff22;\nconst DELETE_TOOL_COLOR = 0xff3333;\n\nexport class StageDebugDelegate {\n\tprivate stage: ZylemStage;\n\tprivate options: Required<StageDebugDelegateOptions>;\n\tprivate mouseNdc: Vector2 = new Vector2(-2, -2);\n\tprivate raycaster: Raycaster = new Raycaster();\n\tprivate isMouseDown = false;\n\tprivate disposeFns: Array<() => void> = [];\n\tprivate debugCursor: DebugEntityCursor | null = null;\n\tprivate debugLines: LineSegments | null = null;\n\n\tconstructor(stage: ZylemStage, options?: StageDebugDelegateOptions) {\n\t\tthis.stage = stage;\n\t\tthis.options = {\n\t\t\tmaxRayDistance: options?.maxRayDistance ?? 5_000,\n\t\t\taddEntityFactory: options?.addEntityFactory ?? null,\n\t\t};\n\t\tthis.attachDomListeners();\n\t}\n\n\tprivate initDebugVisuals(): void {\n\t\tif (this.debugLines || !this.stage.scene) return;\n\n\t\tthis.debugLines = new LineSegments(\n\t\t\tnew BufferGeometry(),\n\t\t\tnew LineBasicMaterial({ vertexColors: true })\n\t\t);\n\t\tthis.stage.scene.scene.add(this.debugLines);\n\t\tthis.debugLines.visible = true;\n\n\t\tthis.debugCursor = new DebugEntityCursor(this.stage.scene.scene);\n\t}\n\n\tprivate disposeDebugVisuals(): void {\n\t\tif (this.debugLines && this.stage.scene) {\n\t\t\tthis.stage.scene.scene.remove(this.debugLines);\n\t\t\tthis.debugLines.geometry.dispose();\n\t\t\t(this.debugLines.material as LineBasicMaterial).dispose();\n\t\t\tthis.debugLines = null;\n\t\t}\n\t\tthis.debugCursor?.dispose();\n\t\tthis.debugCursor = null;\n\t}\n\n\tupdate(): void {\n\t\tif (!debugState.enabled) {\n\t\t\tif (this.debugLines) {\n\t\t\t\tthis.disposeDebugVisuals();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.stage.scene || !this.stage.world || !this.stage.cameraRef) return;\n\n\t\t// Initialize visuals if not already created\n\t\tif (!this.debugLines) {\n\t\t\tthis.initDebugVisuals();\n\t\t}\n\n\t\tconst { world, cameraRef } = this.stage;\n\n\t\tif (this.debugLines) {\n\t\t\tconst { vertices, colors } = world.world.debugRender();\n\t\t\tthis.debugLines.geometry.setAttribute('position', new BufferAttribute(vertices, 3));\n\t\t\tthis.debugLines.geometry.setAttribute('color', new BufferAttribute(colors, 4));\n\t\t}\n\t\tconst tool = getDebugTool();\n\t\tconst isCursorTool = tool === 'select' || tool === 'delete';\n\n\t\tthis.raycaster.setFromCamera(this.mouseNdc, cameraRef.camera);\n\t\tconst origin = this.raycaster.ray.origin.clone();\n\t\tconst direction = this.raycaster.ray.direction.clone().normalize();\n\n\t\tconst rapierRay = new Ray(\n\t\t\t{ x: origin.x, y: origin.y, z: origin.z },\n\t\t\t{ x: direction.x, y: direction.y, z: direction.z },\n\t\t);\n\t\tconst hit: RayColliderToi | null = world.world.castRay(rapierRay, this.options.maxRayDistance, true);\n\n\t\tif (hit && isCursorTool) {\n\t\t\t// @ts-ignore - access compat object's parent userData mapping back to GameEntity\n\t\t\tconst rigidBody = hit.collider?._parent;\n\t\t\tconst hoveredUuid: string | undefined = rigidBody?.userData?.uuid;\n\t\t\tif (hoveredUuid) {\n\t\t\t\tconst entity = this.stage._debugMap.get(hoveredUuid);\n\t\t\t\tif (entity) setHoveredEntity(entity as any);\n\t\t\t} else {\n\t\t\t\tresetHoveredEntity();\n\t\t\t}\n\n\t\t\tif (this.isMouseDown) {\n\t\t\t\tthis.handleActionOnHit(hoveredUuid ?? null, origin, direction, hit.toi);\n\t\t\t}\n\t\t}\n\t\tthis.isMouseDown = false;\n\n\t\tconst hoveredUuid = getHoveredEntity();\n\t\tif (!hoveredUuid) {\n\t\t\tthis.debugCursor?.hide();\n\t\t\treturn;\n\t\t}\n\t\tconst hoveredEntity: any = this.stage._debugMap.get(`${hoveredUuid}`);\n\t\tconst targetObject = hoveredEntity?.group ?? hoveredEntity?.mesh ?? null;\n\t\tif (!targetObject) {\n\t\t\tthis.debugCursor?.hide();\n\t\t\treturn;\n\t\t}\n\t\tswitch (tool) {\n\t\t\tcase 'select':\n\t\t\t\tthis.debugCursor?.setColor(SELECT_TOOL_COLOR);\n\t\t\t\tbreak;\n\t\t\tcase 'delete':\n\t\t\t\tthis.debugCursor?.setColor(DELETE_TOOL_COLOR);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.debugCursor?.setColor(0xffffff);\n\t\t\t\tbreak;\n\t\t}\n\t\tthis.debugCursor?.updateFromObject(targetObject);\n\t}\n\n\tdispose(): void {\n\t\tthis.disposeFns.forEach((fn) => fn());\n\t\tthis.disposeFns = [];\n\t\tthis.disposeDebugVisuals();\n\t}\n\n\tprivate handleActionOnHit(hoveredUuid: string | null, origin: Vector3, direction: Vector3, toi: number) {\n\t\tconst tool = getDebugTool();\n\t\tswitch (tool) {\n\t\t\tcase 'select': {\n\t\t\t\tif (hoveredUuid) {\n\t\t\t\t\tconst entity = this.stage._debugMap.get(hoveredUuid);\n\t\t\t\t\tif (entity) setSelectedEntity(entity as any);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'delete': {\n\t\t\t\tif (hoveredUuid) {\n\t\t\t\t\tthis.stage.removeEntityByUuid(hoveredUuid);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\tif (!this.options.addEntityFactory) break;\n\t\t\t\tconst hitPosition = origin.clone().add(direction.clone().multiplyScalar(toi));\n\t\t\t\tconst newNode = this.options.addEntityFactory({ position: hitPosition });\n\t\t\t\tif (newNode) {\n\t\t\t\t\tPromise.resolve(newNode).then((node) => {\n\t\t\t\t\t\tif (node) this.stage.spawnEntity(node);\n\t\t\t\t\t}).catch(() => { });\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate attachDomListeners() {\n\t\tconst canvas = this.stage.cameraRef?.renderer.domElement ?? this.stage.scene?.zylemCamera.renderer.domElement;\n\t\tif (!canvas) return;\n\n\t\tconst onMouseMove = (e: MouseEvent) => {\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tconst x = ((e.clientX - rect.left) / rect.width) * 2 - 1;\n\t\t\tconst y = -(((e.clientY - rect.top) / rect.height) * 2 - 1);\n\t\t\tthis.mouseNdc.set(x, y);\n\t\t};\n\n\t\tconst onMouseDown = (e: MouseEvent) => {\n\t\t\tthis.isMouseDown = true;\n\t\t};\n\n\t\tcanvas.addEventListener('mousemove', onMouseMove);\n\t\tcanvas.addEventListener('mousedown', onMouseDown);\n\n\t\tthis.disposeFns.push(() => canvas.removeEventListener('mousemove', onMouseMove));\n\t\tthis.disposeFns.push(() => canvas.removeEventListener('mousedown', onMouseDown));\n\t}\n}\n\n\n","import {\n\tBox3,\n\tBoxGeometry,\n\tColor,\n\tEdgesGeometry,\n\tGroup,\n\tLineBasicMaterial,\n\tLineSegments,\n\tMesh,\n\tMeshBasicMaterial,\n\tObject3D,\n\tScene,\n\tVector3,\n} from 'three';\n\n/**\n * Debug overlay that displays an axis-aligned bounding box around a target Object3D.\n * Shows a semi-transparent fill plus a wireframe outline. Intended for SELECT/DELETE tools.\n */\nexport class DebugEntityCursor {\n\tprivate scene: Scene;\n\tprivate container: Group;\n\tprivate fillMesh: Mesh;\n\tprivate edgeLines: LineSegments;\n\tprivate currentColor: Color = new Color(0x00ff00);\n\tprivate bbox: Box3 = new Box3();\n\tprivate size: Vector3 = new Vector3();\n\tprivate center: Vector3 = new Vector3();\n\n\tconstructor(scene: Scene) {\n\t\tthis.scene = scene;\n\n\t\tconst initialGeometry = new BoxGeometry(1, 1, 1);\n\n\t\tthis.fillMesh = new Mesh(\n\t\t\tinitialGeometry,\n\t\t\tnew MeshBasicMaterial({\n\t\t\t\tcolor: this.currentColor,\n\t\t\t\ttransparent: true,\n\t\t\t\topacity: 0.12,\n\t\t\t\tdepthWrite: false,\n\t\t\t})\n\t\t);\n\n\t\tconst edges = new EdgesGeometry(initialGeometry);\n\t\tthis.edgeLines = new LineSegments(\n\t\t\tedges,\n\t\t\tnew LineBasicMaterial({ color: this.currentColor, linewidth: 1 })\n\t\t);\n\n\t\tthis.container = new Group();\n\t\tthis.container.name = 'DebugEntityCursor';\n\t\tthis.container.add(this.fillMesh);\n\t\tthis.container.add(this.edgeLines);\n\t\tthis.container.visible = false;\n\n\t\tthis.scene.add(this.container);\n\t}\n\n\tsetColor(color: Color | number): void {\n\t\tthis.currentColor.set(color as any);\n\t\t(this.fillMesh.material as MeshBasicMaterial).color.set(this.currentColor);\n\t\t(this.edgeLines.material as LineBasicMaterial).color.set(this.currentColor);\n\t}\n\n\t/**\n\t * Update the cursor to enclose the provided Object3D using a world-space AABB.\n\t */\n\tupdateFromObject(object: Object3D | null | undefined): void {\n\t\tif (!object) {\n\t\t\tthis.hide();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.bbox.setFromObject(object);\n\t\tif (!isFinite(this.bbox.min.x) || !isFinite(this.bbox.max.x)) {\n\t\t\tthis.hide();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.bbox.getSize(this.size);\n\t\tthis.bbox.getCenter(this.center);\n\n\t\tconst newGeom = new BoxGeometry(\n\t\t\tMath.max(this.size.x, 1e-6),\n\t\t\tMath.max(this.size.y, 1e-6),\n\t\t\tMath.max(this.size.z, 1e-6)\n\t\t);\n\t\tthis.fillMesh.geometry.dispose();\n\t\tthis.fillMesh.geometry = newGeom;\n\n\t\tconst newEdges = new EdgesGeometry(newGeom);\n\t\tthis.edgeLines.geometry.dispose();\n\t\tthis.edgeLines.geometry = newEdges;\n\n\t\tthis.container.position.copy(this.center);\n\t\tthis.container.visible = true;\n\t}\n\n\thide(): void {\n\t\tthis.container.visible = false;\n\t}\n\n\tdispose(): void {\n\t\tthis.scene.remove(this.container);\n\t\tthis.fillMesh.geometry.dispose();\n\t\t(this.fillMesh.material as MeshBasicMaterial).dispose();\n\t\tthis.edgeLines.geometry.dispose();\n\t\t(this.edgeLines.material as LineBasicMaterial).dispose();\n\t}\n}\n\n\n","import { Object3D } from 'three';\nimport { subscribe } from 'valtio/vanilla';\n\nimport type { CameraDebugDelegate, CameraDebugState } from '../camera/zylem-camera';\nimport { debugState } from '../debug/debug-state';\nimport type { ZylemStage } from './zylem-stage';\n\nconst cloneSelected = (selected: string[]): string[] => [...selected];\n\n/**\n * Debug delegate that bridges the stage's entity map and debug state to the camera.\n */\nexport class StageCameraDebugDelegate implements CameraDebugDelegate {\n\tprivate stage: ZylemStage;\n\n\tconstructor(stage: ZylemStage) {\n\t\tthis.stage = stage;\n\t}\n\n\tsubscribe(listener: (state: CameraDebugState) => void): () => void {\n\t\tconst notify = () => listener(this.snapshot());\n\t\tnotify();\n\t\treturn subscribe(debugState, notify);\n\t}\n\n\tresolveTarget(uuid: string): Object3D | null {\n\t\tconst entity: any = this.stage._debugMap.get(uuid)\n\t\t\t|| this.stage.world?.collisionMap.get(uuid)\n\t\t\t|| null;\n\t\tconst target = entity?.group ?? entity?.mesh ?? null;\n\t\treturn target ?? null;\n\t}\n\n\tprivate snapshot(): CameraDebugState {\n\t\treturn {\n\t\t\tenabled: debugState.enabled,\n\t\t\tselected: debugState.selectedEntity ? [debugState.selectedEntity.uuid] : [],\n\t\t};\n\t}\n}\n\n","import { Vector2 } from 'three';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { Perspectives } from '../camera/perspective';\nimport { CameraWrapper } from '../camera/camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport type { ZylemStage } from './zylem-stage';\n\n/**\n * Delegate for camera creation and management within a stage.\n * Accepts an injected stage reference for context.\n */\nexport class StageCameraDelegate {\n\tprivate stage: ZylemStage;\n\n\tconstructor(stage: ZylemStage) {\n\t\tthis.stage = stage;\n\t}\n\n\t/**\n\t * Create a default third-person camera based on window size.\n\t */\n\tcreateDefaultCamera(): ZylemCamera {\n\t\tconst width = window.innerWidth;\n\t\tconst height = window.innerHeight;\n\t\tconst screenResolution = new Vector2(width, height);\n\t\treturn new ZylemCamera(Perspectives.ThirdPerson, screenResolution);\n\t}\n\n\t/**\n\t * Resolve the camera to use for the stage.\n\t * Uses the provided camera, stage camera wrapper, or creates a default.\n\t * \n\t * @param cameraOverride Optional camera override\n\t * @param cameraWrapper Optional camera wrapper from stage options\n\t * @returns The resolved ZylemCamera instance\n\t */\n\tresolveCamera(cameraOverride?: ZylemCamera | null, cameraWrapper?: CameraWrapper): ZylemCamera {\n\t\tif (cameraOverride) {\n\t\t\treturn cameraOverride;\n\t\t}\n\t\tif (cameraWrapper) {\n\t\t\treturn cameraWrapper.cameraRef;\n\t\t}\n\t\treturn this.createDefaultCamera();\n\t}\n\n\t/**\n\t * Build a CameraManager from stage options.\n\t * Supports single camera (backward compatible) and multiple cameras.\n\t * \n\t * @param cameraOverride Optional camera override from game-level config\n\t * @param cameraWrappers Camera wrappers from stage options (can be single or array)\n\t * @returns A CameraManager populated with the resolved cameras\n\t */\n\tbuildCameraManager(\n\t\tcameraOverride?: ZylemCamera | null,\n\t\t...cameraWrappers: (CameraWrapper | undefined)[]\n\t): CameraManager {\n\t\tconst manager = new CameraManager();\n\n\t\t// If there's a camera override, use it as the primary\n\t\tif (cameraOverride) {\n\t\t\tmanager.addCamera(cameraOverride, cameraOverride.name || 'main');\n\t\t\treturn manager;\n\t\t}\n\n\t\t// Add cameras from wrappers\n\t\tconst validWrappers = cameraWrappers.filter((w): w is CameraWrapper => w !== undefined);\n\n\t\tif (validWrappers.length > 0) {\n\t\t\tfor (const wrapper of validWrappers) {\n\t\t\t\tconst cam = wrapper.cameraRef;\n\t\t\t\tmanager.addCamera(cam, cam.name || undefined);\n\t\t\t}\n\t\t} else {\n\t\t\t// No cameras provided: create a default\n\t\t\tconst defaultCam = this.createDefaultCamera();\n\t\t\tmanager.addCamera(defaultCam, 'default');\n\t\t}\n\n\t\treturn manager;\n\t}\n}\n","import { Vector2, Camera, PerspectiveCamera, Vector3, Object3D, OrthographicCamera, Scene } from 'three';\nimport { PerspectiveType, Perspectives } from './perspective';\nimport { ThirdPersonCamera } from './third-person';\nimport { Fixed2DCamera } from './fixed-2d';\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';\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 * Interface for perspective-specific camera controllers\n */\nexport interface PerspectiveController {\n\tsetup(params: { screenResolution: Vector2; renderer: ZylemRenderer; scene: Scene; camera: ZylemCamera }): void;\n\tupdate(delta: number): void;\n\tresize(width: number, height: number): void;\n}\n\n/**\n * ZylemCamera is a lightweight camera wrapper that manages the Three.js camera,\n * perspective controller, and viewport configuration. It no longer owns a renderer;\n * rendering is handled by RendererManager.\n */\nexport class ZylemCamera {\n\tcameraRig: Object3D | null = null;\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 * Replaces the old single `target` property.\n\t */\n\ttargets: StageEntity[] = [];\n\n\t/**\n\t * @deprecated Use `targets` array instead. This getter/setter is 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// Perspective controller delegation\n\tperspectiveController: PerspectiveController | null = null;\n\n\t// Orbit controls\n\tprivate orbitController: CameraOrbitController | null = null;\n\tprivate _useOrbitalControls = false;\n\n\t/** Reference to the shared renderer manager (set during setup) */\n\tprivate _rendererManager: RendererManager | null = null;\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 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\t}\n\n\t/**\n\t * Setup the camera with a scene and renderer manager.\n\t * The renderer manager provides shared rendering infrastructure.\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// Setup perspective controller\n\t\tif (this.perspectiveController && this._rendererManager) {\n\t\t\tthis.perspectiveController.setup({\n\t\t\t\tscreenResolution: this.screenResolution,\n\t\t\t\trenderer: this._rendererManager.renderer,\n\t\t\t\tscene: scene,\n\t\t\t\tcamera: this\n\t\t\t});\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\tthis.cameraRig\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 camera controllers (called each frame).\n\t * Does NOT render -- rendering is handled by RendererManager.\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 perspective controller updates when orbit controls are active\n\t\tif (this.perspectiveController && !this.isDebugModeActive() && !this._useOrbitalControls) {\n\t\t\tthis.perspectiveController.update(delta);\n\t\t}\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/**\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/**\n\t * Dispose camera resources (not the renderer -- that's managed by RendererManager).\n\t */\n\tdestroy(): void {\n\t\ttry {\n\t\t\tthis.orbitController?.dispose();\n\t\t} catch { /* noop */ }\n\t\tthis.sceneRef = null;\n\t\tthis.targets = [];\n\t\tthis._rendererManager = null;\n\t}\n\n\t/**\n\t * Attach a delegate to react to debug state changes.\n\t */\n\tsetDebugDelegate(delegate: CameraDebugDelegate | null): void {\n\t\tthis.orbitController?.setDebugDelegate(delegate);\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.perspectiveController) {\n\t\t\tthis.perspectiveController.resize(width, height);\n\t\t}\n\t}\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 * 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(): void {\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): void {\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): void {\n\t\tthis.moveCamera(position);\n\t}\n\n\trotate(pitch: number, yaw: number, roll: number): void {\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 * @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/**\n\t * @deprecated Renderer is now owned by RendererManager\n\t */\n\tget renderer(): any {\n\t\treturn this._rendererManager?.renderer;\n\t}\n\n\t/**\n\t * @deprecated Composer is now owned by RendererManager\n\t */\n\tget composer(): any {\n\t\treturn this._rendererManager?.composer;\n\t}\n\n\t/**\n\t * @deprecated Use RendererManager.setPixelRatio() instead\n\t */\n\tsetPixelRatio(dpr: number): void {\n\t\tthis._rendererManager?.setPixelRatio(dpr);\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} as const;\n\nexport type PerspectiveType = (typeof Perspectives)[keyof typeof Perspectives];","import { Scene, Vector2, Vector3 } from 'three';\nimport { PerspectiveController, ZylemCamera } from './zylem-camera';\nimport { ZylemRenderer } from './renderer-manager';\n\n/**\n * Third-person camera controller that supports multiple targets.\n *\n * - 0 targets: stays at configured position, looks at world origin\n * - 1 target: classic third-person follow (lerp to target + offset)\n * - 2+ targets: weighted-center framing -- computes centroid of all targets,\n * zooms out based on max distance between them, and looks at centroid\n */\nexport class ThirdPersonCamera implements PerspectiveController {\n\tdistance: Vector3;\n\tscreenResolution: Vector2 | null = null;\n\trenderer: ZylemRenderer | null = null;\n\tscene: Scene | null = null;\n\tcameraRef: ZylemCamera | null = null;\n\n\t/** Padding multiplier when framing multiple targets. Higher = more zoom out. */\n\tpaddingFactor = 1.5;\n\n\t/** Minimum camera distance when multi-framing (prevents extreme zoom-in). */\n\tminDistance = 5;\n\n\t/** Lerp factor for camera position smoothing. */\n\tlerpFactor = 0.1;\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: ZylemRenderer; 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 * Handles 0, 1, and multi-target scenarios.\n\t */\n\tupdate(delta: number) {\n\t\tif (!this.cameraRef) return;\n\n\t\tconst targets = this.cameraRef.targets;\n\n\t\tif (targets.length === 0) {\n\t\t\t// No targets: look at world origin, stay at current position\n\t\t\tthis.cameraRef.camera.lookAt(new Vector3(0, 0, 0));\n\t\t\treturn;\n\t\t}\n\n\t\tif (targets.length === 1) {\n\t\t\t// Single target: classic third-person follow\n\t\t\tthis.updateSingleTarget(targets[0]);\n\t\t\treturn;\n\t\t}\n\n\t\t// Multiple targets: weighted-center framing\n\t\tthis.updateMultiTarget(targets);\n\t}\n\n\t/**\n\t * Classic single-target follow: lerp to target position + offset, lookAt target.\n\t */\n\tprivate updateSingleTarget(target: { group: { position: Vector3 } }) {\n\t\tconst useTarget = target.group?.position || new Vector3(0, 0, 0);\n\t\tconst desiredCameraPosition = useTarget.clone().add(this.distance);\n\t\tthis.cameraRef!.camera.position.lerp(desiredCameraPosition, this.lerpFactor);\n\t\tthis.cameraRef!.camera.lookAt(useTarget);\n\t}\n\n\t/**\n\t * Multi-target framing: compute centroid, measure spread, zoom out to fit all.\n\t */\n\tprivate updateMultiTarget(targets: Array<{ group: { position: Vector3 } }>) {\n\t\t// Compute centroid (average position of all targets)\n\t\tconst centroid = new Vector3();\n\t\tfor (const t of targets) {\n\t\t\tcentroid.add(t.group.position);\n\t\t}\n\t\tcentroid.divideScalar(targets.length);\n\n\t\t// Compute max distance from centroid to any target\n\t\tlet maxDistFromCentroid = 0;\n\t\tfor (const t of targets) {\n\t\t\tconst dist = centroid.distanceTo(t.group.position);\n\t\t\tif (dist > maxDistFromCentroid) {\n\t\t\t\tmaxDistFromCentroid = dist;\n\t\t\t}\n\t\t}\n\n\t\t// Scale the camera distance based on the spread of targets\n\t\tconst dynamicDistance = Math.max(maxDistFromCentroid * this.paddingFactor, this.minDistance);\n\n\t\t// Compute desired camera position: centroid + offset direction scaled by dynamic distance\n\t\tconst offsetDirection = this.distance.clone().normalize();\n\t\tconst desiredCameraPosition = centroid.clone().add(\n\t\t\toffsetDirection.multiplyScalar(dynamicDistance)\n\t\t);\n\n\t\t// Preserve the vertical offset proportionally\n\t\tconst baseLen = this.distance.length();\n\t\tif (baseLen > 0) {\n\t\t\tconst heightRatio = this.distance.y / baseLen;\n\t\t\tdesiredCameraPosition.y = centroid.y + dynamicDistance * heightRatio;\n\t\t}\n\n\t\t// Smooth camera movement\n\t\tthis.cameraRef!.camera.position.lerp(desiredCameraPosition, this.lerpFactor);\n\t\tthis.cameraRef!.camera.lookAt(centroid);\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}\n\n\t/**\n\t * Set the distance offset from the target\n\t */\n\tsetDistance(distance: Vector3) {\n\t\tthis.distance = distance;\n\t}\n}\n","import { Scene, Vector2 } from 'three';\nimport { PerspectiveController, ZylemCamera } from './zylem-camera';\nimport { ZylemRenderer } from './renderer-manager';\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: ZylemRenderer | 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: ZylemRenderer; 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 { 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\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.renderer.setAnimationLoop((delta: number) => {\n\t\t\tonFrame(delta || 0);\n\t\t});\n\t}\n\n\t/**\n\t * Stop the render loop.\n\t */\n\tstopRenderLoop(): void {\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 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","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 */\n\trender(scene: Scene): void {\n\t\tif (!this._rendererManager || this._activeCameras.length === 0) return;\n\t\tthis._rendererManager.renderCameras(scene, this._activeCameras as ZylemCamera[]);\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","import { LoadingEvent } from '../core/interfaces';\nimport { gameEventBus, StageLoadingPayload } from '../game/game-event-bus';\n\n/**\n * Event name for stage loading events.\n * Dispatched via window for cross-application communication.\n */\nexport const STAGE_LOADING_EVENT = 'STAGE_LOADING_EVENT';\n\n/**\n * Delegate for managing loading events and progress within a stage.\n * Handles subscription to loading events and broadcasting progress.\n * Emits to game event bus for game-level observation.\n */\nexport class StageLoadingDelegate {\n\tprivate loadingHandlers: Array<(event: LoadingEvent) => void> = [];\n\tprivate stageName?: string;\n\tprivate stageIndex?: number;\n\n\t/**\n\t * Set stage context for event bus emissions.\n\t */\n\tsetStageContext(stageName: string, stageIndex: number): void {\n\t\tthis.stageName = stageName;\n\t\tthis.stageIndex = stageIndex;\n\t}\n\n\t/**\n\t * Subscribe to loading events.\n\t * \n\t * @param callback Invoked for each loading event (start, progress, complete)\n\t * @returns Unsubscribe function\n\t */\n\tonLoading(callback: (event: LoadingEvent) => void): () => void {\n\t\tthis.loadingHandlers.push(callback);\n\t\treturn () => {\n\t\t\tthis.loadingHandlers = this.loadingHandlers.filter((h) => h !== callback);\n\t\t};\n\t}\n\n\t/**\n\t * Emit a loading event to all subscribers and to the game event bus.\n\t * \n\t * @param event The loading event to broadcast\n\t */\n\temit(event: LoadingEvent): void {\n\t\t// Dispatch to direct subscribers\n\t\tfor (const handler of this.loadingHandlers) {\n\t\t\ttry {\n\t\t\t\thandler(event);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Loading handler failed', e);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Emit to game event bus for game-level observation\n\t\tconst payload: StageLoadingPayload = {\n\t\t\t...event,\n\t\t\tstageName: this.stageName,\n\t\t\tstageIndex: this.stageIndex,\n\t\t};\n\t\t\n\t\tif (event.type === 'start') {\n\t\t\tgameEventBus.emit('stage:loading:start', payload);\n\t\t} else if (event.type === 'progress') {\n\t\t\tgameEventBus.emit('stage:loading:progress', payload);\n\t\t} else if (event.type === 'complete') {\n\t\t\tgameEventBus.emit('stage:loading:complete', payload);\n\t\t}\n\t}\n\n\t/**\n\t * Emit a start loading event.\n\t */\n\temitStart(message: string = 'Loading stage...'): void {\n\t\tthis.emit({ type: 'start', message, progress: 0 });\n\t}\n\n\t/**\n\t * Emit a progress loading event.\n\t */\n\temitProgress(message: string, current: number, total: number): void {\n\t\tconst progress = total > 0 ? current / total : 0;\n\t\tthis.emit({ type: 'progress', message, progress, current, total });\n\t}\n\n\t/**\n\t * Emit a complete loading event.\n\t */\n\temitComplete(message: string = 'Stage loaded'): void {\n\t\tthis.emit({ type: 'complete', message, progress: 1 });\n\t}\n\n\t/**\n\t * Clear all loading handlers.\n\t */\n\tdispose(): void {\n\t\tthis.loadingHandlers = [];\n\t}\n}\n","import { zylemEventBus } from '../events';\nimport { ZylemScene } from '../graphics/zylem-scene';\nimport { GameEntity } from '../entities/entity';\n\n/**\n * Delegate for handling deferred model loading in entities.\n * Subscribes to model:loaded events and adds entity groups to the scene\n * when they become available after async loading completes.\n */\nexport class StageEntityModelDelegate {\n\tprivate scene: ZylemScene | null = null;\n\tprivate pendingEntities: Map<string, GameEntity<any>> = new Map();\n\tprivate modelLoadedHandler: ((payload: { entityId: string; success: boolean }) => void) | null = null;\n\n\t/**\n\t * Initialize the delegate with the scene reference and start listening.\n\t */\n\tattach(scene: ZylemScene): void {\n\t\tthis.scene = scene;\n\t\tthis.modelLoadedHandler = (payload) => {\n\t\t\tthis.handleModelLoaded(payload.entityId, payload.success);\n\t\t};\n\t\tzylemEventBus.on('entity:model:loaded', this.modelLoadedHandler);\n\t}\n\n\t/**\n\t * Register an entity for observation.\n\t * When its model loads, the group will be added to the scene.\n\t */\n\tobserve(entity: GameEntity<any>): void {\n\t\tthis.pendingEntities.set(entity.uuid, entity);\n\t}\n\n\t/**\n\t * Unregister an entity (e.g., when removed before model loads).\n\t */\n\tunobserve(entityId: string): void {\n\t\tthis.pendingEntities.delete(entityId);\n\t}\n\n\t/**\n\t * Handle model loaded event - add group to scene if entity is pending.\n\t */\n\tprivate handleModelLoaded(entityId: string, success: boolean): void {\n\t\tconst entity = this.pendingEntities.get(entityId);\n\t\tif (!entity || !success) {\n\t\t\tthis.pendingEntities.delete(entityId);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scene?.addEntityGroup(entity);\n\t\tthis.pendingEntities.delete(entityId);\n\t}\n\n\t/**\n\t * Cleanup all subscriptions and pending entities.\n\t */\n\tdispose(): void {\n\t\tif (this.modelLoadedHandler) {\n\t\t\tzylemEventBus.off('entity:model:loaded', this.modelLoadedHandler);\n\t\t\tthis.modelLoadedHandler = null;\n\t\t}\n\t\tthis.pendingEntities.clear();\n\t\tthis.scene = null;\n\t}\n}\n","import { Color, Vector3 } from 'three';\nimport { BaseNode } from '../core/base-node';\nimport { CameraWrapper } from '../camera/camera';\nimport { isBaseNode, isCameraWrapper, isConfigObject, isEntityInput } from '../core/utility/options-parser';\nimport { ZylemBlueColor } from '../core/utility/vector';\nimport type { ZylemShader } from '../graphics/material';\n\n/**\n * Stage configuration type for user-facing options.\n */\nexport type StageConfigLike = Partial<{\n\tinputs: Record<string, string[]>;\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader: ZylemShader;\n\tgravity: Vector3;\n\tvariables: Record<string, any>;\n}>;\n\n/**\n * Internal stage configuration class.\n */\nexport class StageConfig {\n\tconstructor(\n\t\tpublic inputs: Record<string, string[]>,\n\t\tpublic backgroundColor: Color | string,\n\t\tpublic backgroundImage: string | null,\n\t\tpublic backgroundShader: ZylemShader | null,\n\t\tpublic gravity: Vector3,\n\t\tpublic variables: Record<string, any>,\n\t) { }\n}\n\n/**\n * Create default stage configuration.\n */\nexport function createDefaultStageConfig(): StageConfig {\n\treturn new StageConfig(\n\t\t{\n\t\t\tp1: ['gamepad-1', 'keyboard-1'],\n\t\t\tp2: ['gamepad-2', 'keyboard-2'],\n\t\t},\n\t\tZylemBlueColor,\n\t\tnull,\n\t\tnull,\n\t\tnew Vector3(0, 0, 0),\n\t\t{},\n\t);\n}\n\n/**\n * Result of parsing stage options.\n */\nexport interface ParsedStageOptions {\n\tconfig: StageConfig;\n\tentities: BaseNode[];\n\tasyncEntities: Array<BaseNode | Promise<any> | (() => BaseNode | Promise<any>)>;\n\t/** @deprecated Use `cameras` array instead for multi-camera support */\n\tcamera?: CameraWrapper;\n\t/** All camera wrappers found in stage options */\n\tcameras: CameraWrapper[];\n}\n\n/**\n * Parse stage options array and resolve configuration.\n * Separates config objects, camera wrappers, and entity inputs.\n * \n * @param options Stage options array\n * @returns Parsed stage options with resolved config, entities, and camera\n */\nexport function parseStageOptions(options: any[] = []): ParsedStageOptions {\n\tconst defaults = createDefaultStageConfig();\n\tlet config: Partial<StageConfig> = {};\n\tconst entities: BaseNode[] = [];\n\tconst asyncEntities: Array<BaseNode | Promise<any> | (() => BaseNode | Promise<any>)> = [];\n\tconst cameras: CameraWrapper[] = [];\n\n\tfor (const item of options) {\n\t\tif (isCameraWrapper(item)) {\n\t\t\tcameras.push(item);\n\t\t} else if (isBaseNode(item)) {\n\t\t\tentities.push(item);\n\t\t} else if (isEntityInput(item) && !isBaseNode(item)) {\n\t\t\tasyncEntities.push(item);\n\t\t} else if (isConfigObject(item)) {\n\t\t\tconfig = { ...config, ...item };\n\t\t}\n\t}\n\n\t// Merge user config with defaults\n\tconst resolvedConfig = new StageConfig(\n\t\tconfig.inputs ?? defaults.inputs,\n\t\tconfig.backgroundColor ?? defaults.backgroundColor,\n\t\tconfig.backgroundImage ?? defaults.backgroundImage,\n\t\tconfig.backgroundShader ?? defaults.backgroundShader,\n\t\tconfig.gravity ?? defaults.gravity,\n\t\tconfig.variables ?? defaults.variables,\n\t);\n\n\t// Backward compat: first camera is the legacy `camera` field\n\tconst camera = cameras.length > 0 ? cameras[0] : undefined;\n\n\treturn { config: resolvedConfig, entities, asyncEntities, camera, cameras };\n}\n\n/**\n * Factory for authoring stage configuration objects in user code.\n * Returns a plain object that can be passed to `createStage(...)`.\n */\nexport function stageConfig(config: StageConfigLike): StageConfigLike {\n\treturn { ...config };\n}\n","import { BaseNode } from '../base-node';\nimport { CameraWrapper } from '../../camera/camera';\n\n/**\n * Check if an item is a BaseNode (has a create function).\n */\nexport function isBaseNode(item: unknown): item is BaseNode {\n\treturn !!item && typeof item === 'object' && typeof (item as any).create === 'function';\n}\n\n/**\n * Check if an item is a Promise-like (thenable).\n */\nexport function isThenable(item: unknown): item is Promise<any> {\n\treturn !!item && typeof (item as any).then === 'function';\n}\n\n/**\n * Check if an item is a CameraWrapper.\n */\nexport function isCameraWrapper(item: unknown): item is CameraWrapper {\n\treturn !!item && typeof item === 'object' && (item as any).constructor?.name === 'CameraWrapper';\n}\n\n/**\n * Check if an item is a plain config object (not a special type).\n * Excludes BaseNode, CameraWrapper, functions, and promises.\n */\nexport function isConfigObject(item: unknown): boolean {\n\tif (!item || typeof item !== 'object') return false;\n\tif (isBaseNode(item)) return false;\n\tif (isCameraWrapper(item)) return false;\n\tif (isThenable(item)) return false;\n\tif (typeof (item as any).then === 'function') return false;\n\t// Must be a plain object\n\treturn (item as any).constructor === Object || (item as any).constructor?.name === 'Object';\n}\n\n/**\n * Check if an item is an entity input (BaseNode, Promise, or factory function).\n */\nexport function isEntityInput(item: unknown): boolean {\n\tif (!item) return false;\n\tif (isBaseNode(item)) return true;\n\tif (typeof item === 'function') return true;\n\tif (isThenable(item)) return true;\n\treturn false;\n}\n","import { RigidBody } from '@dimforge/rapier3d-compat';\nimport { TransformState } from './transform-store';\n\n/**\n * Entity that can have transformations applied from a store\n */\nexport interface TransformableEntity {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Apply accumulated transformations from the store to the physics body.\n * \n * This is called automatically after onUpdate() callbacks complete,\n * flushing all pending transformations to the physics engine in a single batch.\n * \n * Flow:\n * 1. Check dirty flags to see what changed\n * 2. Apply changes to RigidBody\n * 3. Reset store for next frame\n * \n * @param entity Entity with physics body and transform store\n * @param store Transform store containing pending changes\n */\nexport function applyTransformChanges(\n\tentity: TransformableEntity,\n\tstore: TransformState\n): void {\n\tif (!entity.body) return;\n\n\t// Apply velocity if dirty\n\tif (store.dirty.velocity) {\n\t\tentity.body.setLinvel(store.velocity, true);\n\t}\n\n\t// Apply rotation if dirty\n\tif (store.dirty.rotation) {\n\t\tentity.body.setRotation(store.rotation, true);\n\t}\n\n\t// Apply angular velocity if dirty\n\tif (store.dirty.angularVelocity) {\n\t\tentity.body.setAngvel(store.angularVelocity, true);\n\t}\n\n\t// Apply position deltas if dirty\n\tif (store.dirty.position) {\n\t\tconst current = entity.body.translation();\n\t\tentity.body.setTranslation(\n\t\t\t{\n\t\t\t\tx: current.x + store.position.x,\n\t\t\t\ty: current.y + store.position.y,\n\t\t\t\tz: current.z + store.position.z,\n\t\t\t},\n\t\t\ttrue\n\t\t);\n\t}\n}\n","import { BaseNode } from './base-node';\nimport {\n\tSetupContext,\n\tUpdateContext,\n\tDestroyContext,\n\tLoadedContext,\n\tCleanupContext,\n} from './base-node-life-cycle';\nimport type { NodeInterface } from './node-interface';\n\nconst VESSEL_TYPE = Symbol('vessel');\n\n/**\n * A Vessel is an empty container entity that holds child entities.\n * It has no geometry, physics, or rendering of its own, but propagates\n * lifecycle events to its children and provides a logical grouping mechanism.\n *\n * Child entities added to a Vessel will be individually spawned into the\n * stage's physics world and render scene when the Vessel is spawned.\n */\nexport class Vessel extends BaseNode<{}, Vessel> {\n\tstatic type = VESSEL_TYPE;\n\n\tprotected _setup(_params: SetupContext<this>): void { }\n\n\tprotected async _loaded(_params: LoadedContext<this>): Promise<void> { }\n\n\tprotected _update(_params: UpdateContext<this>): void { }\n\n\tprotected _destroy(_params: DestroyContext<this>): void { }\n\n\tprotected _cleanup(_params: CleanupContext<this>): void { }\n\n\tpublic create(): this {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add one or more child entities to this vessel.\n\t * Overrides parent to support multiple arguments.\n\t * @returns this for chaining\n\t */\n\tpublic add(...nodes: NodeInterface[]): this {\n\t\tfor (const node of nodes) {\n\t\t\tsuper.add(node);\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/**\n * Create a vessel containing the given child entities.\n * @param args Child BaseNode entities to add\n * @returns A new Vessel with the children added\n */\nexport function vessel(...args: Array<BaseNode>): Vessel {\n\tconst instance = new Vessel();\n\targs.forEach(arg => instance.add(arg));\n\treturn instance;\n}\n","import { Vector2, Vector3 } from \"three\";\nimport { PerspectiveType } from \"./perspective\";\nimport { ZylemCamera } from \"./zylem-camera\";\nimport { RendererType, Viewport, DEFAULT_VIEWPORT } from \"./renderer-manager\";\nimport { StageEntity } from \"../interfaces/entity\";\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}\n\n/**\n * CameraWrapper is the user-facing camera handle returned by createCamera().\n * It provides convenience methods for target management, orbital controls, and viewport configuration.\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\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// 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// Mark for enablement -- actual OrbitControls are created during setup()\n\t\t// when the renderer DOM element is available\n\t\t(zylemCamera as any)._useOrbitalControls = true;\n\t}\n\n\treturn new CameraWrapper(zylemCamera);\n}\n","import { proxy } from 'valtio/vanilla';\nimport { Vector3 } from 'three';\nimport type { StageOptions, ZylemStageConfig } from './zylem-stage';\nimport { ZylemBlueColor } from '../core/utility/vector';\n\n/**\n * Reactive defaults for building `Stage` instances. These values are applied\n * automatically by the `stage()` builder and can be changed at runtime to\n * influence future stage creations.\n */\nconst initialDefaults: Partial<ZylemStageConfig> = {\n\tbackgroundColor: ZylemBlueColor,\n\tbackgroundImage: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard'],\n\t\tp2: ['gamepad-2', 'keyboard'],\n\t},\n\tgravity: new Vector3(0, 0, 0),\n\tvariables: {},\n};\n\nconst stageDefaultsState = proxy<Partial<ZylemStageConfig>>({\n\t...initialDefaults,\n});\n\n/** Replace multiple defaults at once (shallow merge). */\nfunction setStageDefaults(partial: Partial<ZylemStageConfig>): void {\n\tObject.assign(stageDefaultsState, partial);\n}\n\n/** Reset defaults back to library defaults. */\nfunction resetStageDefaults(): void {\n\tObject.assign(stageDefaultsState, initialDefaults);\n}\n\nexport function getStageOptions(options: StageOptions): StageOptions {\n\tconst defaults = getStageDefaultConfig();\n\tlet originalConfig = {};\n\tif (typeof options[0] === 'object') {\n\t\toriginalConfig = options.shift() ?? {};\n\t}\n\tconst combinedConfig = { ...defaults, ...originalConfig };\n\treturn [combinedConfig, ...options] as StageOptions;\n}\n\n/** Get a plain object copy of the current defaults. */\nfunction getStageDefaultConfig(): Partial<ZylemStageConfig> {\n\treturn {\n\t\tbackgroundColor: stageDefaultsState.backgroundColor,\n\t\tbackgroundImage: stageDefaultsState.backgroundImage ?? null,\n\t\tinputs: stageDefaultsState.inputs ? { ...stageDefaultsState.inputs } : undefined,\n\t\tgravity: stageDefaultsState.gravity,\n\t\tvariables: stageDefaultsState.variables ? { ...stageDefaultsState.variables } : undefined,\n\t};\n}\n\n\n","import { InputPlayer } from './input';\nimport { GameInputConfig, GameInputPlayerConfig, KeyboardMapping } from '../game/game-interfaces';\n\n/**\n * Creates a GameInputConfig scoped to a single player.\n */\nfunction playerKeyMapping(player: InputPlayer, keyMapping: KeyboardMapping): GameInputConfig {\n\treturn { [player]: { key: keyMapping } } as GameInputConfig;\n}\n\n/**\n * Maps arrow keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useArrowsForAxes('p1'));\n */\nexport function useArrowsForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'ArrowLeft': ['axes.Left'],\n\t\t'ArrowRight': ['axes.Right'],\n\t\t'ArrowUp': ['axes.Up'],\n\t\t'ArrowDown': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps arrow keys to directions (Up/Down/Left/Right) for the given player.\n * Useful when `includeDefaults` is false and you still want arrow-key directions.\n * @example stage.setInputConfiguration(useArrowsForDirections('p1'));\n */\nexport function useArrowsForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'ArrowLeft': ['directions.Left'],\n\t\t'ArrowRight': ['directions.Right'],\n\t\t'ArrowUp': ['directions.Up'],\n\t\t'ArrowDown': ['directions.Down'],\n\t});\n}\n\n/**\n * Maps W/A/S/D keys to directions (Up/Down/Left/Right) for the given player.\n * @example stage.setInputConfiguration(useWASDForDirections('p1'));\n */\nexport function useWASDForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'w': ['directions.Up'],\n\t\t's': ['directions.Down'],\n\t\t'a': ['directions.Left'],\n\t\t'd': ['directions.Right'],\n\t});\n}\n\n/**\n * Maps W/A/S/D keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useWASDForAxes('p1'));\n */\nexport function useWASDForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'a': ['axes.Left'],\n\t\t'd': ['axes.Right'],\n\t\t'w': ['axes.Up'],\n\t\t's': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps I/J/K/L keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useIJKLForAxes('p1'));\n */\nexport function useIJKLForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'j': ['axes.Left'],\n\t\t'l': ['axes.Right'],\n\t\t'i': ['axes.Up'],\n\t\t'k': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps I/J/K/L keys to directions (Up/Down/Left/Right) for the given player.\n * @example stage.setInputConfiguration(useIJKLForDirections('p1'));\n */\nexport function useIJKLForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'j': ['directions.Left'],\n\t\t'l': ['directions.Right'],\n\t\t'i': ['directions.Up'],\n\t\t'k': ['directions.Down'],\n\t});\n}\n\nconst INPUT_PLAYERS: (keyof GameInputConfig)[] = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8'];\n\n/**\n * Deep-merges multiple GameInputConfig objects into one.\n * At the player level, configs are merged (both apply).\n * At the key level, later configs win on conflict.\n * @example mergeInputConfigs(useArrowsForAxes('p1'), useWASDForDirections('p1'));\n */\nexport function mergeInputConfigs(...configs: GameInputConfig[]): GameInputConfig {\n\tconst result: GameInputConfig = {};\n\n\tfor (const config of configs) {\n\t\tfor (const player of INPUT_PLAYERS) {\n\t\t\tconst source = config[player];\n\t\t\tif (!source) continue;\n\n\t\t\tconst target: GameInputPlayerConfig = result[player] ?? {};\n\t\t\tresult[player] = {\n\t\t\t\tkey: { ...target.key, ...source.key },\n\t\t\t\tmouse: { ...target.mouse, ...source.mouse },\n\t\t\t\tincludeDefaults: source.includeDefaults ?? target.includeDefaults,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn result;\n}\n","import { BaseNode } from '../core/base-node';\nimport { DestroyFunction, SetupContext, SetupFunction, UpdateFunction } from '../core/base-node-life-cycle';\nimport { LoadingEvent, StageOptionItem, StageOptions, ZylemStage } from './zylem-stage';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { CameraWrapper } from '../camera/camera';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { stageState } from './stage-state';\nimport { getStageOptions } from './stage-default';\nimport { EntityTypeMap } from '../types/entity-type-map';\nimport { EventEmitterDelegate, zylemEventBus, type StageEvents } from '../events';\nimport { GameInputConfig } from '../game/game-interfaces';\nimport { mergeInputConfigs } from '../input/input-presets';\n\ntype NodeLike = { create: Function };\ntype AnyNode = NodeLike | Promise<NodeLike>;\ntype EntityInput = AnyNode | (() => AnyNode) | (() => Promise<any>);\n\nexport class Stage {\n\twrappedStage: ZylemStage | null;\n\toptions: StageOptionItem[] = [];\n\t// Entities added after construction, consumed on each load\n\tprivate _pendingEntities: BaseNode[] = [];\n\n\t// Lifecycle callback arrays\n\tprivate setupCallbacks: Array<SetupFunction<ZylemStage>> = [];\n\tprivate updateCallbacks: Array<UpdateFunction<ZylemStage>> = [];\n\tprivate destroyCallbacks: Array<DestroyFunction<ZylemStage>> = [];\n\tprivate pendingLoadingCallbacks: Array<(event: LoadingEvent) => void> = [];\n\n\t// Event delegate for dispatch/listen API\n\tprivate eventDelegate = new EventEmitterDelegate<StageEvents>();\n\n\t/** Per-stage input configuration overrides. Merged with game-level defaults on stage load. */\n\tinputConfig: GameInputConfig | null = null;\n\n\t/**\n\t * Callback set by the game to trigger input reconfiguration\n\t * when this stage's input config changes at runtime.\n\t * @internal\n\t */\n\tonInputConfigChanged: (() => void) | null = null;\n\n\tconstructor(options: StageOptions) {\n\t\tthis.options = options;\n\t\tthis.wrappedStage = null;\n\t}\n\n\t/**\n\t * Set composable input configuration for this stage.\n\t * Multiple configs are deep-merged (later configs win on key conflicts).\n\t * If this stage is currently active, the change takes effect immediately.\n\t * @example stage.setInputConfiguration(useArrowsForAxes('p1'), useWASDForDirections('p2'));\n\t */\n\tsetInputConfiguration(...configs: GameInputConfig[]): this {\n\t\tthis.inputConfig = mergeInputConfigs(...configs);\n\t\tif (this.onInputConfigChanged) {\n\t\t\tthis.onInputConfigChanged();\n\t\t}\n\t\treturn this;\n\t}\n\n\tasync load(id: string, camera?: ZylemCamera | CameraWrapper | null, rendererManager?: RendererManager | null) {\n\t\tstageState.entities = [];\n\t\t// Combine original options with pending entities, then clear pending\n\t\tconst loadOptions = [...this.options, ...this._pendingEntities] as StageOptions;\n\t\tthis._pendingEntities = [];\n\t\t\n\t\tthis.wrappedStage = new ZylemStage(loadOptions);\n\t\tthis.wrappedStage.wrapperRef = this;\n\n\t\t// Flush pending loading callbacks BEFORE load so we catch start/progress events\n\t\tthis.pendingLoadingCallbacks.forEach(cb => {\n\t\t\tthis.wrappedStage!.onLoading(cb);\n\t\t});\n\t\tthis.pendingLoadingCallbacks = [];\n\n\t\tconst zylemCamera = camera instanceof CameraWrapper ? camera.cameraRef : camera;\n\t\tawait this.wrappedStage!.load(id, zylemCamera, rendererManager);\n\n\t\tthis.wrappedStage!.onEntityAdded((child) => {\n\t\t\tconst next = this.wrappedStage!.buildEntityState(child);\n\t\t\tstageState.entities = [...stageState.entities, next];\n\t\t}, { replayExisting: true });\n\n\t\t// Apply lifecycle callbacks to wrapped stage\n\t\tthis.applyLifecycleCallbacks();\n\n\t}\n\n\tprivate applyLifecycleCallbacks() {\n\t\tif (!this.wrappedStage) return;\n\n\t\t// Compose setup callbacks into a single function\n\t\tif (this.setupCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.setup = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.setupCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\n\t\t// Compose update callbacks\n\t\tif (this.updateCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.update = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.updateCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\n\t\t// Compose destroy callbacks\n\t\tif (this.destroyCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.destroy = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.destroyCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t}\n\n\tasync addEntities(entities: BaseNode[]) {\n\t\t// Store in pending, don't mutate options\n\t\tthis._pendingEntities.push(...entities);\n\t\tif (!this.wrappedStage) { return; }\n\t\tthis.wrappedStage!.enqueue(...entities);\n\t}\n\n\tadd(...inputs: Array<EntityInput>) {\n\t\tthis.addToBlueprints(...inputs);\n\t\tthis.addToStage(...inputs);\n\t}\n\n\tprivate addToBlueprints(...inputs: Array<EntityInput>) {\n\t\tif (this.wrappedStage) { return; }\n\t\t// Add to options (persistent) so they're available on reload\n\t\tthis.options.push(...(inputs as unknown as StageOptionItem[]));\n\t}\n\n\tprivate addToStage(...inputs: Array<EntityInput>) {\n\t\tif (!this.wrappedStage) { return; }\n\t\tthis.wrappedStage!.enqueue(...(inputs as any));\n\t}\n\n\tstart(params: SetupContext<ZylemStage>) {\n\t\tthis.wrappedStage?.nodeSetup(params);\n\t}\n\n\t// Fluent API for adding lifecycle callbacks\n\tonUpdate(...callbacks: UpdateFunction<ZylemStage>[]): this {\n\t\tthis.updateCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the update callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.update = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.updateCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonSetup(...callbacks: SetupFunction<ZylemStage>[]): this {\n\t\tthis.setupCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the setup callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.setup = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.setupCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonDestroy(...callbacks: DestroyFunction<ZylemStage>[]): this {\n\t\tthis.destroyCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the destroy callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.destroy = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.destroyCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonLoading(callback: (event: LoadingEvent) => void) {\n\t\tif (!this.wrappedStage) { \n\t\t\tthis.pendingLoadingCallbacks.push(callback);\n\t\t\treturn () => {\n\t\t\t\tthis.pendingLoadingCallbacks = this.pendingLoadingCallbacks.filter(c => c !== callback);\n\t\t\t};\n\t\t}\n\t\treturn this.wrappedStage.onLoading(callback);\n\t}\n\n\t/**\n\t * Find an entity by name on the current stage.\n\t * @param name The name of the entity to find\n\t * @param type Optional type symbol for type inference (e.g., TEXT_TYPE, SPRITE_TYPE)\n\t * @returns The entity if found, or undefined\n\t * @example stage.getEntityByName('scoreText', TEXT_TYPE)\n\t */\n\tgetEntityByName<T extends symbol | void = void>(\n\t\tname: string,\n\t\ttype?: T\n\t): T extends keyof EntityTypeMap ? EntityTypeMap[T] | undefined : BaseNode | undefined {\n\t\tconst entity = this.wrappedStage?.children.find(c => c.name === name);\n\t\treturn entity as any;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Camera management\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add a camera to this stage.\n\t * @param camera The ZylemCamera or CameraWrapper to add\n\t * @param name Optional name for lookup\n\t */\n\taddCamera(camera: ZylemCamera | CameraWrapper, name?: string): string | null {\n\t\tconst zylemCam = camera instanceof CameraWrapper ? camera.cameraRef : camera;\n\t\treturn this.wrappedStage?.addCamera(zylemCam, name) ?? null;\n\t}\n\n\t/**\n\t * Remove a camera from this stage by name or reference.\n\t */\n\tremoveCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean {\n\t\tif (nameOrRef instanceof CameraWrapper) {\n\t\t\treturn this.wrappedStage?.removeCamera(nameOrRef.cameraRef) ?? false;\n\t\t}\n\t\treturn this.wrappedStage?.removeCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Set the active camera by name or reference.\n\t */\n\tsetActiveCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean {\n\t\tif (nameOrRef instanceof CameraWrapper) {\n\t\t\treturn this.wrappedStage?.setActiveCamera(nameOrRef.cameraRef) ?? false;\n\t\t}\n\t\treturn this.wrappedStage?.setActiveCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Get a camera by name from the camera manager.\n\t */\n\tgetCamera(name: string): ZylemCamera | null {\n\t\treturn this.wrappedStage?.getCamera(name) ?? null;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Events API\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Dispatch an event from the stage.\n\t * Events are emitted both locally and to the global event bus.\n\t */\n\tdispatch<K extends keyof StageEvents>(event: K, payload: StageEvents[K]): void {\n\t\tthis.eventDelegate.dispatch(event, payload);\n\t\t(zylemEventBus as any).emit(event, payload);\n\t}\n\n\t/**\n\t * Listen for events on this stage instance.\n\t * @returns Unsubscribe function\n\t */\n\tlisten<K extends keyof StageEvents>(event: K, handler: (payload: StageEvents[K]) => void): () => void {\n\t\treturn this.eventDelegate.listen(event, handler);\n\t}\n\n\t/**\n\t * Clean up stage resources including event subscriptions.\n\t */\n\tdispose(): void {\n\t\tthis.eventDelegate.dispose();\n\t}\n}\n\n/**\n * Create a stage with optional camera\n */\nexport function createStage(...options: StageOptions): Stage {\n\tconst _options = getStageOptions(options);\n\treturn new Stage([..._options] as StageOptions);\n}","import { Euler, Quaternion, Vector2 } from \"three\";\nimport { GameEntity } from \"../entities\";\nimport { Stage } from \"./stage\";\n\nexport interface EntitySpawner {\n\tspawn: (stage: Stage, x: number, y: number) => Promise<GameEntity<any>>;\n\tspawnRelative: (source: any, stage: Stage, offset?: Vector2) => Promise<any | void>;\n}\n\nexport function entitySpawner(factory: (x: number, y: number) => Promise<any> | GameEntity<any>): EntitySpawner {\n\treturn {\n\t\tspawn: async (stage: Stage, x: number, y: number) => {\n\t\t\tconst instance = await Promise.resolve(factory(x, y));\n\t\t\tstage.add(instance);\n\t\t\treturn instance;\n\t\t},\n\t\tspawnRelative: async (source: any, stage: Stage, offset: Vector2 = new Vector2(0, 1)) => {\n\t\t\tif (!source.body) {\n\t\t\t\tconsole.warn('body missing for entity during spawnRelative');\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst { x, y, z } = source.body.translation();\n\t\t\tlet rz = (source as any)._rotation2DAngle ?? 0;\n\t\t\ttry {\n\t\t\t\tconst r = source.body.rotation();\n\t\t\t\tconst q = new Quaternion(r.x, r.y, r.z, r.w);\n\t\t\t\tconst e = new Euler().setFromQuaternion(q, 'XYZ');\n\t\t\t\trz = e.z;\n\t\t\t} catch { /* use fallback angle */ }\n\n\t\t\tconst offsetX = Math.sin(-rz) * (offset.x ?? 0);\n\t\t\tconst offsetY = Math.cos(-rz) * (offset.y ?? 0);\n\n\t\t\tconst instance = await Promise.resolve(factory(x + offsetX, y + offsetY));\n\t\t\tstage.add(instance);\n\t\t\treturn instance;\n\t\t}\n\t};\n}","import { subscribe } from 'valtio/vanilla';\nimport { stageState } from './stage-state';\nimport type { StageStateInterface } from '../types/stage-types';\n\n/**\n * Event name for stage state changes.\n * Dispatched when the stage state proxy is updated.\n */\nexport const STAGE_STATE_CHANGE = 'STAGE_STATE_CHANGE';\n\n/**\n * Event detail payload for STAGE_STATE_CHANGE events.\n */\nexport interface StageStateChangeEvent {\n\tentities: StageStateInterface['entities'];\n\tvariables: StageStateInterface['variables'];\n}\n\n/**\n * Initialize the stage state dispatcher.\n * Subscribes to stageState changes and dispatches STAGE_STATE_CHANGE events to the window.\n * \n * @returns Unsubscribe function to stop dispatching events.\n * \n * @example\n * // Start dispatching stage state changes\n * const unsubscribe = initStageStateDispatcher();\n * \n * // Later, stop dispatching\n * unsubscribe();\n */\nexport function initStageStateDispatcher(): () => void {\n\treturn subscribe(stageState, () => {\n\t\tconst detail: StageStateChangeEvent = {\n\t\t\tentities: stageState.entities,\n\t\t\tvariables: stageState.variables,\n\t\t};\n\t\twindow.dispatchEvent(new CustomEvent(STAGE_STATE_CHANGE, { detail }));\n\t});\n}\n\n/**\n * Manually dispatch the current stage state.\n * Useful for initial sync when a listener is added.\n */\nexport function dispatchStageState(): void {\n\tconst detail: StageStateChangeEvent = {\n\t\tentities: stageState.entities,\n\t\tvariables: stageState.variables,\n\t};\n\twindow.dispatchEvent(new CustomEvent(STAGE_STATE_CHANGE, { detail }));\n}\n"],"mappings":"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","names":["Color","Vector3","ActiveCollisionTypes","ColliderDesc","MeshStandardMaterial","Group","Vector3","all","Map","on","type","handler","handlers","get","push","set","off","splice","indexOf","emit","evt","slice","map","proxy","position","Vector3","Quaternion","Vector3","rotation","Quaternion","Vector3","Vector3","Vector3","Color","Vector2","Vector3","RepeatWrapping","ShaderMaterial","Vector3","Group","MeshStandardMaterial","Color","Vector3","ShaderMaterial","Mesh","Texture","MeshBasicNodeMaterial","proxy","state","Color","MeshBasicNodeMaterial","ShaderMaterial","Mesh","Texture","position","Vector3","Vector3","Quaternion","Vector3","Quaternion","scale","rotation","Color","Vector3","proxy","subscribe","Color","Vector3","Vector3","Vector3","proxy","Color","subscribe","nanoid","BufferGeometry","LineBasicMaterial","LineSegments","Vector2","BoxGeometry","Color","Group","Mesh","Vector3","Vector2","LineSegments","BufferGeometry","LineBasicMaterial","hoveredUuid","subscribe","subscribe","Vector2","PerspectiveCamera","Vector3","Object3D","Vector3","Vector3","state","Vector2","WebGLRenderer","Vector2","WebGLRenderer","Object3D","Vector3","PerspectiveCamera","position","Vector2","Vector2","Vector2","Vector3","Vector3","nanoid","Vector3","state","Color","subscribe","Vector2","Vector3","proxy","Vector3","Vector3","proxy","Euler","Quaternion","Vector2","subscribe","subscribe"]}
1
+ {"version":3,"sources":["../src/lib/stage/zylem-stage.ts","../src/lib/collision/world.ts","../src/lib/game/game-state.ts","../src/lib/game/game-event-bus.ts","../src/lib/entities/actor.ts","../src/lib/entities/entity.ts","../src/lib/systems/transformable.system.ts","../src/lib/physics/physics-pose.ts","../src/lib/core/flags.ts","../src/lib/core/base-node.ts","../../../node_modules/.pnpm/mitt@3.0.1/node_modules/mitt/src/index.ts","../src/lib/events/event-emitter-delegate.ts","../src/lib/events/zylem-events.ts","../src/lib/actions/capabilities/transform-store.ts","../src/lib/actions/capabilities/moveable.ts","../src/lib/actions/capabilities/velocity-intents.ts","../src/lib/actions/capabilities/rotatable.ts","../src/lib/actions/capabilities/transformable.ts","../src/lib/entities/parts/collision-factories.ts","../src/lib/core/clone-utils.ts","../src/lib/entities/common.ts","../src/lib/graphics/shaders/vertex/object.shader.ts","../src/lib/graphics/shaders/standard.shader.ts","../src/lib/core/asset-manager.ts","../src/lib/core/loaders/texture-loader.ts","../src/lib/core/loaders/gltf-loader.ts","../src/lib/core/loaders/model-clone.ts","../src/lib/core/loaders/fbx-loader.ts","../src/lib/core/loaders/obj-loader.ts","../src/lib/core/loaders/audio-loader.ts","../src/lib/core/loaders/file-loader.ts","../src/lib/core/entity-asset-loader.ts","../src/lib/entities/delegates/animation.ts","../src/lib/graphics/material.ts","../src/lib/core/utility/strings.ts","../src/lib/physics/physics-protocol.ts","../src/lib/physics/physics-body-handle.ts","../src/lib/physics/physics-proxy.ts","../src/lib/physics/serialize-descriptors.ts","../src/lib/graphics/zylem-scene.ts","../src/lib/debug/debug-state.ts","../src/lib/graphics/instance-manager.ts","../src/lib/stage/stage-state.ts","../src/lib/core/utility/vector.ts","../src/lib/core/lifecycle-base.ts","../src/lib/stage/stage-debug-delegate.ts","../src/lib/stage/stage-camera-debug-delegate.ts","../src/lib/stage/debug-entity-cursor.ts","../src/lib/stage/stage-camera-delegate.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/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","../src/lib/stage/stage-loading-delegate.ts","../src/lib/stage/stage-entity-model-delegate.ts","../src/lib/stage/stage-config.ts","../src/lib/core/utility/options-parser.ts","../src/lib/actions/capabilities/apply-transform.ts","../src/lib/stage/stage-entity-delegate.ts","../src/lib/core/vessel.ts","../src/lib/camera/camera.ts","../src/lib/stage/stage-default.ts","../src/lib/input/input-presets.ts","../src/lib/stage/stage.ts","../src/lib/stage/entity-spawner.ts","../src/lib/stage/stage-events.ts"],"sourcesContent":["import { createWorld as createECS } from 'bitecs';\nimport { Color, Vector3 } from 'three';\n\nimport { ZylemWorld } from '../collision/world';\nimport { ZylemScene } from '../graphics/zylem-scene';\nimport { InstanceManager } from '../graphics/instance-manager';\nimport { resetStageVariables, setStageBackgroundColor, setStageBackgroundImage, setStageVariables, clearVariables, initialStageState } from './stage-state';\n\nimport { GameEntityInterface } from '../types/entity-types';\nimport { debugState } from '../debug/debug-state';\n\nimport { SetupContext, UpdateContext, DestroyContext } from '../core/base-node-life-cycle';\nimport { LifeCycleBase } from '../core/lifecycle-base';\nimport createTransformSystem, { StageSystem } from '../systems/transformable.system';\nimport { BaseNode } from '../core/base-node';\nimport { nanoid } from 'nanoid';\nimport { Stage } from './stage';\nimport { CameraWrapper } from '../camera/camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { StageDebugDelegate } from './stage-debug-delegate';\nimport { StageCameraDelegate } from './stage-camera-delegate';\nimport { StageLoadingDelegate } from './stage-loading-delegate';\nimport { StageEntityModelDelegate } from './stage-entity-model-delegate';\nimport { BaseEntityInterface } from '../types/entity-types';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { LoadingEvent } from '../core/interfaces';\nimport { parseStageOptions } from './stage-config';\nimport type { BehaviorSystem, BehaviorSystemFactory } from '../behaviors/behavior-system';\nimport { applyTransformChanges, TransformableEntity } from '../actions/capabilities/apply-transform';\nimport { StageEntityDelegate, StageEntityInput } from './stage-entity-delegate';\nexport type { LoadingEvent };\n\nexport interface ZylemStageConfig {\n\tinputs: Record<string, string[]>;\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader: any | null;\n\tgravity: Vector3;\n\tvariables: Record<string, any>;\n\t/** Physics update rate in Hz (default 60). */\n\tphysicsRate: number;\n\t/** Run physics in a Web Worker for true parallelism (default false). */\n\tusePhysicsWorker: boolean;\n\t/** URL to the physics worker script (required when usePhysicsWorker is true). */\n\tphysicsWorkerUrl?: URL | string;\n\tstageRef?: Stage;\n}\n\nexport type StageOptionItem = Partial<ZylemStageConfig> | CameraWrapper | StageEntityInput;\nexport type StageOptions = [] | [Partial<ZylemStageConfig>, ...StageOptionItem[]];\n\nexport type StageState = ZylemStageConfig & { entities: GameEntityInterface[] };\n\nconst STAGE_TYPE = 'Stage';\n\n/**\n * ZylemStage orchestrates scene, physics world, entities, and lifecycle.\n *\n * Responsibilities:\n * - Manage stage configuration (background, inputs, gravity, variables)\n * - Initialize and own `ZylemScene` and `ZylemWorld`\n * - Coordinate delegates for entities, camera, loading, debug, and models\n * - Drive per-frame updates and transform system\n */\nexport class ZylemStage extends LifeCycleBase<ZylemStage> {\n\tpublic type = STAGE_TYPE;\n\n\tstate: StageState = { ...initialStageState };\n\tgravity: Vector3;\n\n\tworld: ZylemWorld | null;\n\tscene: ZylemScene | null;\n\tinstanceManager: InstanceManager | null = null;\n\n\tecs = createECS();\n\ttransformSystem: ReturnType<typeof createTransformSystem> | null = null;\n\tdebugDelegate: StageDebugDelegate | null = null;\n\n\tuuid: string;\n\twrapperRef: Stage | null = null;\n\tcamera?: CameraWrapper;\n\tcameras: CameraWrapper[] = [];\n\tcameraRef?: ZylemCamera | null = null;\n\t/** Camera manager for multi-camera support */\n\tcameraManagerRef: CameraManager | null = null;\n\t/** Shared renderer manager (injected by the game) */\n\trendererManager: RendererManager | null = null;\n\n\t// Delegates\n\tprivate cameraDelegate: StageCameraDelegate;\n\tprivate loadingDelegate: StageLoadingDelegate;\n\tprivate entityModelDelegate: StageEntityModelDelegate;\n\tprivate readonly childUpdateParams = {} as UpdateContext<any>;\n\n\t/** Entity management delegate — public for external consumers (debug, transform system). */\n\treadonly entityDelegate: StageEntityDelegate;\n\n\t/**\n\t * Create a new stage.\n\t * @param options Stage options: partial config, camera, and initial entities or factories\n\t */\n\tconstructor(options: StageOptions = []) {\n\t\tsuper();\n\t\tthis.world = null;\n\t\tthis.scene = null;\n\t\tthis.uuid = nanoid();\n\n\t\t// Initialize delegates\n\t\tthis.cameraDelegate = new StageCameraDelegate(this);\n\t\tthis.loadingDelegate = new StageLoadingDelegate();\n\t\tthis.entityModelDelegate = new StageEntityModelDelegate();\n\t\tthis.entityDelegate = new StageEntityDelegate(this.loadingDelegate, this.entityModelDelegate);\n\n\t\t// Parse the options array using the stage-config module\n\t\tconst parsed = parseStageOptions(options);\n\t\tthis.camera = parsed.camera;\n\t\tthis.cameras = parsed.cameras;\n\t\tthis.entityDelegate.children = parsed.entities;\n\n\t\t// Async entities are queued via enqueue which handles deferred loading\n\t\tif (parsed.asyncEntities.length) {\n\t\t\tthis.entityDelegate.enqueue(...parsed.asyncEntities);\n\t\t}\n\n\t\t// Update state with resolved config\n\t\tthis.state = {\n\t\t\t...this.state,\n\t\t\tinputs: parsed.config.inputs,\n\t\t\tbackgroundColor: parsed.config.backgroundColor,\n\t\t\tbackgroundImage: parsed.config.backgroundImage,\n\t\t\tbackgroundShader: parsed.config.backgroundShader,\n\t\t\tgravity: parsed.config.gravity,\n\t\t\tvariables: parsed.config.variables,\n\t\t\tphysicsRate: parsed.config.physicsRate,\n\t\t\tusePhysicsWorker: parsed.config.usePhysicsWorker,\n\t\t\tphysicsWorkerUrl: parsed.config.physicsWorkerUrl,\n\t\t\tentities: [],\n\t\t};\n\n\t\tthis.gravity = parsed.config.gravity ?? new Vector3(0, 0, 0);\n\t}\n\n\tprivate setState() {\n\t\tconst { backgroundColor, backgroundImage } = this.state;\n\t\tconst color = backgroundColor instanceof Color ? backgroundColor : new Color(backgroundColor);\n\t\tsetStageBackgroundColor(color);\n\t\tsetStageBackgroundImage(backgroundImage);\n\t\tsetStageVariables(this.state.variables ?? {});\n\t}\n\n\t/**\n\t * Load and initialize the stage's scene and world.\n\t * Uses generator pattern to yield control to event loop for real-time progress.\n\t * @param id DOM element id for the renderer container\n\t * @param camera Optional camera override\n\t */\n\tasync load(id: string, camera?: ZylemCamera | null, rendererManager?: RendererManager | null) {\n\t\tthis.setState();\n\n\t\tif (rendererManager) {\n\t\t\tthis.rendererManager = rendererManager;\n\t\t}\n\n\t\t// Build camera manager first so we can use its primary camera as the\n\t\t// canonical camera reference.\n\t\tif (this.rendererManager) {\n\t\t\tthis.cameraManagerRef = this.cameraDelegate.buildCameraManager(\n\t\t\t\tcamera,\n\t\t\t\t...this.cameras\n\t\t\t);\n\t\t}\n\n\t\t// Derive the resolved camera from the camera manager's primary camera\n\t\t// (when available), otherwise fall back to the legacy single-camera path.\n\t\tconst zylemCamera = this.cameraManagerRef?.primaryCamera\n\t\t\t?? this.cameraDelegate.resolveCamera(camera, this.camera);\n\t\tthis.cameraRef = zylemCamera;\n\t\tthis.scene = new ZylemScene(id, zylemCamera, this.state);\n\n\t\tconst gravity = this.gravity ?? new Vector3(0, 0, 0);\n\t\tif (this.state.usePhysicsWorker) {\n\t\t\tconst workerUrl = this.state.physicsWorkerUrl\n\t\t\t\t? new URL(this.state.physicsWorkerUrl, typeof location !== 'undefined' ? location.href : undefined)\n\t\t\t\t: undefined;\n\t\t\tthis.world = await ZylemWorld.loadPhysicsWorker(gravity, this.state.physicsRate, workerUrl);\n\t\t} else {\n\t\t\tconst physicsWorld = await ZylemWorld.loadPhysics(gravity);\n\t\t\tthis.world = new ZylemWorld(physicsWorld, this.state.physicsRate);\n\t\t}\n\n\t\tthis.scene.setup();\n\n\t\t// Setup cameras: prefer camera manager, fall back to legacy single camera\n\t\tif (this.cameraManagerRef && this.rendererManager) {\n\t\t\tawait this.scene.setupCameraManager(this.scene.scene, this.cameraManagerRef, this.rendererManager);\n\t\t\tconst primaryCam = this.cameraManagerRef.primaryCamera;\n\t\t\tif (primaryCam) {\n\t\t\t\tthis.rendererManager.setupRenderPass(this.scene.scene, primaryCam.camera);\n\t\t\t}\n\t\t\tthis.rendererManager.startRenderLoop((delta) => {\n\t\t\t\tthis.cameraManagerRef?.update(delta);\n\t\t\t\tthis.cameraManagerRef?.render(this.scene!.scene);\n\t\t\t});\n\t\t} else {\n\t\t\tthis.scene.setupCamera(this.scene.scene, zylemCamera);\n\t\t}\n\n\t\tthis.entityModelDelegate.attach(\n\t\t\tthis.scene,\n\t\t\t(entity) => this.entityDelegate.handleLateModelReady(entity),\n\t\t);\n\n\t\t// Initialize instance manager for mesh batching\n\t\tthis.instanceManager = new InstanceManager();\n\t\tthis.instanceManager.setScene(this.scene.scene);\n\n\t\t// Attach entity delegate context now that scene/world are ready\n\t\tthis.entityDelegate.attach({\n\t\t\tscene: this.scene,\n\t\t\tworld: this.world,\n\t\t\tecs: this.ecs,\n\t\t\tinstanceManager: this.instanceManager,\n\t\t\tcamera: zylemCamera,\n\t\t});\n\n\t\tthis.loadingDelegate.emitStart();\n\t\tawait this.entityDelegate.runEntityLoadGenerator();\n\n\t\tthis.transformSystem = createTransformSystem({\n\t\t\t_childrenMap: this.entityDelegate.childrenMap,\n\t\t\t_world: this.world,\n\t\t} as unknown as StageSystem);\n\t\tthis.entityDelegate.isLoaded = true;\n\t\tthis.loadingDelegate.emitComplete();\n\t}\n\n\tprotected _setup(params: SetupContext<ZylemStage>): void {\n\t\tif (!this.scene || !this.world) {\n\t\t\tthis.logMissingEntities();\n\t\t\treturn;\n\t\t}\n\t\t// Debug delegate is self-managing — it subscribes to debugState internally\n\t\t// and activates/deactivates visuals and camera debug automatically.\n\t\tthis.debugDelegate = new StageDebugDelegate(this);\n\t}\n\n\tprotected _update(params: UpdateContext<ZylemStage>): void {\n\t\tconst { delta } = params;\n\t\tif (!this.scene || !this.world) {\n\t\t\tthis.logMissingEntities();\n\t\t\treturn;\n\t\t}\n\t\tthis.world.update(params);\n\n\t\t// Run registered ECS behavior systems\n\t\tfor (const system of this.entityDelegate.behaviorSystems) {\n\t\t\tsystem.update(this.ecs, delta);\n\t\t}\n\n\t\tfor (const child of this.entityDelegate.childrenMap.values()) {\n\t\t\tconst childParams = this.childUpdateParams;\n\t\t\tchildParams.delta = params.delta;\n\t\t\tchildParams.inputs = params.inputs;\n\t\t\tchildParams.globals = params.globals;\n\t\t\tchildParams.camera = params.camera;\n\t\t\tchildParams.stage = params.stage;\n\t\t\tchildParams.game = params.game;\n\t\t\tchildParams.me = child;\n\t\t\tchild.nodeUpdate(childParams);\n\n\t\t\t// Apply pending transformations after update callbacks\n\t\t\tconst transformable = child as unknown as TransformableEntity;\n\t\t\tif (transformable.transformStore) {\n\t\t\t\tapplyTransformChanges(transformable, transformable.transformStore);\n\t\t\t}\n\n\t\t\tif (child.markedForRemoval) {\n\t\t\t\tthis.entityDelegate.removeEntityByUuid(child.uuid);\n\t\t\t}\n\t\t}\n\n\t\t// Sync physics to rendering AFTER transforms are applied\n\t\tthis.transformSystem?.system(this.ecs);\n\n\t\t// Sync instanced mesh transforms\n\t\tthis.instanceManager?.update();\n\t\tthis.scene.update({ delta });\n\t\tthis.scene.updateSkybox(delta);\n\t}\n\n\tpublic outOfLoop() {\n\t\tthis.debugUpdate();\n\t}\n\n\t/** Update debug overlays and helpers if enabled. */\n\tpublic debugUpdate() {\n\t\tif (debugState.enabled) {\n\t\t\tthis.debugDelegate?.update();\n\t\t}\n\t}\n\n\t/** Cleanup owned resources when the stage is destroyed. */\n\tprotected _destroy(params: DestroyContext<ZylemStage>): void {\n\t\t// Delegate handles entity + behavior system cleanup\n\t\tthis.entityDelegate.destroyAll();\n\n\t\tthis.world?.destroy();\n\t\tthis.scene?.destroy();\n\n\t\t// Debug delegate handles its own unsubscription and cleanup\n\t\tthis.debugDelegate?.dispose();\n\t\tthis.debugDelegate = null;\n\n\t\tthis.entityModelDelegate.dispose();\n\n\t\t// Dispose instance manager\n\t\tthis.instanceManager?.dispose();\n\t\tthis.instanceManager = null;\n\n\t\t// Stop renderer render loop if using renderer manager\n\t\tif (this.rendererManager) {\n\t\t\tthis.rendererManager.stopRenderLoop();\n\t\t}\n\n\t\tthis.world = null as any;\n\t\tthis.scene = null as any;\n\t\tthis.cameraRef = null;\n\t\tthis.cameraManagerRef = null;\n\n\t\t// Cleanup transform system\n\t\tthis.transformSystem?.destroy(this.ecs);\n\t\tthis.transformSystem = null;\n\n\t\t// Clear reactive stage variables on unload\n\t\tresetStageVariables();\n\t\tclearVariables(this);\n\t}\n\n\t// ─── Forwarding API ──────────────────────────────────────────────────────\n\n\t/** Forward to entity delegate. */\n\tasync spawnEntity(child: BaseNode) {\n\t\treturn this.entityDelegate.spawnEntity(child);\n\t}\n\n\t/** Forward to entity delegate. */\n\tbuildEntityState(child: BaseNode): Partial<BaseEntityInterface> {\n\t\treturn this.entityDelegate.buildEntityState(child);\n\t}\n\n\t/** Forward to entity delegate. */\n\tonEntityAdded(callback: (entity: BaseNode) => void, options?: { replayExisting?: boolean }) {\n\t\treturn this.entityDelegate.onEntityAdded(callback, options);\n\t}\n\n\tonLoading(callback: (event: LoadingEvent) => void) {\n\t\treturn this.loadingDelegate.onLoading(callback);\n\t}\n\n\t/**\n\t * Register an ECS behavior system to run each frame.\n\t * @param systemOrFactory A BehaviorSystem instance or factory function\n\t * @returns this for chaining\n\t */\n\tregisterSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): this {\n\t\tthis.entityDelegate.registerSystem(systemOrFactory);\n\t\treturn this;\n\t}\n\n\t/** Forward to entity delegate. */\n\tremoveEntityByUuid(uuid: string): boolean {\n\t\treturn this.entityDelegate.removeEntityByUuid(uuid);\n\t}\n\n\t/** Forward to entity delegate. */\n\tgetEntityByName(name: string) {\n\t\treturn this.entityDelegate.getEntityByName(name);\n\t}\n\n\t/** Forward to entity delegate. */\n\tenqueue(...items: StageEntityInput[]) {\n\t\tthis.entityDelegate.enqueue(...items);\n\t}\n\n\tlogMissingEntities() {\n\t\tconsole.warn('Zylem world or scene is null');\n\t}\n\n\t// ─── Camera management forwarding ─────────────────────────────────────\n\n\t/** Add a camera to this stage's camera manager. */\n\taddCamera(camera: ZylemCamera, name?: string): string | null {\n\t\tif (!this.cameraManagerRef) {\n\t\t\tconsole.warn('ZylemStage: CameraManager not available. Ensure stage is loaded with a RendererManager.');\n\t\t\treturn null;\n\t\t}\n\t\treturn this.cameraManagerRef.addCamera(camera, name);\n\t}\n\n\t/** Remove a camera from this stage's camera manager. */\n\tremoveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\treturn this.cameraManagerRef?.removeCamera(nameOrRef) ?? false;\n\t}\n\n\t/** Set the active camera by name or reference. */\n\tsetActiveCamera(nameOrRef: string | ZylemCamera): boolean {\n\t\treturn this.cameraManagerRef?.setActiveCamera(nameOrRef) ?? false;\n\t}\n\n\t/** Get a camera by name from the camera manager. */\n\tgetCamera(name: string): ZylemCamera | null {\n\t\treturn this.cameraManagerRef?.getCamera(name) ?? null;\n\t}\n\n\t/** Resize renderer viewport. */\n\tresize(width: number, height: number) {\n\t\tif (this.scene) {\n\t\t\tthis.scene.updateRenderer(width, height);\n\t\t}\n\t}\n}\n","import { Vector3 } from 'three';\nimport RAPIER, { World } from '@dimforge/rapier3d-compat';\n\nimport { Entity } from '../interfaces/entity';\nimport { state } from '../game/game-state';\nimport { UpdateContext } from '../core/base-node-life-cycle';\nimport { ZylemActor } from '../entities/actor';\nimport {\n\tGameEntity,\n\ttype CollisionDispatchMetadata,\n\ttype CollisionPhase,\n} from '../entities/entity';\nimport { PhysicsProxy } from '../physics/physics-proxy';\nimport { serializeBodyDesc, serializeColliderDesc, serializeCharacterController } from '../physics/serialize-descriptors';\nimport type { CollisionPair } from '../physics/physics-protocol';\nimport {\n\tcommitDirectBodyPoseHistoryStep,\n\tcollapseDirectBodyPoseHistory,\n\tprepareDirectBodyPoseHistoryStep,\n\tregisterDirectBodyPoseHistory,\n} from '../physics/physics-pose';\n\n/**\n * Interface for entities that handle collision events.\n */\nexport interface CollisionHandlerDelegate {\n\thandlePostCollision(params: any): boolean;\n\thandleIntersectionEvent(params: any): void;\n}\n\n/**\n * Type guard to check if an object implements CollisionHandlerDelegate.\n */\nexport function isCollisionHandlerDelegate(obj: any): obj is CollisionHandlerDelegate {\n\treturn typeof obj?.handlePostCollision === \"function\" && typeof obj?.handleIntersectionEvent === \"function\";\n}\n\nexport interface CollisionSnapshotEntry {\n\tuuidA: string;\n\tuuidB: string;\n\thasContact: boolean;\n\thasIntersection: boolean;\n}\n\nfunction createCollisionSnapshotKey(uuidA: string, uuidB: string): string {\n\treturn uuidA < uuidB ? `${uuidA}|${uuidB}` : `${uuidB}|${uuidA}`;\n}\n\nexport function buildCollisionSnapshot(\n\tpairs: CollisionPair[],\n): Map<string, CollisionSnapshotEntry> {\n\tconst snapshot = new Map<string, CollisionSnapshotEntry>();\n\n\tfor (const pair of pairs) {\n\t\tif (pair.uuidA === pair.uuidB) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst key = createCollisionSnapshotKey(pair.uuidA, pair.uuidB);\n\t\tconst uuidA = pair.uuidA < pair.uuidB ? pair.uuidA : pair.uuidB;\n\t\tconst uuidB = pair.uuidA < pair.uuidB ? pair.uuidB : pair.uuidA;\n\t\tconst existing = snapshot.get(key);\n\n\t\tif (existing) {\n\t\t\tif (pair.contactType === 'contact') {\n\t\t\t\texisting.hasContact = true;\n\t\t\t} else {\n\t\t\t\texisting.hasIntersection = true;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tsnapshot.set(key, {\n\t\t\tuuidA,\n\t\t\tuuidB,\n\t\t\thasContact: pair.contactType === 'contact',\n\t\t\thasIntersection: pair.contactType === 'intersection',\n\t\t});\n\t}\n\n\treturn snapshot;\n}\n\n/**\n * Physics world wrapper supporting two modes:\n *\n * - **Direct mode** (default): Rapier world lives on the main thread.\n * This is the original behavior with the Phase-1 fixed-timestep accumulator.\n *\n * - **Worker mode**: Physics runs in a Web Worker via {@link PhysicsProxy}.\n * Entity bodies are replaced with {@link PhysicsBodyHandle} instances that\n * cache transforms and queue write commands. Collision events are delivered\n * asynchronously (one frame latency).\n */\nexport class ZylemWorld implements Entity<ZylemWorld> {\n\ttype = 'World';\n\n\t/** Rapier world instance (null in worker mode). */\n\tworld: World;\n\n\tcollisionMap: Map<string, GameEntity<any>> = new Map();\n\tcollisionBehaviorMap: Map<string, GameEntity<any>> = new Map();\n\t_removalMap: Map<string, GameEntity<any>> = new Map();\n\tprivate activeCollisionPairs: Map<string, CollisionSnapshotEntry> = new Map();\n\tprivate currentCollisionTimeMs = 0;\n\n\t/** Fixed timestep in seconds used for each physics step. */\n\treadonly fixedTimestep: number;\n\t/** Unprocessed time carried over between frames. */\n\tprivate accumulator = 0;\n\t/** Maximum number of physics steps allowed per frame to prevent spiral-of-death. */\n\tprivate static readonly MAX_STEPS_PER_FRAME = 5;\n\t/**\n\t * Interpolation alpha (0..1) representing the fraction of an unprocessed\n\t * timestep remaining after the last physics step. Can be used to interpolate\n\t * rendering transforms between the previous and current physics state.\n\t */\n\tinterpolationAlpha = 0;\n\n\t// ─── Worker Mode ─────────────────────────────────────────────────────\n\n\t/** When true, physics runs in a Web Worker via the proxy. */\n\treadonly workerMode: boolean;\n\t/** Physics worker proxy (only set in worker mode). */\n\tprivate proxy: PhysicsProxy | null = null;\n\t/** Pending step promise (worker mode). */\n\tprivate _pendingStep: Promise<void> | null = null;\n\tprivate readonly trackedDirectBodies = new WeakSet<RAPIER.RigidBody>();\n\n\tstatic async loadPhysics(gravity: Vector3) {\n\t\tawait RAPIER.init();\n\t\tconst physicsWorld = new RAPIER.World(gravity);\n\t\treturn physicsWorld;\n\t}\n\n\t/**\n\t * Initialize physics in worker mode. Returns a ZylemWorld that\n\t * delegates all physics to a Web Worker.\n\t *\n\t * @param gravity World gravity.\n\t * @param physicsRate Physics tick rate in Hz.\n\t * @param workerUrl Optional URL to the worker script.\n\t */\n\tstatic async loadPhysicsWorker(\n\t\tgravity: Vector3,\n\t\tphysicsRate = 60,\n\t\tworkerUrl?: URL,\n\t): Promise<ZylemWorld> {\n\t\tconst proxy = new PhysicsProxy();\n\t\tawait proxy.init(\n\t\t\t[gravity.x, gravity.y, gravity.z],\n\t\t\tphysicsRate,\n\t\t\tworkerUrl,\n\t\t);\n\n\t\tconst zw = new ZylemWorld(null as unknown as World, physicsRate, true);\n\t\tzw.proxy = proxy;\n\n\t\treturn zw;\n\t}\n\n\t/**\n\t * @param world The Rapier physics world instance (null in worker mode).\n\t * @param physicsRate Physics update rate in Hz (default 60).\n\t * @param useWorker Whether to use worker mode (default false).\n\t */\n\tconstructor(world: World, physicsRate = 60, useWorker = false) {\n\t\tthis.world = world;\n\t\tthis.workerMode = useWorker;\n\t\tthis.fixedTimestep = 1 / physicsRate;\n\t\tif (!useWorker && world) {\n\t\t\tthis.world.integrationParameters.dt = this.fixedTimestep;\n\t\t}\n\t}\n\n\t// ─── Entity Management ───────────────────────────────────────────────\n\n\taddEntity(entity: any) {\n\t\tif (this.workerMode) {\n\t\t\tthis.addEntityWorker(entity);\n\t\t\treturn;\n\t\t}\n\t\tthis.addEntityDirect(entity);\n\t}\n\n\tsetForRemoval(entity: any) {\n\t\tif (entity.physicsAttached) {\n\t\t\tthis._removalMap.set(entity.uuid, entity);\n\t\t}\n\t}\n\n\tdestroyEntity(entity: GameEntity<any>) {\n\t\tif (this.workerMode) {\n\t\t\tthis.destroyEntityWorker(entity);\n\t\t\treturn;\n\t\t}\n\t\tthis.destroyEntityDirect(entity);\n\t}\n\n\tsetup() { }\n\n\t// ─── Update ──────────────────────────────────────────────────────────\n\n\t/**\n\t * Advance the physics simulation.\n\t *\n\t * In direct mode, uses the fixed-timestep accumulator on the main thread.\n\t * In worker mode, sends a step command and awaits the result.\n\t */\n\tupdate(params: UpdateContext<any>) {\n\t\tif (this.workerMode) {\n\t\t\tthis.updateWorker(params);\n\t\t\treturn;\n\t\t}\n\t\tthis.updateDirect(params);\n\t}\n\n\t/**\n\t * In worker mode, the step is async. Call this to await the\n\t * pending step before reading transform data.\n\t */\n\tasync awaitStep(): Promise<void> {\n\t\tif (this._pendingStep) {\n\t\t\tawait this._pendingStep;\n\t\t\tthis._pendingStep = null;\n\t\t}\n\t}\n\n\t// ─── Direct Mode Implementation ──────────────────────────────────────\n\n\tprivate addEntityDirect(entity: any) {\n\t\tconst rigidBody = this.world.createRigidBody(entity.bodyDesc);\n\t\tentity.body = rigidBody;\n\t\tentity.physicsAttached = true;\n\t\tentity.body.userData = { uuid: entity.uuid, ref: entity };\n\t\tregisterDirectBodyPoseHistory(rigidBody);\n\t\tthis.patchDirectBodyPoseTracking(rigidBody);\n\t\tif (this.world.gravity.x === 0 && this.world.gravity.y === 0 && this.world.gravity.z === 0) {\n\t\t\tentity.body.lockTranslations(true, true);\n\t\t\tentity.body.lockRotations(true, true);\n\t\t}\n\n\t\tconst collider = this.world.createCollider(entity.colliderDesc, entity.body);\n\t\tentity.collider = collider;\n\t\tentity.colliders = [collider];\n\n\t\tif (entity.colliderDescs?.length > 1) {\n\t\t\tfor (let i = 1; i < entity.colliderDescs.length; i++) {\n\t\t\t\tconst additionalCollider = this.world.createCollider(entity.colliderDescs[i], entity.body);\n\t\t\t\tentity.colliders.push(additionalCollider);\n\t\t\t}\n\t\t}\n\n\t\tif (entity.controlledRotation || entity instanceof ZylemActor) {\n\t\t\tentity.body.lockRotations(true, true);\n\t\t\tentity.characterController = this.world.createCharacterController(0.01);\n\t\t\tentity.characterController.setMaxSlopeClimbAngle(45 * Math.PI / 180);\n\t\t\tentity.characterController.setMinSlopeSlideAngle(30 * Math.PI / 180);\n\t\t\tentity.characterController.enableSnapToGround(0.01);\n\t\t\tentity.characterController.setSlideEnabled(true);\n\t\t\tentity.characterController.setApplyImpulsesToDynamicBodies(true);\n\t\t\tentity.characterController.setCharacterMass(1);\n\t\t}\n\t\tthis.collisionMap.set(entity.uuid, entity);\n\t}\n\n\tprivate destroyEntityDirect(entity: GameEntity<any>) {\n\t\tif ((entity as any).characterController) {\n\t\t\ttry { (entity as any).characterController.free(); } catch { /* noop */ }\n\t\t\t(entity as any).characterController = null;\n\t\t}\n\t\tif (entity.colliders?.length) {\n\t\t\tfor (const collider of entity.colliders) {\n\t\t\t\ttry { this.world.removeCollider(collider, true); } catch { /* noop */ }\n\t\t\t}\n\t\t} else if (entity.collider) {\n\t\t\ttry { this.world.removeCollider(entity.collider, true); } catch { /* noop */ }\n\t\t}\n\t\tif (entity.body) {\n\t\t\ttry { this.world.removeRigidBody(entity.body); } catch { /* noop */ }\n\t\t\tthis.removeEntityFromTracking(entity.uuid);\n\t\t}\n\t\tthis.clearEntityPhysicsState(entity);\n\t}\n\n\tprivate updateDirect(params: UpdateContext<any>) {\n\t\tconst { delta } = params;\n\t\tif (!this.world) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.currentCollisionTimeMs += delta * 1000;\n\t\tthis.processPendingRemovals();\n\t\tthis.accumulator += delta;\n\n\t\tconst maxAccumulator = this.fixedTimestep * ZylemWorld.MAX_STEPS_PER_FRAME;\n\t\tthis.accumulator = Math.min(this.accumulator, maxAccumulator);\n\n\t\twhile (this.accumulator >= this.fixedTimestep) {\n\t\t\tthis.captureDirectBodyPreviousPoses();\n\t\t\tthis.world.step();\n\t\t\tthis.captureDirectBodyCurrentPoses();\n\t\t\tthis.accumulator -= this.fixedTimestep;\n\t\t}\n\n\t\tthis.processCollisionPairs(\n\t\t\tthis.collectCollisionPairsFromWorld(),\n\t\t\tdelta,\n\t\t\tthis.currentCollisionTimeMs,\n\t\t);\n\t\tthis.interpolationAlpha = this.accumulator / this.fixedTimestep;\n\t}\n\n\tprivate captureDirectBodyPreviousPoses() {\n\t\tfor (const [, collider] of this.collisionMap) {\n\t\t\tconst body = (collider as GameEntity<any>).body as RAPIER.RigidBody | null;\n\t\t\tif (body) {\n\t\t\t\tprepareDirectBodyPoseHistoryStep(body);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate captureDirectBodyCurrentPoses() {\n\t\tfor (const [, collider] of this.collisionMap) {\n\t\t\tconst body = (collider as GameEntity<any>).body as RAPIER.RigidBody | null;\n\t\t\tif (body) {\n\t\t\t\tcommitDirectBodyPoseHistoryStep(body);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate patchDirectBodyPoseTracking(body: RAPIER.RigidBody) {\n\t\tif (this.trackedDirectBodies.has(body)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst trackedBody = body as RAPIER.RigidBody & {\n\t\t\tsetTranslation: (\n\t\t\t\ttranslation: { x: number; y: number; z: number },\n\t\t\t\twakeUp: boolean,\n\t\t\t) => void;\n\t\t\tsetRotation: (\n\t\t\t\trotation: { x: number; y: number; z: number; w: number },\n\t\t\t\twakeUp: boolean,\n\t\t\t) => void;\n\t\t};\n\t\tconst originalSetTranslation = body.setTranslation.bind(body);\n\t\tconst originalSetRotation = body.setRotation.bind(body);\n\n\t\ttrackedBody.setTranslation = (translation, wakeUp) => {\n\t\t\toriginalSetTranslation(translation, wakeUp);\n\t\t\tcollapseDirectBodyPoseHistory(body);\n\t\t};\n\t\ttrackedBody.setRotation = (rotation, wakeUp) => {\n\t\t\toriginalSetRotation(rotation, wakeUp);\n\t\t\tcollapseDirectBodyPoseHistory(body);\n\t\t};\n\n\t\tthis.trackedDirectBodies.add(body);\n\t}\n\n\t// ─── Worker Mode Implementation ──────────────────────────────────────\n\n\tprivate addEntityWorker(entity: any) {\n\t\tif (!this.proxy) return;\n\n\t\tconst bodyDesc = serializeBodyDesc(entity.bodyDesc);\n\t\tconst colliderDescs = (entity.colliderDescs?.length > 0 ? entity.colliderDescs : [entity.colliderDesc])\n\t\t\t.filter(Boolean)\n\t\t\t.map(serializeColliderDesc);\n\n\t\tconst needsCharCtrl = entity.controlledRotation || entity instanceof ZylemActor;\n\t\tconst charCtrl = needsCharCtrl ? serializeCharacterController() : undefined;\n\n\t\tconst handle = this.proxy.addBody(entity.uuid, bodyDesc, colliderDescs, charCtrl);\n\n\t\t// Replace entity.body with the handle. The handle provides the same\n\t\t// read API (translation(), rotation(), linvel(), angvel()) and queues\n\t\t// write operations as commands for the worker.\n\t\tentity.body = handle as any;\n\t\tentity.physicsAttached = true;\n\t\tentity.collider = null;\n\t\tentity.colliders = [];\n\n\t\tthis.collisionMap.set(entity.uuid, entity);\n\t}\n\n\tprivate destroyEntityWorker(entity: GameEntity<any>) {\n\t\tif (!this.proxy) return;\n\t\tthis.proxy.removeBody(entity.uuid);\n\t\tthis.removeEntityFromTracking(entity.uuid);\n\t\tthis.clearEntityPhysicsState(entity);\n\t}\n\n\tprivate updateWorker(params: UpdateContext<any>) {\n\t\tif (!this.proxy) return;\n\n\t\tconst { delta } = params;\n\t\tthis.currentCollisionTimeMs += delta * 1000;\n\t\tthis.processPendingRemovals();\n\t\tconst collisionTimeMs = this.currentCollisionTimeMs;\n\t\tthis._pendingStep = this.proxy.step(delta).then((result) => {\n\t\t\tthis.interpolationAlpha = result.interpolationAlpha;\n\t\t\tthis.processCollisionPairs(result.collisions, delta, collisionTimeMs);\n\t\t});\n\t}\n\n\t// ─── Shared collision behavior processing ────────────────────────────\n\n\tupdatePostCollisionBehaviors(delta: number) {\n\t\tconst dictionaryRef = this.collisionBehaviorMap;\n\t\tfor (let [id, collider] of dictionaryRef) {\n\t\t\tconst gameEntity = collider as any;\n\t\t\tif (!isCollisionHandlerDelegate(gameEntity)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst active = gameEntity.handlePostCollision({ entity: gameEntity, delta });\n\t\t\tif (!active) {\n\t\t\t\tthis.collisionBehaviorMap.delete(id);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate processPendingRemovals() {\n\t\tif (this._removalMap.size === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const [, entity] of this._removalMap) {\n\t\t\tthis.destroyEntity(entity);\n\t\t}\n\t\tthis._removalMap.clear();\n\t}\n\n\tprivate removeEntityFromTracking(uuid: string) {\n\t\tthis.collisionMap.delete(uuid);\n\t\tthis._removalMap.delete(uuid);\n\t\tthis.pruneActiveCollisionPairs(uuid);\n\t}\n\n\tprivate pruneActiveCollisionPairs(uuid: string) {\n\t\tfor (const [key, pair] of this.activeCollisionPairs) {\n\t\t\tif (pair.uuidA === uuid || pair.uuidB === uuid) {\n\t\t\t\tthis.activeCollisionPairs.delete(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate collectCollisionPairsFromWorld(): CollisionPair[] {\n\t\tconst pairs: CollisionPair[] = [];\n\t\tif (!this.world) {\n\t\t\treturn pairs;\n\t\t}\n\n\t\tfor (const [, collider] of this.collisionMap) {\n\t\t\tconst gameEntity = collider as GameEntity<any>;\n\t\t\tconst body = gameEntity.body as RAPIER.RigidBody | null;\n\t\t\tif (!body) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst primaryCollider = body.collider(0);\n\t\t\tif (!primaryCollider) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tthis.world.contactsWith(primaryCollider, (otherCollider) => {\n\t\t\t\tconst otherBody = otherCollider.parent();\n\t\t\t\tconst otherUuid = (otherBody?.userData as any)?.uuid as string | undefined;\n\t\t\t\tif (otherUuid) {\n\t\t\t\t\tpairs.push({\n\t\t\t\t\t\tuuidA: gameEntity.uuid,\n\t\t\t\t\t\tuuidB: otherUuid,\n\t\t\t\t\t\tcontactType: 'contact',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.world.intersectionsWith(primaryCollider, (otherCollider) => {\n\t\t\t\tconst otherBody = otherCollider.parent();\n\t\t\t\tconst otherUuid = (otherBody?.userData as any)?.uuid as string | undefined;\n\t\t\t\tif (otherUuid) {\n\t\t\t\t\tpairs.push({\n\t\t\t\t\t\tuuidA: gameEntity.uuid,\n\t\t\t\t\t\tuuidB: otherUuid,\n\t\t\t\t\t\tcontactType: 'intersection',\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn pairs;\n\t}\n\n\tprivate processCollisionPairs(\n\t\tpairs: CollisionPair[],\n\t\tdelta: number,\n\t\tnowMs: number = this.currentCollisionTimeMs,\n\t) {\n\t\tconst snapshot = buildCollisionSnapshot(pairs);\n\n\t\tfor (const [key, pair] of snapshot) {\n\t\t\tconst wasActive = this.activeCollisionPairs.has(key);\n\t\t\tif (!wasActive) {\n\t\t\t\tthis.dispatchCollisionPhase(pair, 'enter', nowMs);\n\t\t\t}\n\t\t\tthis.dispatchCollisionPhase(pair, 'stay', nowMs);\n\n\t\t\tif (pair.hasIntersection) {\n\t\t\t\tthis.dispatchIntersectionDelegates(pair, delta);\n\t\t\t}\n\t\t}\n\n\t\tthis.updatePostCollisionBehaviors(delta);\n\t\tthis.activeCollisionPairs = snapshot;\n\t}\n\n\tprivate dispatchCollisionPhase(\n\t\tpair: CollisionSnapshotEntry,\n\t\tphase: CollisionPhase,\n\t\tnowMs: number,\n\t) {\n\t\tconst dispatch: CollisionDispatchMetadata = { phase, nowMs };\n\t\tconst entityA = this.collisionMap.get(pair.uuidA);\n\t\tconst entityB = this.collisionMap.get(pair.uuidB);\n\n\t\tif (entityA && entityB) {\n\t\t\tentityA._collision(entityB, state.globals, dispatch);\n\t\t}\n\n\t\tconst refreshedA = this.collisionMap.get(pair.uuidA);\n\t\tconst refreshedB = this.collisionMap.get(pair.uuidB);\n\t\tif (refreshedA && refreshedB) {\n\t\t\trefreshedB._collision(refreshedA, state.globals, dispatch);\n\t\t}\n\t}\n\n\tprivate dispatchIntersectionDelegates(\n\t\tpair: CollisionSnapshotEntry,\n\t\tdelta: number,\n\t) {\n\t\tconst entityA = this.collisionMap.get(pair.uuidA);\n\t\tconst entityB = this.collisionMap.get(pair.uuidB);\n\n\t\tif (entityA && entityB && isCollisionHandlerDelegate(entityA)) {\n\t\t\tentityA.handleIntersectionEvent({\n\t\t\t\tentity: entityA,\n\t\t\t\tother: entityB,\n\t\t\t\tdelta,\n\t\t\t});\n\t\t\tthis.collisionBehaviorMap.set(entityA.uuid, entityA);\n\t\t}\n\n\t\tconst refreshedA = this.collisionMap.get(pair.uuidA);\n\t\tconst refreshedB = this.collisionMap.get(pair.uuidB);\n\t\tif (refreshedA && refreshedB && isCollisionHandlerDelegate(refreshedB)) {\n\t\t\trefreshedB.handleIntersectionEvent({\n\t\t\t\tentity: refreshedB,\n\t\t\t\tother: refreshedA,\n\t\t\t\tdelta,\n\t\t\t});\n\t\t\tthis.collisionBehaviorMap.set(refreshedB.uuid, refreshedB);\n\t\t}\n\t}\n\n\t// ─── Cleanup ─────────────────────────────────────────────────────────\n\n\tdestroy() {\n\t\ttry {\n\t\t\tif (this.workerMode) {\n\t\t\t\tfor (const [, entity] of this.collisionMap) {\n\t\t\t\t\tthis.clearEntityPhysicsState(entity);\n\t\t\t\t}\n\t\t\t\tthis.proxy?.dispose();\n\t\t\t\tthis.proxy = null;\n\t\t\t} else {\n\t\t\t\tfor (const [, entity] of this.collisionMap) {\n\t\t\t\t\ttry { this.destroyEntityDirect(entity); } catch { /* noop */ }\n\t\t\t\t}\n\t\t\t\ttry { this.world?.free(); } catch { /* noop */ }\n\t\t\t\t// @ts-ignore\n\t\t\t\tthis.world = undefined as any;\n\t\t\t}\n\t\t\tthis.collisionMap.clear();\n\t\t\tthis.collisionBehaviorMap.clear();\n\t\t\tthis._removalMap.clear();\n\t\t\tthis.activeCollisionPairs.clear();\n\t\t} catch { /* noop */ }\n\t}\n\n\tprivate clearEntityPhysicsState(entity: GameEntity<any>): void {\n\t\tentity.physicsAttached = false;\n\t\tentity.body = null;\n\t\tentity.collider = undefined;\n\t\tentity.colliders = [];\n\t\t(entity as any).characterController = null;\n\t}\n\n}\n","import { proxy, subscribe } from 'valtio/vanilla';\nimport { getByPath, setByPath } from '../core/utility/path-utils';\nimport { gameEventBus } from './game-event-bus';\n\n/**\n * Internal game state store using valtio proxy for reactivity.\n */\nconst state = proxy({\n\tid: '',\n\tglobals: {} as Record<string, unknown>,\n\ttime: 0,\n});\n\n/**\n * Track active subscriptions for cleanup on game dispose.\n */\nconst activeSubscriptions: Set<() => void> = new Set();\n\n/**\n * Set a global value by path.\n * Emits a 'game:state:updated' event when the value changes.\n * @example setGlobal('score', 100)\n * @example setGlobal('player.health', 50)\n */\nexport function setGlobal(path: string, value: unknown): void {\n\tconst previousValue = getByPath(state.globals, path);\n\tsetByPath(state.globals, path, value);\n\n\tgameEventBus.emit('game:state:updated', {\n\t\tpath,\n\t\tvalue,\n\t\tpreviousValue,\n\t});\n}\n\n/**\n * Create/initialize a global with a default value.\n * Only sets the value if it doesn't already exist.\n * Use this to ensure globals have initial values before game starts.\n * @example createGlobal('score', 0)\n * @example createGlobal('player.health', 100)\n */\nexport function createGlobal<T>(path: string, defaultValue: T): T {\n\tconst existing = getByPath<T>(state.globals, path);\n\tif (existing === undefined) {\n\t\tsetByPath(state.globals, path, defaultValue);\n\t\treturn defaultValue;\n\t}\n\treturn existing;\n}\n\n/**\n * Get a global value by path.\n * @example getGlobal('score') // 100\n * @example getGlobal<number>('player.health') // 50\n */\nexport function getGlobal<T = unknown>(path: string): T | undefined {\n\treturn getByPath<T>(state.globals, path);\n}\n\n/**\n * Subscribe to changes on a global value at a specific path.\n * Returns an unsubscribe function. Subscriptions are automatically\n * cleaned up when the game is disposed.\n * @example const unsub = onGlobalChange('score', (val) => console.log(val));\n */\nexport function onGlobalChange<T = unknown>(\n\tpath: string,\n\tcallback: (value: T) => void\n): () => void {\n\tlet previous = getByPath<T>(state.globals, path);\n\tconst unsub = subscribe(state.globals, () => {\n\t\tconst current = getByPath<T>(state.globals, path);\n\t\tif (current !== previous) {\n\t\t\tprevious = current;\n\t\t\tcallback(current as T);\n\t\t}\n\t});\n\tactiveSubscriptions.add(unsub);\n\treturn () => {\n\t\tunsub();\n\t\tactiveSubscriptions.delete(unsub);\n\t};\n}\n\n/**\n * Subscribe to changes on multiple global paths.\n * Callback fires when any of the paths change, receiving all current values.\n * Subscriptions are automatically cleaned up when the game is disposed.\n * @example const unsub = onGlobalChanges(['score', 'lives'], ([score, lives]) => console.log(score, lives));\n */\nexport function onGlobalChanges<T extends unknown[] = unknown[]>(\n\tpaths: string[],\n\tcallback: (values: T) => void\n): () => void {\n\tlet previousValues = paths.map(p => getByPath(state.globals, p));\n\tconst unsub = subscribe(state.globals, () => {\n\t\tconst currentValues = paths.map(p => getByPath(state.globals, p));\n\t\tconst hasChange = currentValues.some((val, i) => val !== previousValues[i]);\n\t\tif (hasChange) {\n\t\t\tpreviousValues = currentValues;\n\t\t\tcallback(currentValues as T);\n\t\t}\n\t});\n\tactiveSubscriptions.add(unsub);\n\treturn () => {\n\t\tunsub();\n\t\tactiveSubscriptions.delete(unsub);\n\t};\n}\n\n/**\n * Get the entire globals object (read-only snapshot).\n */\nexport function getGlobals<T = Record<string, unknown>>(): T {\n\treturn state.globals as T;\n}\n\n/**\n * Initialize globals from an object. Used internally during game setup.\n */\nexport function initGlobals(globals: Record<string, unknown>): void {\n\tfor (const [key, value] of Object.entries(globals)) {\n\t\tsetByPath(state.globals, key, value);\n\t}\n}\n\n/**\n * Reset all globals. Used internally on game dispose.\n */\nexport function resetGlobals(): void {\n\tstate.globals = {};\n}\n\n/**\n * Unsubscribe all active global subscriptions.\n * Used internally on game dispose to prevent old callbacks from firing.\n */\nexport function clearGlobalSubscriptions(): void {\n\tfor (const unsub of activeSubscriptions) {\n\t\tunsub();\n\t}\n\tactiveSubscriptions.clear();\n}\n\nexport { state };","import { LoadingEvent } from '../core/interfaces';\n\n/**\n * Event types for the game event bus.\n */\nexport type GameEventType = \n\t| 'stage:loading:start'\n\t| 'stage:loading:progress'\n\t| 'stage:loading:complete'\n\t| 'game:state:updated';\n\n/**\n * Payload for stage loading events.\n */\nexport interface StageLoadingPayload extends LoadingEvent {\n\tstageName?: string;\n\tstageIndex?: number;\n}\n\n/**\n * Payload for game state update events.\n */\nexport interface GameStateUpdatedPayload {\n\tpath: string;\n\tvalue: unknown;\n\tpreviousValue?: unknown;\n}\n\n/**\n * Event map for typed event handling.\n */\nexport interface GameEventMap {\n\t'stage:loading:start': StageLoadingPayload;\n\t'stage:loading:progress': StageLoadingPayload;\n\t'stage:loading:complete': StageLoadingPayload;\n\t'game:state:updated': GameStateUpdatedPayload;\n}\n\ntype EventCallback<T> = (payload: T) => void;\n\n/**\n * Simple event bus for game-stage communication.\n * Used to decouple stage loading events from direct coupling.\n */\nexport class GameEventBus {\n\tprivate listeners: Map<GameEventType, Set<EventCallback<any>>> = new Map();\n\n\t/**\n\t * Subscribe to an event type.\n\t */\n\ton<K extends GameEventType>(event: K, callback: EventCallback<GameEventMap[K]>): () => void {\n\t\tif (!this.listeners.has(event)) {\n\t\t\tthis.listeners.set(event, new Set());\n\t\t}\n\t\tthis.listeners.get(event)!.add(callback);\n\t\treturn () => this.off(event, callback);\n\t}\n\n\t/**\n\t * Unsubscribe from an event type.\n\t */\n\toff<K extends GameEventType>(event: K, callback: EventCallback<GameEventMap[K]>): void {\n\t\tthis.listeners.get(event)?.delete(callback);\n\t}\n\n\t/**\n\t * Emit an event to all subscribers.\n\t */\n\temit<K extends GameEventType>(event: K, payload: GameEventMap[K]): void {\n\t\tconst callbacks = this.listeners.get(event);\n\t\tif (!callbacks) return;\n\t\tfor (const cb of callbacks) {\n\t\t\ttry {\n\t\t\t\tcb(payload);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error(`Error in event handler for ${event}`, e);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear all listeners.\n\t */\n\tdispose(): void {\n\t\tthis.listeners.clear();\n\t}\n}\n\n/**\n * Singleton event bus instance for global game events.\n */\nexport const gameEventBus = new GameEventBus();\n","import { ActiveCollisionTypes, ColliderDesc } from '@dimforge/rapier3d-compat';\nimport {\n\tBox3,\n\tBufferAttribute,\n\tObject3D,\n\tSkinnedMesh,\n\tMesh,\n\tMeshStandardMaterial,\n\tGroup,\n\tVector3,\n\tMaterial,\n\tMatrix4,\n} from 'three';\n\nimport { BaseNode } from '../core/base-node';\nimport { GameEntityOptions, GameEntity } from './entity';\nimport { createEntity } from './create';\nimport {\n\tCleanupContext,\n\tUpdateContext,\n\tUpdateFunction,\n} from '../core/base-node-life-cycle';\nimport { AssetLoaderResult, EntityAssetLoader } from '../core/entity-asset-loader';\nimport { EntityLoaderDelegate } from './delegates/loader';\nimport { Vec3 } from '../core/vector';\nimport { AnimationDelegate, AnimationOptions } from './delegates/animation';\nimport { MaterialOptions } from '../graphics/material';\nimport { DebugInfoProvider } from './delegates/debug';\nimport { EntityBuilder, EntityCollisionBuilder } from './builder';\nimport { commonDefaults } from './common';\nimport { standardShader } from '../graphics/shaders/standard.shader';\n\ntype AnimationObject = {\n\tkey?: string;\n\tpath: string;\n};\n\nexport type CollisionShapeType = 'capsule' | 'bounds' | 'trimesh' | 'model';\ntype ResolvedCollisionShape = 'capsule' | 'bounds' | 'trimesh';\n\ntype ZylemActorOptions = GameEntityOptions & {\n\tstatic?: boolean;\n\tanimations?: AnimationObject[];\n\tmodels?: string[];\n\tscale?: Vec3;\n\tmaterial?: MaterialOptions;\n\tcollisionShape?: CollisionShapeType;\n};\n\ntype TransparentMaterial = Material & {\n\topacity: number;\n\ttransparent: boolean;\n\tneedsUpdate: boolean;\n};\n\ntype TrimeshMetadata = {\n\tshape: 'trimesh';\n\tvertices: number[];\n\tindices: number[];\n};\n\ntype ModelBounds = {\n\tsize: Vector3;\n\tcenter: Vector3;\n};\n\ntype ModelTrimesh = {\n\tvertices: Float32Array;\n\tindices: Uint32Array;\n\tcenter: Vector3;\n};\n\ntype CollisionSourceSelection = {\n\tfile: string | null;\n\treuseVisibleModel: boolean;\n};\n\nconst actorDefaults: ZylemActorOptions = {\n\t...commonDefaults,\n\tmaterial: {\n\t\tshader: standardShader,\n\t},\n\tanimations: [],\n\tmodels: [],\n\tcollisionShape: 'capsule',\n};\n\nfunction getActorScale(options: ZylemActorOptions): Vector3 {\n\treturn new Vector3(\n\t\toptions.scale?.x ?? 1,\n\t\toptions.scale?.y ?? 1,\n\t\toptions.scale?.z ?? 1,\n\t);\n}\n\nfunction getCollisionPosition(\n\toptions: ZylemActorOptions,\n): { x: number; y: number; z: number } | null {\n\tconst position = options.collision?.position;\n\tif (!position) {\n\t\treturn null;\n\t}\n\treturn {\n\t\tx: position.x ?? 0,\n\t\ty: position.y ?? 0,\n\t\tz: position.z ?? 0,\n\t};\n}\n\nfunction hasExplicitCollisionSize(options: ZylemActorOptions): boolean {\n\treturn Boolean(options.collision?.size);\n}\n\nfunction warnDynamicTrimeshOnce(actor: ZylemActor): void {\n\tif (actor.hasWarnedDynamicTrimesh) {\n\t\treturn;\n\t}\n\tactor.hasWarnedDynamicTrimesh = true;\n\tconsole.warn(\n\t\t`Actor \"${actor.name || actor.uuid}\" requested collisionShape=\"trimesh\" on a dynamic body; falling back to bounds.`,\n\t);\n}\n\nfunction resolveCollisionShape(\n\tshape: CollisionShapeType | undefined,\n\tisStatic: boolean,\n\tonDynamicTrimesh?: () => void,\n): ResolvedCollisionShape {\n\tconst normalized = shape === 'model' ? 'bounds' : (shape ?? 'capsule');\n\tif (normalized === 'trimesh' && !isStatic) {\n\t\tonDynamicTrimesh?.();\n\t\treturn 'bounds';\n\t}\n\treturn normalized;\n}\n\nfunction tagTrimeshCollider(\n\tcolliderDesc: ColliderDesc,\n\tvertices: Float32Array,\n\tindices: Uint32Array,\n): ColliderDesc {\n\t(colliderDesc as any).__zylemShapeData = {\n\t\tshape: 'trimesh',\n\t\tvertices: Array.from(vertices),\n\t\tindices: Array.from(indices),\n\t} as TrimeshMetadata;\n\treturn colliderDesc;\n}\n\nfunction createCapsuleColliderFromDimensions(\n\tsize: { x: number; y: number; z: number },\n\ttranslation: { x: number; y: number; z: number },\n): ColliderDesc {\n\tconst fullWidth = size.x || 0.5;\n\tconst fullHeight = size.y || 1;\n\tconst fullDepth = size.z || 0.5;\n\tconst radius = Math.max(fullWidth, fullDepth) / 2;\n\tconst halfTotalHeight = fullHeight / 2;\n\tconst halfCylinder = Math.max(0, halfTotalHeight - radius);\n\tconst colliderDesc = ColliderDesc.capsule(halfCylinder, radius);\n\tcolliderDesc.setSensor(false);\n\tcolliderDesc.setTranslation(translation.x, translation.y, translation.z);\n\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\treturn colliderDesc;\n}\n\nfunction createCapsuleCollider(options: ZylemActorOptions): ColliderDesc {\n\tconst size = options.collision?.size ?? options.size ?? { x: 0.5, y: 1, z: 0.5 };\n\tconst fullHeight = (size as any).y || 1;\n\tconst collisionPosition = getCollisionPosition(options);\n\n\treturn createCapsuleColliderFromDimensions(\n\t\t{\n\t\t\tx: (size as any).x || 0.5,\n\t\t\ty: fullHeight,\n\t\t\tz: (size as any).z || 0.5,\n\t\t},\n\t\tcollisionPosition ?? { x: 0, y: fullHeight / 2, z: 0 },\n\t);\n}\n\nfunction createExplicitBoxCollider(options: ZylemActorOptions): ColliderDesc | null {\n\tconst collisionSize = options.collision?.size;\n\tif (!collisionSize) {\n\t\treturn null;\n\t}\n\n\tconst halfWidth = (collisionSize as any).x / 2;\n\tconst halfHeight = (collisionSize as any).y / 2;\n\tconst halfDepth = (collisionSize as any).z / 2;\n\tconst colliderDesc = ColliderDesc.cuboid(halfWidth, halfHeight, halfDepth);\n\tconst collisionPosition = getCollisionPosition(options);\n\n\tcolliderDesc.setSensor(false);\n\tcolliderDesc.setTranslation(\n\t\tcollisionPosition?.x ?? 0,\n\t\tcollisionPosition?.y ?? halfHeight,\n\t\tcollisionPosition?.z ?? 0,\n\t);\n\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\treturn colliderDesc;\n}\n\nfunction computeActorSpaceMatrix(\n\tchild: Object3D,\n\tactorRoot: Object3D,\n\tactorScale: Vector3,\n): Matrix4 {\n\tconst actorRootInverse = actorRoot.matrixWorld.clone().invert();\n\tconst actorSpaceMatrix = actorRootInverse.multiply(child.matrixWorld);\n\treturn new Matrix4()\n\t\t.makeScale(actorScale.x, actorScale.y, actorScale.z)\n\t\t.multiply(actorSpaceMatrix);\n}\n\nfunction computeModelBounds(\n\tmodelRoot: Object3D,\n\tactorRoot: Object3D,\n\tactorScale: Vector3,\n): ModelBounds | null {\n\tmodelRoot.updateMatrixWorld(true);\n\n\tlet foundMesh = false;\n\tconst aggregated = new Box3();\n\tmodelRoot.traverse((child) => {\n\t\tif (!(child as any).isMesh) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mesh = child as Mesh;\n\t\tconst geometry = mesh.geometry;\n\t\tif (!geometry) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet localBounds: Box3 | null = null;\n\t\tif (mesh instanceof SkinnedMesh) {\n\t\t\tmesh.computeBoundingBox();\n\t\t\tlocalBounds = mesh.boundingBox?.clone() ?? null;\n\t\t} else {\n\t\t\tgeometry.computeBoundingBox();\n\t\t\tlocalBounds = geometry.boundingBox?.clone() ?? null;\n\t\t}\n\n\t\tif (!localBounds) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transformedBounds = localBounds\n\t\t\t.applyMatrix4(computeActorSpaceMatrix(mesh, actorRoot, actorScale));\n\n\t\tif (!foundMesh) {\n\t\t\taggregated.copy(transformedBounds);\n\t\t\tfoundMesh = true;\n\t\t\treturn;\n\t\t}\n\n\t\taggregated.union(transformedBounds);\n\t});\n\n\tif (!foundMesh || aggregated.isEmpty()) {\n\t\treturn null;\n\t}\n\n\tconst size = new Vector3();\n\tconst center = new Vector3();\n\taggregated.getSize(size);\n\taggregated.getCenter(center);\n\treturn { size, center };\n}\n\nfunction computeModelTrimesh(\n\tmodelRoot: Object3D,\n\tactorRoot: Object3D,\n\tactorScale: Vector3,\n): ModelTrimesh | null {\n\tmodelRoot.updateMatrixWorld(true);\n\n\tconst vertices: number[] = [];\n\tconst indices: number[] = [];\n\tconst bounds = new Box3();\n\tconst point = new Vector3();\n\tlet foundMesh = false;\n\n\tmodelRoot.traverse((child) => {\n\t\tif (!(child as any).isMesh) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mesh = child as Mesh;\n\t\tconst geometry = mesh.geometry;\n\t\tif (!geometry) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst position = geometry.getAttribute('position');\n\t\tif (!(position instanceof BufferAttribute)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst transform = computeActorSpaceMatrix(mesh, actorRoot, actorScale);\n\t\tconst vertexOffset = vertices.length / 3;\n\n\t\tfor (let i = 0; i < position.count; i++) {\n\t\t\tpoint.set(position.getX(i), position.getY(i), position.getZ(i));\n\t\t\tpoint.applyMatrix4(transform);\n\t\t\tvertices.push(point.x, point.y, point.z);\n\t\t\tbounds.expandByPoint(point);\n\t\t}\n\n\t\tconst index = geometry.getIndex();\n\t\tif (index) {\n\t\t\tfor (let i = 0; i < index.count; i++) {\n\t\t\t\tindices.push(vertexOffset + index.getX(i));\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = 0; i < position.count; i++) {\n\t\t\t\tindices.push(vertexOffset + i);\n\t\t\t}\n\t\t}\n\n\t\tfoundMesh = true;\n\t});\n\n\tif (!foundMesh || vertices.length === 0 || indices.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst center = new Vector3();\n\tbounds.getCenter(center);\n\n\treturn {\n\t\tvertices: new Float32Array(vertices),\n\t\tindices: new Uint32Array(indices),\n\t\tcenter,\n\t};\n}\n\nfunction createBoundsColliderFromModel(\n\tmodelRoot: Object3D | null,\n\tactorRoot: Object3D | null,\n\toptions: ZylemActorOptions,\n): ColliderDesc {\n\tconst explicitCollider = createExplicitBoxCollider(options);\n\tif (explicitCollider) {\n\t\treturn explicitCollider;\n\t}\n\n\tif (!modelRoot || !actorRoot) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst bounds = computeModelBounds(modelRoot, actorRoot, getActorScale(options));\n\tif (!bounds) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst colliderDesc = ColliderDesc.cuboid(\n\t\tbounds.size.x / 2,\n\t\tbounds.size.y / 2,\n\t\tbounds.size.z / 2,\n\t);\n\tconst collisionPosition = getCollisionPosition(options);\n\tcolliderDesc.setSensor(false);\n\tcolliderDesc.setTranslation(\n\t\tcollisionPosition?.x ?? bounds.center.x,\n\t\tcollisionPosition?.y ?? bounds.center.y,\n\t\tcollisionPosition?.z ?? bounds.center.z,\n\t);\n\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\treturn colliderDesc;\n}\n\nfunction createCapsuleColliderFromModel(\n\tsizingRoot: Object3D | null,\n\tsizingActorRoot: Object3D | null,\n\talignmentRoot: Object3D | null,\n\talignmentActorRoot: Object3D | null,\n\toptions: ZylemActorOptions,\n): ColliderDesc {\n\tif (hasExplicitCollisionSize(options)) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tif (!sizingRoot || !sizingActorRoot) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst sizingBounds = computeModelBounds(\n\t\tsizingRoot,\n\t\tsizingActorRoot,\n\t\tgetActorScale(options),\n\t);\n\tif (!sizingBounds) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst collisionPosition = getCollisionPosition(options);\n\tlet translation = collisionPosition;\n\tif (!translation) {\n\t\tconst alignmentBounds = alignmentRoot && alignmentActorRoot\n\t\t\t? computeModelBounds(alignmentRoot, alignmentActorRoot, getActorScale(options))\n\t\t\t: null;\n\t\ttranslation = alignmentBounds\n\t\t\t? {\n\t\t\t\tx: alignmentBounds.center.x,\n\t\t\t\ty: alignmentBounds.center.y,\n\t\t\t\tz: alignmentBounds.center.z,\n\t\t\t}\n\t\t\t: {\n\t\t\t\tx: sizingBounds.center.x,\n\t\t\t\ty: sizingBounds.center.y,\n\t\t\t\tz: sizingBounds.center.z,\n\t\t\t};\n\t}\n\n\treturn createCapsuleColliderFromDimensions(\n\t\t{\n\t\t\tx: sizingBounds.size.x,\n\t\t\ty: sizingBounds.size.y,\n\t\t\tz: sizingBounds.size.z,\n\t\t},\n\t\ttranslation,\n\t);\n}\n\nfunction createTrimeshColliderFromModel(\n\tmodelRoot: Object3D | null,\n\tactorRoot: Object3D | null,\n\toptions: ZylemActorOptions,\n): ColliderDesc {\n\tconst explicitCollider = createExplicitBoxCollider(options);\n\tif (explicitCollider) {\n\t\treturn explicitCollider;\n\t}\n\n\tif (!modelRoot || !actorRoot) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst trimesh = computeModelTrimesh(modelRoot, actorRoot, getActorScale(options));\n\tif (!trimesh) {\n\t\treturn createCapsuleCollider(options);\n\t}\n\n\tconst colliderDesc = tagTrimeshCollider(\n\t\tColliderDesc.trimesh(trimesh.vertices, trimesh.indices),\n\t\ttrimesh.vertices,\n\t\ttrimesh.indices,\n\t);\n\tconst collisionPosition = getCollisionPosition(options);\n\tif (collisionPosition) {\n\t\tcolliderDesc.setTranslation(\n\t\t\tcollisionPosition.x - trimesh.center.x,\n\t\t\tcollisionPosition.y - trimesh.center.y,\n\t\t\tcollisionPosition.z - trimesh.center.z,\n\t\t);\n\t}\n\tcolliderDesc.setSensor(false);\n\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.DEFAULT;\n\treturn colliderDesc;\n}\n\nfunction disposeObjectResources(object: Object3D | null): void {\n\tif (!object) {\n\t\treturn;\n\t}\n\n\tobject.traverse((child) => {\n\t\tif (!(child as any).isMesh) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst mesh = child as SkinnedMesh;\n\t\tmesh.geometry?.dispose();\n\t\tif (Array.isArray(mesh.material)) {\n\t\t\tmesh.material.forEach((material) => material.dispose());\n\t\t} else {\n\t\t\tmesh.material?.dispose();\n\t\t}\n\t});\n}\n\nclass ActorCollisionBuilder extends EntityCollisionBuilder {\n\tprivate objectModel: Object3D | null = null;\n\tprivate collisionSource: Object3D | null = null;\n\tprivate collisionShape: CollisionShapeType = 'capsule';\n\n\tconstructor(data: any) {\n\t\tsuper();\n\t\tthis.objectModel = data.objectModel;\n\t\tthis.collisionSource = data.collisionSource ?? data.objectModel ?? null;\n\t\tthis.collisionShape = data.collisionShape ?? 'capsule';\n\t}\n\n\tcollider(options: ZylemActorOptions): ColliderDesc {\n\t\tconst resolvedShape = resolveCollisionShape(\n\t\t\tthis.collisionShape,\n\t\t\tBoolean(options.collision?.static),\n\t\t);\n\n\t\tif (resolvedShape === 'bounds') {\n\t\t\treturn createBoundsColliderFromModel(this.objectModel, this.objectModel, options);\n\t\t}\n\n\t\tif (resolvedShape === 'trimesh') {\n\t\t\treturn createTrimeshColliderFromModel(this.objectModel, this.objectModel, options);\n\t\t}\n\n\t\treturn createCapsuleColliderFromModel(\n\t\t\tthis.collisionSource,\n\t\t\tthis.collisionSource,\n\t\t\tthis.objectModel,\n\t\t\tthis.objectModel,\n\t\t\toptions,\n\t\t);\n\t}\n}\n\nclass ActorBuilder extends EntityBuilder<ZylemActor, ZylemActorOptions> {\n\tprotected createEntity(options: Partial<ZylemActorOptions>): ZylemActor {\n\t\treturn new ZylemActor(options);\n\t}\n}\n\nexport const ACTOR_TYPE = Symbol('Actor');\n\nexport class ZylemActor extends GameEntity<ZylemActorOptions> implements EntityLoaderDelegate, DebugInfoProvider {\n\tstatic type = ACTOR_TYPE;\n\n\tprivate _object: Object3D | null = null;\n\tprivate _collisionSource: Object3D | null = null;\n\tprivate _animationDelegate: AnimationDelegate | null = null;\n\tprivate _modelFileNames: string[] = [];\n\tprivate _assetLoader: EntityAssetLoader = new EntityAssetLoader();\n\tprivate _loadGeneration = 0;\n\tprivate _loadStatus: 'idle' | 'loading' | 'loaded' = 'idle';\n\n\tcontrolledRotation: boolean = false;\n\thasWarnedDynamicTrimesh = false;\n\n\tconstructor(options?: ZylemActorOptions) {\n\t\tsuper();\n\t\tthis.options = { ...actorDefaults, ...options };\n\t\tthis.prependUpdate(this.actorUpdate.bind(this) as UpdateFunction<this>);\n\t\tthis.controlledRotation = true;\n\t}\n\n\toverride create(): this {\n\t\tif (this._loadStatus === 'idle' && (this.options.models?.length ?? 0) > 0) {\n\t\t\tthis.load();\n\t\t}\n\t\treturn super.create();\n\t}\n\n\tload(): void {\n\t\tif (this._loadStatus === 'loading' || this._loadStatus === 'loaded') {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._modelFileNames = [...(this.options.models || [])];\n\t\tif (this._modelFileNames.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.disposeRuntimeState(true);\n\t\tthis._loadStatus = 'loading';\n\t\tthis.loadModelsDeferred(++this._loadGeneration);\n\t}\n\n\tdata(): any {\n\t\treturn {\n\t\t\tanimations: this._animationDelegate?.animations,\n\t\t\tobjectModel: this._object,\n\t\t\tcollisionSource: this._collisionSource ?? this._object,\n\t\t\tcollisionShape: this.options.collisionShape,\n\t\t};\n\t}\n\n\tneedsDeferredModelCollision(): boolean {\n\t\tif (!this.requiresLoadedCollisionSource()) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn !this.getRuntimeCollisionSource();\n\t}\n\n\tsynchronizeRuntimeCollider(): void {\n\t\tconst resolvedShape = this.getResolvedCollisionShape();\n\t\tlet colliderDesc: ColliderDesc;\n\n\t\tif (resolvedShape === 'bounds') {\n\t\t\tcolliderDesc = createBoundsColliderFromModel(\n\t\t\t\tthis._object,\n\t\t\t\tthis.group ?? this._object,\n\t\t\t\tthis.options,\n\t\t\t);\n\t\t} else if (resolvedShape === 'trimesh') {\n\t\t\tcolliderDesc = createTrimeshColliderFromModel(\n\t\t\t\tthis._object,\n\t\t\t\tthis.group ?? this._object,\n\t\t\t\tthis.options,\n\t\t\t);\n\t\t} else {\n\t\t\tconst collisionSource = this.getRuntimeCollisionSource();\n\t\t\tcolliderDesc = createCapsuleColliderFromModel(\n\t\t\t\tcollisionSource,\n\t\t\t\tcollisionSource,\n\t\t\t\tthis._object,\n\t\t\t\tthis._object,\n\t\t\t\tthis.options,\n\t\t\t);\n\t\t}\n\n\t\tthis.colliderDesc = colliderDesc;\n\t\tif (this.colliderDescs.length > 0) {\n\t\t\tthis.colliderDescs[0] = colliderDesc;\n\t\t} else {\n\t\t\tthis.colliderDescs.push(colliderDesc);\n\t\t}\n\t}\n\n\tactorUpdate(params: UpdateContext<ZylemActorOptions>): void {\n\t\tthis._animationDelegate?.update(params.delta);\n\t}\n\n\tactorDestroy(): void {\n\t\tthis._loadGeneration += 1;\n\t\tthis._loadStatus = 'idle';\n\t\tthis.disposeRuntimeState(true);\n\t\tthis._modelFileNames = [];\n\t}\n\n\toverride _cleanup(params: CleanupContext<this>): void {\n\t\tsuper._cleanup(params);\n\t\tthis.actorDestroy();\n\t}\n\n\tplayAnimation(animationOptions: AnimationOptions) {\n\t\tthis._animationDelegate?.playAnimation(animationOptions);\n\t}\n\n\tget object(): Object3D | null {\n\t\treturn this._object;\n\t}\n\n\tget collisionSource(): Object3D | null {\n\t\treturn this._collisionSource ?? this._object;\n\t}\n\n\tgetDebugInfo(): Record<string, any> {\n\t\tconst debugInfo: Record<string, any> = {\n\t\t\ttype: 'Actor',\n\t\t\tmodels: this._modelFileNames.length > 0 ? this._modelFileNames : 'none',\n\t\t\tmodelLoaded: !!this._object,\n\t\t\tscale: this.options.scale\n\t\t\t\t? `${this.options.scale.x}, ${this.options.scale.y}, ${this.options.scale.z}`\n\t\t\t\t: '1, 1, 1',\n\t\t\tcollisionShape: this.getResolvedCollisionShape(),\n\t\t};\n\n\t\tif (this._animationDelegate) {\n\t\t\tdebugInfo.currentAnimation = this._animationDelegate.currentAnimationKey || 'none';\n\t\t\tdebugInfo.animationsCount = this.options.animations?.length || 0;\n\t\t}\n\n\t\tif (this._object) {\n\t\t\tlet meshCount = 0;\n\t\t\tlet vertexCount = 0;\n\t\t\tthis._object.traverse((child) => {\n\t\t\t\tif (!(child as any).isMesh) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tmeshCount++;\n\t\t\t\tconst geometry = (child as SkinnedMesh).geometry;\n\t\t\t\tif (geometry?.attributes.position) {\n\t\t\t\t\tvertexCount += geometry.attributes.position.count;\n\t\t\t\t}\n\t\t\t});\n\t\t\tdebugInfo.meshCount = meshCount;\n\t\t\tdebugInfo.vertexCount = vertexCount;\n\t\t}\n\n\t\treturn debugInfo;\n\t}\n\n\tprivate getResolvedCollisionShape(): ResolvedCollisionShape {\n\t\treturn resolveCollisionShape(\n\t\t\tthis.options.collisionShape,\n\t\t\tBoolean(this.options.collision?.static),\n\t\t\t() => warnDynamicTrimeshOnce(this),\n\t\t);\n\t}\n\n\tprivate requiresLoadedCollisionSource(): boolean {\n\t\tconst resolvedShape = this.getResolvedCollisionShape();\n\t\tif (resolvedShape === 'bounds' || resolvedShape === 'trimesh') {\n\t\t\treturn !hasExplicitCollisionSize(this.options);\n\t\t}\n\t\tif (resolvedShape === 'capsule') {\n\t\t\treturn !hasExplicitCollisionSize(this.options)\n\t\t\t\t&& this.getCollisionSourceSelection().file !== null;\n\t\t}\n\t\treturn false;\n\t}\n\n\tprivate getRuntimeCollisionSource(): Object3D | null {\n\t\tconst resolvedShape = this.getResolvedCollisionShape();\n\t\tif (resolvedShape === 'bounds' || resolvedShape === 'trimesh') {\n\t\t\treturn this._object;\n\t\t}\n\t\treturn this._collisionSource ?? this._object;\n\t}\n\n\tprivate getCollisionSourceSelection(): CollisionSourceSelection {\n\t\tconst modelFile = this.options.models?.[0] ?? null;\n\t\tconst animationFile = this.options.animations?.[0]?.path ?? null;\n\n\t\tif (animationFile) {\n\t\t\treturn {\n\t\t\t\tfile: animationFile,\n\t\t\t\treuseVisibleModel: animationFile === modelFile,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tfile: modelFile,\n\t\t\treuseVisibleModel: true,\n\t\t};\n\t}\n\n\tprivate disposeRuntimeState(clearGroup: boolean): void {\n\t\tif (this._animationDelegate) {\n\t\t\tthis._animationDelegate.dispose();\n\t\t\tthis._animationDelegate = null;\n\t\t}\n\n\t\tconst collisionSource = this._collisionSource;\n\t\tdisposeObjectResources(this._object);\n\t\tif (collisionSource && collisionSource !== this._object) {\n\t\t\tdisposeObjectResources(collisionSource);\n\t\t}\n\n\t\tthis._object = null;\n\t\tthis._collisionSource = null;\n\n\t\tif (clearGroup && this.group) {\n\t\t\tthis.group.clear();\n\t\t\tthis.group = undefined;\n\t\t}\n\t}\n\n\tprivate loadModelsDeferred(loadGeneration: number): void {\n\t\tthis.dispatch('entity:model:loading', {\n\t\t\tentityId: this.uuid,\n\t\t\tfiles: this._modelFileNames,\n\t\t});\n\n\t\tconst collisionSourceSelection = this.getCollisionSourceSelection();\n\t\tconst promises = this._modelFileNames.map((file) =>\n\t\t\tthis._assetLoader.loadFile(file, { clone: true }),\n\t\t);\n\t\tconst collisionSourcePromise = collisionSourceSelection.file && !collisionSourceSelection.reuseVisibleModel\n\t\t\t? this._assetLoader.loadFile(collisionSourceSelection.file, { clone: true })\n\t\t\t: Promise.resolve<AssetLoaderResult | null>(null);\n\n\t\tPromise.all([Promise.all(promises), collisionSourcePromise])\n\t\t\t.then(([results, collisionSourceResult]) => {\n\t\t\t\tif (loadGeneration !== this._loadGeneration) {\n\t\t\t\t\tresults.forEach((result) => disposeObjectResources(result.object ?? null));\n\t\t\t\t\tif (collisionSourceResult?.object) {\n\t\t\t\t\t\tdisposeObjectResources(collisionSourceResult.object);\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._object = results[0]?.object ?? null;\n\t\t\t\tthis._collisionSource = collisionSourceSelection.reuseVisibleModel\n\t\t\t\t\t? this._object\n\t\t\t\t\t: collisionSourceResult?.object ?? this._object;\n\t\t\t\tthis._loadStatus = this._object ? 'loaded' : 'idle';\n\n\t\t\t\tlet meshCount = 0;\n\t\t\t\tif (this._object) {\n\t\t\t\t\tthis._object.traverse((child) => {\n\t\t\t\t\t\tif ((child as any).isMesh) {\n\t\t\t\t\t\t\tmeshCount++;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tthis.group = new Group();\n\t\t\t\t\tthis.group.add(this._object);\n\t\t\t\t\tthis.group.scale.copy(getActorScale(this.options));\n\n\t\t\t\t\tthis.applyMaterialOverrides();\n\n\t\t\t\t\tthis._animationDelegate = new AnimationDelegate(this._object);\n\t\t\t\t\tvoid this._animationDelegate.loadAnimations(this.options.animations || []).then(() => {\n\t\t\t\t\t\tif (loadGeneration !== this._loadGeneration) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.dispatch('entity:animation:loaded', {\n\t\t\t\t\t\t\tentityId: this.uuid,\n\t\t\t\t\t\t\tanimationCount: this.options.animations?.length || 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tthis.dispatch('entity:model:loaded', {\n\t\t\t\t\tentityId: this.uuid,\n\t\t\t\t\tsuccess: !!this._object,\n\t\t\t\t\tmeshCount,\n\t\t\t\t});\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\tif (loadGeneration !== this._loadGeneration) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthis._loadStatus = 'idle';\n\t\t\t\tconsole.error('Failed to load actor model', error);\n\t\t\t\tthis.dispatch('entity:model:loaded', {\n\t\t\t\t\tentityId: this.uuid,\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tmeshCount: 0,\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tprivate applyMaterialOverrides(): void {\n\t\tconst materialOptions = this.options.material;\n\t\tif (\n\t\t\t!materialOptions\n\t\t\t|| (!materialOptions.color && !materialOptions.path && materialOptions.opacity === undefined)\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this._object) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._object.traverse((child) => {\n\t\t\tif (!(child as any).isMesh) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst mesh = child as Mesh;\n\t\t\tif (materialOptions.color) {\n\t\t\t\tconst newMaterial = new MeshStandardMaterial({\n\t\t\t\t\tcolor: materialOptions.color,\n\t\t\t\t\temissiveIntensity: 0.5,\n\t\t\t\t\tlightMapIntensity: 0.5,\n\t\t\t\t\tfog: true,\n\t\t\t\t\topacity: materialOptions.opacity ?? 1,\n\t\t\t\t\ttransparent: materialOptions.opacity !== undefined && materialOptions.opacity < 1,\n\t\t\t\t});\n\t\t\t\tmesh.castShadow = true;\n\t\t\t\tmesh.receiveShadow = true;\n\t\t\t\tmesh.material = newMaterial;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (materialOptions.opacity === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst applyOpacity = (material: Material): Material => {\n\t\t\t\tconst clonedMaterial = material.clone();\n\t\t\t\tif ('opacity' in clonedMaterial && 'transparent' in clonedMaterial) {\n\t\t\t\t\tconst transparentMaterial = clonedMaterial as TransparentMaterial;\n\t\t\t\t\ttransparentMaterial.opacity = materialOptions.opacity!;\n\t\t\t\t\ttransparentMaterial.transparent = materialOptions.opacity! < 1;\n\t\t\t\t\ttransparentMaterial.needsUpdate = true;\n\t\t\t\t}\n\t\t\t\treturn clonedMaterial;\n\t\t\t};\n\n\t\t\tmesh.material = Array.isArray(mesh.material)\n\t\t\t\t? mesh.material.map(applyOpacity)\n\t\t\t\t: applyOpacity(mesh.material);\n\t\t});\n\t}\n}\n\ntype ActorOptions = BaseNode | ZylemActorOptions;\n\nexport function createActor(...args: Array<ActorOptions>): ZylemActor {\n\treturn createEntity<ZylemActor, ZylemActorOptions>({\n\t\targs,\n\t\tdefaultConfig: actorDefaults,\n\t\tEntityClass: ZylemActor,\n\t\tBuilderClass: ActorBuilder,\n\t\tCollisionBuilderClass: ActorCollisionBuilder,\n\t\tentityType: ZylemActor.type,\n\t\tcloneFactory: (options) => createActor(options ?? {}),\n\t});\n}\n","import { Mesh, Material, ShaderMaterial, Group, Color, Vector3 } from 'three';\nimport {\n\tCollider,\n\tColliderDesc,\n\tRigidBody,\n\tRigidBodyDesc,\n\tVector,\n} from '@dimforge/rapier3d-compat';\nimport { position, rotation, scale } from '../systems/transformable.system';\nimport { Vec3 } from '../core/vector';\nimport { MaterialBuilder, MaterialOptions } from '../graphics/material';\nimport { CollisionOptions } from '../collision/collision-builder';\nimport { BaseNode } from '../core/base-node';\nimport {\n\tDestroyContext,\n\tSetupContext,\n\tUpdateContext,\n\tLoadedContext,\n\tCleanupContext,\n} from '../core/base-node-life-cycle';\nimport type { EntityMeshBuilder, EntityCollisionBuilder } from './builder';\nimport { Behavior } from '../behaviors/behavior';\nimport {\n\tEventEmitterDelegate,\n\tzylemEventBus,\n\ttype EntityEvents,\n} from '../events';\nimport type {\n\tBehaviorDescriptor,\n\tBehaviorRef,\n\tBehaviorHandle,\n} from '../behaviors/behavior-descriptor';\nimport type { TransformState } from '../actions/capabilities/transform-store';\nimport { createTransformStore } from '../actions/capabilities/transform-store';\nimport { makeTransformable } from '../actions/capabilities/transformable';\nimport { clearVelocityIntent } from '../actions/capabilities/velocity-intents';\nimport type { MoveableEntity } from '../actions/capabilities/moveable';\nimport type { RotatableEntityAPI } from '../actions/capabilities/rotatable';\nimport {\n\tcloneCollisionComponent,\n\tisCollisionComponent,\n\ttype CollisionComponent,\n} from './parts/collision-factories';\nimport type { NodeInterface } from '../core/node-interface';\nimport { commonDefaults } from './common';\nimport type { Action } from '../actions/action';\nimport { deepCloneValue, deepMergeValues } from '../core/clone-utils';\n\nexport interface CollisionContext<\n\tT,\n\tO extends GameEntityOptions,\n\tTGlobals extends Record<string, unknown> = any,\n> {\n\tentity: T;\n\t// Use 'any' for other's options type to break recursive type variance issues\n\tother: GameEntity<O | any>;\n\tglobals: TGlobals;\n}\n\nexport type CollisionPhase = 'enter' | 'stay';\n\nexport interface CollisionRegistrationOptions {\n\tphase?: CollisionPhase;\n\tcooldownMs?: number;\n}\n\ninterface NormalizedCollisionRegistrationOptions {\n\tphase: CollisionPhase;\n\tcooldownMs?: number;\n}\n\nexport interface CollisionRegistration<T, O extends GameEntityOptions> {\n\tid: number;\n\tcallback: (params: CollisionContext<T, O>) => void;\n\toptions: NormalizedCollisionRegistrationOptions;\n}\n\nexport interface CollisionDispatchMetadata {\n\tphase: CollisionPhase;\n\tnowMs: number;\n}\n\nexport interface CollisionDelegate<T, O extends GameEntityOptions> {\n\t// Use 'any' for entity and options types to avoid contravariance issues\n\t// with function parameters. Type safety is still enforced at the call site via onCollision()\n\tcollision?: CollisionRegistration<any, any>[];\n\tcooldowns?: Map<string, number>;\n\tnextId?: number;\n}\n\nexport type IBuilder<BuilderOptions = any> = {\n\tpreBuild: (options: BuilderOptions) => BuilderOptions;\n\tbuild: (options: BuilderOptions) => BuilderOptions;\n\tpostBuild: (options: BuilderOptions) => BuilderOptions;\n};\n\nexport type GameEntityOptions = {\n\tname?: string;\n\tcolor?: Color;\n\tsize?: Vec3;\n\tposition?: Vec3;\n\tbatched?: boolean;\n\tcollision?: Partial<CollisionOptions>;\n\tmaterial?: Partial<MaterialOptions>;\n\tcustom?: { [key: string]: any };\n\tcollisionType?: string;\n\tcollisionGroup?: string;\n\tcollisionFilter?: string[];\n\t_builders?: {\n\t\tmeshBuilder?: IBuilder | EntityMeshBuilder | null;\n\t\tcollisionBuilder?: IBuilder | EntityCollisionBuilder | null;\n\t\tmaterialBuilder?: MaterialBuilder | null;\n\t};\n};\n\nexport abstract class GameEntityLifeCycle {\n\tabstract _setup(params: SetupContext<this>): void;\n\tabstract _update(params: UpdateContext<this>): void;\n\tabstract _destroy(params: DestroyContext<this>): void;\n}\n\nexport interface EntityDebugInfo {\n\tbuildInfo: () => Record<string, string>;\n}\n\ntype EntityCloneFactory<O extends GameEntityOptions, E extends GameEntity<O>> = (\n\toptions?: Partial<O>,\n) => E;\n\ntype TrackedEntityComponent =\n\t| { kind: 'mesh'; component: Mesh }\n\t| { kind: 'collision'; component: CollisionComponent };\n\nfunction isCollisionRegistrationOptions(\n\tvalue: unknown,\n): value is CollisionRegistrationOptions {\n\treturn value != null && typeof value === 'object';\n}\n\nfunction normalizeCollisionRegistrationOptions(\n\toptions?: CollisionRegistrationOptions,\n): NormalizedCollisionRegistrationOptions {\n\treturn {\n\t\tphase: options?.phase ?? 'stay',\n\t\tcooldownMs: options?.cooldownMs,\n\t};\n}\n\nfunction getCollisionNowMs(): number {\n\tif (typeof performance !== 'undefined' && typeof performance.now === 'function') {\n\t\treturn performance.now();\n\t}\n\treturn Date.now();\n}\n\nexport class GameEntity<O extends GameEntityOptions>\n\textends BaseNode<O>\n\timplements GameEntityLifeCycle, EntityDebugInfo, MoveableEntity, RotatableEntityAPI {\n\tpublic behaviors: Behavior[] = [];\n\tpublic group: Group | undefined;\n\tpublic mesh: Mesh | undefined;\n\tpublic materials: Material[] | undefined;\n\tpublic bodyDesc: RigidBodyDesc | null = null;\n\tpublic body: RigidBody | null = null;\n\tpublic physicsAttached = false;\n\tpublic colliderDesc: ColliderDesc | undefined;\n\tpublic collider: Collider | undefined;\n\tpublic custom: Record<string, any> = {};\n\n\t// Compound entity support: multiple colliders and meshes\n\t/** All collider descriptions for this entity (including primary) */\n\tpublic colliderDescs: ColliderDesc[] = [];\n\t/** All colliders attached to this entity's rigid body */\n\tpublic colliders: Collider[] = [];\n\t/** Additional meshes for compound visual entities (added via add()) */\n\tpublic compoundMeshes: Mesh[] = [];\n\n\tpublic debugInfo: Record<string, any> = {};\n\tpublic debugMaterial: ShaderMaterial | undefined;\n\n\tpublic collisionDelegate: CollisionDelegate<this, O> = {\n\t\tcollision: [],\n\t\tcooldowns: new Map(),\n\t\tnextId: 0,\n\t};\n\tpublic collisionType?: string;\n\n\t// Instancing support\n\t/** Batch key for instanced rendering (null if not instanced) */\n\tpublic batchKey: string | null = null;\n\t/** Index within the instanced mesh batch */\n\tpublic instanceId: number = -1;\n\t/** Whether this entity uses instanced rendering */\n\tpublic isInstanced: boolean = false;\n\n\t// Event delegate for dispatch/listen API\n\tprotected eventDelegate = new EventEmitterDelegate<EntityEvents>();\n\n\t// Behavior references (new ECS pattern)\n\tprivate behaviorRefs: BehaviorRef[] = [];\n\tprivate cloneFactory: EntityCloneFactory<O, this> | null = null;\n\tprivate trackAddedComponents: boolean = false;\n\tprivate trackedComponents: TrackedEntityComponent[] = [];\n\n\t// Transform store for batched physics updates (auto-created in create())\n\tpublic transformStore: TransformState;\n\n\t// Movement & rotation methods are assigned at runtime by makeTransformable.\n\t// The `implements` clause above ensures the type contract; declarations below\n\t// satisfy the compiler while the constructor fills them in.\n\tmoveX!: (delta: number) => void;\n\tmoveY!: (delta: number) => void;\n\tmoveZ!: (delta: number) => void;\n\tmoveXY!: (deltaX: number, deltaY: number) => void;\n\tmoveXZ!: (deltaX: number, deltaZ: number) => void;\n\tmove!: (vector: Vector3) => void;\n\tresetVelocity!: () => void;\n\tmoveForwardXY!: (delta: number, rotation2DAngle: number) => void;\n\tgetPosition!: () => Vector | null;\n\tgetVelocity!: () => Vector | null;\n\tsetPosition!: (x: number, y: number, z: number) => void;\n\tsetPositionX!: (x: number) => void;\n\tsetPositionY!: (y: number) => void;\n\tsetPositionZ!: (z: number) => void;\n\twrapAroundXY!: (boundsX: number, boundsY: number) => void;\n\twrapAround3D!: (boundsX: number, boundsY: number, boundsZ: number) => void;\n\trotateInDirection!: (moveVector: Vector3) => void;\n\trotateYEuler!: (amount: number) => void;\n\trotateEuler!: (eulerRotation: Vector3) => void;\n\trotateX!: (delta: number) => void;\n\trotateY!: (delta: number) => void;\n\trotateZ!: (delta: number) => void;\n\tsetRotationY!: (y: number) => void;\n\tsetRotationX!: (x: number) => void;\n\tsetRotationZ!: (z: number) => void;\n\tsetRotationDegrees!: (x: number, y: number, z: number) => void;\n\tsetRotationDegreesY!: (y: number) => void;\n\tsetRotationDegreesX!: (x: number) => void;\n\tsetRotationDegreesZ!: (z: number) => void;\n\tsetRotation!: (x: number, y: number, z: number) => void;\n\tgetRotation!: () => any;\n\n\tconstructor() {\n\t\tsuper();\n\t\tthis.transformStore = createTransformStore();\n\t\tmakeTransformable(this);\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Composable add() - accepts Mesh, CollisionComponent, or child entities\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add meshes, collision components, or child entities to this entity.\n\t * Supports fluent chaining: `entity.add(boxMesh()).add(boxCollision())`.\n\t *\n\t * - `Mesh`: First mesh becomes the primary mesh; subsequent meshes are\n\t * compound meshes grouped together.\n\t * - `CollisionComponent`: First sets bodyDesc + colliderDesc; subsequent\n\t * add extra colliders to the same rigid body.\n\t * - `NodeInterface`: Added as a child entity (delegates to BaseNode.add).\n\t */\n\tpublic add(...components: Array<NodeInterface | Mesh | CollisionComponent>): this {\n\t\tfor (const component of components) {\n\t\t\tif (component instanceof Mesh) {\n\t\t\t\tthis.addMeshComponent(component);\n\t\t\t\tthis.trackComponent(component);\n\t\t\t} else if (isCollisionComponent(component)) {\n\t\t\t\tthis.addCollisionComponent(component);\n\t\t\t\tthis.trackComponent(component);\n\t\t\t} else {\n\t\t\t\tsuper.add(component as NodeInterface);\n\t\t\t}\n\t\t}\n\t\treturn this;\n\t}\n\n\tprivate addMeshComponent(mesh: Mesh): void {\n\t\tif (!this.mesh) {\n\t\t\t// First mesh becomes the primary mesh\n\t\t\tthis.mesh = mesh;\n\t\t\tif (!this.materials) {\n\t\t\t\tthis.materials = [];\n\t\t\t}\n\t\t\tif (mesh.material) {\n\t\t\t\tconst mat = mesh.material;\n\t\t\t\tif (Array.isArray(mat)) {\n\t\t\t\t\tthis.materials.push(...mat);\n\t\t\t\t} else {\n\t\t\t\t\tthis.materials.push(mat);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Subsequent meshes are compound meshes\n\t\t\tthis.compoundMeshes.push(mesh);\n\t\t\t// Ensure the entity has a group so all meshes are parented together\n\t\t\tif (!this.group) {\n\t\t\t\tthis.group = new Group();\n\t\t\t\tthis.group.add(this.mesh);\n\t\t\t}\n\t\t\tthis.group.add(mesh);\n\t\t}\n\t}\n\n\tprivate addCollisionComponent(collision: CollisionComponent): void {\n\t\tif (!this.bodyDesc) {\n\t\t\t// First collision sets the body description and primary collider\n\t\t\tthis.bodyDesc = collision.bodyDesc;\n\t\t\tthis.colliderDesc = collision.colliderDesc;\n\t\t\tthis.colliderDescs.push(collision.colliderDesc);\n\t\t\t// Apply entity position to the body\n\t\t\tconst pos = this.options?.position ?? { x: 0, y: 0, z: 0 };\n\t\t\tthis.bodyDesc.setTranslation(pos.x, pos.y, pos.z);\n\t\t} else {\n\t\t\t// Subsequent collisions add extra colliders to the same body\n\t\t\tthis.colliderDescs.push(collision.colliderDesc);\n\t\t}\n\t}\n\n\tprivate trackComponent(component: Mesh | CollisionComponent): void {\n\t\tif (!this.trackAddedComponents) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (component instanceof Mesh) {\n\t\t\tthis.trackedComponents.push({\n\t\t\t\tkind: 'mesh',\n\t\t\t\tcomponent: cloneMeshComponent(component),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tthis.trackedComponents.push({\n\t\t\tkind: 'collision',\n\t\t\tcomponent: cloneCollisionComponent(component),\n\t\t});\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Actions API -- entity-scoped, self-contained stateful actions\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tprivate _actions: Action[] = [];\n\n\t/**\n\t * Run a fire-and-forget action. Auto-removed when done.\n\t * @example `me.runAction(moveBy({ x: 10, duration: 0.3 }))`\n\t */\n\tpublic runAction<A extends Action>(action: A): A {\n\t\tthis._actions.push(action);\n\t\treturn action;\n\t}\n\n\t/**\n\t * Register a persistent action (throttle, onPress). Not removed when done.\n\t * @example `const press = entity.action(onPress())`\n\t */\n\tpublic action<A extends Action>(action: A): A {\n\t\taction.persistent = true;\n\t\tthis._actions.push(action);\n\t\treturn action;\n\t}\n\n\t/**\n\t * Tick all registered actions. Called automatically before user onUpdate callbacks.\n\t *\n\t * Resets velocity/angularVelocity accumulation before ticking so that\n\t * actions can compose via `+=` without cross-frame build-up.\n\t * (The existing move helpers like `moveXY` use `=` which doesn't accumulate,\n\t * but action composition needs additive writes on a clean slate each frame.)\n\t */\n\tpublic _tickActions(delta: number): void {\n\t\tif (this._actions.length === 0) return;\n\n\t\t// Clear accumulation from the previous frame so that\n\t\t// actions can compose via `+=` on a clean slate each frame.\n\t\tconst store = this.transformStore;\n\t\tstore.velocity.x = 0;\n\t\tstore.velocity.y = 0;\n\t\tstore.velocity.z = 0;\n\t\tclearVelocityIntent(store, 'actions');\n\t\tstore.angularVelocity.x = 0;\n\t\tstore.angularVelocity.y = 0;\n\t\tstore.angularVelocity.z = 0;\n\t\tstore.dirty.angularVelocity = false;\n\n\t\tfor (let i = this._actions.length - 1; i >= 0; i--) {\n\t\t\tconst act = this._actions[i];\n\t\t\tact.tick(this, delta);\n\t\t\tif (act.done && !act.persistent) {\n\t\t\t\tthis._actions.splice(i, 1);\n\t\t\t}\n\t\t}\n\n\t\tif (this._actions.length === 0) {\n\t\t\tstore.velocity.x = 0;\n\t\t\tstore.velocity.y = 0;\n\t\t\tstore.velocity.z = 0;\n\t\t\tclearVelocityIntent(store, 'actions');\n\t\t\tstore.angularVelocity.x = 0;\n\t\t\tstore.angularVelocity.y = 0;\n\t\t\tstore.angularVelocity.z = 0;\n\t\t\tstore.dirty.angularVelocity = false;\n\t\t}\n\t}\n\n\tpublic create(): this {\n\t\tconst { position: setupPosition } = this.options;\n\t\tconst { x, y, z } = setupPosition || { x: 0, y: 0, z: 0 };\n\t\tthis.behaviors = [\n\t\t\t{ component: position, values: { x, y, z } },\n\t\t\t{ component: scale, values: { x: 0, y: 0, z: 0 } },\n\t\t\t{ component: rotation, values: { x: 0, y: 0, z: 0, w: 0 } },\n\t\t];\n\t\tthis.name = this.options.name || '';\n\t\treturn this;\n\t}\n\n\tpublic clone(overrides?: Partial<O>): this {\n\t\tif (!this.cloneFactory) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cannot clone ${this.constructor.name}: clone() is only supported for entities created by official factory helpers.`,\n\t\t\t);\n\t\t}\n\n\t\tconst clone = this.cloneFactory(\n\t\t\tdeepMergeValues(this.options, overrides),\n\t\t) as this;\n\n\t\tconst behaviorAliases = this.copyBehaviorRefsTo(clone);\n\t\tconst wrapCallback = <T extends Function>(callback: T): T =>\n\t\t\twrapBehaviorCallback(callback, behaviorAliases);\n\n\t\tthis.replayUserLifecycleRegistrationsTo(clone, wrapCallback);\n\n\t\tconst collisionRegistrations = this.getCollisionRegistrations();\n\t\tif (collisionRegistrations.length > 0) {\n\t\t\tfor (const registration of collisionRegistrations) {\n\t\t\t\tclone.onCollision(\n\t\t\t\t\twrapCallback(registration.callback),\n\t\t\t\t\tregistration.options,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tfor (const trackedComponent of this.trackedComponents) {\n\t\t\tif (trackedComponent.kind === 'mesh') {\n\t\t\t\tclone.add(cloneMeshComponent(trackedComponent.component));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tclone.add(cloneCollisionComponent(trackedComponent.component));\n\t\t}\n\n\t\tthis.cloneChildrenInto(clone);\n\n\t\treturn clone;\n\t}\n\n\tpublic finalizeCloneSupport(factory: (options?: Partial<O>) => GameEntity<O>): this {\n\t\tthis.cloneFactory = factory as EntityCloneFactory<O, this>;\n\t\tthis.enableUserLifecycleTracking();\n\t\tthis.trackAddedComponents = true;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add collision callbacks\n\t */\n\tpublic onCollision(\n\t\tcallback: (params: CollisionContext<this, O>) => void,\n\t\toptions?: CollisionRegistrationOptions,\n\t): this;\n\tpublic onCollision(\n\t\t...callbacks: ((params: CollisionContext<this, O>) => void)[]\n\t): this;\n\tpublic onCollision(\n\t\t...args: Array<((params: CollisionContext<this, O>) => void) | CollisionRegistrationOptions | undefined>\n\t): this {\n\t\tconst existing = [...(this.collisionDelegate.collision ?? [])];\n\t\tlet nextId = this.collisionDelegate.nextId ?? 0;\n\n\t\tif (\n\t\t\targs.length === 1\n\t\t\t|| (\n\t\t\t\targs.length === 2\n\t\t\t\t&& (\n\t\t\t\t\targs[1] == null\n\t\t\t\t\t|| isCollisionRegistrationOptions(args[1])\n\t\t\t\t)\n\t\t\t)\n\t\t) {\n\t\t\tconst callback = args[0] as ((params: CollisionContext<this, O>) => void) | undefined;\n\t\t\tif (!callback) {\n\t\t\t\treturn this;\n\t\t\t}\n\n\t\t\tconst options = args[1] as CollisionRegistrationOptions | undefined;\n\t\t\texisting.push({\n\t\t\t\tid: nextId,\n\t\t\t\tcallback,\n\t\t\t\toptions: normalizeCollisionRegistrationOptions(options),\n\t\t\t});\n\t\t\tnextId += 1;\n\t\t\tthis.collisionDelegate.collision = existing;\n\t\t\tthis.collisionDelegate.nextId = nextId;\n\t\t\treturn this;\n\t\t}\n\n\t\tfor (const callback of args as Array<(params: CollisionContext<this, O>) => void>) {\n\t\t\texisting.push({\n\t\t\t\tid: nextId,\n\t\t\t\tcallback,\n\t\t\t\toptions: normalizeCollisionRegistrationOptions(),\n\t\t\t});\n\t\t\tnextId += 1;\n\t\t}\n\n\t\tthis.collisionDelegate.collision = existing;\n\t\tthis.collisionDelegate.nextId = nextId;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Use a behavior on this entity via typed descriptor.\n\t * Behaviors will be auto-registered as systems when the entity is spawned.\n\t * @param descriptor The behavior descriptor (import from behaviors module)\n\t * @param options Optional overrides for the behavior's default options\n\t * @returns BehaviorHandle with behavior-specific methods for lazy FSM access\n\t */\n\tpublic use<\n\t\tO extends Record<string, any>,\n\t\tH extends Record<string, any> = Record<string, never>,\n\t>(\n\t\tdescriptor: BehaviorDescriptor<O, H>,\n\t\toptions?: Partial<O>,\n\t): BehaviorHandle<O, H> {\n\t\tconst behaviorRef: BehaviorRef<O> = {\n\t\t\tdescriptor: descriptor as BehaviorDescriptor<O, any>,\n\t\t\toptions: { ...descriptor.defaultOptions, ...options } as O,\n\t\t};\n\t\tthis.behaviorRefs.push(behaviorRef as BehaviorRef<any>);\n\n\t\t// Create base handle\n\t\tconst baseHandle = {\n\t\t\tgetFSM: () => behaviorRef.fsm ?? null,\n\t\t\tgetOptions: () => behaviorRef.options,\n\t\t\tref: behaviorRef,\n\t\t};\n\n\t\t// Merge behavior-specific methods if createHandle is provided\n\t\tconst customMethods = descriptor.createHandle?.(behaviorRef) ?? ({} as H);\n\n\t\treturn {\n\t\t\t...baseHandle,\n\t\t\t...customMethods,\n\t\t} as BehaviorHandle<O, H>;\n\t}\n\n\t/**\n\t * Get all behavior references attached to this entity.\n\t * Used by the stage to auto-register required systems.\n\t */\n\tpublic getBehaviorRefs(): BehaviorRef[] {\n\t\treturn this.behaviorRefs;\n\t}\n\n\tpublic getCollisionCallbacks(): Array<(params: CollisionContext<this, O>) => void> {\n\t\treturn this.getCollisionRegistrations().map((registration) => registration.callback);\n\t}\n\n\tpublic getCollisionRegistrations(): Array<CollisionRegistration<this, O>> {\n\t\treturn (this.collisionDelegate.collision ?? []).map((registration) => ({\n\t\t\tid: registration.id,\n\t\t\tcallback: registration.callback,\n\t\t\toptions: { ...registration.options },\n\t\t}));\n\t}\n\n\tprivate copyBehaviorRefsTo(target: GameEntity<any>): Map<BehaviorRef, BehaviorRef> {\n\t\tconst aliases = new Map<BehaviorRef, BehaviorRef>();\n\n\t\tfor (const ref of this.behaviorRefs) {\n\t\t\ttarget.use(ref.descriptor, deepCloneValue(ref.options));\n\t\t\tconst targetRef = target.getBehaviorRefs().at(-1);\n\t\t\tif (targetRef) {\n\t\t\t\taliases.set(ref, targetRef);\n\t\t\t}\n\t\t}\n\n\t\treturn aliases;\n\t}\n\n\t/**\n\t * Entity-specific setup - resets actions for a fresh stage session.\n\t * (User callbacks are handled by BaseNode's lifecycleCallbacks.setup)\n\t */\n\tpublic _setup(params: SetupContext<this>): void {\n\t\t// Reset actions for the new stage session.\n\t\t// Remove completed fire-and-forget actions; reset all others\n\t\t// so they replay from the beginning.\n\t\tfor (let i = this._actions.length - 1; i >= 0; i--) {\n\t\t\tconst act = this._actions[i];\n\t\t\tif (act.done && !act.persistent) {\n\t\t\t\tthis._actions.splice(i, 1);\n\t\t\t} else {\n\t\t\t\tact.reset();\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected async _loaded(_params: LoadedContext<this>): Promise<void> { }\n\n\t/**\n\t * Entity-specific update - updates materials.\n\t * Transform changes are applied by the stage after all update callbacks complete.\n\t * (User callbacks are handled by BaseNode's lifecycleCallbacks.update)\n\t */\n\tpublic _update(params: UpdateContext<this>): void {\n\t\tthis.updateMaterials(params);\n\t}\n\n\t/**\n\t * Entity-specific destroy -- reserved for consumer game logic.\n\t * Engine-internal resource disposal runs in _cleanup() instead.\n\t */\n\tpublic _destroy(params: DestroyContext<this>): void { }\n\n\t/**\n\t * Engine-internal resource cleanup -- runs automatically after destroy.\n\t * Disposes GPU/DOM resources (meshes, materials, debug material).\n\t *\n\t * Note: actions, collision callbacks, and behavior refs are intentionally\n\t * NOT cleared here -- they are registered by consumer code at module level\n\t * and must persist across stage reloads. Actions are reset in _setup().\n\t */\n\tprotected _cleanup(_params: CleanupContext<this>): void {\n\t\t// Dispose entity event emitter & subscriptions\n\t\tthis.disposeEvents();\n\n\t\t// Dispose compound meshes\n\t\tfor (const m of this.compoundMeshes) {\n\t\t\tm.geometry?.dispose();\n\t\t\tif (Array.isArray(m.material)) {\n\t\t\t\tm.material.forEach(mat => mat.dispose());\n\t\t\t} else {\n\t\t\t\tm.material?.dispose();\n\t\t\t}\n\t\t}\n\t\tthis.compoundMeshes.length = 0;\n\n\t\t// Dispose debug material\n\t\tthis.debugMaterial?.dispose();\n\t\tthis.debugMaterial = undefined;\n\n\t\t// Remove group from parent (camera or scene)\n\t\tthis.group?.removeFromParent();\n\n\t\t// Note: physics references (body, collider, colliders) are intentionally\n\t\t// NOT nulled here. They are needed by removeEntityByUuid() → world.destroyEntity()\n\t\t// which runs later when the stage processes markedForRemoval entities.\n\t}\n\n\tpublic _collision(\n\t\tother: GameEntity<O>,\n\t\tglobals?: any,\n\t\tdispatch: CollisionDispatchMetadata = {\n\t\t\tphase: 'stay',\n\t\t\tnowMs: getCollisionNowMs(),\n\t\t},\n\t): void {\n\t\tif (!this.collisionDelegate.collision?.length) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst cooldowns = this.collisionDelegate.cooldowns ?? new Map<string, number>();\n\t\tthis.collisionDelegate.cooldowns = cooldowns;\n\n\t\tfor (const registration of this.collisionDelegate.collision) {\n\t\t\tif (registration.options.phase !== dispatch.phase) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst cooldownMs = registration.options.cooldownMs;\n\t\t\tif (cooldownMs != null) {\n\t\t\t\tconst cooldownKey = `${registration.id}:${other.uuid}`;\n\t\t\t\tconst lastTriggeredAt = cooldowns.get(cooldownKey);\n\t\t\t\tif (\n\t\t\t\t\tlastTriggeredAt != null\n\t\t\t\t\t&& (dispatch.nowMs - lastTriggeredAt) < cooldownMs\n\t\t\t\t) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcooldowns.set(cooldownKey, dispatch.nowMs);\n\t\t\t}\n\n\t\t\tregistration.callback({ entity: this, other, globals });\n\t\t}\n\t}\n\n\tprotected updateMaterials(params: any) {\n\t\tif (!this.materials?.length) {\n\t\t\treturn;\n\t\t}\n\t\tfor (const material of this.materials) {\n\t\t\tif (material instanceof ShaderMaterial) {\n\t\t\t\tif (material.uniforms) {\n\t\t\t\t\tmaterial.uniforms.iTime &&\n\t\t\t\t\t\t(material.uniforms.iTime.value += params.delta);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic buildInfo(): Record<string, string> {\n\t\tconst info: Record<string, string> = {};\n\t\tinfo.name = this.name;\n\t\tinfo.uuid = this.uuid;\n\t\tinfo.eid = this.eid.toString();\n\t\treturn info;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Events API\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Dispatch an event from this entity.\n\t * Events are emitted both locally and to the global event bus.\n\t */\n\tdispatch<K extends keyof EntityEvents>(\n\t\tevent: K,\n\t\tpayload: EntityEvents[K],\n\t): void {\n\t\tthis.eventDelegate.dispatch(event, payload);\n\t\t(zylemEventBus as any).emit(event, payload);\n\t}\n\n\t/**\n\t * Listen for events on this entity instance.\n\t * @returns Unsubscribe function\n\t */\n\tlisten<K extends keyof EntityEvents>(\n\t\tevent: K,\n\t\thandler: (payload: EntityEvents[K]) => void,\n\t): () => void {\n\t\treturn this.eventDelegate.listen(event, handler);\n\t}\n\n\t/**\n\t * Clean up entity event subscriptions.\n\t */\n\tdisposeEvents(): void {\n\t\tthis.eventDelegate.dispose();\n\t}\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Bare entity factory\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Create a bare entity with no mesh or collision.\n * Use `.add(boxMesh(), boxCollision())` to compose its shape.\n *\n * @example\n * ```ts\n * const box = create({ position: { x: 0, y: 5, z: 0 } })\n * .add(boxMesh({ size: { x: 2, y: 2, z: 2 } }))\n * .add(boxCollision({ size: { x: 2, y: 2, z: 2 } }));\n * ```\n */\nexport function create(options?: Partial<GameEntityOptions>): GameEntity<GameEntityOptions> {\n\tconst entity = new (GameEntity as any)() as GameEntity<GameEntityOptions>;\n\tentity.options = { ...commonDefaults, ...options } as GameEntityOptions;\n\treturn finalizeEntityCloneSupport(\n\t\tentity,\n\t\t(cloneOptions) => create(cloneOptions ?? {}),\n\t);\n}\n\nfunction cloneMeshComponent(mesh: Mesh): Mesh {\n\tconst clonedMesh = mesh.clone(true);\n\tconst originalNodes: any[] = [];\n\tconst clonedNodes: any[] = [];\n\n\tmesh.traverse((node) => originalNodes.push(node));\n\tclonedMesh.traverse((node) => clonedNodes.push(node));\n\n\tfor (let i = 0; i < originalNodes.length; i++) {\n\t\tconst originalNode = originalNodes[i];\n\t\tconst clonedNode = clonedNodes[i];\n\n\t\tif (originalNode?.geometry?.clone) {\n\t\t\tclonedNode.geometry = originalNode.geometry.clone();\n\t\t}\n\n\t\tif (originalNode?.material) {\n\t\t\tclonedNode.material = Array.isArray(originalNode.material)\n\t\t\t\t? originalNode.material.map((material: Material) => material.clone())\n\t\t\t\t: originalNode.material.clone();\n\t\t}\n\t}\n\n\treturn clonedMesh;\n}\n\nfunction wrapBehaviorCallback<T extends Function>(\n\tcallback: T,\n\taliases: Map<BehaviorRef, BehaviorRef>,\n): T {\n\tif (aliases.size === 0) {\n\t\treturn callback;\n\t}\n\n\treturn ((...args: any[]) => {\n\t\tconst previousValues = Array.from(aliases.entries()).map(([sourceRef, targetRef]) => ({\n\t\t\tsourceRef,\n\t\t\toptions: sourceRef.options,\n\t\t\tfsm: sourceRef.fsm,\n\t\t\thasFSM: Object.prototype.hasOwnProperty.call(sourceRef, 'fsm'),\n\t\t\ttargetRef,\n\t\t}));\n\n\t\tfor (const entry of previousValues) {\n\t\t\tentry.sourceRef.options = entry.targetRef.options;\n\t\t\tif (entry.targetRef.fsm === undefined) {\n\t\t\t\tdelete entry.sourceRef.fsm;\n\t\t\t} else {\n\t\t\t\tentry.sourceRef.fsm = entry.targetRef.fsm;\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\treturn callback(...args);\n\t\t} finally {\n\t\t\tfor (let i = previousValues.length - 1; i >= 0; i--) {\n\t\t\t\tconst entry = previousValues[i];\n\t\t\t\tentry.sourceRef.options = entry.options;\n\t\t\t\tif (!entry.hasFSM) {\n\t\t\t\t\tdelete entry.sourceRef.fsm;\n\t\t\t\t} else {\n\t\t\t\t\tentry.sourceRef.fsm = entry.fsm;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}) as unknown as T;\n}\n\nexport function finalizeEntityCloneSupport<E extends GameEntity<any>>(\n\tentity: E,\n\tfactory: (options?: Partial<E['options']>) => E,\n): E {\n\tentity.finalizeCloneSupport(factory as any);\n\treturn entity;\n}\n","import {\n\tdefineSystem,\n\tdefineQuery,\n\tdefineComponent,\n\tTypes,\n\tremoveQuery,\n\ttype IWorld,\n} from 'bitecs';\nimport { Quaternion } from 'three';\nimport { StageEntity } from '../interfaces/entity';\nimport {\n\tgetBodyRenderPose,\n\ttype PhysicsPoseReadable,\n} from '../physics/physics-pose';\n\nexport type StageSystem = {\n\t_childrenMap: Map<number, StageEntity & { body: PhysicsPoseReadable | null }>;\n\t_world: { interpolationAlpha: number } | null;\n}\n\nexport const position = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32\n});\n\nexport const rotation = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32,\n\tw: Types.f32\n});\n\nexport const scale = defineComponent({\n\tx: Types.f32,\n\ty: Types.f32,\n\tz: Types.f32\n});\n\n// Reusable quaternion to avoid allocations per frame\nconst _tempQuaternion = new Quaternion();\n\nexport type TransformSystemResult = {\n\tsystem: ReturnType<typeof defineSystem>;\n\tdestroy: (world: IWorld) => void;\n};\n\nexport default function createTransformSystem(stage: StageSystem): TransformSystemResult {\n\tconst queryTerms = [position, rotation];\n\tconst transformQuery = defineQuery(queryTerms);\n\tconst stageEntities = stage._childrenMap;\n\tconst interpolationSource = stage._world;\n\n\tconst system = defineSystem((world) => {\n\t\tconst entities = transformQuery(world);\n\t\tif (stageEntities === undefined) {\n\t\t\treturn world;\n\t\t}\n\n\t\tfor (const [key, stageEntity] of stageEntities) {\n\t\t\t// Early bailout - combine conditions\n\t\t\tif (!stageEntity?.body || stageEntity.markedForRemoval) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst id = entities[key];\n\t\t\tconst body = stageEntity.body;\n\t\t\tconst target = stageEntity.group ?? stageEntity.mesh;\n\t\t\tconst renderPose = target\n\t\t\t\t? getBodyRenderPose(body, interpolationSource?.interpolationAlpha ?? 0)\n\t\t\t\t: null;\n\n\t\t\t// Position sync\n\t\t\tconst translation = body.translation();\n\t\t\tposition.x[id] = translation.x;\n\t\t\tposition.y[id] = translation.y;\n\t\t\tposition.z[id] = translation.z;\n\n\t\t\tif (target && renderPose) {\n\t\t\t\ttarget.position.set(\n\t\t\t\t\trenderPose.position.x,\n\t\t\t\t\trenderPose.position.y,\n\t\t\t\t\trenderPose.position.z,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Skip rotation if controlled externally\n\t\t\tif (stageEntity.controlledRotation) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Rotation sync - reuse quaternion\n\t\t\tconst rot = body.rotation();\n\t\t\trotation.x[id] = rot.x;\n\t\t\trotation.y[id] = rot.y;\n\t\t\trotation.z[id] = rot.z;\n\t\t\trotation.w[id] = rot.w;\n\n\t\t\tif (target && renderPose) {\n\t\t\t\t_tempQuaternion.set(\n\t\t\t\t\trenderPose.rotation.x,\n\t\t\t\t\trenderPose.rotation.y,\n\t\t\t\t\trenderPose.rotation.z,\n\t\t\t\t\trenderPose.rotation.w,\n\t\t\t\t);\n\t\t\t\ttarget.setRotationFromQuaternion(_tempQuaternion);\n\t\t\t}\n\t\t}\n\n\t\treturn world;\n\t});\n\n\tconst destroy = (world: IWorld) => {\n\t\t// Remove the query from bitecs world tracking\n\t\tremoveQuery(world, transformQuery);\n\t};\n\n\treturn { system, destroy };\n}\n","import { Quaternion } from 'three';\n\nexport interface PhysicsVector3 {\n\tx: number;\n\ty: number;\n\tz: number;\n}\n\nexport interface PhysicsQuaternion {\n\tx: number;\n\ty: number;\n\tz: number;\n\tw: number;\n}\n\nexport interface PhysicsPose {\n\tposition: PhysicsVector3;\n\trotation: PhysicsQuaternion;\n}\n\nexport interface PhysicsPoseHistory {\n\tprevious: PhysicsPose;\n\tcurrent: PhysicsPose;\n}\n\nexport interface PhysicsPoseReadable {\n\ttranslation(): PhysicsVector3;\n\trotation(): PhysicsQuaternion;\n}\n\nexport interface PhysicsRenderPoseProvider {\n\tgetPoseHistory(): PhysicsPoseHistory;\n\tgetRenderPose(alpha: number): PhysicsPose;\n}\n\nconst directBodyPoseHistory = new WeakMap<object, PhysicsPoseHistory>();\nconst _previousQuaternion = new Quaternion();\nconst _currentQuaternion = new Quaternion();\nconst _renderQuaternion = new Quaternion();\n\nexport function createPhysicsPose(\n\tposition: Partial<PhysicsVector3> = {},\n\trotation: Partial<PhysicsQuaternion> = {},\n): PhysicsPose {\n\treturn {\n\t\tposition: {\n\t\t\tx: position.x ?? 0,\n\t\t\ty: position.y ?? 0,\n\t\t\tz: position.z ?? 0,\n\t\t},\n\t\trotation: {\n\t\t\tx: rotation.x ?? 0,\n\t\t\ty: rotation.y ?? 0,\n\t\t\tz: rotation.z ?? 0,\n\t\t\tw: rotation.w ?? 1,\n\t\t},\n\t};\n}\n\nexport function clonePhysicsVector3(vector: PhysicsVector3): PhysicsVector3 {\n\treturn { x: vector.x, y: vector.y, z: vector.z };\n}\n\nexport function clonePhysicsQuaternion(\n\trotation: PhysicsQuaternion,\n): PhysicsQuaternion {\n\treturn { x: rotation.x, y: rotation.y, z: rotation.z, w: rotation.w };\n}\n\nexport function clonePhysicsPose(pose: PhysicsPose): PhysicsPose {\n\treturn {\n\t\tposition: clonePhysicsVector3(pose.position),\n\t\trotation: clonePhysicsQuaternion(pose.rotation),\n\t};\n}\n\nexport function clampInterpolationAlpha(alpha: number): number {\n\tif (!Number.isFinite(alpha)) return 0;\n\treturn Math.max(0, Math.min(1, alpha));\n}\n\nexport function capturePhysicsPose(body: PhysicsPoseReadable): PhysicsPose {\n\treturn {\n\t\tposition: clonePhysicsVector3(body.translation()),\n\t\trotation: clonePhysicsQuaternion(body.rotation()),\n\t};\n}\n\nexport function createCollapsedPhysicsPoseHistory(\n\tpose: PhysicsPose,\n): PhysicsPoseHistory {\n\tconst current = clonePhysicsPose(pose);\n\treturn {\n\t\tprevious: clonePhysicsPose(current),\n\t\tcurrent,\n\t};\n}\n\nexport function registerDirectBodyPoseHistory(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst history = createCollapsedPhysicsPoseHistory(capturePhysicsPose(body));\n\tdirectBodyPoseHistory.set(body, history);\n\treturn history;\n}\n\nexport function getDirectBodyPoseHistory(\n\tbody: object,\n): PhysicsPoseHistory | null {\n\treturn directBodyPoseHistory.get(body) ?? null;\n}\n\nexport function collapseDirectBodyPoseHistory(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst pose = capturePhysicsPose(body);\n\tconst history =\n\t\tdirectBodyPoseHistory.get(body) ?? createCollapsedPhysicsPoseHistory(pose);\n\n\thistory.previous = clonePhysicsPose(pose);\n\thistory.current = clonePhysicsPose(pose);\n\tdirectBodyPoseHistory.set(body, history);\n\n\treturn history;\n}\n\nexport function prepareDirectBodyPoseHistoryStep(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\treturn collapseDirectBodyPoseHistory(body);\n}\n\nexport function commitDirectBodyPoseHistoryStep(\n\tbody: object & PhysicsPoseReadable,\n): PhysicsPoseHistory {\n\tconst pose = capturePhysicsPose(body);\n\tconst history =\n\t\tdirectBodyPoseHistory.get(body) ?? createCollapsedPhysicsPoseHistory(pose);\n\n\thistory.current = clonePhysicsPose(pose);\n\tdirectBodyPoseHistory.set(body, history);\n\n\treturn history;\n}\n\nexport function interpolatePhysicsPose(\n\tprevious: PhysicsPose,\n\tcurrent: PhysicsPose,\n\talpha: number,\n): PhysicsPose {\n\tconst t = clampInterpolationAlpha(alpha);\n\n\t_previousQuaternion.set(\n\t\tprevious.rotation.x,\n\t\tprevious.rotation.y,\n\t\tprevious.rotation.z,\n\t\tprevious.rotation.w,\n\t);\n\t_currentQuaternion.set(\n\t\tcurrent.rotation.x,\n\t\tcurrent.rotation.y,\n\t\tcurrent.rotation.z,\n\t\tcurrent.rotation.w,\n\t);\n\t_renderQuaternion.slerpQuaternions(\n\t\t_previousQuaternion,\n\t\t_currentQuaternion,\n\t\tt,\n\t);\n\n\treturn {\n\t\tposition: {\n\t\t\tx: previous.position.x + (current.position.x - previous.position.x) * t,\n\t\t\ty: previous.position.y + (current.position.y - previous.position.y) * t,\n\t\t\tz: previous.position.z + (current.position.z - previous.position.z) * t,\n\t\t},\n\t\trotation: {\n\t\t\tx: _renderQuaternion.x,\n\t\t\ty: _renderQuaternion.y,\n\t\t\tz: _renderQuaternion.z,\n\t\t\tw: _renderQuaternion.w,\n\t\t},\n\t};\n}\n\nexport function getBodyPoseHistory(body: unknown): PhysicsPoseHistory | null {\n\tif (isRenderPoseProvider(body)) {\n\t\treturn body.getPoseHistory();\n\t}\n\tif (isPhysicsPoseReadable(body)) {\n\t\treturn directBodyPoseHistory.get(body as object) ?? null;\n\t}\n\treturn null;\n}\n\nexport function getBodyRenderPose(\n\tbody: PhysicsPoseReadable | PhysicsRenderPoseProvider,\n\talpha: number,\n): PhysicsPose {\n\tif (isRenderPoseProvider(body)) {\n\t\treturn body.getRenderPose(alpha);\n\t}\n\n\tconst history = directBodyPoseHistory.get(body as object);\n\tif (!history) {\n\t\treturn capturePhysicsPose(body);\n\t}\n\n\tconst latestPose = capturePhysicsPose(body);\n\tif (!posesEqual(latestPose, history.current)) {\n\t\tconst collapsed = collapseDirectBodyPoseHistory(body as object & PhysicsPoseReadable);\n\t\treturn clonePhysicsPose(collapsed.current);\n\t}\n\n\treturn interpolatePhysicsPose(history.previous, history.current, alpha);\n}\n\nfunction isPhysicsPoseReadable(value: unknown): value is PhysicsPoseReadable {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === 'object' &&\n\t\ttypeof (value as PhysicsPoseReadable).translation === 'function' &&\n\t\ttypeof (value as PhysicsPoseReadable).rotation === 'function'\n\t);\n}\n\nfunction isRenderPoseProvider(value: unknown): value is PhysicsRenderPoseProvider {\n\treturn (\n\t\tvalue != null &&\n\t\ttypeof value === 'object' &&\n\t\ttypeof (value as PhysicsRenderPoseProvider).getPoseHistory === 'function' &&\n\t\ttypeof (value as PhysicsRenderPoseProvider).getRenderPose === 'function'\n\t);\n}\n\nfunction posesEqual(a: PhysicsPose, b: PhysicsPose): boolean {\n\treturn (\n\t\ta.position.x === b.position.x &&\n\t\ta.position.y === b.position.y &&\n\t\ta.position.z === b.position.z &&\n\t\ta.rotation.x === b.rotation.x &&\n\t\ta.rotation.y === b.rotation.y &&\n\t\ta.rotation.z === b.rotation.z &&\n\t\ta.rotation.w === b.rotation.w\n\t);\n}\n","/** Vite build flags */\nexport const DEBUG_FLAG = import.meta.env.VITE_DEBUG_FLAG === 'true';","import {\n\tCleanupContext,\n\tCleanupFunction,\n\tDestroyContext,\n\tDestroyFunction,\n\tLoadedContext,\n\tLoadedFunction,\n\tSetupContext,\n\tSetupFunction,\n\tUpdateContext,\n\tUpdateFunction,\n} from \"./base-node-life-cycle\";\nimport { DEBUG_FLAG } from \"./flags\";\nimport { nanoid } from \"nanoid\";\nimport { NodeInterface } from \"./node-interface\";\n\nexport type BaseNodeOptions<T = any> = BaseNode | Partial<T>;\nexport type LifecycleRegistrationMethod =\n\t| 'onSetup'\n\t| 'onLoaded'\n\t| 'onUpdate'\n\t| 'onDestroy'\n\t| 'onCleanup'\n\t| 'prependSetup'\n\t| 'prependUpdate';\n\nexport interface LifecycleRegistration {\n\tmethod: LifecycleRegistrationMethod;\n\tcallbacks: Function[];\n}\n\n/**\n * Lifecycle callback arrays - each lifecycle event can have multiple callbacks\n * that execute in order.\n */\nexport interface LifecycleCallbacks<T> {\n\tsetup: Array<SetupFunction<T>>;\n\tloaded: Array<LoadedFunction<T>>;\n\tupdate: Array<UpdateFunction<T>>;\n\tdestroy: Array<DestroyFunction<T>>;\n\tcleanup: Array<CleanupFunction<T>>;\n}\n\nexport abstract class BaseNode<Options = any, T = any> implements NodeInterface {\n\tprotected parent: NodeInterface | null = null;\n\tprotected children: NodeInterface[] = [];\n\tpublic options: Options;\n\tpublic eid: number = 0;\n\tpublic uuid: string = '';\n\tpublic name: string = '';\n\tpublic markedForRemoval: boolean = false;\n\n\t/**\n\t * Lifecycle callback arrays - use onSetup(), onUpdate(), etc. to add callbacks\n\t * Uses `any` for the type parameter to avoid invariance issues when subclasses\n\t * are assigned to BaseNode references. Type safety is enforced by the public\n\t * onSetup/onUpdate/etc. methods which are typed with `this`.\n\t */\n\tprotected lifecycleCallbacks: LifecycleCallbacks<any> = {\n\t\tsetup: [],\n\t\tloaded: [],\n\t\tupdate: [],\n\t\tdestroy: [],\n\t\tcleanup: [],\n\t};\n\tprivate trackLifecycleRegistrations: boolean = false;\n\tprivate userLifecycleRegistrations: LifecycleRegistration[] = [];\n\n\tconstructor(args: BaseNodeOptions[] = []) {\n\t\tconst options = args\n\t\t\t.filter(arg => !(arg instanceof BaseNode))\n\t\t\t.reduce((acc, opt) => ({ ...acc, ...opt }), {});\n\t\tthis.options = options as Options;\n\t\tthis.uuid = nanoid();\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Fluent API for adding lifecycle callbacks\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add setup callbacks to be executed in order during nodeSetup\n\t */\n\tpublic onSetup(...callbacks: Array<SetupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.setup.push(...callbacks);\n\t\tthis.recordLifecycleRegistration('onSetup', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add loaded callbacks to be executed in order during nodeLoaded\n\t */\n\tpublic onLoaded(...callbacks: Array<LoadedFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.loaded.push(...callbacks);\n\t\tthis.recordLifecycleRegistration('onLoaded', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add update callbacks to be executed in order during nodeUpdate\n\t */\n\tpublic onUpdate(...callbacks: Array<UpdateFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.update.push(...callbacks);\n\t\tthis.recordLifecycleRegistration('onUpdate', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add destroy callbacks to be executed in order during nodeDestroy\n\t */\n\tpublic onDestroy(...callbacks: Array<DestroyFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.destroy.push(...callbacks);\n\t\tthis.recordLifecycleRegistration('onDestroy', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Add cleanup callbacks to be executed in order during nodeCleanup\n\t */\n\tpublic onCleanup(...callbacks: Array<CleanupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.cleanup.push(...callbacks);\n\t\tthis.recordLifecycleRegistration('onCleanup', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Prepend setup callbacks (run before existing ones)\n\t */\n\tpublic prependSetup(...callbacks: Array<SetupFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.setup.unshift(...callbacks);\n\t\tthis.recordLifecycleRegistration('prependSetup', callbacks);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Prepend update callbacks (run before existing ones)\n\t */\n\tpublic prependUpdate(...callbacks: Array<UpdateFunction<this>>): this {\n\t\tthis.lifecycleCallbacks.update.unshift(...callbacks);\n\t\tthis.recordLifecycleRegistration('prependUpdate', callbacks);\n\t\treturn this;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Tree structure\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic setParent(parent: NodeInterface | null): void {\n\t\tthis.parent = parent;\n\t}\n\n\tpublic getParent(): NodeInterface | null {\n\t\treturn this.parent;\n\t}\n\n\tpublic add(baseNode: NodeInterface): void {\n\t\tthis.children.push(baseNode);\n\t\tbaseNode.setParent(this);\n\t}\n\n\tpublic remove(baseNode: NodeInterface): void {\n\t\tconst index = this.children.indexOf(baseNode);\n\t\tif (index !== -1) {\n\t\t\tthis.children.splice(index, 1);\n\t\t\tbaseNode.setParent(null);\n\t\t}\n\t}\n\n\tpublic getChildren(): NodeInterface[] {\n\t\treturn this.children;\n\t}\n\n\tpublic isComposite(): boolean {\n\t\treturn this.children.length > 0;\n\t}\n\n\tpublic enableUserLifecycleTracking(): void {\n\t\tthis.trackLifecycleRegistrations = true;\n\t}\n\n\tprotected replayUserLifecycleRegistrationsTo(\n\t\ttarget: BaseNode<any, any>,\n\t\twrap?: <T extends Function>(callback: T) => T,\n\t): void {\n\t\tfor (const registration of this.userLifecycleRegistrations) {\n\t\t\tconst callbacks = wrap\n\t\t\t\t? registration.callbacks.map((callback) => wrap(callback as never))\n\t\t\t\t: [...registration.callbacks];\n\n\t\t\tswitch (registration.method) {\n\t\t\t\tcase 'onSetup':\n\t\t\t\t\ttarget.onSetup(...callbacks as Array<SetupFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'onLoaded':\n\t\t\t\t\ttarget.onLoaded(...callbacks as Array<LoadedFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'onUpdate':\n\t\t\t\t\ttarget.onUpdate(...callbacks as Array<UpdateFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'onDestroy':\n\t\t\t\t\ttarget.onDestroy(...callbacks as Array<DestroyFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'onCleanup':\n\t\t\t\t\ttarget.onCleanup(...callbacks as Array<CleanupFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'prependSetup':\n\t\t\t\t\ttarget.prependSetup(...callbacks as Array<SetupFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'prependUpdate':\n\t\t\t\t\ttarget.prependUpdate(...callbacks as Array<UpdateFunction<any>>);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected cloneChildrenInto(target: BaseNode<any, any>): void {\n\t\tfor (const child of this.children) {\n\t\t\ttarget.add(cloneNode(child));\n\t\t}\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Abstract methods for subclass implementation\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic abstract create(): T;\n\n\tprotected abstract _setup(params: SetupContext<this>): void;\n\n\tprotected abstract _loaded(params: LoadedContext<this>): Promise<void>;\n\n\tprotected abstract _update(params: UpdateContext<this>): void;\n\n\tprotected abstract _destroy(params: DestroyContext<this>): void;\n\n\tprotected abstract _cleanup(params: CleanupContext<this>): void;\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Node lifecycle execution - runs internal + callback arrays\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic nodeSetup(params: SetupContext<this>) {\n\t\tif (DEBUG_FLAG) { /** */ }\n\t\tthis.markedForRemoval = false;\n\t\tif (typeof this._setup === 'function') {\n\t\t\tthis._setup(params);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.setup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tthis.children.forEach(child => child.nodeSetup(params));\n\t}\n\n\tpublic nodeUpdate(params: UpdateContext<this>): void {\n\t\tif (this.markedForRemoval) {\n\t\t\treturn;\n\t\t}\n\t\tif (typeof this._update === 'function') {\n\t\t\tthis._update(params);\n\t\t}\n\t\t// Tick entity actions before user callbacks so state is fresh\n\t\tif (typeof (this as any)._tickActions === 'function') {\n\t\t\t(this as any)._tickActions(params.delta);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.update) {\n\t\t\tcallback(params);\n\t\t}\n\t\tthis.children.forEach(child => child.nodeUpdate(params));\n\t}\n\n\tpublic nodeDestroy(params: DestroyContext<this>): void {\n\t\t// Guard against re-entry (e.g. destroy called twice during collision loop)\n\t\tif (this.markedForRemoval) return;\n\n\t\tthis.children.forEach(child => child.nodeDestroy(params));\n\n\t\t// Destroy phase -- consumer game logic (onDestroy callbacks + _destroy override)\n\t\tfor (const callback of this.lifecycleCallbacks.destroy) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._destroy === 'function') {\n\t\t\tthis._destroy(params);\n\t\t}\n\t\tthis.markedForRemoval = true;\n\n\t\t// Cleanup phase -- engine-internal resource disposal (onCleanup callbacks + _cleanup override)\n\t\tfor (const callback of this.lifecycleCallbacks.cleanup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._cleanup === 'function') {\n\t\t\tthis._cleanup(params);\n\t\t}\n\t}\n\n\tpublic async nodeLoaded(params: LoadedContext<this>): Promise<void> {\n\t\tif (typeof this._loaded === 'function') {\n\t\t\tawait this._loaded(params);\n\t\t}\n\t\tfor (const callback of this.lifecycleCallbacks.loaded) {\n\t\t\tcallback(params);\n\t\t}\n\t}\n\n\tpublic nodeCleanup(params: CleanupContext<this>): void {\n\t\tthis.children.forEach(child => (child as any).nodeCleanup?.(params));\n\t\tfor (const callback of this.lifecycleCallbacks.cleanup) {\n\t\t\tcallback(params);\n\t\t}\n\t\tif (typeof this._cleanup === 'function') {\n\t\t\tthis._cleanup(params);\n\t\t}\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Options\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\tpublic getOptions(): Options {\n\t\treturn this.options;\n\t}\n\n\tpublic setOptions(options: Partial<Options>): void {\n\t\tthis.options = { ...this.options, ...options };\n\t}\n\n\tprivate recordLifecycleRegistration(\n\t\tmethod: LifecycleRegistrationMethod,\n\t\tcallbacks: Function[],\n\t): void {\n\t\tif (!this.trackLifecycleRegistrations || callbacks.length === 0) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.userLifecycleRegistrations.push({\n\t\t\tmethod,\n\t\t\tcallbacks: [...callbacks],\n\t\t});\n\t}\n}\n\nexport function cloneNode(node: NodeInterface): NodeInterface {\n\tconst maybeClone = (node as any)?.clone;\n\tif (typeof maybeClone !== 'function') {\n\t\tthrow new Error(\n\t\t\t`Cannot clone child node \"${node.name || node.uuid || 'unknown'}\": missing clone() support.`,\n\t\t);\n\t}\n\treturn maybeClone.call(node);\n}\n","export type EventType = string | symbol;\n\n// An event handler can take an optional event argument\n// and should not return a value\nexport type Handler<T = unknown> = (event: T) => void;\nexport type WildcardHandler<T = Record<string, unknown>> = (\n\ttype: keyof T,\n\tevent: T[keyof T]\n) => void;\n\n// An array of all currently registered event handlers for a type\nexport type EventHandlerList<T = unknown> = Array<Handler<T>>;\nexport type WildCardEventHandlerList<T = Record<string, unknown>> = Array<\n\tWildcardHandler<T>\n>;\n\n// A map of event types and their corresponding event handlers.\nexport type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<\n\tkeyof Events | '*',\n\tEventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>\n>;\n\nexport interface Emitter<Events extends Record<EventType, unknown>> {\n\tall: EventHandlerMap<Events>;\n\n\ton<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;\n\ton(type: '*', handler: WildcardHandler<Events>): void;\n\n\toff<Key extends keyof Events>(\n\t\ttype: Key,\n\t\thandler?: Handler<Events[Key]>\n\t): void;\n\toff(type: '*', handler: WildcardHandler<Events>): void;\n\n\temit<Key extends keyof Events>(type: Key, event: Events[Key]): void;\n\temit<Key extends keyof Events>(\n\t\ttype: undefined extends Events[Key] ? Key : never\n\t): void;\n}\n\n/**\n * Mitt: Tiny (~200b) functional event emitter / pubsub.\n * @name mitt\n * @returns {Mitt}\n */\nexport default function mitt<Events extends Record<EventType, unknown>>(\n\tall?: EventHandlerMap<Events>\n): Emitter<Events> {\n\ttype GenericEventHandler =\n\t\t| Handler<Events[keyof Events]>\n\t\t| WildcardHandler<Events>;\n\tall = all || new Map();\n\n\treturn {\n\t\t/**\n\t\t * A Map of event names to registered handler functions.\n\t\t */\n\t\tall,\n\n\t\t/**\n\t\t * Register an event handler for the given type.\n\t\t * @param {string|symbol} type Type of event to listen for, or `'*'` for all events\n\t\t * @param {Function} handler Function to call in response to given event\n\t\t * @memberOf mitt\n\t\t */\n\t\ton<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\thandlers.push(handler);\n\t\t\t} else {\n\t\t\t\tall!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Remove an event handler for the given type.\n\t\t * If `handler` is omitted, all handlers of the given type are removed.\n\t\t * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)\n\t\t * @param {Function} [handler] Handler function to remove\n\t\t * @memberOf mitt\n\t\t */\n\t\toff<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {\n\t\t\tconst handlers: Array<GenericEventHandler> | undefined = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\tif (handler) {\n\t\t\t\t\thandlers.splice(handlers.indexOf(handler) >>> 0, 1);\n\t\t\t\t} else {\n\t\t\t\t\tall!.set(type, []);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Invoke all handlers for the given type.\n\t\t * If present, `'*'` handlers are invoked after type-matched handlers.\n\t\t *\n\t\t * Note: Manually firing '*' handlers is not supported.\n\t\t *\n\t\t * @param {string|symbol} type The event type to invoke\n\t\t * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler\n\t\t * @memberOf mitt\n\t\t */\n\t\temit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {\n\t\t\tlet handlers = all!.get(type);\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as EventHandlerList<Events[keyof Events]>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(evt!);\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\thandlers = all!.get('*');\n\t\t\tif (handlers) {\n\t\t\t\t(handlers as WildCardEventHandlerList<Events>)\n\t\t\t\t\t.slice()\n\t\t\t\t\t.map((handler) => {\n\t\t\t\t\t\thandler(type, evt!);\n\t\t\t\t\t});\n\t\t\t}\n\t\t}\n\t};\n}\n","import mitt, { Emitter } from 'mitt';\n\n/**\n * Event scope identifier for routing events.\n */\nexport type EventScope = 'game' | 'stage' | 'entity';\n\n/**\n * Reusable delegate for event emission and subscription.\n * Use via composition in Game, Stage, and Entity classes.\n * \n * @example\n * class Game {\n * private eventDelegate = new EventEmitterDelegate<GameEvents>();\n * \n * dispatch<K extends keyof GameEvents>(event: K, payload: GameEvents[K]) {\n * this.eventDelegate.dispatch(event, payload);\n * }\n * }\n */\nexport class EventEmitterDelegate<TEvents extends Record<string, unknown>> {\n\tprivate emitter: Emitter<TEvents>;\n\tprivate unsubscribes: (() => void)[] = [];\n\n\tconstructor() {\n\t\tthis.emitter = mitt<TEvents>();\n\t}\n\n\t/**\n\t * Dispatch an event to all listeners.\n\t */\n\tdispatch<K extends keyof TEvents>(event: K, payload: TEvents[K]): void {\n\t\tthis.emitter.emit(event, payload);\n\t}\n\n\t/**\n\t * Subscribe to an event. Returns an unsubscribe function.\n\t */\n\tlisten<K extends keyof TEvents>(\n\t\tevent: K,\n\t\thandler: (payload: TEvents[K]) => void\n\t): () => void {\n\t\tthis.emitter.on(event, handler);\n\t\tconst unsub = () => this.emitter.off(event, handler);\n\t\tthis.unsubscribes.push(unsub);\n\t\treturn unsub;\n\t}\n\n\t/**\n\t * Subscribe to all events.\n\t */\n\tlistenAll(handler: (type: keyof TEvents, payload: TEvents[keyof TEvents]) => void): () => void {\n\t\tthis.emitter.on('*', handler as any);\n\t\tconst unsub = () => this.emitter.off('*', handler as any);\n\t\tthis.unsubscribes.push(unsub);\n\t\treturn unsub;\n\t}\n\n\t/**\n\t * Clean up all subscriptions.\n\t */\n\tdispose(): void {\n\t\tthis.unsubscribes.forEach(fn => fn());\n\t\tthis.unsubscribes = [];\n\t\tthis.emitter.all.clear();\n\t}\n}\n","import mitt from 'mitt';\nimport type { LoadingEvent } from '../core/interfaces';\n\n/**\n * Payload for game loading events with stage context.\n */\nexport interface GameLoadingPayload extends LoadingEvent {\n\tstageName?: string;\n\tstageIndex?: number;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Game Events\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Payload for stage configuration sent to editor. */\nexport interface StageConfigPayload {\n\tid: string;\n\tbackgroundColor: string;\n\tbackgroundImage: string | null;\n\tgravity: { x: number; y: number; z: number };\n\tinputs: Record<string, string[]>;\n\tvariables: Record<string, unknown>;\n}\n\n/** Payload for entity configuration sent to editor. */\nexport interface EntityConfigPayload {\n\tuuid: string;\n\tname: string;\n\ttype: string;\n\tposition: { x: number; y: number; z: number };\n\trotation: { x: number; y: number; z: number };\n\tscale: { x: number; y: number; z: number };\n}\n\n/** Payload for state dispatch events from game to editor. */\nexport interface StateDispatchPayload {\n\tscope: 'game' | 'stage' | 'entity';\n\tpath: string;\n\tvalue: unknown;\n\tpreviousValue?: unknown;\n\tconfig?: {\n\t\tid: string;\n\t\taspectRatio: number;\n\t\tfullscreen: boolean;\n\t\tbodyBackground: string | undefined;\n\t\tinternalResolution: { width: number; height: number } | undefined;\n\t\tdebug: boolean;\n\t} | null;\n\tstageConfig?: StageConfigPayload | null;\n\tentities?: EntityConfigPayload[] | null;\n}\n\nexport type GameEvents = {\n\t'loading:start': GameLoadingPayload;\n\t'loading:progress': GameLoadingPayload;\n\t'loading:complete': GameLoadingPayload;\n\t'paused': { paused: boolean };\n\t'debug': { enabled: boolean };\n\t'state:dispatch': StateDispatchPayload;\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Stage Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type StageEvents = {\n\t'stage:loaded': { stageId: string };\n\t'stage:unloaded': { stageId: string };\n\t'stage:variable:changed': { key: string; value: unknown };\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Entity Events\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type EntityEvents = {\n\t'entity:spawned': { entityId: string; name: string };\n\t'entity:destroyed': { entityId: string };\n\t'entity:collision': { entityId: string; otherId: string };\n\t'entity:model:loading': { entityId: string; files: string[] };\n\t'entity:model:loaded': { entityId: string; success: boolean; meshCount?: number };\n\t'entity:animation:loaded': { entityId: string; animationCount: number };\n};\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Combined Event Map\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport type ZylemEvents = GameEvents & StageEvents & EntityEvents;\n\n/**\n * Global event bus for cross-package communication.\n * \n * Usage:\n * ```ts\n * import { zylemEventBus } from '@zylem/game-lib';\n * \n * // Subscribe\n * const unsub = zylemEventBus.on('loading:progress', (e) => console.log(e));\n * \n * // Emit\n * zylemEventBus.emit('loading:progress', { type: 'progress', progress: 0.5 });\n * \n * // Cleanup\n * unsub();\n * ```\n */\nexport const zylemEventBus = mitt<ZylemEvents>();\n","import { proxy } from 'valtio';\n\nexport type VelocityIntentMode = 'replace' | 'add';\n\nexport interface VelocityIntent {\n\tx?: number;\n\ty?: number;\n\tz?: number;\n\tmode: VelocityIntentMode;\n\tpriority?: number;\n}\n\n/**\n * Transform state managed by Valtio for batched physics updates.\n * \n * This store accumulates transformation intents during the frame,\n * then applies them all at once after onUpdate() callbacks complete.\n * \n * Design decisions:\n * - Position: Accumulated deltas (additive)\n * - Rotation: Last value wins (replacement)\n * - Velocity: Accumulated deltas (additive)\n * - Angular velocity: Accumulated deltas (additive)\n */\nexport interface TransformState {\n\t/** Position deltas to be applied (accumulated) */\n\tposition: { x: number; y: number; z: number };\n\t\n\t/** Rotation quaternion (last value wins) */\n\trotation: { x: number; y: number; z: number; w: number };\n\t\n\t/** Linear velocity (accumulated) */\n\tvelocity: { x: number; y: number; z: number };\n\t\n\t/** Angular velocity (accumulated) */\n\tangularVelocity: { x: number; y: number; z: number };\n\n\t/** Per-source velocity intents composed once per frame */\n\tvelocityChannels: Record<string, VelocityIntent>;\n\t\n\t/** Dirty flags to track what needs to be applied */\n\tdirty: {\n\t\tposition: boolean;\n\t\trotation: boolean;\n\t\t/** @deprecated Use per-axis velocityX/Y/Z flags for new code */\n\t\tvelocity: boolean;\n\t\tvelocityX: boolean;\n\t\tvelocityY: boolean;\n\t\tvelocityZ: boolean;\n\t\tvelocityChannels: boolean;\n\t\tangularVelocity: boolean;\n\t};\n}\n\n/**\n * Create a new transform store with optional initial values.\n * The store is a Valtio proxy, making it reactive for debugging/visualization.\n * \n * @param initial Optional initial state values\n * @returns Reactive transform state\n */\nexport function createTransformStore(initial?: Partial<TransformState>): TransformState {\n\tconst defaultState: TransformState = {\n\t\tposition: { x: 0, y: 0, z: 0 },\n\t\trotation: { x: 0, y: 0, z: 0, w: 1 },\n\t\tvelocity: { x: 0, y: 0, z: 0 },\n\t\tangularVelocity: { x: 0, y: 0, z: 0 },\n\t\tvelocityChannels: {},\n\t\tdirty: {\n\t\t\tposition: false,\n\t\t\trotation: false,\n\t\t\tvelocity: false,\n\t\t\tvelocityX: false,\n\t\t\tvelocityY: false,\n\t\t\tvelocityZ: false,\n\t\t\tvelocityChannels: false,\n\t\t\tangularVelocity: false,\n\t\t},\n\t};\n\n\treturn proxy({\n\t\t...defaultState,\n\t\t...initial,\n\t\t// Ensure dirty flags are properly initialized even if partial initial state\n\t\tdirty: {\n\t\t\t...defaultState.dirty,\n\t\t\t...initial?.dirty,\n\t\t},\n\t});\n}\n\n/**\n * Reset a transform store to its initial clean state.\n * Called after applying changes to prepare for the next frame.\n * \n * @param store The transform store to reset\n */\nexport function resetTransformStore(store: TransformState): void {\n\t// Reset position deltas\n\tstore.position.x = 0;\n\tstore.position.y = 0;\n\tstore.position.z = 0;\n\n\t// Reset rotation to identity quaternion\n\tstore.rotation.x = 0;\n\tstore.rotation.y = 0;\n\tstore.rotation.z = 0;\n\tstore.rotation.w = 1;\n\n\t// Reset velocity\n\tstore.velocity.x = 0;\n\tstore.velocity.y = 0;\n\tstore.velocity.z = 0;\n\n\t// Reset angular velocity\n\tstore.angularVelocity.x = 0;\n\tstore.angularVelocity.y = 0;\n\tstore.angularVelocity.z = 0;\n\n\t// Reset per-source velocity intents\n\tfor (const sourceId of Object.keys(store.velocityChannels)) {\n\t\tdelete store.velocityChannels[sourceId];\n\t}\n\n\t// Clear all dirty flags\n\tstore.dirty.position = false;\n\tstore.dirty.rotation = false;\n\tstore.dirty.velocity = false;\n\tstore.dirty.velocityX = false;\n\tstore.dirty.velocityY = false;\n\tstore.dirty.velocityZ = false;\n\tstore.dirty.velocityChannels = false;\n\tstore.dirty.angularVelocity = false;\n}\n","import { Vector3 } from 'three';\nimport { RigidBody, Vector } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\nimport { setVelocityIntent } from './velocity-intents';\n\nexport interface EntityWithBody {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Move an entity along the X axis, preserving other velocities.\n */\nexport function moveX(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(entity.transformStore, 'actions', { x: delta }, { mode: 'replace' });\n}\n\n/**\n * Move an entity along the Y axis, preserving other velocities.\n */\nexport function moveY(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(entity.transformStore, 'actions', { y: delta }, { mode: 'replace' });\n}\n\n/**\n * Move an entity along the Z axis, preserving other velocities.\n */\nexport function moveZ(entity: EntityWithBody, delta: number): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(entity.transformStore, 'actions', { z: delta }, { mode: 'replace' });\n}\n\n/**\n * Move an entity along the X and Y axis, preserving Z velocity.\n */\nexport function moveXY(entity: EntityWithBody, deltaX: number, deltaY: number): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(\n\t\tentity.transformStore,\n\t\t'actions',\n\t\t{ x: deltaX, y: deltaY },\n\t\t{ mode: 'replace' },\n\t);\n}\n\n/**\n * Move an entity along the X and Z axis, preserving Y velocity.\n */\nexport function moveXZ(entity: EntityWithBody, deltaX: number, deltaZ: number): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(\n\t\tentity.transformStore,\n\t\t'actions',\n\t\t{ x: deltaX, z: deltaZ },\n\t\t{ mode: 'replace' },\n\t);\n}\n\n/**\n * Move entity based on a vector, adding to existing velocities.\n */\nexport function move(entity: EntityWithBody, vector: Vector3): void {\n\tif (!entity.transformStore) return;\n\tsetVelocityIntent(\n\t\tentity.transformStore,\n\t\t'actions',\n\t\t{ x: vector.x, y: vector.y, z: vector.z },\n\t\t{ mode: 'add' },\n\t);\n}\n\n/**\n * Reset entity velocity\n */\nexport function resetVelocity(entity: EntityWithBody): void {\n\tif (!entity.body) return;\n\tentity.body.setLinvel(new Vector3(0, 0, 0), true);\n\tentity.body.setLinearDamping(5);\n}\n\n/**\n * Move entity forward in 2D space, preserving Z velocity\n */\nexport function moveForwardXY(entity: EntityWithBody, delta: number, rotation2DAngle: number): void {\n\tconst deltaX = Math.sin(-rotation2DAngle) * delta;\n\tconst deltaY = Math.cos(-rotation2DAngle) * delta;\n\tmoveXY(entity, deltaX, deltaY);\n}\n\n/**\n * Get entity position\n */\nexport function getPosition(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.translation();\n}\n\n/**\n * Get entity velocity\n */\nexport function getVelocity(entity: EntityWithBody): Vector | null {\n\tif (!entity.body) return null;\n\treturn entity.body.linvel();\n}\n\n/**\n * Set entity position\n */\nexport function setPosition(entity: EntityWithBody, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity X position\n */\nexport function setPositionX(entity: EntityWithBody, x: number): void {\n\tif (!entity.body) return;\n\tconst { y, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Y position\n */\nexport function setPositionY(entity: EntityWithBody, y: number): void {\n\tif (!entity.body) return;\n\tconst { x, z } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Set entity Z position\n */\nexport function setPositionZ(entity: EntityWithBody, z: number): void {\n\tif (!entity.body) return;\n\tconst { x, y } = entity.body.translation();\n\tentity.body.setTranslation({ x, y, z }, true);\n}\n\n/**\n * Wrap entity around 2D bounds\n */\nexport function wrapAroundXY(entity: EntityWithBody, boundsX: number, boundsY: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\n\tif (newX !== x || newY !== y) {\n\t\tsetPosition(entity, newX, newY, 0);\n\t}\n}\n\n/**\n * Wrap entity around 3D bounds\n */\nexport function wrapAround3D(entity: EntityWithBody, boundsX: number, boundsY: number, boundsZ: number): void {\n\tconst position = getPosition(entity);\n\tif (!position) return;\n\n\tconst { x, y, z } = position;\n\tconst newX = x > boundsX ? -boundsX : (x < -boundsX ? boundsX : x);\n\tconst newY = y > boundsY ? -boundsY : (y < -boundsY ? boundsY : y);\n\tconst newZ = z > boundsZ ? -boundsZ : (z < -boundsZ ? boundsZ : z);\n\n\tif (newX !== x || newY !== y || newZ !== z) {\n\t\tsetPosition(entity, newX, newY, newZ);\n\t}\n}\n\n/**\n * Enhanced moveable entity with bound methods\n */\nexport interface MoveableEntity extends EntityWithBody {\n\tmoveX(delta: number): void;\n\tmoveY(delta: number): void;\n\tmoveZ(delta: number): void;\n\tmoveXY(deltaX: number, deltaY: number): void;\n\tmoveXZ(deltaX: number, deltaZ: number): void;\n\tmove(vector: Vector3): void;\n\tresetVelocity(): void;\n\tmoveForwardXY(delta: number, rotation2DAngle: number): void;\n\tgetPosition(): Vector | null;\n\tgetVelocity(): Vector | null;\n\tsetPosition(x: number, y: number, z: number): void;\n\tsetPositionX(x: number): void;\n\tsetPositionY(y: number): void;\n\tsetPositionZ(z: number): void;\n\twrapAroundXY(boundsX: number, boundsY: number): void;\n\twrapAround3D(boundsX: number, boundsY: number, boundsZ: number): void;\n}\n\n/**\n * Enhance an entity with additive movement methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeMoveable<T extends EntityWithBody>(entity: T): T & MoveableEntity {\n\tconst moveable = entity as T & MoveableEntity;\n\n\t// Create transform store if it doesn't exist\n\tif (!moveable.transformStore) {\n\t\tmoveable.transformStore = createTransformStore();\n\t}\n\n\tmoveable.moveX = (delta: number) => moveX(entity, delta);\n\tmoveable.moveY = (delta: number) => moveY(entity, delta);\n\tmoveable.moveZ = (delta: number) => moveZ(entity, delta);\n\tmoveable.moveXY = (deltaX: number, deltaY: number) => moveXY(entity, deltaX, deltaY);\n\tmoveable.moveXZ = (deltaX: number, deltaZ: number) => moveXZ(entity, deltaX, deltaZ);\n\tmoveable.move = (vector: Vector3) => move(entity, vector);\n\tmoveable.resetVelocity = () => resetVelocity(entity);\n\tmoveable.moveForwardXY = (delta: number, rotation2DAngle: number) => moveForwardXY(entity, delta, rotation2DAngle);\n\tmoveable.getPosition = () => getPosition(entity);\n\tmoveable.getVelocity = () => getVelocity(entity);\n\tmoveable.setPosition = (x: number, y: number, z: number) => setPosition(entity, x, y, z);\n\tmoveable.setPositionX = (x: number) => setPositionX(entity, x);\n\tmoveable.setPositionY = (y: number) => setPositionY(entity, y);\n\tmoveable.setPositionZ = (z: number) => setPositionZ(entity, z);\n\tmoveable.wrapAroundXY = (boundsX: number, boundsY: number) => wrapAroundXY(entity, boundsX, boundsY);\n\tmoveable.wrapAround3D = (boundsX: number, boundsY: number, boundsZ: number) => wrapAround3D(entity, boundsX, boundsY, boundsZ);\n\n\treturn moveable;\n}","import { TransformState, VelocityIntentMode } from './transform-store';\n\nexport interface VelocityIntentOptions {\n\tmode?: VelocityIntentMode;\n\tpriority?: number;\n}\n\nexport interface VelocityIntentVector {\n\tx?: number;\n\ty?: number;\n\tz?: number;\n}\n\nexport function setVelocityIntent(\n\tstore: TransformState,\n\tsourceId: string,\n\tvector: VelocityIntentVector,\n\toptions: VelocityIntentOptions = {},\n): void {\n\tconst prev = store.velocityChannels[sourceId];\n\tconst mode = options.mode ?? prev?.mode ?? 'replace';\n\tconst priority = options.priority ?? prev?.priority ?? 0;\n\tconst isAdditiveMerge = mode === 'add' && prev?.mode === 'add';\n\n\tconst x =\n\t\tvector.x == null\n\t\t\t? prev?.x\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.x ?? 0) + vector.x\n\t\t\t\t: vector.x;\n\tconst y =\n\t\tvector.y == null\n\t\t\t? prev?.y\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.y ?? 0) + vector.y\n\t\t\t\t: vector.y;\n\tconst z =\n\t\tvector.z == null\n\t\t\t? prev?.z\n\t\t\t: isAdditiveMerge\n\t\t\t\t? (prev?.z ?? 0) + vector.z\n\t\t\t\t: vector.z;\n\n\tstore.velocityChannels[sourceId] = {\n\t\tx,\n\t\ty,\n\t\tz,\n\t\tmode,\n\t\tpriority,\n\t};\n\tstore.dirty.velocityChannels = true;\n}\n\nexport function clearVelocityIntent(store: TransformState, sourceId: string): void {\n\tif (!(sourceId in store.velocityChannels)) return;\n\tdelete store.velocityChannels[sourceId];\n\tstore.dirty.velocityChannels = true;\n}\n","import { Euler, Vector3, MathUtils, Quaternion } from 'three';\nimport { RigidBody } from '@dimforge/rapier3d-compat';\nimport type { TransformState } from './transform-store';\nimport { createTransformStore } from './transform-store';\n\nexport interface RotatableEntity {\n\tbody: RigidBody | null;\n\tgroup: any;\n\ttransformStore?: TransformState;\n}\n\nfunction syncImmediateRotation(entity: RotatableEntity): void {\n\tif (!entity.group || !entity.transformStore) return;\n\n\tentity.group.setRotationFromQuaternion(\n\t\tnew Quaternion(\n\t\t\tentity.transformStore.rotation.x,\n\t\t\tentity.transformStore.rotation.y,\n\t\t\tentity.transformStore.rotation.z,\n\t\t\tentity.transformStore.rotation.w,\n\t\t),\n\t);\n}\n\n/**\n * Rotate an entity in the direction of a movement vector\n */\nexport function rotateInDirection(entity: RotatableEntity, moveVector: Vector3): void {\n\tif (!entity.body) return;\n\tconst rotate = Math.atan2(-moveVector.x, moveVector.z);\n\trotateYEuler(entity, rotate);\n}\n\n/**\n * Rotate an entity around the Y axis using Euler angles\n */\nexport function rotateYEuler(entity: RotatableEntity, amount: number): void {\n\trotateEuler(entity, new Vector3(0, -amount, 0));\n}\n\n/**\n * Rotate an entity using Euler angles\n */\nexport function rotateEuler(entity: RotatableEntity, rotation: Vector3): void {\n\tif (!entity.transformStore) return;\n\tconst quat = new Quaternion().setFromEuler(\n\t\tnew Euler(rotation.x, rotation.y, rotation.z),\n\t);\n\tentity.transformStore.rotation.w = quat.w;\n\tentity.transformStore.rotation.x = quat.x;\n\tentity.transformStore.rotation.y = quat.y;\n\tentity.transformStore.rotation.z = quat.z;\n\tentity.transformStore.dirty.rotation = true;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Rotate an entity around the Y axis.\n */\nexport function rotateY(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaY = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Y-axis rotation: q_delta = (0, deltaY, 0, deltaW)\n\tconst newW = q.w * deltaW - q.y * deltaY;\n\tconst newX = q.x * deltaW + q.z * deltaY;\n\tconst newY = q.y * deltaW + q.w * deltaY;\n\tconst newZ = q.z * deltaW - q.x * deltaY;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Rotate an entity around the X axis.\n */\nexport function rotateX(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaX = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For X-axis rotation: q_delta = (deltaX, 0, 0, deltaW)\n\tconst newW = q.w * deltaW - q.x * deltaX;\n\tconst newX = q.x * deltaW + q.w * deltaX;\n\tconst newY = q.y * deltaW + q.z * deltaX;\n\tconst newZ = q.z * deltaW - q.y * deltaX;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Rotate an entity around the Z axis.\n */\nexport function rotateZ(entity: RotatableEntity, delta: number): void {\n\tif (!entity.transformStore) return;\n\t\n\t// Create delta rotation quaternion\n\tconst halfAngle = delta / 2;\n\tconst deltaW = Math.cos(halfAngle);\n\tconst deltaZ = Math.sin(halfAngle);\n\t\n\t// Get current rotation from store\n\tconst q = entity.transformStore.rotation;\n\t\n\t// Multiply quaternions: q_new = q_current * q_delta\n\t// For Z-axis rotation: q_delta = (0, 0, deltaZ, deltaW)\n\tconst newW = q.w * deltaW - q.z * deltaZ;\n\tconst newX = q.x * deltaW - q.y * deltaZ;\n\tconst newY = q.y * deltaW + q.x * deltaZ;\n\tconst newZ = q.z * deltaW + q.w * deltaZ;\n\t\n\tentity.transformStore.rotation.w = newW;\n\tentity.transformStore.rotation.x = newX;\n\tentity.transformStore.rotation.y = newY;\n\tentity.transformStore.rotation.z = newZ;\n\tentity.transformStore.dirty.rotation = true;\n\t(entity as any)._rotation2DAngle = ((entity as any)._rotation2DAngle ?? 0) + delta;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Set rotation around Y axis.\n */\nexport function setRotationY(entity: RotatableEntity, y: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = y / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst yComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = yComponent;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Set rotation around Y axis\n */\nexport function setRotationDegreesY(entity: RotatableEntity, y: number): void {\n\tif (!entity.body) return;\n\tsetRotationY(entity, MathUtils.degToRad(y));\n}\n\n/**\n * Set rotation around X axis.\n */\nexport function setRotationX(entity: RotatableEntity, x: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = x / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst xComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = xComponent;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = 0;\n\tentity.transformStore.dirty.rotation = true;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Set rotation around X axis\n */\nexport function setRotationDegreesX(entity: RotatableEntity, x: number): void {\n\tif (!entity.body) return;\n\tsetRotationX(entity, MathUtils.degToRad(x));\n}\n\n/**\n * Set rotation around Z axis.\n */\nexport function setRotationZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst halfAngle = z / 2;\n\tconst w = Math.cos(halfAngle);\n\tconst zComponent = Math.sin(halfAngle);\n\tentity.transformStore.rotation.w = w;\n\tentity.transformStore.rotation.x = 0;\n\tentity.transformStore.rotation.y = 0;\n\tentity.transformStore.rotation.z = zComponent;\n\tentity.transformStore.dirty.rotation = true;\n\t(entity as any)._rotation2DAngle = z;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Set rotation around Z axis\n */\nexport function setRotationDegreesZ(entity: RotatableEntity, z: number): void {\n\tif (!entity.body) return;\n\tsetRotationZ(entity, MathUtils.degToRad(z));\n}\n\n/**\n * Set rotation for all axes.\n */\nexport function setRotation(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.transformStore) return;\n\tconst quat = new Quaternion().setFromEuler(new Euler(x, y, z));\n\tentity.transformStore.rotation.w = quat.w;\n\tentity.transformStore.rotation.x = quat.x;\n\tentity.transformStore.rotation.y = quat.y;\n\tentity.transformStore.rotation.z = quat.z;\n\tentity.transformStore.dirty.rotation = true;\n\t(entity as any)._rotation2DAngle = z;\n\tsyncImmediateRotation(entity);\n}\n\n/**\n * Set rotation for all axes\n */\nexport function setRotationDegrees(entity: RotatableEntity, x: number, y: number, z: number): void {\n\tif (!entity.body) return;\n\tsetRotation(entity, MathUtils.degToRad(x), MathUtils.degToRad(y), MathUtils.degToRad(z));\n}\n\n/**\n * Get current rotation\n */\nexport function getRotation(entity: RotatableEntity): any {\n\tif (!entity.body) return null;\n\treturn entity.body.rotation();\n}\n\n/**\n * Rotatable entity API with bound methods\n */\nexport interface RotatableEntityAPI extends RotatableEntity {\n\trotateInDirection(moveVector: Vector3): void;\n\trotateYEuler(amount: number): void;\n\trotateEuler(rotation: Vector3): void;\n\trotateY(delta: number): void;\n\trotateX(delta: number): void;\n\trotateZ(delta: number): void;\n\tsetRotationY(y: number): void;\n\tsetRotationX(x: number): void;\n\tsetRotationZ(z: number): void;\n\tsetRotationDegrees(x: number, y: number, z: number): void;\n\tsetRotationDegreesY(y: number): void;\n\tsetRotationDegreesX(x: number): void;\n\tsetRotationDegreesZ(z: number): void;\n\tsetRotation(x: number, y: number, z: number): void;\n\tgetRotation(): any;\n}\n\n/**\n * Enhance an entity instance with rotatable methods.\n * Automatically creates a transform store if one doesn't exist.\n */\nexport function makeRotatable<T extends RotatableEntity>(entity: T): T & RotatableEntityAPI {\n\tconst rotatableEntity = entity as T & RotatableEntityAPI;\n\n\t// Create transform store if it doesn't exist\n\tif (!rotatableEntity.transformStore) {\n\t\trotatableEntity.transformStore = createTransformStore();\n\t}\n\n\trotatableEntity.rotateInDirection = (moveVector: Vector3) => rotateInDirection(entity, moveVector);\n\trotatableEntity.rotateYEuler = (amount: number) => rotateYEuler(entity, amount);\n\trotatableEntity.rotateEuler = (rotation: Vector3) => rotateEuler(entity, rotation);\n\trotatableEntity.rotateX = (delta: number) => rotateX(entity, delta);\n\trotatableEntity.rotateY = (delta: number) => rotateY(entity, delta);\n\trotatableEntity.rotateZ = (delta: number) => rotateZ(entity, delta);\n\trotatableEntity.setRotationY = (y: number) => setRotationY(entity, y);\n\trotatableEntity.setRotationX = (x: number) => setRotationX(entity, x);\n\trotatableEntity.setRotationZ = (z: number) => setRotationZ(entity, z);\n\trotatableEntity.setRotationDegreesY = (y: number) => setRotationDegreesY(entity, y);\n\trotatableEntity.setRotationDegreesX = (x: number) => setRotationDegreesX(entity, x);\n\trotatableEntity.setRotationDegreesZ = (z: number) => setRotationDegreesZ(entity, z);\n\trotatableEntity.setRotationDegrees = (x: number, y: number, z: number) => setRotationDegrees(entity, x, y, z);\n\trotatableEntity.setRotation = (x: number, y: number, z: number) => setRotation(entity, x, y, z);\n\trotatableEntity.getRotation = () => getRotation(entity);\n\n\treturn rotatableEntity;\n}\n","import { makeMoveable, EntityWithBody, MoveableEntity } from './moveable';\nimport { makeRotatable, RotatableEntity, RotatableEntityAPI } from './rotatable';\n\n/**\n * Enhance an entity with both movement and rotation capabilities.\n * Transform store is automatically created by makeMoveable and makeRotatable.\n */\nexport function makeTransformable<\n\tT extends RotatableEntity & EntityWithBody\n>(entity: T): T & MoveableEntity & RotatableEntityAPI {\n\tconst withMovement = makeMoveable(entity);\n\tconst withRotation = makeRotatable(withMovement);\n\treturn withRotation;\n}\n\n","import {\n\tActiveCollisionTypes,\n\tColliderDesc,\n\tRigidBodyDesc,\n\tRigidBodyType,\n} from '@dimforge/rapier3d-compat';\nimport { Vector3 } from 'three';\nimport type { Vec3 } from '../../core/vector';\nimport {\n\tgetOrCreateCollisionGroupId,\n\tcreateCollisionFilter,\n\ttype CollisionOptions,\n} from '../../collision/collision-builder';\nimport { deepCloneValue } from '../../core/clone-utils';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// CollisionComponent type returned by all collision factories\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * A built collision component containing a rigid body description and collider description.\n * Returned by collision factory functions (boxCollision, sphereCollision, etc.)\n * and consumed by GameEntity.add().\n */\nexport interface CollisionComponent {\n\t__kind: 'collision';\n\tbodyDesc: RigidBodyDesc;\n\tcolliderDesc: ColliderDesc;\n\tcloneComponent: () => CollisionComponent;\n}\n\n/**\n * Type guard for CollisionComponent.\n */\nexport function isCollisionComponent(obj: any): obj is CollisionComponent {\n\treturn obj && obj.__kind === 'collision';\n}\n\nexport function cloneCollisionComponent(component: CollisionComponent): CollisionComponent {\n\treturn component.cloneComponent();\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Shared helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface BaseCollisionOptions {\n\t/** Whether the body is static (fixed) or dynamic */\n\tstatic?: boolean;\n\t/** Whether this collider is a sensor */\n\tsensor?: boolean;\n\t/** Position offset relative to the entity origin */\n\toffset?: Vec3;\n\t/** Collision type string for group filtering */\n\tcollisionType?: string;\n\t/** Allowed collision types for filtering */\n\tcollisionFilter?: string[];\n}\n\nfunction buildBodyDesc(isStatic: boolean): RigidBodyDesc {\n\tconst type = isStatic ? RigidBodyType.Fixed : RigidBodyType.Dynamic;\n\treturn new RigidBodyDesc(type)\n\t\t.setTranslation(0, 0, 0)\n\t\t.setGravityScale(1.0)\n\t\t.setCanSleep(false)\n\t\t.setCcdEnabled(true);\n}\n\nfunction applyCollisionOptions(\n\tcolliderDesc: ColliderDesc,\n\topts: BaseCollisionOptions,\n): void {\n\tif (opts.offset) {\n\t\tcolliderDesc.setTranslation(opts.offset.x, opts.offset.y, opts.offset.z);\n\t}\n\tif (opts.sensor) {\n\t\tcolliderDesc.setSensor(true);\n\t\tcolliderDesc.activeCollisionTypes = ActiveCollisionTypes.KINEMATIC_FIXED;\n\t}\n\tif (opts.collisionType) {\n\t\tconst groupId = getOrCreateCollisionGroupId(opts.collisionType);\n\t\tlet filter = 0b1111111111111111;\n\t\tif (opts.collisionFilter) {\n\t\t\tfilter = createCollisionFilter(opts.collisionFilter);\n\t\t}\n\t\tcolliderDesc.setCollisionGroups((groupId << 16) | filter);\n\t}\n}\n\nfunction makeComponent(\n\tcolliderDesc: ColliderDesc,\n\topts: BaseCollisionOptions,\n\tcloneComponentFactory: () => CollisionComponent,\n): CollisionComponent {\n\tapplyCollisionOptions(colliderDesc, opts);\n\treturn {\n\t\t__kind: 'collision',\n\t\tbodyDesc: buildBodyDesc(opts.static ?? false),\n\t\tcolliderDesc,\n\t\tcloneComponent: cloneComponentFactory,\n\t};\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Box\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface BoxCollisionOptions extends BaseCollisionOptions {\n\t/** Box dimensions (default: 1x1x1) */\n\tsize?: Vec3;\n}\n\n/**\n * Create a box (cuboid) collision component.\n */\nexport function boxCollision(opts: BoxCollisionOptions = {}): CollisionComponent {\n\tconst size = opts.size ?? { x: 1, y: 1, z: 1 };\n\tconst desc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => boxCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Sphere\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface SphereCollisionOptions extends BaseCollisionOptions {\n\t/** Sphere radius (default: 1) */\n\tradius?: number;\n}\n\n/**\n * Create a sphere (ball) collision component.\n */\nexport function sphereCollision(opts: SphereCollisionOptions = {}): CollisionComponent {\n\tconst desc = ColliderDesc.ball(opts.radius ?? 1);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => sphereCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cone\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ConeCollisionOptions extends BaseCollisionOptions {\n\t/** Base radius (default: 1) */\n\tradius?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a cone collision component.\n */\nexport function coneCollision(opts: ConeCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 1;\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cone(height / 2, radius);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => coneCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Pyramid (cone collider with 4-sided visual approximation)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PyramidCollisionOptions extends BaseCollisionOptions {\n\t/** Base radius (default: 1) */\n\tradius?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a pyramid collision component (approximated as a cone).\n */\nexport function pyramidCollision(opts: PyramidCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 1;\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cone(height / 2, radius);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => pyramidCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Cylinder\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface CylinderCollisionOptions extends BaseCollisionOptions {\n\t/** Top radius (default: 1) */\n\tradiusTop?: number;\n\t/** Bottom radius (default: 1) */\n\tradiusBottom?: number;\n\t/** Height (default: 2) */\n\theight?: number;\n}\n\n/**\n * Create a cylinder collision component.\n */\nexport function cylinderCollision(opts: CylinderCollisionOptions = {}): CollisionComponent {\n\tconst radius = Math.max(opts.radiusTop ?? 1, opts.radiusBottom ?? 1);\n\tconst height = opts.height ?? 2;\n\tconst desc = ColliderDesc.cylinder(height / 2, radius);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => cylinderCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Pill (capsule)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PillCollisionOptions extends BaseCollisionOptions {\n\t/** Capsule hemisphere radius (default: 0.5) */\n\tradius?: number;\n\t/** Cylindrical section length (default: 1) */\n\tlength?: number;\n}\n\n/**\n * Create a pill (capsule) collision component.\n */\nexport function pillCollision(opts: PillCollisionOptions = {}): CollisionComponent {\n\tconst radius = opts.radius ?? 0.5;\n\tconst length = opts.length ?? 1;\n\tconst desc = ColliderDesc.capsule(length / 2, radius);\n\tconst clonedOpts = deepCloneValue(opts);\n\treturn makeComponent(desc, opts, () => pillCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Plane (heightfield)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface PlaneCollisionOptions extends BaseCollisionOptions {\n\t/** Tile dimensions (default: 10x10) */\n\ttile?: { x: number; y: number };\n\t/** Number of subdivisions per axis (default: 10) */\n\tsubdivisions?: number;\n\t/** Pre-computed height data for the heightfield */\n\theightData?: Float32Array;\n}\n\n/**\n * Create a plane (heightfield) collision component.\n * For flat planes, pass no heightData — a zeroed heightfield is used.\n */\nexport function planeCollision(opts: PlaneCollisionOptions = {}): CollisionComponent {\n\tconst tile = opts.tile ?? { x: 10, y: 10 };\n\tconst subdivisions = opts.subdivisions ?? 10;\n\tconst size = new Vector3(tile.x, 1, tile.y);\n\n\tconst totalVerts = (subdivisions + 1) * (subdivisions + 1);\n\tconst heightData = opts.heightData ?? new Float32Array(totalVerts);\n\n\tconst desc = ColliderDesc.heightfield(\n\t\tsubdivisions,\n\t\tsubdivisions,\n\t\theightData,\n\t\tsize,\n\t);\n\n\tconst effectiveOpts = { ...opts, static: opts.static ?? true };\n\tconst clonedOpts = deepCloneValue(effectiveOpts);\n\treturn makeComponent(desc, effectiveOpts, () => planeCollision(clonedOpts));\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Zone (sensor cuboid)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport interface ZoneCollisionOptions extends BaseCollisionOptions {\n\t/** Zone dimensions (default: 1x1x1) */\n\tsize?: Vec3;\n}\n\n/**\n * Create a zone (sensor cuboid) collision component.\n * Always a sensor; static by default.\n */\nexport function zoneCollision(opts: ZoneCollisionOptions = {}): CollisionComponent {\n\tconst size = opts.size ?? { x: 1, y: 1, z: 1 };\n\tconst desc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2);\n\tdesc.setSensor(true);\n\tdesc.activeCollisionTypes = ActiveCollisionTypes.KINEMATIC_FIXED;\n\tconst effectiveOpts = { ...opts, static: opts.static ?? true, sensor: true };\n\tconst clonedOpts = deepCloneValue(effectiveOpts);\n\treturn makeComponent(desc, effectiveOpts, () => zoneCollision(clonedOpts));\n}\n","import { Color, Vector2, Vector3 } from 'three';\n\ntype PlainObject = Record<string, unknown>;\n\nfunction isPlainObject(value: unknown): value is PlainObject {\n\tif (!value || typeof value !== 'object') {\n\t\treturn false;\n\t}\n\tconst proto = Object.getPrototypeOf(value);\n\treturn proto === Object.prototype || proto === null;\n}\n\nexport function deepCloneValue<T>(value: T): T {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\n\tif (typeof value === 'function' || typeof value !== 'object') {\n\t\treturn value;\n\t}\n\n\tif (value instanceof Color || value instanceof Vector2 || value instanceof Vector3) {\n\t\treturn value.clone() as T;\n\t}\n\n\tif (value instanceof Float32Array) {\n\t\treturn new Float32Array(value) as T;\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => deepCloneValue(item)) as T;\n\t}\n\n\tif (isPlainObject(value)) {\n\t\tconst cloned: PlainObject = {};\n\t\tfor (const [key, entry] of Object.entries(value)) {\n\t\t\tif (key === '_builders') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tcloned[key] = deepCloneValue(entry);\n\t\t}\n\t\treturn cloned as T;\n\t}\n\n\treturn value;\n}\n\nexport function deepMergeValues<T>(base: T, overrides?: Partial<T>): T {\n\tconst clonedBase = deepCloneValue(base);\n\tif (!overrides) {\n\t\treturn clonedBase;\n\t}\n\n\tif (!isPlainObject(clonedBase) || !isPlainObject(overrides)) {\n\t\treturn deepCloneValue(overrides as T);\n\t}\n\n\tconst result = clonedBase as PlainObject;\n\n\tfor (const [key, overrideValue] of Object.entries(overrides)) {\n\t\tif (key === '_builders' || overrideValue === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst currentValue = result[key];\n\t\tif (isPlainObject(currentValue) && isPlainObject(overrideValue)) {\n\t\t\tresult[key] = deepMergeValues(currentValue, overrideValue);\n\t\t\tcontinue;\n\t\t}\n\n\t\tresult[key] = deepCloneValue(overrideValue);\n\t}\n\n\treturn result as T;\n}\n","import { Color, Vector3 } from 'three';\nimport { standardShader } from '../graphics/shaders/standard.shader';\nimport { GameEntityOptions } from './entity';\nimport { BaseNode } from '../core/base-node';\n\nexport const commonDefaults: Partial<GameEntityOptions> = {\n position: new Vector3(0, 0, 0),\n material: {\n color: new Color('#ffffff'),\n shader: standardShader\n },\n collision: {\n static: false,\n },\n};\n\n/**\n * Merge a variadic args array (BaseNode children + options object) with defaults.\n * Returns the merged options. This replaces the createEntity() arg parsing logic.\n */\nexport function mergeArgs<T extends GameEntityOptions>(\n args: Array<BaseNode | Partial<T>>,\n defaults: Partial<T>,\n): T {\n const configArgs = args.filter(\n (arg): arg is Partial<T> => !(arg instanceof BaseNode),\n );\n let merged: Partial<T> = { ...defaults };\n for (const opt of configArgs) {\n merged = { ...merged, ...opt };\n }\n return merged as 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","/**\n * Centralized Asset Manager for Zylem\n * \n * Provides caching, parallel loading, and unified access to all asset types.\n * All asset loading should funnel through this manager.\n */\n\nimport { Texture, Object3D, LoadingManager, Cache } from 'three';\nimport { GLTF } from 'three/addons/loaders/GLTFLoader.js';\nimport mitt, { Emitter } from 'mitt';\n\nimport {\n\tAssetType,\n\tAssetLoadOptions,\n\tAssetManagerEvents,\n\tBatchLoadItem,\n\tModelLoadResult\n} from './asset-types';\n\nimport {\n\tTextureLoaderAdapter,\n\tGLTFLoaderAdapter,\n\tFBXLoaderAdapter,\n\tOBJLoaderAdapter,\n\tAudioLoaderAdapter,\n\tFileLoaderAdapter,\n\tJsonLoaderAdapter,\n\tTextureOptions,\n\tGLTFLoadOptions,\n\tFBXLoadOptions,\n\tOBJLoadOptions,\n\tFileLoadOptions\n} from './loaders';\n\n/**\n * Asset cache entry\n */\ninterface CacheEntry<T> {\n\tpromise: Promise<T>;\n\tresult?: T;\n\tloadedAt: number;\n}\n\n/**\n * AssetManager - Singleton for all asset loading\n * \n * Features:\n * - URL-based caching with deduplication\n * - Typed load methods for each asset type\n * - Batch loading with Promise.all() for parallelism\n * - Progress events via LoadingManager\n * - Clone support for shared assets (textures, models)\n */\nexport class AssetManager {\n\tprivate static instance: AssetManager | null = null;\n\n\t// Caches for different asset types\n\tprivate textureCache: Map<string, CacheEntry<Texture>> = new Map();\n\tprivate modelCache: Map<string, CacheEntry<ModelLoadResult>> = new Map();\n\tprivate audioCache: Map<string, CacheEntry<AudioBuffer>> = new Map();\n\tprivate fileCache: Map<string, CacheEntry<string | ArrayBuffer>> = new Map();\n\tprivate jsonCache: Map<string, CacheEntry<unknown>> = new Map();\n\n\t// Loaders\n\tprivate textureLoader: TextureLoaderAdapter;\n\tprivate gltfLoader: GLTFLoaderAdapter;\n\tprivate fbxLoader: FBXLoaderAdapter;\n\tprivate objLoader: OBJLoaderAdapter;\n\tprivate audioLoader: AudioLoaderAdapter;\n\tprivate fileLoader: FileLoaderAdapter;\n\tprivate jsonLoader: JsonLoaderAdapter;\n\n\t// Loading manager for progress tracking\n\tprivate loadingManager: LoadingManager;\n\n\t// Event emitter\n\tprivate events: Emitter<AssetManagerEvents>;\n\n\t// Stats\n\tprivate stats = {\n\t\ttexturesLoaded: 0,\n\t\tmodelsLoaded: 0,\n\t\taudioLoaded: 0,\n\t\tfilesLoaded: 0,\n\t\tcacheHits: 0,\n\t\tcacheMisses: 0\n\t};\n\n\tprivate constructor() {\n\t\t// Initialize loaders\n\t\tthis.textureLoader = new TextureLoaderAdapter();\n\t\tthis.gltfLoader = new GLTFLoaderAdapter();\n\t\tthis.fbxLoader = new FBXLoaderAdapter();\n\t\tthis.objLoader = new OBJLoaderAdapter();\n\t\tthis.audioLoader = new AudioLoaderAdapter();\n\t\tthis.fileLoader = new FileLoaderAdapter();\n\t\tthis.jsonLoader = new JsonLoaderAdapter();\n\n\t\t// Initialize loading manager\n\t\tthis.loadingManager = new LoadingManager();\n\t\tthis.loadingManager.onProgress = (url, loaded, total) => {\n\t\t\tthis.events.emit('batch:progress', { loaded, total });\n\t\t};\n\n\t\t// Initialize event emitter\n\t\tthis.events = mitt<AssetManagerEvents>();\n\n\t\t// Enable Three.js built-in cache\n\t\tCache.enabled = true;\n\t}\n\n\t/**\n\t * Get the singleton instance\n\t */\n\tstatic getInstance(): AssetManager {\n\t\tif (!AssetManager.instance) {\n\t\t\tAssetManager.instance = new AssetManager();\n\t\t}\n\t\treturn AssetManager.instance;\n\t}\n\n\t/**\n\t * Reset the singleton (useful for testing)\n\t */\n\tstatic resetInstance(): void {\n\t\tif (AssetManager.instance) {\n\t\t\tAssetManager.instance.clearCache();\n\t\t\tAssetManager.instance = null;\n\t\t}\n\t}\n\n\t// ==================== TEXTURE LOADING ====================\n\n\t/**\n\t * Load a texture with caching\n\t */\n\tasync loadTexture(url: string, options?: TextureOptions): Promise<Texture> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.TEXTURE,\n\t\t\tthis.textureCache,\n\t\t\t() => this.textureLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(texture) => {\n\t\t\t\tif (!options?.clone) return texture;\n\t\t\t\tconst cloned = this.textureLoader.clone(texture);\n\t\t\t\t// Re-apply per-instance texture options to the clone so that\n\t\t\t\t// different callers sharing the same cached base texture can\n\t\t\t\t// use independent repeat / wrap values.\n\t\t\t\tif (options.repeat) {\n\t\t\t\t\tcloned.repeat.copy(options.repeat);\n\t\t\t\t}\n\t\t\t\tif (options.wrapS !== undefined) {\n\t\t\t\t\tcloned.wrapS = options.wrapS;\n\t\t\t\t}\n\t\t\t\tif (options.wrapT !== undefined) {\n\t\t\t\t\tcloned.wrapT = options.wrapT;\n\t\t\t\t}\n\t\t\t\treturn cloned;\n\t\t\t}\n\t\t);\n\t}\n\n\t// ==================== MODEL LOADING ====================\n\n\t/**\n\t * Load a GLTF/GLB model with caching\n\t */\n\tasync loadGLTF(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.GLTF,\n\t\t\tthis.modelCache,\n\t\t\t() => this.gltfLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.gltfLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Load an FBX model with caching\n\t */\n\tasync loadFBX(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.FBX,\n\t\t\tthis.modelCache,\n\t\t\t() => this.fbxLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.fbxLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Load an OBJ model with caching\n\t */\n\tasync loadOBJ(url: string, options?: OBJLoadOptions): Promise<ModelLoadResult> {\n\t\t// Include mtlPath in cache key for OBJ files\n\t\tconst cacheKey = options?.mtlPath ? `${url}:${options.mtlPath}` : url;\n\t\treturn this.loadWithCache(\n\t\t\tcacheKey,\n\t\t\tAssetType.OBJ,\n\t\t\tthis.modelCache,\n\t\t\t() => this.objLoader.load(url, options),\n\t\t\toptions,\n\t\t\t(result) => options?.clone ? this.objLoader.clone(result) : result\n\t\t);\n\t}\n\n\t/**\n\t * Auto-detect model type and load\n\t */\n\tasync loadModel(url: string, options?: AssetLoadOptions): Promise<ModelLoadResult> {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\t\n\t\tswitch (ext) {\n\t\t\tcase 'gltf':\n\t\t\tcase 'glb':\n\t\t\t\treturn this.loadGLTF(url, options);\n\t\t\tcase 'fbx':\n\t\t\t\treturn this.loadFBX(url, options);\n\t\t\tcase 'obj':\n\t\t\t\treturn this.loadOBJ(url, options);\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported model format: ${ext}`);\n\t\t}\n\t}\n\n\t// ==================== AUDIO LOADING ====================\n\n\t/**\n\t * Load an audio buffer with caching\n\t */\n\tasync loadAudio(url: string, options?: AssetLoadOptions): Promise<AudioBuffer> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.AUDIO,\n\t\t\tthis.audioCache,\n\t\t\t() => this.audioLoader.load(url, options),\n\t\t\toptions\n\t\t);\n\t}\n\n\t// ==================== FILE LOADING ====================\n\n\t/**\n\t * Load a raw file with caching\n\t */\n\tasync loadFile(url: string, options?: FileLoadOptions): Promise<string | ArrayBuffer> {\n\t\tconst cacheKey = options?.responseType ? `${url}:${options.responseType}` : url;\n\t\treturn this.loadWithCache(\n\t\t\tcacheKey,\n\t\t\tAssetType.FILE,\n\t\t\tthis.fileCache,\n\t\t\t() => this.fileLoader.load(url, options),\n\t\t\toptions\n\t\t);\n\t}\n\n\t/**\n\t * Load a JSON file with caching\n\t */\n\tasync loadJSON<T = unknown>(url: string, options?: AssetLoadOptions): Promise<T> {\n\t\treturn this.loadWithCache(\n\t\t\turl,\n\t\t\tAssetType.JSON,\n\t\t\tthis.jsonCache,\n\t\t\t() => this.jsonLoader.load<T>(url, options),\n\t\t\toptions\n\t\t) as Promise<T>;\n\t}\n\n\t// ==================== BATCH LOADING ====================\n\n\t/**\n\t * Load multiple assets in parallel\n\t */\n\tasync loadBatch(items: BatchLoadItem[]): Promise<Map<string, any>> {\n\t\tconst results = new Map<string, any>();\n\t\t\n\t\tconst promises = items.map(async (item) => {\n\t\t\ttry {\n\t\t\t\tlet result: any;\n\t\t\t\t\n\t\t\t\tswitch (item.type) {\n\t\t\t\t\tcase AssetType.TEXTURE:\n\t\t\t\t\t\tresult = await this.loadTexture(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.GLTF:\n\t\t\t\t\t\tresult = await this.loadGLTF(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.FBX:\n\t\t\t\t\t\tresult = await this.loadFBX(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.OBJ:\n\t\t\t\t\t\tresult = await this.loadOBJ(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.AUDIO:\n\t\t\t\t\t\tresult = await this.loadAudio(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.FILE:\n\t\t\t\t\t\tresult = await this.loadFile(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase AssetType.JSON:\n\t\t\t\t\t\tresult = await this.loadJSON(item.url, item.options);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tthrow new Error(`Unknown asset type: ${item.type}`);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tresults.set(item.url, result);\n\t\t\t} catch (error) {\n\t\t\t\tthis.events.emit('asset:error', {\n\t\t\t\t\turl: item.url,\n\t\t\t\t\ttype: item.type,\n\t\t\t\t\terror: error as Error\n\t\t\t\t});\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t});\n\n\t\tawait Promise.all(promises);\n\t\t\n\t\tthis.events.emit('batch:complete', { urls: items.map(i => i.url) });\n\t\t\n\t\treturn results;\n\t}\n\n\t/**\n\t * Preload assets without returning results\n\t */\n\tasync preload(items: BatchLoadItem[]): Promise<void> {\n\t\tawait this.loadBatch(items);\n\t}\n\n\t// ==================== CACHE MANAGEMENT ====================\n\n\t/**\n\t * Check if an asset is cached\n\t */\n\tisCached(url: string): boolean {\n\t\treturn this.textureCache.has(url) ||\n\t\t\tthis.modelCache.has(url) ||\n\t\t\tthis.audioCache.has(url) ||\n\t\t\tthis.fileCache.has(url) ||\n\t\t\tthis.jsonCache.has(url);\n\t}\n\n\t/**\n\t * Clear all caches or a specific URL\n\t */\n\tclearCache(url?: string): void {\n\t\tif (url) {\n\t\t\tthis.textureCache.delete(url);\n\t\t\tthis.modelCache.delete(url);\n\t\t\tthis.audioCache.delete(url);\n\t\t\tthis.fileCache.delete(url);\n\t\t\tthis.jsonCache.delete(url);\n\t\t} else {\n\t\t\tthis.textureCache.clear();\n\t\t\tthis.modelCache.clear();\n\t\t\tthis.audioCache.clear();\n\t\t\tthis.fileCache.clear();\n\t\t\tthis.jsonCache.clear();\n\t\t\tCache.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Get cache statistics\n\t */\n\tgetStats(): typeof this.stats {\n\t\treturn { ...this.stats };\n\t}\n\n\t// ==================== EVENTS ====================\n\n\t/**\n\t * Subscribe to asset manager events\n\t */\n\ton<K extends keyof AssetManagerEvents>(\n\t\tevent: K,\n\t\thandler: (payload: AssetManagerEvents[K]) => void\n\t): void {\n\t\tthis.events.on(event, handler);\n\t}\n\n\t/**\n\t * Unsubscribe from asset manager events\n\t */\n\toff<K extends keyof AssetManagerEvents>(\n\t\tevent: K,\n\t\thandler: (payload: AssetManagerEvents[K]) => void\n\t): void {\n\t\tthis.events.off(event, handler);\n\t}\n\n\t// ==================== PRIVATE HELPERS ====================\n\n\t/**\n\t * Generic cache wrapper for loading assets\n\t */\n\tprivate async loadWithCache<T>(\n\t\turl: string,\n\t\ttype: AssetType,\n\t\tcache: Map<string, CacheEntry<T>>,\n\t\tloader: () => Promise<T>,\n\t\toptions?: AssetLoadOptions,\n\t\tcloner?: (result: T) => T\n\t): Promise<T> {\n\t\t// Check for force reload\n\t\tif (options?.forceReload) {\n\t\t\tcache.delete(url);\n\t\t}\n\n\t\t// Check cache\n\t\tconst cached = cache.get(url);\n\t\tif (cached) {\n\t\t\tthis.stats.cacheHits++;\n\t\t\tthis.events.emit('asset:loaded', { url, type, fromCache: true });\n\t\t\t\n\t\t\tconst result = await cached.promise;\n\t\t\treturn cloner ? cloner(result) : result;\n\t\t}\n\n\t\t// Cache miss - start loading\n\t\tthis.stats.cacheMisses++;\n\t\tthis.events.emit('asset:loading', { url, type });\n\n\t\tconst promise = loader();\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tpromise,\n\t\t\tloadedAt: Date.now()\n\t\t};\n\t\tcache.set(url, entry);\n\n\t\ttry {\n\t\t\tconst result = await promise;\n\t\t\tentry.result = result;\n\t\t\t\n\t\t\t// Update stats\n\t\t\tthis.updateStats(type);\n\t\t\t\n\t\t\tthis.events.emit('asset:loaded', { url, type, fromCache: false });\n\t\t\t\n\t\t\treturn cloner ? cloner(result) : result;\n\t\t} catch (error) {\n\t\t\t// Remove failed entry from cache\n\t\t\tcache.delete(url);\n\t\t\tthis.events.emit('asset:error', { url, type, error: error as Error });\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate updateStats(type: AssetType): void {\n\t\tswitch (type) {\n\t\t\tcase AssetType.TEXTURE:\n\t\t\t\tthis.stats.texturesLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.GLTF:\n\t\t\tcase AssetType.FBX:\n\t\t\tcase AssetType.OBJ:\n\t\t\t\tthis.stats.modelsLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.AUDIO:\n\t\t\t\tthis.stats.audioLoaded++;\n\t\t\t\tbreak;\n\t\t\tcase AssetType.FILE:\n\t\t\tcase AssetType.JSON:\n\t\t\t\tthis.stats.filesLoaded++;\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Singleton instance export for convenience\n */\nexport const assetManager = AssetManager.getInstance();","/**\n * Texture loader adapter for the Asset Manager\n */\n\nimport { TextureLoader, Texture, RepeatWrapping, Vector2, Wrapping } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport interface TextureOptions extends AssetLoadOptions {\n\trepeat?: Vector2;\n\twrapS?: Wrapping;\n\twrapT?: Wrapping;\n}\n\nexport class TextureLoaderAdapter implements LoaderAdapter<Texture> {\n\tprivate loader: TextureLoader;\n\n\tconstructor() {\n\t\tthis.loader = new TextureLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'tga'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: TextureOptions): Promise<Texture> {\n\t\tconst texture = await this.loader.loadAsync(url, (event) => {\n\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t}\n\t\t});\n\n\t\t// Apply texture options\n\t\tif (options?.repeat) {\n\t\t\ttexture.repeat.copy(options.repeat);\n\t\t}\n\t\ttexture.wrapS = options?.wrapS ?? RepeatWrapping;\n\t\ttexture.wrapT = options?.wrapT ?? RepeatWrapping;\n\n\t\treturn texture;\n\t}\n\n\t/**\n\t * Clone a texture for independent usage\n\t */\n\tclone(texture: Texture): Texture {\n\t\tconst cloned = texture.clone();\n\t\tcloned.needsUpdate = true;\n\t\treturn cloned;\n\t}\n}\n","/**\n * GLTF loader adapter for the Asset Manager\n * Uses native fetch (already async/non-blocking in browsers) + parseAsync.\n * Automatically configures DRACOLoader for Draco-compressed meshes.\n */\n\nimport { GLTF, GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\nimport { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\nimport { cloneModelObject } from './model-clone';\n\nconst DRACO_DECODER_PATH = 'https://www.gstatic.com/draco/v1/decoders/';\n\nexport interface GLTFLoadOptions extends AssetLoadOptions {\n\t/** \n\t * Use async fetch + parseAsync pattern instead of loader.load()\n\t * Note: fetch() is already non-blocking in browsers, so this mainly\n\t * provides a cleaner async/await pattern rather than performance gains\n\t */\n\tuseAsyncFetch?: boolean;\n}\n\nexport class GLTFLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: GLTFLoader;\n\tprivate dracoLoader: DRACOLoader;\n\n\tconstructor() {\n\t\tthis.dracoLoader = new DRACOLoader();\n\t\tthis.dracoLoader.setDecoderPath(DRACO_DECODER_PATH);\n\n\t\tthis.loader = new GLTFLoader();\n\t\tthis.loader.setDRACOLoader(this.dracoLoader);\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['gltf', 'glb'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\tif (options?.useAsyncFetch) {\n\t\t\treturn this.loadWithAsyncFetch(url, options);\n\t\t}\n\t\treturn this.loadMainThread(url, options);\n\t}\n\n\t/**\n\t * Load using native fetch + parseAsync\n\t * Both fetch and parsing are async, keeping the main thread responsive\n\t */\n\tprivate async loadWithAsyncFetch(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\ttry {\n\t\t\tconst response = await fetch(url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n\t\t\t}\n\t\t\tconst buffer = await response.arrayBuffer();\n\n\t\t\t// Parse on main thread using GLTFLoader.parseAsync\n\t\t\t// The url is passed as the path for resolving relative resources\n\t\t\tconst gltf = await this.loader.parseAsync(buffer, url);\n\n\t\t\treturn {\n\t\t\t\tobject: gltf.scene,\n\t\t\t\tanimations: gltf.animations,\n\t\t\t\tgltf\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Async fetch GLTF load failed for ${url}, falling back to loader.load():`, error);\n\t\t\treturn this.loadMainThread(url, options);\n\t\t}\n\t}\n\n\tprivate async loadMainThread(url: string, options?: GLTFLoadOptions): Promise<ModelLoadResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(gltf: GLTF) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject: gltf.scene,\n\t\t\t\t\t\tanimations: gltf.animations,\n\t\t\t\t\t\tgltf\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded GLTF scene for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: cloneModelObject(result.object),\n\t\t\tanimations: result.animations?.map(anim => anim.clone()),\n\t\t\tgltf: result.gltf\n\t\t};\n\t}\n}\n","import { Material, Mesh, Object3D } from 'three';\nimport { clone as cloneSkeleton } from 'three/addons/utils/SkeletonUtils.js';\n\n/**\n * Clone a model hierarchy with independent mesh resources.\n *\n * SkeletonUtils preserves skinned mesh bindings, then we deep-clone\n * geometry/material so per-instance overrides and disposal are safe.\n */\nexport function cloneModelObject(object: Object3D): Object3D {\n\tconst clonedObject = cloneSkeleton(object);\n\tconst originalNodes: Object3D[] = [];\n\tconst clonedNodes: Object3D[] = [];\n\n\tobject.traverse((node) => originalNodes.push(node));\n\tclonedObject.traverse((node) => clonedNodes.push(node));\n\n\tfor (let i = 0; i < originalNodes.length; i++) {\n\t\tconst originalNode = originalNodes[i];\n\t\tconst clonedNode = clonedNodes[i];\n\t\tif (!(originalNode instanceof Mesh) || !(clonedNode instanceof Mesh)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (originalNode.geometry?.clone) {\n\t\t\tclonedNode.geometry = originalNode.geometry.clone();\n\t\t}\n\n\t\tif (!originalNode.material) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tclonedNode.material = Array.isArray(originalNode.material)\n\t\t\t? originalNode.material.map((material: Material) => material.clone())\n\t\t\t: originalNode.material.clone();\n\t}\n\n\treturn clonedObject;\n}\n","/**\n * FBX loader adapter for the Asset Manager\n * Uses native fetch (already async/non-blocking in browsers) + parse\n */\n\nimport { Object3D } from 'three';\nimport { FBXLoader } from 'three/addons/loaders/FBXLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\nimport { cloneModelObject } from './model-clone';\n\nexport interface FBXLoadOptions extends AssetLoadOptions {\n\t/** \n\t * Use async fetch + parse pattern instead of loader.load()\n\t * Note: fetch() is already non-blocking in browsers\n\t */\n\tuseAsyncFetch?: boolean;\n}\n\nexport class FBXLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: FBXLoader;\n\n\tconstructor() {\n\t\tthis.loader = new FBXLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'fbx';\n\t}\n\n\tasync load(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\tif (options?.useAsyncFetch) {\n\t\t\treturn this.loadWithAsyncFetch(url, options);\n\t\t}\n\t\treturn this.loadMainThread(url, options);\n\t}\n\n\t/**\n\t * Load using native fetch + parse\n\t */\n\tprivate async loadWithAsyncFetch(url: string, _options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\ttry {\n\t\t\tconst response = await fetch(url);\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);\n\t\t\t}\n\t\t\tconst buffer = await response.arrayBuffer();\n\n\t\t\t// Parse on main thread using FBXLoader.parse\n\t\t\tconst object = this.loader.parse(buffer, url);\n\n\t\t\treturn {\n\t\t\t\tobject,\n\t\t\t\tanimations: (object as any).animations || []\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tconsole.error(`Async fetch FBX load failed for ${url}, falling back to loader.load():`, error);\n\t\t\treturn this.loadMainThread(url, _options);\n\t\t}\n\t}\n\n\tprivate async loadMainThread(url: string, options?: FBXLoadOptions): Promise<ModelLoadResult> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(object: Object3D) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tanimations: (object as any).animations || []\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded FBX object for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: cloneModelObject(result.object),\n\t\t\tanimations: result.animations?.map(anim => anim.clone())\n\t\t};\n\t}\n}\n","/**\n * OBJ loader adapter for the Asset Manager\n * Supports optional MTL (material) file loading\n */\n\nimport { Object3D, Group } from 'three';\nimport { OBJLoader } from 'three/addons/loaders/OBJLoader.js';\nimport { MTLLoader } from 'three/addons/loaders/MTLLoader.js';\nimport { LoaderAdapter, AssetLoadOptions, ModelLoadResult } from '../asset-types';\nimport { cloneModelObject } from './model-clone';\n\nexport interface OBJLoadOptions extends AssetLoadOptions {\n\t/** Path to MTL material file */\n\tmtlPath?: string;\n}\n\nexport class OBJLoaderAdapter implements LoaderAdapter<ModelLoadResult> {\n\tprivate loader: OBJLoader;\n\tprivate mtlLoader: MTLLoader;\n\n\tconstructor() {\n\t\tthis.loader = new OBJLoader();\n\t\tthis.mtlLoader = new MTLLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'obj';\n\t}\n\n\tasync load(url: string, options?: OBJLoadOptions): Promise<ModelLoadResult> {\n\t\t// Load MTL first if provided\n\t\tif (options?.mtlPath) {\n\t\t\tawait this.loadMTL(options.mtlPath);\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(object: Group) => {\n\t\t\t\t\tresolve({\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tanimations: []\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async loadMTL(url: string): Promise<void> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.mtlLoader.load(\n\t\t\t\turl,\n\t\t\t\t(materials) => {\n\t\t\t\t\tmaterials.preload();\n\t\t\t\t\tthis.loader.setMaterials(materials);\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t\tundefined,\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n\n\t/**\n\t * Clone a loaded OBJ object for reuse\n\t */\n\tclone(result: ModelLoadResult): ModelLoadResult {\n\t\treturn {\n\t\t\tobject: cloneModelObject(result.object),\n\t\t\tanimations: []\n\t\t};\n\t}\n}\n","/**\n * Audio loader adapter for the Asset Manager\n */\n\nimport { AudioLoader } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport class AudioLoaderAdapter implements LoaderAdapter<AudioBuffer> {\n\tprivate loader: AudioLoader;\n\n\tconstructor() {\n\t\tthis.loader = new AudioLoader();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ['mp3', 'ogg', 'wav', 'flac', 'aac', 'm4a'].includes(ext || '');\n\t}\n\n\tasync load(url: string, options?: AssetLoadOptions): Promise<AudioBuffer> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(buffer) => resolve(buffer),\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n}\n","/**\n * File loader adapter for the Asset Manager\n */\n\nimport { FileLoader } from 'three';\nimport { LoaderAdapter, AssetLoadOptions } from '../asset-types';\n\nexport interface FileLoadOptions extends AssetLoadOptions {\n\tresponseType?: 'text' | 'arraybuffer' | 'blob' | 'json';\n}\n\nexport class FileLoaderAdapter implements LoaderAdapter<string | ArrayBuffer> {\n\tprivate loader: FileLoader;\n\n\tconstructor() {\n\t\tthis.loader = new FileLoader();\n\t}\n\n\tisSupported(_url: string): boolean {\n\t\t// FileLoader can handle any file type\n\t\treturn true;\n\t}\n\n\tasync load(url: string, options?: FileLoadOptions): Promise<string | ArrayBuffer> {\n\t\tconst responseType = options?.responseType ?? 'text';\n\t\tthis.loader.setResponseType(responseType as any);\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.loader.load(\n\t\t\t\turl,\n\t\t\t\t(data) => resolve(data as string | ArrayBuffer),\n\t\t\t\t(event) => {\n\t\t\t\t\tif (options?.onProgress && event.lengthComputable) {\n\t\t\t\t\t\toptions.onProgress(event.loaded / event.total);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(error) => reject(error)\n\t\t\t);\n\t\t});\n\t}\n}\n\n/**\n * JSON loader using FileLoader\n */\nexport class JsonLoaderAdapter implements LoaderAdapter<unknown> {\n\tprivate fileLoader: FileLoaderAdapter;\n\n\tconstructor() {\n\t\tthis.fileLoader = new FileLoaderAdapter();\n\t}\n\n\tisSupported(url: string): boolean {\n\t\tconst ext = url.split('.').pop()?.toLowerCase();\n\t\treturn ext === 'json';\n\t}\n\n\tasync load<T = unknown>(url: string, options?: AssetLoadOptions): Promise<T> {\n\t\tconst data = await this.fileLoader.load(url, { ...options, responseType: 'json' });\n\t\treturn data as T;\n\t}\n}\n","/**\n * Entity Asset Loader - Refactored to use AssetManager\n * \n * This module provides a compatibility layer for existing code that uses EntityAssetLoader.\n * All loading now goes through the centralized AssetManager for caching.\n */\n\nimport { AnimationClip, Object3D } from 'three';\nimport { GLTF } from 'three/addons/loaders/GLTFLoader.js';\nimport { assetManager } from './asset-manager';\nimport type { AssetLoadOptions } from './asset-types';\n\nexport interface AssetLoaderResult {\n\tobject?: Object3D;\n\tanimation?: AnimationClip;\n\tgltf?: GLTF;\n}\n\n/**\n * EntityAssetLoader - Uses AssetManager for all model loading\n * \n * This class is now a thin wrapper around AssetManager, providing backward\n * compatibility for existing code while benefiting from centralized caching.\n */\nexport class EntityAssetLoader {\n\t/**\n\t * Load a model file (FBX, GLTF, GLB, OBJ) using the asset manager\n\t */\n\tasync loadFile(file: string, options?: AssetLoadOptions): Promise<AssetLoaderResult> {\n\t\tconst ext = file.split('.').pop()?.toLowerCase();\n\n\t\tswitch (ext) {\n\t\t\tcase 'fbx': {\n\t\t\t\tconst result = await assetManager.loadFBX(file, options);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object,\n\t\t\t\t\tanimation: result.animations?.[0]\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase 'gltf':\n\t\t\tcase 'glb': {\n\t\t\t\tconst result = await assetManager.loadGLTF(file, options);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object,\n\t\t\t\t\tgltf: result.gltf\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase 'obj': {\n\t\t\t\tconst result = await assetManager.loadOBJ(file, options);\n\t\t\t\treturn {\n\t\t\t\t\tobject: result.object\n\t\t\t\t};\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`Unsupported file type: ${file}`);\n\t\t}\n\t}\n}\n","import {\n\tAnimationAction,\n\tAnimationClip,\n\tAnimationMixer,\n\tBone,\n\tLoopOnce,\n\tLoopRepeat,\n\tObject3D,\n} from 'three';\nimport { EntityAssetLoader, AssetLoaderResult } from '../../core/entity-asset-loader';\n\nexport type AnimationOptions = {\n\tkey: string;\n\tpauseAtEnd?: boolean;\n\tpauseAtPercentage?: number;\n\tfadeToKey?: string;\n\tfadeDuration?: number;\n};\n\ntype AnimationObject = {\n\tkey?: string;\n\tpath: string;\n};\n\nfunction getTrackTargetName(trackName: string): string {\n\tconst propertyIndex = trackName.lastIndexOf('.');\n\treturn propertyIndex >= 0 ? trackName.slice(0, propertyIndex) : trackName;\n}\n\nfunction shouldStripRootMotion(track: any, targetByName: Map<string, Object3D>): boolean {\n\tif (!track?.name?.endsWith('.position')) {\n\t\treturn false;\n\t}\n\n\tconst targetName = getTrackTargetName(track.name);\n\tconst target = targetByName.get(targetName);\n\tif (target instanceof Bone) {\n\t\treturn !(target.parent instanceof Bone);\n\t}\n\n\treturn /hips\\.position$/i.test(track.name) || /root\\.position$/i.test(track.name);\n}\n\nfunction stripClipRootMotion(\n\tclip: AnimationClip,\n\ttargetByName: Map<string, Object3D>,\n): AnimationClip {\n\tfor (const track of clip.tracks) {\n\t\tif (!shouldStripRootMotion(track, targetByName)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!track.values || track.values.length < 3) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst baseX = track.values[0];\n\t\tconst baseZ = track.values[2];\n\t\tfor (let i = 0; i < track.values.length; i += 3) {\n\t\t\ttrack.values[i] = baseX;\n\t\t\ttrack.values[i + 2] = baseZ;\n\t\t}\n\t}\n\n\treturn clip;\n}\n\nexport class AnimationDelegate {\n\tprivate _mixer: AnimationMixer | null = null;\n\tprivate _actions: Record<string, AnimationAction> = {};\n\tprivate _animations: AnimationClip[] = [];\n\tprivate _currentAction: AnimationAction | null = null;\n\n\tprivate _pauseAtPercentage = 0;\n\tprivate _isPaused = false;\n\tprivate _queuedKey: string | null = null;\n\tprivate _fadeDuration = 0.5;\n\n\tprivate _currentKey: string = '';\n\tprivate _assetLoader = new EntityAssetLoader();\n\n\tconstructor(private target: Object3D) { }\n\n\tasync loadAnimations(animations: AnimationObject[]): Promise<void> {\n\t\tif (!animations.length) return;\n\n\t\tconst results = await Promise.all(animations.map(a => this._assetLoader.loadFile(a.path)));\n\t\tconst targetByName = new Map<string, Object3D>();\n\t\tthis.target.traverse((node) => {\n\t\t\tif (node.name) {\n\t\t\t\ttargetByName.set(node.name, node);\n\t\t\t}\n\t\t});\n\t\t\n\t\t// Build animations list while preserving original key mapping\n\t\t// Filter to only successful loads and pair with their original keys\n\t\tconst loadedAnimations: { key: string; clip: AnimationClip }[] = [];\n\t\tresults.forEach((result, i) => {\n\t\t\tif (result.animation) {\n\t\t\t\tloadedAnimations.push({\n\t\t\t\t\tkey: animations[i].key || i.toString(),\n\t\t\t\t\tclip: stripClipRootMotion(result.animation, targetByName),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tif (!loadedAnimations.length) return;\n\n\t\tthis._animations = loadedAnimations.map(a => a.clip);\n\t\tthis._mixer = new AnimationMixer(this.target);\n\t\t\n\t\t// Create actions with correct key mapping\n\t\tloadedAnimations.forEach(({ key, clip }) => {\n\t\t\tthis._actions[key] = this._mixer!.clipAction(clip);\n\t\t});\n\n\t\tthis.playAnimation({ key: loadedAnimations[0].key });\n\t}\n\n\tupdate(delta: number): void {\n\t\tif (!this._mixer || !this._currentAction) return;\n\n\t\tthis._mixer.update(delta);\n\n\t\tconst pauseAtTime = this._currentAction.getClip().duration * (this._pauseAtPercentage / 100);\n\t\tif (\n\t\t\t!this._isPaused &&\n\t\t\tthis._pauseAtPercentage > 0 &&\n\t\t\tthis._currentAction.time >= pauseAtTime\n\t\t) {\n\t\t\tthis._currentAction.time = pauseAtTime;\n\t\t\tthis._currentAction.paused = true;\n\t\t\tthis._isPaused = true;\n\n\t\t\tif (this._queuedKey !== null) {\n\t\t\t\tconst next = this._actions[this._queuedKey];\n\t\t\t\tnext.reset().play();\n\t\t\t\tthis._currentAction.crossFadeTo(next, this._fadeDuration, false);\n\t\t\t\tthis._currentAction = next;\n\t\t\t\tthis._currentKey = this._queuedKey;\n\t\t\t\tthis._queuedKey = null;\n\t\t\t}\n\t\t}\n\t}\n\n\tplayAnimation(opts: AnimationOptions): void {\n\t\tif (!this._mixer) return;\n\t\tconst { key, pauseAtPercentage = 0, pauseAtEnd = false, fadeToKey, fadeDuration = 0.5 } = opts;\n\t\tif (key === this._currentKey) return;\n\n\t\t// Check if the new action exists BEFORE stopping the current animation\n\t\t// This prevents T-posing when an animation key doesn't exist\n\t\tconst action = this._actions[key];\n\t\tif (!action) return;\n\n\t\tthis._queuedKey = fadeToKey || null;\n\t\tthis._fadeDuration = fadeDuration;\n\n\t\tthis._pauseAtPercentage = pauseAtEnd ? 100 : pauseAtPercentage;\n\t\tthis._isPaused = false;\n\n\t\tconst prev = this._currentAction;\n\t\t// Don't stop prev here - crossFadeTo needs it playing for smooth transition\n\n\t\tif (this._pauseAtPercentage > 0) {\n\t\t\taction.setLoop(LoopOnce, Infinity);\n\t\t\taction.clampWhenFinished = true;\n\t\t} else {\n\t\t\taction.setLoop(LoopRepeat, Infinity);\n\t\t\taction.clampWhenFinished = false;\n\t\t}\n\n\t\t// Start the new action\n\t\taction.reset().play();\n\n\t\t// Crossfade from previous if it exists\n\t\tif (prev) {\n\t\t\tprev.crossFadeTo(action, fadeDuration, false);\n\t\t}\n\n\t\tthis._currentAction = action;\n\t\tthis._currentKey = key;\n\t}\n\n\t/**\n\t * Dispose of all animation resources\n\t */\n\tdispose(): void {\n\t\t// Stop all actions\n\t\tObject.values(this._actions).forEach(action => {\n\t\t\taction.stop();\n\t\t});\n\n\t\t// Stop and uncache mixer\n\t\tif (this._mixer) {\n\t\t\tthis._mixer.stopAllAction();\n\t\t\tthis._mixer.uncacheRoot(this.target);\n\t\t\tthis._mixer = null;\n\t\t}\n\n\t\t// Clear references\n\t\tthis._actions = {};\n\t\tthis._animations = [];\n\t\tthis._currentAction = null;\n\t\tthis._currentKey = '';\n\t}\n\n\tget currentAnimationKey() { return this._currentKey; }\n\tget animations() { return this._animations; }\n}\n","import { Color, Material, Vector2, Vector3 } from 'three';\nimport {\n\tMeshPhongMaterial,\n\tMeshStandardMaterial,\n\tRepeatWrapping,\n\tShaderMaterial,\n} from 'three';\nimport {\n\tMeshBasicNodeMaterial,\n\tMeshStandardNodeMaterial,\n} from 'three/webgpu';\nimport { shortHash, sortedStringify } from '../core/utility/strings';\nimport { standardShader } from './shaders/standard.shader';\nimport { assetManager } from '../core/asset-manager';\n\n/**\n * GLSL shader object (traditional approach for WebGL)\n */\nexport type ZylemShaderObject = { fragment: string; vertex: string };\n\n/**\n * TSL shader type (for WebGPU)\n * colorNode should be a TSL node that returns the fragment color\n */\nexport type ZylemTSLShader = {\n\tcolorNode: any; // TSL node - use any since Three.js types are still evolving\n\ttransparent?: boolean;\n};\n\n/**\n * Combined shader type supporting both GLSL and TSL\n */\nexport type ZylemShader = ZylemShaderObject | ZylemTSLShader;\n\n/**\n * Check if a shader is a TSL shader\n */\nexport function isTSLShader(shader: ZylemShader): shader is ZylemTSLShader {\n\treturn 'colorNode' in shader;\n}\n\n/**\n * Check if a shader is a GLSL shader\n */\nexport function isGLSLShader(shader: ZylemShader): shader is ZylemShaderObject {\n\treturn 'fragment' in shader && 'vertex' in shader;\n}\n\nexport interface MaterialOptions {\n\tpath?: string;\n\tnormalMap?: string;\n\trepeat?: Vector2;\n\tshader?: ZylemShader;\n\tcolor?: Color;\n\t/** Opacity from 0 (fully transparent) to 1 (fully opaque). */\n\topacity?: number;\n\t/**\n\t * When true, prefer TSL/NodeMaterial (for WebGPU)\n\t * When false, prefer GLSL/ShaderMaterial (for WebGL)\n\t */\n\tuseTSL?: boolean;\n}\n\ntype BatchGeometryMap = Map<symbol, number>;\n\ninterface BatchMaterialMapObject {\n\tgeometryMap: BatchGeometryMap;\n\tmaterial: Material;\n}\n\ntype BatchKey = ReturnType<typeof shortHash>;\n\nexport type TexturePath = string | null;\n\ntype OpacityCapableMaterial = Material & {\n\topacity: number;\n\ttransparent: boolean;\n\tneedsUpdate: boolean;\n};\n\nexport class MaterialBuilder {\n\tstatic batchMaterialMap: Map<BatchKey, BatchMaterialMapObject> = new Map();\n\n\t/**\n\t * Clear the static batch material cache.\n\t * Should be called during game disposal to prevent stale material references\n\t * from persisting across demo/stage switches.\n\t */\n\tstatic clearBatchCache(): void {\n\t\tMaterialBuilder.batchMaterialMap.clear();\n\t}\n\n\tmaterials: Material[] = [];\n\n\t/** Whether to use TSL/NodeMaterial (for WebGPU compatibility) */\n\tprivate useTSL: boolean;\n\n\tconstructor(useTSL: boolean = false) {\n\t\tthis.useTSL = useTSL;\n\t}\n\n\tbatchMaterial(options: Partial<MaterialOptions>, entityType: symbol) {\n\t\tconst batchKey = shortHash(sortedStringify(options));\n\t\tconst mappedObject = MaterialBuilder.batchMaterialMap.get(batchKey);\n\t\tif (mappedObject) {\n\t\t\tconst count = mappedObject.geometryMap.get(entityType);\n\t\t\tif (count) {\n\t\t\t\tmappedObject.geometryMap.set(entityType, count + 1);\n\t\t\t} else {\n\t\t\t\tmappedObject.geometryMap.set(entityType, 1);\n\t\t\t}\n\t\t} else {\n\t\t\tMaterialBuilder.batchMaterialMap.set(batchKey, {\n\t\t\t\tgeometryMap: new Map([[entityType, 1]]),\n\t\t\t\tmaterial: this.materials[0],\n\t\t\t});\n\t\t}\n\t}\n\n\tbuild(options: Partial<MaterialOptions>, entityType: symbol): void {\n\t\tconst { path, normalMap, repeat, color, shader, opacity, useTSL } = options;\n\t\t\n\t\t// Override TSL preference if specified in options\n\t\tconst shouldUseTSL = useTSL ?? this.useTSL;\n\n\t\t// If shader is provided, use it\n\t\tif (shader) {\n\t\t\tif (isTSLShader(shader)) {\n\t\t\t\t// TSL shader provided directly\n\t\t\t\tthis.setTSLShader(shader, opacity);\n\t\t\t} else if (isGLSLShader(shader)) {\n\t\t\t\t// GLSL shader provided\n\t\t\t\tif (shouldUseTSL) {\n\t\t\t\t\tconsole.warn('MaterialBuilder: GLSL shader provided but TSL mode requested. Using GLSL.');\n\t\t\t\t}\n\t\t\t\tthis.setShader(shader, opacity);\n\t\t\t}\n\t\t} else if (path) {\n\t\t\t// Texture path provided\n\t\t\tthis.setTexture(path, repeat, shouldUseTSL, opacity);\n\t\t}\n\n\t\tif (color) {\n\t\t\tthis.withColor(color, shouldUseTSL, opacity);\n\t\t}\n\n\t\tif (this.materials.length === 0) {\n\t\t\tthis.setColor(new Color('#ffffff'), shouldUseTSL, opacity);\n\t\t}\n\n\t\t// Apply normal map if present (to the last added material)\n\t\tif (normalMap && this.materials.length > 0) {\n\t\t\tthis.setNormalMap(normalMap, repeat);\n\t\t}\n\n\t\tthis.batchMaterial(options, entityType);\n\t}\n\n\twithColor(color: Color, useTSL: boolean = false, opacity?: number): this {\n\t\tthis.setColor(color, useTSL, opacity);\n\t\treturn this;\n\t}\n\n\twithShader(shader: ZylemShaderObject, opacity?: number): this {\n\t\tthis.setShader(shader, opacity);\n\t\treturn this;\n\t}\n\n\twithTSLShader(shader: ZylemTSLShader, opacity?: number): this {\n\t\tthis.setTSLShader(shader, opacity);\n\t\treturn this;\n\t}\n\n\tprivate applyOpacity(material: OpacityCapableMaterial, opacity?: number, forceTransparent: boolean = false): void {\n\t\tif (opacity !== undefined) {\n\t\t\tmaterial.opacity = opacity;\n\t\t}\n\t\tmaterial.transparent = forceTransparent || opacity !== undefined && opacity < 1;\n\t\tmaterial.needsUpdate = true;\n\t}\n\n\t/**\n\t * Set texture - loads in background (deferred).\n\t * Material is created immediately with null map, texture applies when loaded.\n\t */\n\tsetTexture(\n\t\ttexturePath: TexturePath = null,\n\t\trepeat: Vector2 = new Vector2(1, 1),\n\t\tuseTSL: boolean = false,\n\t\topacity?: number,\n\t): void {\n\t\tif (!texturePath) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (useTSL) {\n\t\t\t// For TSL/WebGPU, use NodeMaterial\n\t\t\tconst material = new MeshStandardNodeMaterial();\n\t\t\tthis.applyOpacity(material as OpacityCapableMaterial, opacity);\n\t\t\tthis.materials.push(material);\n\n\t\t\t// Load texture in background and apply when ready\n\t\t\tassetManager.loadTexture(texturePath as string, {\n\t\t\t\tclone: true,\n\t\t\t\trepeat,\n\t\t\t}).then((texture) => {\n\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\tmaterial.map = texture;\n\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t});\n\t\t} else {\n\t\t\t// For WebGL, use traditional material\n\t\t\tconst material = new MeshPhongMaterial({\n\t\t\t\tmap: null,\n\t\t\t\topacity: opacity ?? 1,\n\t\t\t\ttransparent: opacity !== undefined && opacity < 1,\n\t\t\t});\n\t\t\tthis.materials.push(material);\n\n\t\t\t// Load texture in background and apply when ready\n\t\t\tassetManager\n\t\t\t\t.loadTexture(texturePath as string, {\n\t\t\t\t\tclone: true,\n\t\t\t\t\trepeat,\n\t\t\t\t})\n\t\t\t\t.then((texture) => {\n\t\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\t\tmaterial.map = texture;\n\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Set normal map for the current material\n\t */\n\tsetNormalMap(normalMapPath: string, repeat: Vector2 = new Vector2(1, 1)): void {\n\t\tconst material = this.materials[this.materials.length - 1];\n\t\tif (!material) return;\n\n\t\tassetManager\n\t\t\t.loadTexture(normalMapPath, {\n\t\t\t\tclone: true,\n\t\t\t\trepeat,\n\t\t\t})\n\t\t\t.then((texture) => {\n\t\t\t\ttexture.wrapS = RepeatWrapping;\n\t\t\t\ttexture.wrapT = RepeatWrapping;\n\t\t\t\t\n\t\t\t\tif (material instanceof MeshStandardMaterial \n\t\t\t\t\t|| material instanceof MeshPhongMaterial\n\t\t\t\t\t|| material instanceof MeshStandardNodeMaterial) {\n\t\t\t\t\tmaterial.normalMap = texture;\n\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t} else if (material instanceof ShaderMaterial) {\n\t\t\t\t\t// Support for custom shaders if they have tNormal or normalMap uniform\n\t\t\t\t\tif (material.uniforms.tNormal) {\n\t\t\t\t\t\tmaterial.uniforms.tNormal.value = texture;\n\t\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (material.uniforms.normalMap) {\n\t\t\t\t\t\tmaterial.uniforms.normalMap.value = texture;\n\t\t\t\t\t\tmaterial.needsUpdate = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t}\n\n\tsetColor(color: Color, useTSL: boolean = false, opacity?: number) {\n\t\tif (useTSL) {\n\t\t\t// TSL/WebGPU compatible material\n\t\t\tconst material = new MeshStandardNodeMaterial();\n\t\t\tmaterial.color = color;\n\t\t\tthis.applyOpacity(material as OpacityCapableMaterial, opacity);\n\t\t\tthis.materials.push(material);\n\t\t} else {\n\t\t\t// WebGL compatible material\n\t\t\tconst material = new MeshStandardMaterial({\n\t\t\t\tcolor: color,\n\t\t\t\temissiveIntensity: 0.5,\n\t\t\t\tlightMapIntensity: 0.5,\n\t\t\t\tfog: true,\n\t\t\t\topacity: opacity ?? 1,\n\t\t\t\ttransparent: opacity !== undefined && opacity < 1,\n\t\t\t});\n\t\t\tthis.materials.push(material);\n\t\t}\n\t}\n\n\t/**\n\t * Set GLSL shader (WebGL only)\n\t */\n\tsetShader(customShader: ZylemShaderObject, opacity?: number) {\n\t\tconst { fragment, vertex } = customShader ?? standardShader;\n\n\t\tconst shader = new ShaderMaterial({\n\t\t\tuniforms: {\n\t\t\t\tiResolution: { value: new Vector3(1, 1, 1) },\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\tnormalMap: { value: null },\n\t\t\t\tlightDir: { value: new Vector3(1, 1, 1) },\n\t\t\t\tnormalStrength: { value: 1.0 },\n\t\t\t},\n\t\t\tvertexShader: vertex,\n\t\t\tfragmentShader: fragment,\n\t\t\ttransparent: true,\n\t\t\topacity: opacity ?? 1,\n\t\t});\n\t\tthis.materials.push(shader);\n\t}\n\n\t/**\n\t * Set TSL shader (WebGPU compatible)\n\t */\n\tsetTSLShader(tslShader: ZylemTSLShader, opacity?: number) {\n\t\tconst material = new MeshBasicNodeMaterial();\n\t\tmaterial.colorNode = tslShader.colorNode;\n\t\tthis.applyOpacity(\n\t\t\tmaterial as OpacityCapableMaterial,\n\t\t\topacity,\n\t\t\ttslShader.transparent,\n\t\t);\n\t\tthis.materials.push(material);\n\t}\n}\n\n// Re-export TSL utilities for shader authoring\nexport {\n\tuniform,\n\tuv,\n\ttime,\n\tvec3,\n\tvec4,\n\tfloat,\n\tFn,\n} from 'three/tsl';\n","export function sortedStringify(obj: Record<string, any>) {\n\tconst sortedObj = Object.keys(obj)\n\t\t.sort()\n\t\t.reduce((acc: Record<string, any>, key: string) => {\n\t\t\tacc[key] = obj[key];\n\t\t\treturn acc;\n\t\t}, {} as Record<string, any>);\n\n\treturn JSON.stringify(sortedObj);\n}\n\nexport function shortHash(objString: string) {\n\tlet hash = 0;\n\tfor (let i = 0; i < objString.length; i++) {\n\t\thash = Math.imul(31, hash) + objString.charCodeAt(i) | 0;\n\t}\n\treturn hash.toString(36);\n}","/**\n * Message protocol for communication between the main thread and the\n * physics Web Worker.\n *\n * Data flows in two directions:\n * Main → Worker: {@link PhysicsCommand} (init, entity CRUD, per-frame step)\n * Worker → Main: {@link PhysicsEvent} (ready, step results, errors)\n *\n * All types are plain JSON-serializable objects so they can cross the\n * postMessage boundary without structured-clone issues.\n */\n\n// ─── Serializable Descriptor Types ─────────────────────────────────────────\n\n/** Rigid body type mirroring Rapier's RigidBodyType enum values. */\nexport type SerializableBodyType = 'dynamic' | 'fixed' | 'kinematicPositionBased' | 'kinematicVelocityBased';\n\n/**\n * Plain-object representation of a Rapier RigidBodyDesc.\n * Created on the main thread and reconstructed in the worker.\n */\nexport interface SerializableBodyDesc {\n\ttype: SerializableBodyType;\n\ttranslation: [number, number, number];\n\tgravityScale: number;\n\tcanSleep: boolean;\n\tccdEnabled: boolean;\n\tlockTranslations?: boolean;\n\tlockRotations?: boolean;\n}\n\n/** Collider shape kind. Matches the factory functions in collision-factories. */\nexport type ColliderShapeKind =\n\t| 'cuboid'\n\t| 'ball'\n\t| 'capsule'\n\t| 'cone'\n\t| 'cylinder'\n\t| 'trimesh'\n\t| 'heightfield';\n\n/**\n * Plain-object representation of a Rapier ColliderDesc.\n * Shape-specific dimensions are stored in {@link dimensions}.\n */\nexport interface SerializableColliderDesc {\n\tshape: ColliderShapeKind;\n\t/** Shape-specific numeric dimensions (e.g. halfExtents, radius, halfHeight). */\n\tdimensions: number[];\n\t/** For trimesh: flattened xyz vertex array. */\n\tvertices?: number[];\n\t/** For trimesh: triangle indices referencing {@link vertices}. */\n\tindices?: number[];\n\t/** Collider offset translation relative to the body. */\n\ttranslation?: [number, number, number];\n\tsensor?: boolean;\n\tcollisionGroups?: number;\n\tactiveCollisionTypes?: number;\n\t/** For heightfield: number of rows and columns. */\n\theightfieldMeta?: { nrows: number; ncols: number };\n}\n\n/** Describes a character controller to be created alongside the body. */\nexport interface SerializableCharacterController {\n\toffset: number;\n\tmaxSlopeClimbAngle: number;\n\tminSlopeSlideAngle: number;\n\tsnapToGroundDistance: number;\n\tslideEnabled: boolean;\n\tapplyImpulsesToDynamic: boolean;\n\tcharacterMass: number;\n}\n\n// ─── Per-Body Commands (batched inside a step) ─────────────────────────────\n\nexport type BodyCommand =\n\t| { kind: 'setLinvel'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setAngvel'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setTranslation'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'setRotation'; uuid: string; x: number; y: number; z: number; w: number }\n\t| { kind: 'applyImpulse'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'applyTorqueImpulse'; uuid: string; x: number; y: number; z: number }\n\t| { kind: 'lockTranslations'; uuid: string; locked: boolean }\n\t| { kind: 'lockRotations'; uuid: string; locked: boolean }\n\t| { kind: 'addTranslation'; uuid: string; dx: number; dy: number; dz: number }\n\t| { kind: 'setLinearDamping'; uuid: string; damping: number }\n\t| { kind: 'setGravityScale'; uuid: string; scale: number };\n\n// ─── Main → Worker Commands ────────────────────────────────────────────────\n\nexport type PhysicsCommand =\n\t| PhysicsInitCommand\n\t| PhysicsAddBodyCommand\n\t| PhysicsRemoveBodyCommand\n\t| PhysicsStepCommand\n\t| PhysicsDisposeCommand;\n\nexport interface PhysicsInitCommand {\n\ttype: 'init';\n\tgravity: [number, number, number];\n\tphysicsRate: number;\n}\n\nexport interface PhysicsAddBodyCommand {\n\ttype: 'addBody';\n\tuuid: string;\n\tbody: SerializableBodyDesc;\n\tcolliders: SerializableColliderDesc[];\n\tcharacterController?: SerializableCharacterController;\n}\n\nexport interface PhysicsRemoveBodyCommand {\n\ttype: 'removeBody';\n\tuuid: string;\n}\n\nexport interface PhysicsStepCommand {\n\ttype: 'step';\n\tdelta: number;\n\tcommands: BodyCommand[];\n}\n\nexport interface PhysicsDisposeCommand {\n\ttype: 'dispose';\n}\n\n// ─── Worker → Main Events ──────────────────────────────────────────────────\n\nexport type PhysicsEvent =\n\t| PhysicsReadyEvent\n\t| PhysicsStepResultEvent\n\t| PhysicsErrorEvent;\n\nexport interface PhysicsReadyEvent {\n\ttype: 'ready';\n}\n\n/**\n * Result of a physics step sent from the worker each frame.\n *\n * `transforms` is a flat Float32Array with 13 floats per body:\n * [posX, posY, posZ, rotX, rotY, rotZ, rotW, linvelX, linvelY, linvelZ, angvelX, angvelY, angvelZ]\n *\n * The order matches {@link bodyOrder} — an array of UUIDs in the same\n * index order as the transform buffer.\n */\nexport interface PhysicsStepResultEvent {\n\ttype: 'stepResult';\n\t/** Flat buffer: 13 floats per body (pos3, rot4, linvel3, angvel3). */\n\ttransforms: Float32Array;\n\t/** UUID order matching the transforms buffer. */\n\tbodyOrder: string[];\n\t/** Collision pairs detected this frame. */\n\tcollisions: CollisionPair[];\n\t/** Interpolation alpha for rendering (0..1). */\n\tinterpolationAlpha: number;\n}\n\nexport interface PhysicsErrorEvent {\n\ttype: 'error';\n\tmessage: string;\n}\n\n/** A collision pair detected during the physics step. */\nexport interface CollisionPair {\n\tuuidA: string;\n\tuuidB: string;\n\tcontactType: 'contact' | 'intersection';\n}\n\n// ─── Transform Buffer Layout ───────────────────────────────────────────────\n\n/** Number of floats per body in the transforms buffer. */\nexport const FLOATS_PER_BODY = 13;\n\n/** Offsets into the per-body segment of the transforms buffer. */\nexport const TransformOffset = {\n\tPOS_X: 0,\n\tPOS_Y: 1,\n\tPOS_Z: 2,\n\tROT_X: 3,\n\tROT_Y: 4,\n\tROT_Z: 5,\n\tROT_W: 6,\n\tLINVEL_X: 7,\n\tLINVEL_Y: 8,\n\tLINVEL_Z: 9,\n\tANGVEL_X: 10,\n\tANGVEL_Y: 11,\n\tANGVEL_Z: 12,\n} as const;\n","import type { BodyCommand } from './physics-protocol';\nimport {\n\tcreatePhysicsPose,\n\tinterpolatePhysicsPose,\n\ttype PhysicsPose,\n\ttype PhysicsPoseHistory,\n\ttype PhysicsQuaternion,\n\ttype PhysicsVector3,\n} from './physics-pose';\n\n/**\n * Lightweight read-only view of a physics body's state.\n *\n * These values are synced from the worker each frame and represent\n * the body's state after the latest physics step.\n */\nexport interface PhysicsSnapshot {\n\tprevious: PhysicsPose;\n\tcurrent: PhysicsPose;\n\tlinvel: { x: number; y: number; z: number };\n\tangvel: { x: number; y: number; z: number };\n}\n\n/**\n * Main-thread handle for a physics body that lives in a Web Worker.\n *\n * Provides the same read interface as a Rapier RigidBody (translation,\n * rotation, linvel, angvel) by returning cached values that are synced\n * from the worker each frame.\n *\n * Write operations (setLinvel, setTranslation, etc.) are queued as\n * {@link BodyCommand}s and sent to the worker on the next step.\n */\nexport class PhysicsBodyHandle {\n\treadonly uuid: string;\n\n\t/** Last-known physics state, updated from worker each frame. */\n\tprivate _snapshot: PhysicsSnapshot = {\n\t\tprevious: createPhysicsPose(),\n\t\tcurrent: createPhysicsPose(),\n\t\tlinvel: { x: 0, y: 0, z: 0 },\n\t\tangvel: { x: 0, y: 0, z: 0 },\n\t};\n\n\t/** Queued commands to be sent to the worker on next step. */\n\tprivate _pendingCommands: BodyCommand[] = [];\n\n\t/** Optional reference to the proxy's shared command queue. */\n\tprivate _sharedQueue: BodyCommand[] | null = null;\n\n\tconstructor(uuid: string, sharedQueue?: BodyCommand[]) {\n\t\tthis.uuid = uuid;\n\t\tthis._sharedQueue = sharedQueue ?? null;\n\t}\n\n\t// ─── Read API (returns cached values) ────────────────────────────────\n\n\t/** Cached position from last physics step. */\n\ttranslation(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.current.position;\n\t}\n\n\t/** Cached rotation quaternion from last physics step. */\n\trotation(): { x: number; y: number; z: number; w: number } {\n\t\treturn this._snapshot.current.rotation;\n\t}\n\n\t/** Cached linear velocity from last physics step. */\n\tlinvel(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.linvel;\n\t}\n\n\t/** Cached angular velocity from last physics step. */\n\tangvel(): { x: number; y: number; z: number } {\n\t\treturn this._snapshot.angvel;\n\t}\n\n\tgetPoseHistory(): PhysicsPoseHistory {\n\t\treturn this._snapshot;\n\t}\n\n\tgetRenderPose(alpha: number): PhysicsPose {\n\t\treturn interpolatePhysicsPose(\n\t\t\tthis._snapshot.previous,\n\t\t\tthis._snapshot.current,\n\t\t\talpha,\n\t\t);\n\t}\n\n\t// ─── Write API (queues commands) ─────────────────────────────────────\n\n\tsetLinvel(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setLinvel', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis._snapshot.linvel = { ...v };\n\t}\n\n\tsetAngvel(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setAngvel', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis._snapshot.angvel = { ...v };\n\t}\n\n\tsetTranslation(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setTranslation', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t\tthis.setCollapsedTranslation(v);\n\t}\n\n\tsetRotation(q: { x: number; y: number; z: number; w: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setRotation', uuid: this.uuid, x: q.x, y: q.y, z: q.z, w: q.w });\n\t\tthis.setCollapsedRotation(q);\n\t}\n\n\tapplyImpulse(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'applyImpulse', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t}\n\n\tapplyTorqueImpulse(v: { x: number; y: number; z: number }, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'applyTorqueImpulse', uuid: this.uuid, x: v.x, y: v.y, z: v.z });\n\t}\n\n\tlockTranslations(locked: boolean, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'lockTranslations', uuid: this.uuid, locked });\n\t}\n\n\tlockRotations(locked: boolean, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'lockRotations', uuid: this.uuid, locked });\n\t}\n\n\tsetLinearDamping(damping: number): void {\n\t\tthis.enqueue({ kind: 'setLinearDamping', uuid: this.uuid, damping });\n\t}\n\n\tsetGravityScale(scale: number, _wakeUp?: boolean): void {\n\t\tthis.enqueue({ kind: 'setGravityScale', uuid: this.uuid, scale });\n\t}\n\n\t// ─── Stubbed read-only methods for compatibility ─────────────────────\n\n\t/** Returns 'Dynamic' for compatibility; actual type is not synced. */\n\tbodyType(): number {\n\t\treturn 0;\n\t}\n\n\tmass(): number {\n\t\treturn 1;\n\t}\n\n\tisEnabled(): boolean {\n\t\treturn true;\n\t}\n\n\tisSleeping(): boolean {\n\t\treturn false;\n\t}\n\n\t/** Collider access is not available through the handle. Returns null. */\n\tcollider(_index: number): null {\n\t\treturn null;\n\t}\n\n\t// ─── Internal ────────────────────────────────────────────────────────\n\n\t/**\n\t * Update the cached snapshot from worker data.\n\t * Called by the PhysicsProxy after receiving a stepResult.\n\t */\n\t_seedSnapshot(\n\t\tpx: number,\n\t\tpy: number,\n\t\tpz: number,\n\t\trx: number,\n\t\try: number,\n\t\trz: number,\n\t\trw: number,\n\t\tlvx: number,\n\t\tlvy: number,\n\t\tlvz: number,\n\t\tavx: number,\n\t\tavy: number,\n\t\tavz: number,\n\t): void {\n\t\tthis.writePose(this._snapshot.previous, px, py, pz, rx, ry, rz, rw);\n\t\tthis.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);\n\t\tthis._snapshot.linvel.x = lvx;\n\t\tthis._snapshot.linvel.y = lvy;\n\t\tthis._snapshot.linvel.z = lvz;\n\t\tthis._snapshot.angvel.x = avx;\n\t\tthis._snapshot.angvel.y = avy;\n\t\tthis._snapshot.angvel.z = avz;\n\t}\n\n\t_updateSnapshot(\n\t\tpx: number, py: number, pz: number,\n\t\trx: number, ry: number, rz: number, rw: number,\n\t\tlvx: number, lvy: number, lvz: number,\n\t\tavx: number, avy: number, avz: number,\n\t): void {\n\t\tthis.copyPose(this._snapshot.current, this._snapshot.previous);\n\t\tthis.writePose(this._snapshot.current, px, py, pz, rx, ry, rz, rw);\n\t\tthis._snapshot.linvel.x = lvx;\n\t\tthis._snapshot.linvel.y = lvy;\n\t\tthis._snapshot.linvel.z = lvz;\n\t\tthis._snapshot.angvel.x = avx;\n\t\tthis._snapshot.angvel.y = avy;\n\t\tthis._snapshot.angvel.z = avz;\n\t}\n\n\t/** Drain pending commands. */\n\t_drainCommands(): BodyCommand[] {\n\t\tconst cmds = this._pendingCommands;\n\t\tthis._pendingCommands = [];\n\t\treturn cmds;\n\t}\n\n\tprivate enqueue(cmd: BodyCommand): void {\n\t\tif (this._sharedQueue) {\n\t\t\tthis._sharedQueue.push(cmd);\n\t\t} else {\n\t\t\tthis._pendingCommands.push(cmd);\n\t\t}\n\t}\n\n\tprivate copyPose(source: PhysicsPose, target: PhysicsPose): void {\n\t\ttarget.position.x = source.position.x;\n\t\ttarget.position.y = source.position.y;\n\t\ttarget.position.z = source.position.z;\n\t\ttarget.rotation.x = source.rotation.x;\n\t\ttarget.rotation.y = source.rotation.y;\n\t\ttarget.rotation.z = source.rotation.z;\n\t\ttarget.rotation.w = source.rotation.w;\n\t}\n\n\tprivate writePose(\n\t\ttarget: PhysicsPose,\n\t\tpx: number,\n\t\tpy: number,\n\t\tpz: number,\n\t\trx: number,\n\t\try: number,\n\t\trz: number,\n\t\trw: number,\n\t): void {\n\t\ttarget.position.x = px;\n\t\ttarget.position.y = py;\n\t\ttarget.position.z = pz;\n\t\ttarget.rotation.x = rx;\n\t\ttarget.rotation.y = ry;\n\t\ttarget.rotation.z = rz;\n\t\ttarget.rotation.w = rw;\n\t}\n\n\tprivate setCollapsedTranslation(translation: PhysicsVector3): void {\n\t\tthis._snapshot.previous.position.x = translation.x;\n\t\tthis._snapshot.previous.position.y = translation.y;\n\t\tthis._snapshot.previous.position.z = translation.z;\n\t\tthis._snapshot.current.position.x = translation.x;\n\t\tthis._snapshot.current.position.y = translation.y;\n\t\tthis._snapshot.current.position.z = translation.z;\n\t}\n\n\tprivate setCollapsedRotation(rotation: PhysicsQuaternion): void {\n\t\tthis._snapshot.previous.rotation.x = rotation.x;\n\t\tthis._snapshot.previous.rotation.y = rotation.y;\n\t\tthis._snapshot.previous.rotation.z = rotation.z;\n\t\tthis._snapshot.previous.rotation.w = rotation.w;\n\t\tthis._snapshot.current.rotation.x = rotation.x;\n\t\tthis._snapshot.current.rotation.y = rotation.y;\n\t\tthis._snapshot.current.rotation.z = rotation.z;\n\t\tthis._snapshot.current.rotation.w = rotation.w;\n\t}\n}\n","import type {\n\tPhysicsCommand,\n\tPhysicsEvent,\n\tPhysicsStepResultEvent,\n\tPhysicsAddBodyCommand,\n\tBodyCommand,\n\tCollisionPair,\n\tSerializableBodyDesc,\n\tSerializableColliderDesc,\n\tSerializableCharacterController,\n} from './physics-protocol';\nimport { FLOATS_PER_BODY, TransformOffset } from './physics-protocol';\nimport { PhysicsBodyHandle } from './physics-body-handle';\n\n/**\n * Callback signature for collision events dispatched by the proxy.\n */\nexport type CollisionCallback = (pair: CollisionPair) => void;\n\n/**\n * Main-thread proxy that communicates with the physics Web Worker.\n *\n * Usage:\n * ```ts\n * const proxy = new PhysicsProxy();\n * await proxy.init([0, -9.81, 0], 60);\n * const handle = proxy.addBody(uuid, bodyDesc, colliderDescs);\n * // each frame:\n * await proxy.step(delta);\n * ```\n *\n * The proxy owns the worker lifecycle and manages body handles.\n * After each step, all handles are updated with fresh transform data\n * and collision callbacks are fired.\n */\nexport class PhysicsProxy {\n\tprivate worker: Worker | null = null;\n\tprivate handles = new Map<string, PhysicsBodyHandle>();\n\tprivate commandQueue: BodyCommand[] = [];\n\tprivate collisionListeners: CollisionCallback[] = [];\n\tprivate pendingStep: {\n\t\tresolve: (result: PhysicsStepResultEvent) => void;\n\t\treject: (err: Error) => void;\n\t} | null = null;\n\n\t/** Latest interpolation alpha from the worker (0..1). */\n\tinterpolationAlpha = 0;\n\n\t/**\n\t * Spawn the worker and initialize the Rapier world inside it.\n\t * Resolves when the worker reports `ready`.\n\t *\n\t * @param gravity World gravity as [x, y, z].\n\t * @param physicsRate Physics tick rate in Hz (default 60).\n\t * @param workerUrl URL to the physics worker script. The consuming\n\t * application must provide this because bundlers (Vite, Webpack)\n\t * can only resolve worker URLs from application source code.\n\t * Example for Vite:\n\t * ```ts\n\t * new URL('@zylem/game-lib/dist/physics-worker.js', import.meta.url)\n\t * ```\n\t */\n\tasync init(\n\t\tgravity: [number, number, number],\n\t\tphysicsRate = 60,\n\t\tworkerUrl?: URL,\n\t): Promise<void> {\n\t\tif (!workerUrl) {\n\t\t\tthrow new Error(\n\t\t\t\t'[PhysicsProxy] workerUrl is required. Provide physicsWorkerUrl in your stage config.\\n' +\n\t\t\t\t'For Vite: physicsWorkerUrl: new URL(\"@zylem/game-lib/dist/physics-worker.js\", import.meta.url)'\n\t\t\t);\n\t\t}\n\t\tthis.worker = new Worker(workerUrl, { type: 'module' });\n\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tconst onMessage = (e: MessageEvent<PhysicsEvent>) => {\n\t\t\t\tif (e.data.type === 'ready') {\n\t\t\t\t\tthis.worker!.removeEventListener('message', onMessage);\n\t\t\t\t\tthis.worker!.addEventListener('message', this.onWorkerMessage.bind(this));\n\t\t\t\t\tresolve();\n\t\t\t\t} else if (e.data.type === 'error') {\n\t\t\t\t\treject(new Error(e.data.message));\n\t\t\t\t}\n\t\t\t};\n\t\t\tthis.worker!.addEventListener('message', onMessage);\n\n\t\t\tthis.send({ type: 'init', gravity, physicsRate });\n\t\t});\n\t}\n\n\t/**\n\t * Register a body in the worker and return a main-thread handle.\n\t *\n\t * @returns A {@link PhysicsBodyHandle} for reading cached transforms\n\t * and queuing write commands.\n\t */\n\taddBody(\n\t\tuuid: string,\n\t\tbody: SerializableBodyDesc,\n\t\tcolliders: SerializableColliderDesc[],\n\t\tcharacterController?: SerializableCharacterController,\n\t): PhysicsBodyHandle {\n\t\tconst cmd: PhysicsAddBodyCommand = {\n\t\t\ttype: 'addBody',\n\t\t\tuuid,\n\t\t\tbody,\n\t\t\tcolliders,\n\t\t\tcharacterController,\n\t\t};\n\t\tthis.send(cmd);\n\n\t\tconst handle = new PhysicsBodyHandle(uuid, this.commandQueue);\n\t\thandle._seedSnapshot(\n\t\t\tbody.translation[0], body.translation[1], body.translation[2],\n\t\t\t0, 0, 0, 1,\n\t\t\t0, 0, 0,\n\t\t\t0, 0, 0,\n\t\t);\n\t\tthis.handles.set(uuid, handle);\n\t\treturn handle;\n\t}\n\n\t/** Remove a body from the worker and discard its handle. */\n\tremoveBody(uuid: string): void {\n\t\tthis.send({ type: 'removeBody', uuid });\n\t\tthis.handles.delete(uuid);\n\t}\n\n\t/** Get a body handle by entity UUID. */\n\tgetHandle(uuid: string): PhysicsBodyHandle | undefined {\n\t\treturn this.handles.get(uuid);\n\t}\n\n\t/**\n\t * Send a step command to the worker with the current frame delta\n\t * and all queued body commands.\n\t *\n\t * Returns a promise that resolves after the worker replies with\n\t * the step result. Handles are updated and collision callbacks\n\t * are fired before the promise resolves.\n\t */\n\tstep(delta: number): Promise<PhysicsStepResultEvent> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.pendingStep = { resolve, reject };\n\n\t\t\tconst commands = this.commandQueue.splice(0);\n\n\t\t\tfor (const handle of this.handles.values()) {\n\t\t\t\tcommands.push(...handle._drainCommands());\n\t\t\t}\n\n\t\t\tthis.send({ type: 'step', delta, commands });\n\t\t});\n\t}\n\n\t/**\n\t * Subscribe to collision events.\n\t * @returns Unsubscribe function.\n\t */\n\tonCollision(callback: CollisionCallback): () => void {\n\t\tthis.collisionListeners.push(callback);\n\t\treturn () => {\n\t\t\tthis.collisionListeners = this.collisionListeners.filter((cb) => cb !== callback);\n\t\t};\n\t}\n\n\t/** Terminate the worker and release all handles. */\n\tdispose(): void {\n\t\tif (this.worker) {\n\t\t\tthis.send({ type: 'dispose' });\n\t\t\tthis.worker.terminate();\n\t\t\tthis.worker = null;\n\t\t}\n\t\tthis.handles.clear();\n\t\tthis.commandQueue.length = 0;\n\t\tthis.collisionListeners.length = 0;\n\t\tthis.pendingStep = null;\n\t}\n\n\t// ─── Internal ────────────────────────────────────────────────────────\n\n\tprivate send(cmd: PhysicsCommand): void {\n\t\tthis.worker?.postMessage(cmd);\n\t}\n\n\tprivate onWorkerMessage(e: MessageEvent<PhysicsEvent>): void {\n\t\tconst event = e.data;\n\n\t\tswitch (event.type) {\n\t\t\tcase 'stepResult':\n\t\t\t\tthis.applyStepResult(event);\n\t\t\t\tbreak;\n\t\t\tcase 'error':\n\t\t\t\tif (this.pendingStep) {\n\t\t\t\t\tthis.pendingStep.reject(new Error(event.message));\n\t\t\t\t\tthis.pendingStep = null;\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error('[PhysicsProxy] Worker error:', event.message);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate applyStepResult(result: PhysicsStepResultEvent): void {\n\t\tconst { transforms, bodyOrder, collisions, interpolationAlpha } = result;\n\t\tthis.interpolationAlpha = interpolationAlpha;\n\n\t\tfor (let i = 0; i < bodyOrder.length; i++) {\n\t\t\tconst handle = this.handles.get(bodyOrder[i]);\n\t\t\tif (!handle) continue;\n\n\t\t\tconst o = i * FLOATS_PER_BODY;\n\t\t\thandle._updateSnapshot(\n\t\t\t\ttransforms[o + TransformOffset.POS_X],\n\t\t\t\ttransforms[o + TransformOffset.POS_Y],\n\t\t\t\ttransforms[o + TransformOffset.POS_Z],\n\t\t\t\ttransforms[o + TransformOffset.ROT_X],\n\t\t\t\ttransforms[o + TransformOffset.ROT_Y],\n\t\t\t\ttransforms[o + TransformOffset.ROT_Z],\n\t\t\t\ttransforms[o + TransformOffset.ROT_W],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_X],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_Y],\n\t\t\t\ttransforms[o + TransformOffset.LINVEL_Z],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_X],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_Y],\n\t\t\t\ttransforms[o + TransformOffset.ANGVEL_Z],\n\t\t\t);\n\t\t}\n\n\t\tfor (const pair of collisions) {\n\t\t\tfor (const listener of this.collisionListeners) {\n\t\t\t\ttry {\n\t\t\t\t\tlistener(pair);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error('[PhysicsProxy] Collision listener error:', err);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.pendingStep) {\n\t\t\tthis.pendingStep.resolve(result);\n\t\t\tthis.pendingStep = null;\n\t\t}\n\t}\n}\n","import type { RigidBodyDesc, ColliderDesc } from '@dimforge/rapier3d-compat';\nimport { RigidBodyType } from '@dimforge/rapier3d-compat';\nimport type {\n\tSerializableBodyDesc,\n\tSerializableBodyType,\n\tSerializableColliderDesc,\n\tColliderShapeKind,\n\tSerializableCharacterController,\n} from './physics-protocol';\n\n/**\n * Convert a Rapier RigidBodyDesc to a plain serializable object.\n *\n * Rapier descriptors are WASM-backed class instances that cannot cross\n * the postMessage boundary. This extracts the relevant data into a\n * JSON-safe format that the worker can reconstruct.\n */\nexport function serializeBodyDesc(desc: RigidBodyDesc): SerializableBodyDesc {\n\tconst status = (desc as any).status as number;\n\tlet type: SerializableBodyType = 'dynamic';\n\tif (status === RigidBodyType.Fixed) type = 'fixed';\n\telse if (status === RigidBodyType.KinematicPositionBased) type = 'kinematicPositionBased';\n\telse if (status === RigidBodyType.KinematicVelocityBased) type = 'kinematicVelocityBased';\n\n\tconst t = (desc as any).translation ?? { x: 0, y: 0, z: 0 };\n\n\treturn {\n\t\ttype,\n\t\ttranslation: [t.x ?? 0, t.y ?? 0, t.z ?? 0],\n\t\tgravityScale: (desc as any).gravityScale ?? 1,\n\t\tcanSleep: (desc as any).canSleep ?? false,\n\t\tccdEnabled: (desc as any).ccdEnabled ?? true,\n\t};\n}\n\n/**\n * Convert a Rapier ColliderDesc to a plain serializable object.\n *\n * Because Rapier's ColliderDesc uses opaque shape enums and internal\n * buffers, we infer the shape from the descriptor's internal type tag\n * and extract the numeric dimensions.\n */\nexport function serializeColliderDesc(desc: ColliderDesc): SerializableColliderDesc {\n\tconst internal = desc as any;\n\tconst customShapeData = internal.__zylemShapeData as\n\t\t| { shape: 'trimesh'; vertices: number[]; indices: number[] }\n\t\t| undefined;\n\tif (customShapeData?.shape === 'trimesh') {\n\t\tconst result: SerializableColliderDesc = {\n\t\t\tshape: 'trimesh',\n\t\t\tdimensions: [],\n\t\t\tvertices: [...customShapeData.vertices],\n\t\t\tindices: [...customShapeData.indices],\n\t\t};\n\n\t\tconst translation = internal.translation;\n\t\tif (\n\t\t\ttranslation\n\t\t\t&& (translation.x !== 0 || translation.y !== 0 || translation.z !== 0)\n\t\t) {\n\t\t\tresult.translation = [translation.x, translation.y, translation.z];\n\t\t}\n\n\t\tif (internal.isSensor) {\n\t\t\tresult.sensor = true;\n\t\t}\n\n\t\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\t\tresult.collisionGroups = internal.collisionGroups;\n\t\t}\n\n\t\tif (internal.activeCollisionTypes !== undefined) {\n\t\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tconst shapeType = internal.shape?.type ?? internal.shapeType ?? 0;\n\n\tconst { shape, dimensions, heightfieldMeta } = extractShapeData(shapeType, internal);\n\n\tconst result: SerializableColliderDesc = {\n\t\tshape,\n\t\tdimensions,\n\t};\n\n\tconst t = internal.translation;\n\tif (t && (t.x !== 0 || t.y !== 0 || t.z !== 0)) {\n\t\tresult.translation = [t.x, t.y, t.z];\n\t}\n\n\tif (internal.isSensor) {\n\t\tresult.sensor = true;\n\t}\n\n\tif (internal.collisionGroups !== undefined && internal.collisionGroups !== 0xFFFFFFFF) {\n\t\tresult.collisionGroups = internal.collisionGroups;\n\t}\n\n\tif (internal.activeCollisionTypes !== undefined) {\n\t\tresult.activeCollisionTypes = internal.activeCollisionTypes;\n\t}\n\n\tif (heightfieldMeta) {\n\t\tresult.heightfieldMeta = heightfieldMeta;\n\t}\n\n\treturn result;\n}\n\n/**\n * Create a serializable character controller descriptor.\n */\nexport function serializeCharacterController(): SerializableCharacterController {\n\treturn {\n\t\toffset: 0.01,\n\t\tmaxSlopeClimbAngle: 45 * Math.PI / 180,\n\t\tminSlopeSlideAngle: 30 * Math.PI / 180,\n\t\tsnapToGroundDistance: 0.01,\n\t\tslideEnabled: true,\n\t\tapplyImpulsesToDynamic: true,\n\t\tcharacterMass: 1,\n\t};\n}\n\n// ─── Shape Extraction ──────────────────────────────────────────────────────\n\n/**\n * Rapier shape type enum values (from rapier internals):\n * 0 = Ball, 1 = Cuboid, 2 = Capsule, 6 = Cone, 7 = Cylinder,\n * 11 = HeightField\n */\nfunction extractShapeData(\n\tshapeType: number,\n\tinternal: any,\n): { shape: ColliderShapeKind; dimensions: number[]; heightfieldMeta?: { nrows: number; ncols: number } } {\n\tswitch (shapeType) {\n\t\tcase 0: // Ball\n\t\t\treturn {\n\t\t\t\tshape: 'ball',\n\t\t\t\tdimensions: [internal.shape?.radius ?? internal.halfExtents?.x ?? 1],\n\t\t\t};\n\t\tcase 1: // Cuboid\n\t\t\treturn {\n\t\t\t\tshape: 'cuboid',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfExtents?.x ?? internal.halfExtents?.x ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.y ?? internal.halfExtents?.y ?? 0.5,\n\t\t\t\t\tinternal.shape?.halfExtents?.z ?? internal.halfExtents?.z ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 2: // Capsule\n\t\t\treturn {\n\t\t\t\tshape: 'capsule',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 0.5,\n\t\t\t\t\tinternal.shape?.radius ?? 0.5,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 6: // Cone\n\t\t\treturn {\n\t\t\t\tshape: 'cone',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 7: // Cylinder\n\t\t\treturn {\n\t\t\t\tshape: 'cylinder',\n\t\t\t\tdimensions: [\n\t\t\t\t\tinternal.shape?.halfHeight ?? 1,\n\t\t\t\t\tinternal.shape?.radius ?? 1,\n\t\t\t\t],\n\t\t\t};\n\t\tcase 11: { // HeightField\n\t\t\tconst nrows = internal.shape?.nrows ?? 10;\n\t\t\tconst ncols = internal.shape?.ncols ?? 10;\n\t\t\tconst heights = internal.shape?.heights;\n\t\t\treturn {\n\t\t\t\tshape: 'heightfield',\n\t\t\t\tdimensions: heights ? Array.from(heights) : [],\n\t\t\t\theightfieldMeta: { nrows, ncols },\n\t\t\t};\n\t\t}\n\t\tdefault:\n\t\t\treturn { shape: 'cuboid', dimensions: [0.5, 0.5, 0.5] };\n\t}\n}\n","import {\n\tScene,\n\tColor,\n\tAmbientLight,\n\tDirectionalLight,\n\tObject3D,\n\tVector3,\n\tGridHelper,\n\tBoxGeometry,\n\tShaderMaterial,\n\tMesh,\n\tBackSide,\n\tMaterial,\n\tTexture,\n\tLight,\n} from 'three';\nimport { MeshBasicNodeMaterial } from 'three/webgpu';\nimport { Entity, LifecycleFunction } from '../interfaces/entity';\nimport { GameEntity } from '../entities/entity';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { debugState } from '../debug/debug-state';\nimport { SetupFunction } from '../core/base-node-life-cycle';\nimport { getGlobals } from '../game/game-state';\nimport { assetManager } from '../core/asset-manager';\nimport { ZylemShader, isTSLShader, isGLSLShader } from './material';\n\ninterface SceneState {\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader?: ZylemShader | null;\n}\n\nexport class ZylemScene implements Entity<ZylemScene> {\n\tpublic type = 'Scene';\n\n\t_setup?: SetupFunction<ZylemScene>;\n\tscene!: Scene;\n\t/** @deprecated Use cameraManager instead */\n\tzylemCamera!: ZylemCamera;\n\tcameraManager: CameraManager | null = null;\n\tcontainerElement: HTMLElement | null = null;\n\tupdate: LifecycleFunction<ZylemScene> = () => { };\n\t_collision?: ((entity: any, other: any, globals?: any) => void) | undefined;\n\t_destroy?: ((globals?: any) => void) | undefined;\n\tname?: string | undefined;\n\ttag?: Set<string> | undefined;\n\n\t// Skybox for background shaders (supports both GLSL ShaderMaterial and TSL MeshBasicNodeMaterial)\n\tprivate skyboxMaterial: Material | null = null;\n\n\tconstructor(id: string, camera: ZylemCamera, state: SceneState) {\n\t\tconst scene = new Scene();\n\t\tconst isColor = state.backgroundColor instanceof Color;\n\t\tconst backgroundColor = (isColor) ? state.backgroundColor : new Color(state.backgroundColor);\n\t\tscene.background = backgroundColor as Color;\n\t\t\n\t\tconsole.log('ZylemScene state.backgroundShader:', state.backgroundShader);\n\t\t\n\t\tif (state.backgroundShader) {\n\t\t\tthis.setupBackgroundShader(scene, state.backgroundShader);\n\t\t} else if (state.backgroundImage) {\n\t\t\t// Load background image asynchronously via asset manager\n\t\t\tassetManager.loadTexture(state.backgroundImage).then(texture => {\n\t\t\t\tscene.background = texture;\n\t\t\t});\n\t\t}\n\n\t\tthis.scene = scene;\n\t\tthis.zylemCamera = camera;\n\n\t\tthis.setupLighting(scene);\n\t\tif (debugState.enabled) {\n\t\t\tthis.debugScene();\n\t\t}\n\t}\n\n\t/**\n\t * Create a large inverted box with the shader for skybox effect\n\t * Supports both GLSL (ShaderMaterial) and TSL (MeshBasicNodeMaterial) shaders\n\t */\n\tprivate setupBackgroundShader(scene: Scene, shader: ZylemShader) {\n\t\t// Clear the solid color background\n\t\tscene.background = null;\n\n\t\tif (isTSLShader(shader)) {\n\t\t\t// TSL shader - use MeshBasicNodeMaterial for WebGPU\n\t\t\tthis.skyboxMaterial = new MeshBasicNodeMaterial();\n\t\t\t(this.skyboxMaterial as MeshBasicNodeMaterial).colorNode = shader.colorNode;\n\t\t\tif (shader.transparent) {\n\t\t\t\tthis.skyboxMaterial.transparent = true;\n\t\t\t}\n\t\t\tthis.skyboxMaterial.side = BackSide;\n\t\t\tthis.skyboxMaterial.depthWrite = false;\n\t\t\tconsole.log('Skybox created with TSL shader');\n\t\t} else if (isGLSLShader(shader)) {\n\t\t\t// GLSL shader - use ShaderMaterial for WebGL\n\t\t\t// Skybox vertex shader with depth trick (pos.xyww ensures depth = 1.0)\n\t\t\tconst skyboxVertexShader = `\n\t\t\t\tvarying vec2 vUv;\n\t\t\t\tvarying vec3 vWorldPosition;\n\t\t\t\t\n\t\t\t\tvoid main() {\n\t\t\t\t\tvUv = uv;\n\t\t\t\t\tvec4 worldPosition = modelMatrix * vec4(position, 1.0);\n\t\t\t\t\tvWorldPosition = worldPosition.xyz;\n\t\t\t\t\tvec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n\t\t\t\t\tgl_Position = pos.xyww; // Ensures depth is always 1.0 (farthest)\n\t\t\t\t}\n\t\t\t`;\n\n\t\t\t// Create shader material with skybox-specific settings\n\t\t\tthis.skyboxMaterial = new ShaderMaterial({\n\t\t\t\tvertexShader: skyboxVertexShader,\n\t\t\t\tfragmentShader: shader.fragment,\n\t\t\t\tuniforms: {\n\t\t\t\t\tiTime: { value: 0.0 },\n\t\t\t\t},\n\t\t\t\tside: BackSide, // Render on inside of geometry\n\t\t\t\tdepthWrite: false, // Don't write to depth buffer\n\t\t\t\tdepthTest: true, // But do test depth\n\t\t\t});\n\t\t\tconsole.log('Skybox created with GLSL shader');\n\t\t}\n\n\t\t// Use BoxGeometry for skybox\n\t\tconst geometry = new BoxGeometry(1, 1, 1);\n\t\tconst skybox = new Mesh(geometry, this.skyboxMaterial!);\n\t\tskybox.scale.setScalar(100000); // Scale up significantly\n\t\tskybox.frustumCulled = false; // Always render\n\t\tscene.add(skybox);\n\t}\n\n\tsetup() {\n\t\tif (this._setup) {\n\t\t\tthis._setup({ me: this, camera: this.zylemCamera, globals: getGlobals() });\n\t\t}\n\t}\n\n\tdestroy() {\n\t\t// Destroy via camera manager if available, otherwise legacy single camera\n\t\tif (this.cameraManager) {\n\t\t\tthis.cameraManager.dispose();\n\t\t\tthis.cameraManager = null;\n\t\t} else if (this.zylemCamera && (this.zylemCamera as any).destroy) {\n\t\t\t(this.zylemCamera as any).destroy();\n\t\t}\n\t\tif (this.skyboxMaterial) {\n\t\t\tthis.skyboxMaterial.dispose();\n\t\t}\n\t\tif (this.scene) {\n\t\t\t// Dispose background texture if present\n\t\t\tif (this.scene.background instanceof Texture) {\n\t\t\t\tthis.scene.background.dispose();\n\t\t\t\tthis.scene.background = null;\n\t\t\t}\n\n\t\t\tthis.scene.traverse((obj: any) => {\n\t\t\t\tif (obj.geometry) {\n\t\t\t\t\tobj.geometry.dispose?.();\n\t\t\t\t}\n\t\t\t\tif (obj.material) {\n\t\t\t\t\tconst materials = Array.isArray(obj.material) ? obj.material : [obj.material];\n\t\t\t\t\tfor (const mat of materials) {\n\t\t\t\t\t\t// Dispose all texture maps on the material\n\t\t\t\t\t\tif (mat.map) mat.map.dispose?.();\n\t\t\t\t\t\tif (mat.normalMap) mat.normalMap.dispose?.();\n\t\t\t\t\t\tif (mat.aoMap) mat.aoMap.dispose?.();\n\t\t\t\t\t\tif (mat.emissiveMap) mat.emissiveMap.dispose?.();\n\t\t\t\t\t\tif (mat.roughnessMap) mat.roughnessMap.dispose?.();\n\t\t\t\t\t\tif (mat.metalnessMap) mat.metalnessMap.dispose?.();\n\t\t\t\t\t\tif (mat.envMap) mat.envMap.dispose?.();\n\t\t\t\t\t\tif (mat.lightMap) mat.lightMap.dispose?.();\n\t\t\t\t\t\tif (mat.bumpMap) mat.bumpMap.dispose?.();\n\t\t\t\t\t\tif (mat.displacementMap) mat.displacementMap.dispose?.();\n\t\t\t\t\t\tif (mat.alphaMap) mat.alphaMap.dispose?.();\n\t\t\t\t\t\tmat.dispose?.();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Dispose shadow map render targets on lights\n\t\t\t\tif ((obj as Light).isLight && (obj as any).shadow?.map) {\n\t\t\t\t\t(obj as any).shadow.map.dispose();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.scene.clear();\n\t\t}\n\t}\n\n\t/**\n\t * Setup camera with the scene.\n\t * Supports both legacy single camera and CameraManager modes.\n\t */\n\tsetupCamera(scene: Scene, camera: ZylemCamera, rendererManager?: RendererManager) {\n\t\t// Add camera rig or camera directly to scene\n\t\tthis.addCameraToScene(scene, camera);\n\n\t\tif (rendererManager) {\n\t\t\t// New path: camera setup with shared renderer manager\n\t\t\tcamera.setup(scene, rendererManager);\n\t\t} else {\n\t\t\t// Legacy path: camera handles its own renderer\n\t\t\tcamera.setupLegacy(scene);\n\t\t}\n\t}\n\n\t/**\n\t * Setup with a CameraManager (multi-camera support).\n\t */\n\tasync setupCameraManager(scene: Scene, cameraManager: CameraManager, rendererManager: RendererManager): Promise<void> {\n\t\tthis.cameraManager = cameraManager;\n\n\t\t// Add all active cameras to the scene\n\t\tfor (const camera of cameraManager.activeCameras) {\n\t\t\tthis.addCameraToScene(scene, camera);\n\t\t}\n\n\t\t// Setup the camera manager (initializes all cameras)\n\t\tawait cameraManager.setup(scene, rendererManager);\n\t}\n\n\t/**\n\t * Add a camera (rig or direct) to the scene graph.\n\t */\n\tprivate addCameraToScene(scene: Scene, camera: ZylemCamera): void {\n\t\tif (camera.cameraRig) {\n\t\t\tscene.add(camera.cameraRig);\n\t\t} else {\n\t\t\tscene.add(camera.camera as Object3D);\n\t\t}\n\t}\n\n\t/**\n\t * Setup scene lighting\n\t */\n\tsetupLighting(scene: Scene) {\n\t\tconst ambientLight = new AmbientLight(0xffffff, 2);\n\t\tscene.add(ambientLight);\n\n\t\tconst directionalLight = new DirectionalLight(0xffffff, 2);\n\t\tdirectionalLight.name = 'Light';\n\t\tdirectionalLight.position.set(0, 100, 0);\n\t\tdirectionalLight.castShadow = true;\n\t\tdirectionalLight.shadow.camera.near = 0.1;\n\t\tdirectionalLight.shadow.camera.far = 2000;\n\t\tdirectionalLight.shadow.camera.left = -100;\n\t\tdirectionalLight.shadow.camera.right = 100;\n\t\tdirectionalLight.shadow.camera.top = 100;\n\t\tdirectionalLight.shadow.camera.bottom = -100;\n\t\tdirectionalLight.shadow.mapSize.width = 2048;\n\t\tdirectionalLight.shadow.mapSize.height = 2048;\n\t\tscene.add(directionalLight);\n\t}\n\n\t/**\n\t * Update renderer size - delegates to camera manager or camera\n\t */\n\tupdateRenderer(width: number, height: number) {\n\t\tif (this.cameraManager) {\n\t\t\t// Resize all cameras\n\t\t\tfor (const camera of this.cameraManager.allCameras) {\n\t\t\t\tcamera.resize(width, height);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.zylemCamera.resize(width, height);\n\t\t}\n\t}\n\n\t/**\n\t * Add object to scene\n\t */\n\tadd(object: Object3D, position: Vector3 = new Vector3(0, 0, 0)) {\n\t\tobject.position.set(position.x, position.y, position.z);\n\t\tthis.scene.add(object);\n\t}\n\n\t/**\n\t * Add game entity to scene\n\t */\n\taddEntity(entity: GameEntity<any>) {\n\t\tconst target = entity.group ?? entity.mesh;\n\t\tif (!target || this.isAttachedOutsideScene(target)) return;\n\t\tthis.add(target, entity.options.position);\n\t}\n\n\t/**\n\t * Add an entity's group or mesh to the scene (for late-loaded models).\n\t * Uses entity's current body position if physics is active.\n\t */\n\taddEntityGroup(entity: GameEntity<any>): void {\n\t\tconst target = entity.group ?? entity.mesh;\n\t\tif (!target || this.isAttachedOutsideScene(target)) return;\n\n\t\tlet position = entity.options.position ?? new Vector3(0, 0, 0);\n\t\tif (entity.physicsAttached && entity.body) {\n\t\t\ttry {\n\t\t\t\tconst translation = entity.body.translation();\n\t\t\t\tposition = new Vector3(\n\t\t\t\t\ttranslation.x,\n\t\t\t\t\ttranslation.y,\n\t\t\t\t\ttranslation.z,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\tposition = entity.options.position ?? new Vector3(0, 0, 0);\n\t\t\t}\n\t\t}\n\n\t\tthis.add(target, position);\n\t}\n\n\tprivate isAttachedOutsideScene(object: Object3D): boolean {\n\t\treturn object.parent != null && object.parent !== this.scene;\n\t}\n\n\t/**\n\t * Add debug helpers to scene\n\t */\n\tdebugScene() {\n\t\tconst size = 1000;\n\t\tconst divisions = 100;\n\n\t\tconst gridHelper = new GridHelper(size, divisions);\n\t\tthis.scene.add(gridHelper);\n\t}\n\n\t/**\n\t * Update skybox shader uniforms (only applies to GLSL ShaderMaterial)\n\t * TSL shaders use the time node which auto-updates\n\t */\n\tupdateSkybox(delta: number) {\n\t\tif (this.skyboxMaterial && this.skyboxMaterial instanceof ShaderMaterial) {\n\t\t\tif (this.skyboxMaterial.uniforms?.iTime) {\n\t\t\t\tthis.skyboxMaterial.uniforms.iTime.value += delta;\n\t\t\t}\n\t\t}\n\t}\n}\n","import { proxy } from 'valtio';\nimport type { GameEntity } from '../entities/entity';\n\nexport type DebugTools = 'select' | 'translate' | 'rotate' | 'scale' | 'delete' | 'none';\n\nexport interface DebugState {\n\tenabled: boolean;\n\tpaused: boolean;\n\ttool: DebugTools;\n\tselectedEntity: GameEntity<any> | null;\n\thoveredEntity: GameEntity<any> | null;\n\tflags: Set<string>;\n}\n\nexport const debugState = proxy<DebugState>({\n\tenabled: false,\n\tpaused: false,\n\ttool: 'none',\n\tselectedEntity: null,\n\thoveredEntity: null,\n\tflags: new Set(),\n});\n\nexport function isPaused(): boolean {\n\treturn debugState.paused;\n}\n\nexport function setPaused(paused: boolean): void {\n\tdebugState.paused = paused;\n}\n\nexport function setDebugFlag(flag: string, value: boolean): void {\n\tif (value) {\n\t\tdebugState.flags.add(flag);\n\t} else {\n\t\tdebugState.flags.delete(flag);\n\t}\n}\n\nexport function getDebugTool(): DebugTools {\n\treturn debugState.tool;\n}\n\nexport function setDebugTool(tool: DebugTools): void {\n\tdebugState.tool = tool;\n}\n\nexport function getSelectedEntity(): GameEntity<any> | null {\n\treturn debugState.selectedEntity;\n}\n\nexport function setSelectedEntity(entity: GameEntity<any> | null): void {\n\tdebugState.selectedEntity = entity;\n}\n\nexport function getHoveredEntity(): GameEntity<any> | null {\n\treturn debugState.hoveredEntity;\n}\n\nexport function setHoveredEntity(entity: GameEntity<any> | null): void {\n\tdebugState.hoveredEntity = entity;\n}\n\nexport function resetHoveredEntity(): void {\n\tdebugState.hoveredEntity = null;\n}\n","import { BufferGeometry, InstancedMesh, Material, Matrix4, Object3D, Vector3, Quaternion } from 'three';\nimport type { GameEntity, GameEntityOptions } from '../entities/entity';\nimport { shortHash, sortedStringify } from '../core/utility/strings';\n\n/**\n * Represents a batch of entities sharing the same geometry and material\n */\nexport interface BatchGroup {\n\t/** Unique key identifying this batch */\n\tkey: string;\n\t/** The instanced mesh for rendering */\n\tinstancedMesh: InstancedMesh;\n\t/** Original geometry */\n\tgeometry: BufferGeometry;\n\t/** Original material */\n\tmaterial: Material;\n\t/** Map of entity UUID to instance index */\n\tentityMap: Map<string, number>;\n\t/** List of entities in this batch (by their index) */\n\tentities: (GameEntity<any> | null)[];\n\t/** Indices that have been freed and can be reused */\n\tfreeIndices: number[];\n\t/** Active indices for fast iteration */\n\tactiveIndices: number[];\n\t/** Dirty flags for transforms that need syncing */\n\tdirtyIndices: Set<number>;\n\t/** Maximum capacity */\n\tcapacity: number;\n}\n\n/**\n * Configuration for batch key generation\n */\nexport interface BatchKeyConfig {\n\tgeometryType: string;\n\tdimensions: Record<string, number>;\n\tmaterialPath?: string | null;\n\tshaderType?: 'standard' | 'custom';\n\tcolorHex?: number;\n}\n\n/**\n * Manages instanced mesh batching for entities\n */\nexport class InstanceManager {\n\tprivate batches: Map<string, BatchGroup> = new Map();\n\tprivate entityToBatch: Map<string, string> = new Map(); // entity UUID -> batch key\n\tprivate scene: Object3D | null = null;\n\n\t/** Default initial capacity for new batches */\n\tstatic DEFAULT_CAPACITY = 128;\n\t/** Factor to grow batch when full */\n\tstatic GROWTH_FACTOR = 2;\n\n\t/**\n\t * Set the scene to add instanced meshes to\n\t */\n\tsetScene(scene: Object3D): void {\n\t\tthis.scene = scene;\n\t}\n\n\t/**\n\t * Generate a batch key from configuration\n\t */\n\tstatic generateBatchKey(config: BatchKeyConfig): string {\n\t\tconst keyData = {\n\t\t\tgeo: `${config.geometryType}:${sortedStringify(config.dimensions)}`,\n\t\t\tmat: config.materialPath || 'none',\n\t\t\tshader: config.shaderType || 'standard',\n\t\t\tcolor: config.colorHex ?? 0xffffff,\n\t\t};\n\t\treturn shortHash(sortedStringify(keyData));\n\t}\n\n\t/**\n\t * Register an entity with the instance manager\n\t * @returns The instance index, or -1 if registration failed\n\t */\n\tregister(\n\t\tentity: GameEntity<any>,\n\t\tgeometry: BufferGeometry,\n\t\tmaterial: Material,\n\t\tbatchKey: string\n\t): number {\n\t\tlet batch = this.batches.get(batchKey);\n\n\t\tif (!batch) {\n\t\t\tbatch = this.createBatch(batchKey, geometry, material);\n\t\t}\n\n\t\t// Get an index for this entity\n\t\tlet index: number;\n\t\tif (batch.freeIndices.length > 0) {\n\t\t\tindex = batch.freeIndices.pop()!;\n\t\t} else {\n\t\t\tindex = batch.entities.length;\n\t\t\tif (index >= batch.capacity) {\n\t\t\t\tthis.growBatch(batch);\n\t\t\t}\n\t\t\tbatch.entities.push(null);\n\t\t}\n\n\t\t// Store entity reference\n\t\tbatch.entities[index] = entity;\n\t\tbatch.entityMap.set(entity.uuid, index);\n\t\tthis.entityToBatch.set(entity.uuid, batchKey);\n\n\t\t// Update visible instance count\n\t\tbatch.instancedMesh.count = Math.max(batch.instancedMesh.count, index + 1);\n\n\t\t// Add to active list\n\t\tbatch.activeIndices.push(index);\n\n\t\t// Mark dirty for initial transform sync\n\t\tbatch.dirtyIndices.add(index);\n\n\t\treturn index;\n\t}\n\n\t/**\n\t * Unregister an entity from the instance manager\n\t */\n\tunregister(entity: GameEntity<any>): void {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return;\n\n\t\tconst index = batch.entityMap.get(entity.uuid);\n\t\tif (index === undefined) return;\n\n\t\t// Clear the entity slot\n\t\tbatch.entities[index] = null;\n\t\tbatch.entityMap.delete(entity.uuid);\n\t\tthis.entityToBatch.delete(entity.uuid);\n\t\tbatch.freeIndices.push(index);\n\t\t// Remove from active list (swap and pop for O(1))\n\t\tconst idxInActive = batch.activeIndices.indexOf(index);\n\t\tif (idxInActive !== -1) {\n\t\t\tconst last = batch.activeIndices.pop()!;\n\t\t\tif (idxInActive < batch.activeIndices.length) {\n\t\t\t\tbatch.activeIndices[idxInActive] = last;\n\t\t\t}\n\t\t}\n\t\tbatch.dirtyIndices.delete(index);\n\n\t\t// Hide the instance by scaling to zero\n\t\tconst matrix = new Matrix4();\n\t\tmatrix.makeScale(0, 0, 0);\n\t\tbatch.instancedMesh.setMatrixAt(index, matrix);\n\t\tbatch.instancedMesh.instanceMatrix.needsUpdate = true;\n\t}\n\n\t/**\n\t * Mark an entity's transform as dirty (needs syncing)\n\t */\n\tmarkDirty(entity: GameEntity<any>): void {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return;\n\n\t\tconst index = batch.entityMap.get(entity.uuid);\n\t\tif (index !== undefined) {\n\t\t\tbatch.dirtyIndices.add(index);\n\t\t}\n\t}\n\n\t/**\n\t * Update all dirty instance transforms\n\t * Call this once per frame\n\t */\n\t/**\n\t * Update all active instance transforms\n\t * Call this once per frame\n\t */\n\tupdate(): void {\n\t\tconst matrix = new Matrix4();\n\t\tconst pos = new Vector3();\n\t\tconst quat = new Quaternion();\n\t\tconst scale = new Vector3(1, 1, 1);\n\n\t\tfor (const batch of this.batches.values()) {\n\t\t\tif (batch.activeIndices.length === 0) continue;\n\n\t\t\tlet needsUpdate = false;\n\t\t\t// Check if we have explicit dirty updates\n\t\t\tif (batch.dirtyIndices.size > 0) {\n\t\t\t\tfor (const index of batch.dirtyIndices) {\n\t\t\t\t\tthis.updateInstanceMatrix(batch, index, matrix, pos, quat, scale);\n\t\t\t\t}\n\t\t\t\tbatch.dirtyIndices.clear();\n\t\t\t\tneedsUpdate = true;\n\t\t\t}\n\n\t\t\t// Also update all active dynamic entities (assumed dynamic if they have a body)\n\t\t\tfor (const index of batch.activeIndices) {\n\t\t\t\tconst entity = batch.entities[index];\n\t\t\t\t// Optimization: Only update if it has a physics body (dynamic)\n\t\t\t\tif (entity && entity.body) {\n\t\t\t\t\tthis.updateInstanceMatrix(batch, index, matrix, pos, quat, scale);\n\t\t\t\t\tneedsUpdate = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (needsUpdate) {\n\t\t\t\tbatch.instancedMesh.instanceMatrix.needsUpdate = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate updateInstanceMatrix(batch: BatchGroup, index: number, matrix: Matrix4, pos: Vector3, quat: Quaternion, scale: Vector3) {\n\t\tconst entity = batch.entities[index];\n\t\tif (!entity) return;\n\n\t\tif (entity.body) {\n\t\t\tconst translation = entity.body.translation();\n\t\t\tconst rotation = entity.body.rotation();\n\t\t\tpos.set(translation.x, translation.y, translation.z);\n\t\t\tquat.set(rotation.x, rotation.y, rotation.z, rotation.w);\n\t\t\tmatrix.compose(pos, quat, scale);\n\t\t} else if (entity.mesh) {\n\t\t\tentity.mesh.updateMatrix();\n\t\t\tmatrix.copy(entity.mesh.matrix);\n\t\t} else if (entity.group) {\n\t\t\tentity.group.updateMatrix();\n\t\t\tmatrix.copy(entity.group.matrix);\n\t\t}\n\n\t\tbatch.instancedMesh.setMatrixAt(index, matrix);\n\t}\n\n\t/**\n\t * Get batch info for an entity\n\t */\n\tgetBatchInfo(entity: GameEntity<any>): { batchKey: string; instanceId: number } | null {\n\t\tconst batchKey = this.entityToBatch.get(entity.uuid);\n\t\tif (!batchKey) return null;\n\n\t\tconst batch = this.batches.get(batchKey);\n\t\tif (!batch) return null;\n\n\t\tconst instanceId = batch.entityMap.get(entity.uuid);\n\t\tif (instanceId === undefined) return null;\n\n\t\treturn { batchKey, instanceId };\n\t}\n\n\t/**\n\t * Get statistics about current batching\n\t */\n\tgetStats(): { batchCount: number; totalInstances: number; batches: { key: string; count: number; capacity: number }[] } {\n\t\tlet totalInstances = 0;\n\t\tconst batches: { key: string; count: number; capacity: number }[] = [];\n\n\t\tfor (const [key, batch] of this.batches) {\n\t\t\tconst count = batch.entityMap.size;\n\t\t\ttotalInstances += count;\n\t\t\tbatches.push({ key, count, capacity: batch.capacity });\n\t\t}\n\n\t\treturn { batchCount: this.batches.size, totalInstances, batches };\n\t}\n\n\t/**\n\t * Dispose all batches and release resources\n\t */\n\tdispose(): void {\n\t\tfor (const batch of this.batches.values()) {\n\t\t\tif (this.scene) {\n\t\t\t\tthis.scene.remove(batch.instancedMesh);\n\t\t\t}\n\t\t\tbatch.instancedMesh.dispose();\n\t\t\tbatch.geometry.dispose();\n\t\t}\n\t\tthis.batches.clear();\n\t\tthis.entityToBatch.clear();\n\t}\n\n\t/**\n\t * Create a new batch group\n\t */\n\tprivate createBatch(key: string, geometry: BufferGeometry, material: Material): BatchGroup {\n\t\tconst capacity = InstanceManager.DEFAULT_CAPACITY;\n\t\tconst instancedMesh = new InstancedMesh(geometry, material, capacity);\n\t\tinstancedMesh.count = 0; // Start with zero visible instances\n\t\tinstancedMesh.frustumCulled = false; // Let individual instances handle culling\n\n\t\t// Initialize all matrices to hidden (zero scale)\n\t\tconst hiddenMatrix = new Matrix4().makeScale(0, 0, 0);\n\t\tfor (let i = 0; i < capacity; i++) {\n\t\t\tinstancedMesh.setMatrixAt(i, hiddenMatrix);\n\t\t}\n\t\tinstancedMesh.instanceMatrix.needsUpdate = true;\n\n\t\tconst batch: BatchGroup = {\n\t\t\tkey,\n\t\t\tinstancedMesh,\n\t\t\tgeometry,\n\t\t\tmaterial,\n\t\t\tentityMap: new Map(),\n\t\t\tentities: [],\n\t\t\tfreeIndices: [],\n\t\t\tactiveIndices: [],\n\t\t\tdirtyIndices: new Set(),\n\t\t\tcapacity,\n\t\t};\n\n\t\tthis.batches.set(key, batch);\n\n\t\tif (this.scene) {\n\t\t\tthis.scene.add(instancedMesh);\n\t\t}\n\n\t\treturn batch;\n\t}\n\n\t/**\n\t * Grow a batch's capacity\n\t */\n\tprivate growBatch(batch: BatchGroup): void {\n\t\tconst newCapacity = batch.capacity * InstanceManager.GROWTH_FACTOR;\n\n\t\t// Create new instanced mesh with larger capacity\n\t\tconst newInstancedMesh = new InstancedMesh(batch.geometry, batch.material, newCapacity);\n\t\tnewInstancedMesh.count = batch.instancedMesh.count;\n\t\tnewInstancedMesh.frustumCulled = false;\n\n\t\t// Copy existing matrices\n\t\tconst matrix = new Matrix4();\n\t\tfor (let i = 0; i < batch.capacity; i++) {\n\t\t\tbatch.instancedMesh.getMatrixAt(i, matrix);\n\t\t\tnewInstancedMesh.setMatrixAt(i, matrix);\n\t\t}\n\n\t\t// Initialize new slots as hidden\n\t\tconst hiddenMatrix = new Matrix4().makeScale(0, 0, 0);\n\t\tfor (let i = batch.capacity; i < newCapacity; i++) {\n\t\t\tnewInstancedMesh.setMatrixAt(i, hiddenMatrix);\n\t\t}\n\t\tnewInstancedMesh.instanceMatrix.needsUpdate = true;\n\n\t\t// Swap meshes\n\t\tif (this.scene) {\n\t\t\tthis.scene.remove(batch.instancedMesh);\n\t\t\tthis.scene.add(newInstancedMesh);\n\t\t}\n\t\tbatch.instancedMesh.dispose();\n\t\tbatch.instancedMesh = newInstancedMesh;\n\t\tbatch.capacity = newCapacity;\n\t}\n}\n","import { Color, Vector3 } from 'three';\nimport { proxy, subscribe } from 'valtio/vanilla';\nimport { BaseEntityInterface, GameEntityInterface } from '../types/entity-types';\nimport { StageStateInterface } from '../types/stage-types';\nimport { getByPath, setByPath } from '../core/utility/path-utils';\nimport { ZylemBlueColor } from '../core/utility/vector';\n\n/**\n * Initial stage state with default values.\n * Exported for use in ZylemStage construction.\n */\nexport const initialStageState = {\n\tbackgroundColor: ZylemBlueColor,\n\tbackgroundImage: null,\n\tbackgroundShader: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard'],\n\t\tp2: ['gamepad-2', 'keyboard'],\n\t},\n\tgravity: new Vector3(0, 0, 0),\n\tvariables: {},\n\tphysicsRate: 60,\n\tusePhysicsWorker: false,\n\tphysicsWorkerUrl: undefined as URL | string | undefined,\n\tentities: [] as GameEntityInterface[],\n};\n\n/**\n * Stage state proxy for reactive updates.\n */\nconst stageState = proxy({\n\tbackgroundColor: new Color(Color.NAMES.cornflowerblue),\n\tbackgroundImage: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard-1'],\n\t\tp2: ['gamepad-2', 'keyboard-2'],\n\t},\n\tvariables: {},\n\tgravity: new Vector3(0, 0, 0),\n\tentities: [],\n} as StageStateInterface);\n\n// ============================================================\n// Stage state setters (internal use)\n// ============================================================\n\nconst setStageBackgroundColor = (value: Color) => {\n\tstageState.backgroundColor = value;\n};\n\nconst setStageBackgroundImage = (value: string | null) => {\n\tstageState.backgroundImage = value;\n};\n\nconst setEntitiesToStage = (entities: Partial<BaseEntityInterface>[]) => {\n\tstageState.entities = entities;\n};\n\n/** Replace the entire stage variables object (used on stage load). */\nconst setStageVariables = (variables: Record<string, any>) => {\n\tstageState.variables = { ...variables };\n};\n\n/** Reset all stage variables (used on stage unload). */\nconst resetStageVariables = () => {\n\tstageState.variables = {};\n};\n\nconst stageStateToString = (state: StageStateInterface) => {\n\tlet string = `\\n`;\n\tfor (const key in state) {\n\t\tconst value = state[key as keyof StageStateInterface];\n\t\tstring += `${key}:\\n`;\n\t\tif (key === 'entities') {\n\t\t\tfor (const entity of state.entities) {\n\t\t\t\tstring += ` ${entity.uuid}: ${entity.name}\\n`;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === 'object' && value !== null) {\n\t\t\tfor (const subKey in value as Record<string, any>) {\n\t\t\t\tconst subValue = value?.[subKey as keyof typeof value];\n\t\t\t\tif (subValue) {\n\t\t\t\t\tstring += ` ${subKey}: ${subValue}\\n`;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (typeof value === 'string') {\n\t\t\tstring += ` ${key}: ${value}\\n`;\n\t\t}\n\t}\n\treturn string;\n};\n\n// ============================================================\n// Object-scoped variable storage (WeakMap-based)\n// ============================================================\n\n/**\n * WeakMap to store variables keyed by object reference.\n * Variables are automatically garbage collected when the target is collected.\n */\nconst variableStore = new WeakMap<object, Record<string, unknown>>();\n\n/**\n * Separate proxy store for reactivity. We need a regular Map for subscriptions\n * since WeakMap doesn't support iteration/subscriptions.\n */\nconst variableProxyStore = new Map<object, ReturnType<typeof proxy>>();\n\nfunction getOrCreateVariableProxy(target: object): Record<string, unknown> {\n\tlet store = variableProxyStore.get(target) as Record<string, unknown> | undefined;\n\tif (!store) {\n\t\tstore = proxy({});\n\t\tvariableProxyStore.set(target, store);\n\t}\n\treturn store;\n}\n\n/**\n * Set a variable on an object by path.\n * @example setVariable(stage1, 'totalAngle', 0.5)\n * @example setVariable(entity, 'enemy.count', 10)\n */\nexport function setVariable(target: object, path: string, value: unknown): void {\n\tconst store = getOrCreateVariableProxy(target);\n\tsetByPath(store, path, value);\n}\n\n/**\n * Create/initialize a variable with a default value on a target object.\n * Only sets the value if it doesn't already exist.\n * @example createVariable(stage1, 'totalAngle', 0)\n * @example createVariable(entity, 'enemy.count', 10)\n */\nexport function createVariable<T>(target: object, path: string, defaultValue: T): T {\n\tconst store = getOrCreateVariableProxy(target);\n\tconst existing = getByPath<T>(store, path);\n\tif (existing === undefined) {\n\t\tsetByPath(store, path, defaultValue);\n\t\treturn defaultValue;\n\t}\n\treturn existing;\n}\n\n/**\n * Get a variable from an object by path.\n * @example getVariable(stage1, 'totalAngle') // 0.5\n * @example getVariable<number>(entity, 'enemy.count') // 10\n */\nexport function getVariable<T = unknown>(target: object, path: string): T | undefined {\n\tconst store = variableProxyStore.get(target);\n\tif (!store) return undefined;\n\treturn getByPath<T>(store, path);\n}\n\n/**\n * Subscribe to changes on a variable at a specific path for a target object.\n * Returns an unsubscribe function.\n * @example const unsub = onVariableChange(stage1, 'score', (val) => console.log(val));\n */\nexport function onVariableChange<T = unknown>(\n\ttarget: object,\n\tpath: string,\n\tcallback: (value: T) => void\n): () => void {\n\tconst store = getOrCreateVariableProxy(target);\n\tlet previous = getByPath<T>(store, path);\n\treturn subscribe(store, () => {\n\t\tconst current = getByPath<T>(store, path);\n\t\tif (current !== previous) {\n\t\t\tprevious = current;\n\t\t\tcallback(current as T);\n\t\t}\n\t});\n}\n\n/**\n * Subscribe to changes on multiple variable paths for a target object.\n * Callback fires when any of the paths change, receiving all current values.\n * Returns an unsubscribe function.\n * @example const unsub = onVariableChanges(stage1, ['count', 'total'], ([count, total]) => console.log(count, total));\n */\nexport function onVariableChanges<T extends unknown[] = unknown[]>(\n\ttarget: object,\n\tpaths: string[],\n\tcallback: (values: T) => void\n): () => void {\n\tconst store = getOrCreateVariableProxy(target);\n\tlet previousValues = paths.map(p => getByPath(store, p));\n\treturn subscribe(store, () => {\n\t\tconst currentValues = paths.map(p => getByPath(store, p));\n\t\tconst hasChange = currentValues.some((val, i) => val !== previousValues[i]);\n\t\tif (hasChange) {\n\t\t\tpreviousValues = currentValues;\n\t\t\tcallback(currentValues as T);\n\t\t}\n\t});\n}\n\n/**\n * Clear all variables for a target object. Used on stage/entity dispose.\n */\nexport function clearVariables(target: object): void {\n\tvariableProxyStore.delete(target);\n}\n\n// ============================================================\n// Legacy stage variable functions (internal, for stage defaults)\n// ============================================================\n\nconst setStageVariable = (key: string, value: any) => {\n\tstageState.variables[key] = value;\n};\n\nconst getStageVariable = (key: string) => {\n\tif (stageState.variables.hasOwnProperty(key)) {\n\t\treturn stageState.variables[key];\n\t} else {\n\t\tconsole.warn(`Stage variable ${key} not found`);\n\t}\n};\n\nexport {\n\tstageState,\n\t\n\tsetStageBackgroundColor,\n\tsetStageBackgroundImage,\n\t\n\tstageStateToString,\n\tsetStageVariable,\n\tgetStageVariable,\n\tsetStageVariables,\n\tresetStageVariables,\n};","import { Color, Vector3 as ThreeVector3 } from 'three';\nimport { Vector3 } from '@dimforge/rapier3d-compat';\n\n// TODO: needs implementations\n/**\n * @deprecated This type is deprecated.\n */\nexport type Vect3 = ThreeVector3 | Vector3;\n\nexport const ZylemBlueColor = new Color('#0333EC');\nexport const ZylemBlue = '#0333EC';\nexport const ZylemBlueTransparent = '#0333ECA0';\nexport const ZylemGoldText = '#DAA420';\n\nexport const Vec0 = new Vector3(0, 0, 0);\nexport const Vec1 = new Vector3(1, 1, 1);","import { DestroyContext, DestroyFunction, SetupContext, SetupFunction, UpdateContext, UpdateFunction } from './base-node-life-cycle';\n\n/**\n * Provides BaseNode-like lifecycle without ECS/children. Consumers implement\n * the protected hooks and may assign public setup/update/destroy callbacks.\n */\nexport abstract class LifeCycleBase<TSelf> {\n\tupdate: UpdateFunction<TSelf> = () => { };\n\tsetup: SetupFunction<TSelf> = () => { };\n\tdestroy: DestroyFunction<TSelf> = () => { };\n\n\tprotected abstract _setup(context: SetupContext<TSelf>): void;\n\tprotected abstract _update(context: UpdateContext<TSelf>): void;\n\tprotected abstract _destroy(context: DestroyContext<TSelf>): void;\n\n\tnodeSetup(context: SetupContext<TSelf>) {\n\t\tif (typeof (this as any)._setup === 'function') {\n\t\t\tthis._setup(context);\n\t\t}\n\t\tif (this.setup) {\n\t\t\tthis.setup(context);\n\t\t}\n\t}\n\n\tnodeUpdate(context: UpdateContext<TSelf>) {\n\t\tif (typeof (this as any)._update === 'function') {\n\t\t\tthis._update(context);\n\t\t}\n\t\tif (this.update) {\n\t\t\tthis.update(context);\n\t\t}\n\t}\n\n\tnodeDestroy(context: DestroyContext<TSelf>) {\n\t\tif (this.destroy) {\n\t\t\tthis.destroy(context);\n\t\t}\n\t\tif (typeof (this as any)._destroy === 'function') {\n\t\t\tthis._destroy(context);\n\t\t}\n\t}\n}\n\n\n","import { Ray, RayColliderToi } from '@dimforge/rapier3d-compat';\nimport { BufferAttribute, BufferGeometry, LineBasicMaterial, LineSegments, Raycaster, Vector2, Vector3 } from 'three';\nimport { subscribe } from 'valtio/vanilla';\nimport { ZylemStage } from './zylem-stage';\nimport { StageCameraDebugDelegate } from './stage-camera-debug-delegate';\nimport { debugState, getDebugTool, getHoveredEntity, resetHoveredEntity, setHoveredEntity, setSelectedEntity } from '../debug/debug-state';\nimport { DebugEntityCursor } from './debug-entity-cursor';\n\nexport type AddEntityFactory = (params: { position: Vector3; normal?: Vector3 }) => Promise<any> | any;\n\nexport interface StageDebugDelegateOptions {\n\tmaxRayDistance?: number;\n\taddEntityFactory?: AddEntityFactory | null;\n}\n\nconst SELECT_TOOL_COLOR = 0x22ff22;\nconst DELETE_TOOL_COLOR = 0xff3333;\n\n/**\n * Self-managing debug delegate that subscribes to `debugState` internally.\n *\n * When debug is enabled it lazily initializes visuals and DOM listeners.\n * When debug is disabled it tears down visuals but stays alive so it can\n * re-activate without being recreated. Call `dispose()` to fully tear down.\n */\nexport class StageDebugDelegate {\n\tprivate stage: ZylemStage;\n\tprivate options: Required<StageDebugDelegateOptions>;\n\tprivate mouseNdc: Vector2 = new Vector2(-2, -2);\n\tprivate raycaster: Raycaster = new Raycaster();\n\tprivate isMouseDown = false;\n\tprivate domDisposeFns: Array<() => void> = [];\n\tprivate domListenersAttached = false;\n\tprivate debugCursor: DebugEntityCursor | null = null;\n\tprivate debugLines: LineSegments | null = null;\n\tprivate cameraDebugDelegate: StageCameraDebugDelegate | null = null;\n\tprivate debugStateUnsubscribe: (() => void) | null = null;\n\n\tconstructor(stage: ZylemStage, options?: StageDebugDelegateOptions) {\n\t\tthis.stage = stage;\n\t\tthis.options = {\n\t\t\tmaxRayDistance: options?.maxRayDistance ?? 5_000,\n\t\t\taddEntityFactory: options?.addEntityFactory ?? null,\n\t\t};\n\n\t\t// Self-managing: sync with current state then subscribe for changes\n\t\tthis.syncWithDebugState();\n\t\tthis.debugStateUnsubscribe = subscribe(debugState, () => {\n\t\t\tthis.syncWithDebugState();\n\t\t});\n\t}\n\n\tprivate syncWithDebugState(): void {\n\t\tif (debugState.enabled) {\n\t\t\tthis.activate();\n\t\t} else {\n\t\t\tthis.deactivate();\n\t\t}\n\t}\n\n\t/** Initialize DOM listeners and camera debug delegate when debug is turned on. */\n\tprivate activate(): void {\n\t\tif (!this.domListenersAttached) {\n\t\t\tthis.attachDomListeners();\n\t\t\tthis.domListenersAttached = true;\n\t\t}\n\n\t\tif (this.stage.cameraRef && !this.cameraDebugDelegate) {\n\t\t\tthis.cameraDebugDelegate = new StageCameraDebugDelegate(this.stage);\n\t\t\tthis.stage.cameraRef.setDebugDelegate(this.cameraDebugDelegate);\n\t\t}\n\t}\n\n\t/** Tear down visuals and camera debug delegate when debug is turned off. */\n\tprivate deactivate(): void {\n\t\tthis.disposeDebugVisuals();\n\n\t\tif (this.stage.cameraRef) {\n\t\t\tthis.stage.cameraRef.setDebugDelegate(null);\n\t\t}\n\t\tthis.cameraDebugDelegate = null;\n\t}\n\n\tprivate initDebugVisuals(): void {\n\t\tif (this.debugLines || !this.stage.scene) return;\n\n\t\tthis.debugLines = new LineSegments(\n\t\t\tnew BufferGeometry(),\n\t\t\tnew LineBasicMaterial({ vertexColors: true })\n\t\t);\n\t\tthis.stage.scene.scene.add(this.debugLines);\n\t\tthis.debugLines.visible = true;\n\n\t\tthis.debugCursor = new DebugEntityCursor(this.stage.scene.scene);\n\t}\n\n\tprivate disposeDebugVisuals(): void {\n\t\tif (this.debugLines && this.stage.scene) {\n\t\t\tthis.stage.scene.scene.remove(this.debugLines);\n\t\t\tthis.debugLines.geometry.dispose();\n\t\t\t(this.debugLines.material as LineBasicMaterial).dispose();\n\t\t\tthis.debugLines = null;\n\t\t}\n\t\tthis.debugCursor?.dispose();\n\t\tthis.debugCursor = null;\n\t}\n\n\tupdate(): void {\n\t\tif (!debugState.enabled) {\n\t\t\tif (this.debugLines) {\n\t\t\t\tthis.disposeDebugVisuals();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.stage.scene || !this.stage.world || !this.stage.cameraRef) return;\n\n\t\tif (!this.debugLines) {\n\t\t\tthis.initDebugVisuals();\n\t\t}\n\n\t\tconst { world, cameraRef } = this.stage;\n\n\t\t// Debug rendering and raycasting require the direct Rapier world\n\t\t// instance, which is not available in worker mode.\n\t\tconst hasDirectWorld = world.world != null;\n\n\t\tif (this.debugLines && hasDirectWorld) {\n\t\t\tconst { vertices, colors } = world.world.debugRender();\n\t\t\tthis.debugLines.geometry.setAttribute('position', new BufferAttribute(vertices, 3));\n\t\t\tthis.debugLines.geometry.setAttribute('color', new BufferAttribute(colors, 4));\n\t\t}\n\t\tconst tool = getDebugTool();\n\t\tconst isCursorTool = tool === 'select' || tool === 'delete';\n\n\t\tlet hit: RayColliderToi | null = null;\n\t\tlet origin: Vector3 | null = null;\n\t\tlet direction: Vector3 | null = null;\n\n\t\tif (hasDirectWorld) {\n\t\t\tthis.raycaster.setFromCamera(this.mouseNdc, cameraRef.camera);\n\t\t\torigin = this.raycaster.ray.origin.clone();\n\t\t\tdirection = this.raycaster.ray.direction.clone().normalize();\n\n\t\t\tconst rapierRay = new Ray(\n\t\t\t\t{ x: origin.x, y: origin.y, z: origin.z },\n\t\t\t\t{ x: direction.x, y: direction.y, z: direction.z },\n\t\t\t);\n\t\t\thit = world.world.castRay(rapierRay, this.options.maxRayDistance, true);\n\t\t}\n\n\t\tif (hit && isCursorTool) {\n\t\t\t// @ts-ignore - access compat object's parent userData mapping back to GameEntity\n\t\t\tconst rigidBody = hit.collider?._parent;\n\t\t\tconst hoveredUuid: string | undefined = rigidBody?.userData?.uuid;\n\t\t\tif (hoveredUuid) {\n\t\t\t\tconst entity = this.stage.entityDelegate.debugMap.get(hoveredUuid);\n\t\t\t\tif (entity) setHoveredEntity(entity as any);\n\t\t\t} else {\n\t\t\t\tresetHoveredEntity();\n\t\t\t}\n\n\t\t\tif (this.isMouseDown && origin && direction) {\n\t\t\t\tthis.handleActionOnHit(hoveredUuid ?? null, origin, direction, hit.toi);\n\t\t\t}\n\t\t}\n\t\tthis.isMouseDown = false;\n\n\t\tconst hoveredUuid = getHoveredEntity();\n\t\tif (!hoveredUuid) {\n\t\t\tthis.debugCursor?.hide();\n\t\t\treturn;\n\t\t}\n\t\tconst hoveredEntity: any = this.stage.entityDelegate.debugMap.get(`${hoveredUuid}`);\n\t\tconst targetObject = hoveredEntity?.group ?? hoveredEntity?.mesh ?? null;\n\t\tif (!targetObject) {\n\t\t\tthis.debugCursor?.hide();\n\t\t\treturn;\n\t\t}\n\t\tswitch (tool) {\n\t\t\tcase 'select':\n\t\t\t\tthis.debugCursor?.setColor(SELECT_TOOL_COLOR);\n\t\t\t\tbreak;\n\t\t\tcase 'delete':\n\t\t\t\tthis.debugCursor?.setColor(DELETE_TOOL_COLOR);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.debugCursor?.setColor(0xffffff);\n\t\t\t\tbreak;\n\t\t}\n\t\tthis.debugCursor?.updateFromObject(targetObject);\n\t}\n\n\t/** Full teardown — unsubscribes from debugState and cleans up all resources. */\n\tdispose(): void {\n\t\tthis.debugStateUnsubscribe?.();\n\t\tthis.debugStateUnsubscribe = null;\n\t\tthis.deactivate();\n\t\tthis.domDisposeFns.forEach((fn) => fn());\n\t\tthis.domDisposeFns = [];\n\t\tthis.domListenersAttached = false;\n\t}\n\n\tprivate handleActionOnHit(hoveredUuid: string | null, origin: Vector3, direction: Vector3, toi: number) {\n\t\tconst tool = getDebugTool();\n\t\tswitch (tool) {\n\t\t\tcase 'select': {\n\t\t\t\tif (hoveredUuid) {\n\t\t\t\t\tconst entity = this.stage.entityDelegate.debugMap.get(hoveredUuid);\n\t\t\t\t\tif (entity) setSelectedEntity(entity as any);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'delete': {\n\t\t\t\tif (hoveredUuid) {\n\t\t\t\t\tthis.stage.entityDelegate.removeEntityByUuid(hoveredUuid);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'scale': {\n\t\t\t\tif (!this.options.addEntityFactory) break;\n\t\t\t\tconst hitPosition = origin.clone().add(direction.clone().multiplyScalar(toi));\n\t\t\t\tconst newNode = this.options.addEntityFactory({ position: hitPosition });\n\t\t\t\tif (newNode) {\n\t\t\t\t\tPromise.resolve(newNode).then((node) => {\n\t\t\t\t\t\tif (node) this.stage.entityDelegate.spawnEntity(node);\n\t\t\t\t\t}).catch(() => { });\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate attachDomListeners() {\n\t\tconst canvas = this.stage.cameraRef?.renderer.domElement ?? this.stage.scene?.zylemCamera.renderer.domElement;\n\t\tif (!canvas) return;\n\n\t\tconst onMouseMove = (e: MouseEvent) => {\n\t\t\tconst rect = canvas.getBoundingClientRect();\n\t\t\tconst x = ((e.clientX - rect.left) / rect.width) * 2 - 1;\n\t\t\tconst y = -(((e.clientY - rect.top) / rect.height) * 2 - 1);\n\t\t\tthis.mouseNdc.set(x, y);\n\t\t};\n\n\t\tconst onMouseDown = () => {\n\t\t\tthis.isMouseDown = true;\n\t\t};\n\n\t\tcanvas.addEventListener('mousemove', onMouseMove);\n\t\tcanvas.addEventListener('mousedown', onMouseDown);\n\n\t\tthis.domDisposeFns.push(() => canvas.removeEventListener('mousemove', onMouseMove));\n\t\tthis.domDisposeFns.push(() => canvas.removeEventListener('mousedown', onMouseDown));\n\t}\n}\n","import { Object3D } from 'three';\nimport { subscribe } from 'valtio/vanilla';\n\nimport type { CameraDebugDelegate, CameraDebugState } from '../camera/zylem-camera';\nimport { debugState } from '../debug/debug-state';\nimport type { ZylemStage } from './zylem-stage';\n\nconst cloneSelected = (selected: string[]): string[] => [...selected];\n\n/**\n * Debug delegate that bridges the stage's entity map and debug state to the camera.\n */\nexport class StageCameraDebugDelegate implements CameraDebugDelegate {\n\tprivate stage: ZylemStage;\n\n\tconstructor(stage: ZylemStage) {\n\t\tthis.stage = stage;\n\t}\n\n\tsubscribe(listener: (state: CameraDebugState) => void): () => void {\n\t\tconst notify = () => listener(this.snapshot());\n\t\tnotify();\n\t\treturn subscribe(debugState, notify);\n\t}\n\n\tresolveTarget(uuid: string): Object3D | null {\n\t\tconst entity: any = this.stage.entityDelegate.debugMap.get(uuid)\n\t\t\t|| this.stage.world?.collisionMap.get(uuid)\n\t\t\t|| null;\n\t\tconst target = entity?.group ?? entity?.mesh ?? null;\n\t\treturn target ?? null;\n\t}\n\n\tprivate snapshot(): CameraDebugState {\n\t\treturn {\n\t\t\tenabled: debugState.enabled,\n\t\t\tselected: debugState.selectedEntity ? [debugState.selectedEntity.uuid] : [],\n\t\t};\n\t}\n}\n\n","import {\n\tBox3,\n\tBoxGeometry,\n\tColor,\n\tEdgesGeometry,\n\tGroup,\n\tLineBasicMaterial,\n\tLineSegments,\n\tMesh,\n\tMeshBasicMaterial,\n\tObject3D,\n\tScene,\n\tVector3,\n} from 'three';\n\n/**\n * Debug overlay that displays an axis-aligned bounding box around a target Object3D.\n * Shows a semi-transparent fill plus a wireframe outline. Intended for SELECT/DELETE tools.\n */\nexport class DebugEntityCursor {\n\tprivate scene: Scene;\n\tprivate container: Group;\n\tprivate fillMesh: Mesh;\n\tprivate edgeLines: LineSegments;\n\tprivate currentColor: Color = new Color(0x00ff00);\n\tprivate bbox: Box3 = new Box3();\n\tprivate size: Vector3 = new Vector3();\n\tprivate center: Vector3 = new Vector3();\n\n\tconstructor(scene: Scene) {\n\t\tthis.scene = scene;\n\n\t\tconst initialGeometry = new BoxGeometry(1, 1, 1);\n\n\t\tthis.fillMesh = new Mesh(\n\t\t\tinitialGeometry,\n\t\t\tnew MeshBasicMaterial({\n\t\t\t\tcolor: this.currentColor,\n\t\t\t\ttransparent: true,\n\t\t\t\topacity: 0.12,\n\t\t\t\tdepthWrite: false,\n\t\t\t})\n\t\t);\n\n\t\tconst edges = new EdgesGeometry(initialGeometry);\n\t\tthis.edgeLines = new LineSegments(\n\t\t\tedges,\n\t\t\tnew LineBasicMaterial({ color: this.currentColor, linewidth: 1 })\n\t\t);\n\n\t\tthis.container = new Group();\n\t\tthis.container.name = 'DebugEntityCursor';\n\t\tthis.container.add(this.fillMesh);\n\t\tthis.container.add(this.edgeLines);\n\t\tthis.container.visible = false;\n\n\t\tthis.scene.add(this.container);\n\t}\n\n\tsetColor(color: Color | number): void {\n\t\tthis.currentColor.set(color as any);\n\t\t(this.fillMesh.material as MeshBasicMaterial).color.set(this.currentColor);\n\t\t(this.edgeLines.material as LineBasicMaterial).color.set(this.currentColor);\n\t}\n\n\t/**\n\t * Update the cursor to enclose the provided Object3D using a world-space AABB.\n\t */\n\tupdateFromObject(object: Object3D | null | undefined): void {\n\t\tif (!object) {\n\t\t\tthis.hide();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.bbox.setFromObject(object);\n\t\tif (!isFinite(this.bbox.min.x) || !isFinite(this.bbox.max.x)) {\n\t\t\tthis.hide();\n\t\t\treturn;\n\t\t}\n\n\t\tthis.bbox.getSize(this.size);\n\t\tthis.bbox.getCenter(this.center);\n\n\t\tconst newGeom = new BoxGeometry(\n\t\t\tMath.max(this.size.x, 1e-6),\n\t\t\tMath.max(this.size.y, 1e-6),\n\t\t\tMath.max(this.size.z, 1e-6)\n\t\t);\n\t\tthis.fillMesh.geometry.dispose();\n\t\tthis.fillMesh.geometry = newGeom;\n\n\t\tconst newEdges = new EdgesGeometry(newGeom);\n\t\tthis.edgeLines.geometry.dispose();\n\t\tthis.edgeLines.geometry = newEdges;\n\n\t\tthis.container.position.copy(this.center);\n\t\tthis.container.visible = true;\n\t}\n\n\thide(): void {\n\t\tthis.container.visible = false;\n\t}\n\n\tdispose(): void {\n\t\tthis.scene.remove(this.container);\n\t\tthis.fillMesh.geometry.dispose();\n\t\t(this.fillMesh.material as MeshBasicMaterial).dispose();\n\t\tthis.edgeLines.geometry.dispose();\n\t\t(this.edgeLines.material as LineBasicMaterial).dispose();\n\t}\n}\n\n\n","import { Vector2 } from 'three';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { Perspectives } from '../camera/perspective';\nimport { CameraWrapper } from '../camera/camera';\nimport { CameraManager } from '../camera/camera-manager';\nimport type { ZylemStage } from './zylem-stage';\n\n/**\n * Delegate for camera creation and management within a stage.\n * Accepts an injected stage reference for context.\n */\nexport class StageCameraDelegate {\n\tprivate stage: ZylemStage;\n\n\tconstructor(stage: ZylemStage) {\n\t\tthis.stage = stage;\n\t}\n\n\t/**\n\t * Create a default third-person camera based on window size.\n\t */\n\tcreateDefaultCamera(): ZylemCamera {\n\t\tconst width = window.innerWidth;\n\t\tconst height = window.innerHeight;\n\t\tconst screenResolution = new Vector2(width, height);\n\t\treturn new ZylemCamera(Perspectives.ThirdPerson, screenResolution);\n\t}\n\n\t/**\n\t * Resolve the camera to use for the stage.\n\t * Uses the provided camera, stage camera wrapper, or creates a default.\n\t * \n\t * @param cameraOverride Optional camera override\n\t * @param cameraWrapper Optional camera wrapper from stage options\n\t * @returns The resolved ZylemCamera instance\n\t */\n\tresolveCamera(cameraOverride?: ZylemCamera | null, cameraWrapper?: CameraWrapper): ZylemCamera {\n\t\tif (cameraOverride) {\n\t\t\treturn cameraOverride;\n\t\t}\n\t\tif (cameraWrapper) {\n\t\t\treturn cameraWrapper.cameraRef;\n\t\t}\n\t\treturn this.createDefaultCamera();\n\t}\n\n\t/**\n\t * Build a CameraManager from stage options.\n\t * Supports single camera (backward compatible) and multiple cameras.\n\t * \n\t * @param cameraOverride Optional camera override from game-level config\n\t * @param cameraWrappers Camera wrappers from stage options (can be single or array)\n\t * @returns A CameraManager populated with the resolved cameras\n\t */\n\tbuildCameraManager(\n\t\tcameraOverride?: ZylemCamera | null,\n\t\t...cameraWrappers: (CameraWrapper | undefined)[]\n\t): CameraManager {\n\t\tconst manager = new CameraManager();\n\n\t\t// If there's a camera override, use it as the primary\n\t\tif (cameraOverride) {\n\t\t\tmanager.addCamera(cameraOverride, cameraOverride.name || 'main');\n\t\t\treturn manager;\n\t\t}\n\n\t\t// Add cameras from wrappers\n\t\tconst validWrappers = cameraWrappers.filter((w): w is CameraWrapper => w !== undefined);\n\n\t\tif (validWrappers.length > 0) {\n\t\t\tfor (const wrapper of validWrappers) {\n\t\t\t\tconst cam = wrapper.cameraRef;\n\t\t\t\tmanager.addCamera(cam, cam.name || undefined);\n\t\t\t}\n\t\t\t// Activate all cameras beyond the first (addCamera auto-activates only the first).\n\t\t\t// All cameras explicitly passed to createStage should render.\n\t\t\tfor (let i = 1; i < validWrappers.length; i++) {\n\t\t\t\tmanager.addActiveCamera(validWrappers[i].cameraRef);\n\t\t\t}\n\t\t} else {\n\t\t\t// No cameras provided: create a default\n\t\t\tconst defaultCam = this.createDefaultCamera();\n\t\t\tmanager.addCamera(defaultCam, 'default');\n\t\t}\n\n\t\treturn manager;\n\t}\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","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","import { LoadingEvent } from '../core/interfaces';\nimport { gameEventBus, StageLoadingPayload } from '../game/game-event-bus';\n\n/**\n * Event name for stage loading events.\n * Dispatched via window for cross-application communication.\n */\nexport const STAGE_LOADING_EVENT = 'STAGE_LOADING_EVENT';\n\n/**\n * Delegate for managing loading events and progress within a stage.\n * Handles subscription to loading events and broadcasting progress.\n * Emits to game event bus for game-level observation.\n */\nexport class StageLoadingDelegate {\n\tprivate loadingHandlers: Array<(event: LoadingEvent) => void> = [];\n\tprivate stageName?: string;\n\tprivate stageIndex?: number;\n\n\t/**\n\t * Set stage context for event bus emissions.\n\t */\n\tsetStageContext(stageName: string, stageIndex: number): void {\n\t\tthis.stageName = stageName;\n\t\tthis.stageIndex = stageIndex;\n\t}\n\n\t/**\n\t * Subscribe to loading events.\n\t * \n\t * @param callback Invoked for each loading event (start, progress, complete)\n\t * @returns Unsubscribe function\n\t */\n\tonLoading(callback: (event: LoadingEvent) => void): () => void {\n\t\tthis.loadingHandlers.push(callback);\n\t\treturn () => {\n\t\t\tthis.loadingHandlers = this.loadingHandlers.filter((h) => h !== callback);\n\t\t};\n\t}\n\n\t/**\n\t * Emit a loading event to all subscribers and to the game event bus.\n\t * \n\t * @param event The loading event to broadcast\n\t */\n\temit(event: LoadingEvent): void {\n\t\t// Dispatch to direct subscribers\n\t\tfor (const handler of this.loadingHandlers) {\n\t\t\ttry {\n\t\t\t\thandler(event);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('Loading handler failed', e);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// Emit to game event bus for game-level observation\n\t\tconst payload: StageLoadingPayload = {\n\t\t\t...event,\n\t\t\tstageName: this.stageName,\n\t\t\tstageIndex: this.stageIndex,\n\t\t};\n\t\t\n\t\tif (event.type === 'start') {\n\t\t\tgameEventBus.emit('stage:loading:start', payload);\n\t\t} else if (event.type === 'progress') {\n\t\t\tgameEventBus.emit('stage:loading:progress', payload);\n\t\t} else if (event.type === 'complete') {\n\t\t\tgameEventBus.emit('stage:loading:complete', payload);\n\t\t}\n\t}\n\n\t/**\n\t * Emit a start loading event.\n\t */\n\temitStart(message: string = 'Loading stage...'): void {\n\t\tthis.emit({ type: 'start', message, progress: 0 });\n\t}\n\n\t/**\n\t * Emit a progress loading event.\n\t */\n\temitProgress(message: string, current: number, total: number): void {\n\t\tconst progress = total > 0 ? current / total : 0;\n\t\tthis.emit({ type: 'progress', message, progress, current, total });\n\t}\n\n\t/**\n\t * Emit a complete loading event.\n\t */\n\temitComplete(message: string = 'Stage loaded'): void {\n\t\tthis.emit({ type: 'complete', message, progress: 1 });\n\t}\n\n\t/**\n\t * Clear all loading handlers.\n\t */\n\tdispose(): void {\n\t\tthis.loadingHandlers = [];\n\t}\n}\n","import { zylemEventBus } from '../events';\nimport { ZylemScene } from '../graphics/zylem-scene';\nimport { GameEntity } from '../entities/entity';\n\n/**\n * Delegate for handling deferred model loading in entities.\n * Subscribes to model:loaded events and adds entity groups to the scene\n * when they become available after async loading completes.\n */\nexport class StageEntityModelDelegate {\n\tprivate scene: ZylemScene | null = null;\n\tprivate onEntityReady: ((entity: GameEntity<any>) => void) | null = null;\n\tprivate pendingEntities: Map<string, GameEntity<any>> = new Map();\n\tprivate modelLoadedHandler: ((payload: { entityId: string; success: boolean }) => void) | null = null;\n\n\t/**\n\t * Initialize the delegate with the scene reference and start listening.\n\t */\n\tattach(scene: ZylemScene, onEntityReady?: (entity: GameEntity<any>) => void): void {\n\t\tthis.scene = scene;\n\t\tthis.onEntityReady = onEntityReady ?? null;\n\t\tthis.modelLoadedHandler = (payload) => {\n\t\t\tthis.handleModelLoaded(payload.entityId, payload.success);\n\t\t};\n\t\tzylemEventBus.on('entity:model:loaded', this.modelLoadedHandler);\n\t}\n\n\t/**\n\t * Register an entity for observation.\n\t * When its model loads, the group will be added to the scene.\n\t */\n\tobserve(entity: GameEntity<any>): void {\n\t\tif (entity.group || entity.mesh) {\n\t\t\treturn;\n\t\t}\n\t\tthis.pendingEntities.set(entity.uuid, entity);\n\t}\n\n\t/**\n\t * Unregister an entity (e.g., when removed before model loads).\n\t */\n\tunobserve(entityId: string): void {\n\t\tthis.pendingEntities.delete(entityId);\n\t}\n\n\t/**\n\t * Handle model loaded event - add group to scene if entity is pending.\n\t */\n\tprivate handleModelLoaded(entityId: string, success: boolean): void {\n\t\tconst entity = this.pendingEntities.get(entityId);\n\t\tif (!entity || !success) {\n\t\t\tthis.pendingEntities.delete(entityId);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scene?.addEntityGroup(entity);\n\t\tthis.onEntityReady?.(entity);\n\t\tthis.pendingEntities.delete(entityId);\n\t}\n\n\t/**\n\t * Cleanup all subscriptions and pending entities.\n\t */\n\tdispose(): void {\n\t\tif (this.modelLoadedHandler) {\n\t\t\tzylemEventBus.off('entity:model:loaded', this.modelLoadedHandler);\n\t\t\tthis.modelLoadedHandler = null;\n\t\t}\n\t\tthis.pendingEntities.clear();\n\t\tthis.onEntityReady = null;\n\t\tthis.scene = null;\n\t}\n}\n","import { Color, Vector3 } from 'three';\nimport { BaseNode } from '../core/base-node';\nimport { CameraWrapper } from '../camera/camera';\nimport { isBaseNode, isCameraWrapper, isConfigObject, isEntityInput } from '../core/utility/options-parser';\nimport { ZylemBlueColor } from '../core/utility/vector';\nimport type { ZylemShader } from '../graphics/material';\n\n/**\n * Stage configuration type for user-facing options.\n */\nexport type StageConfigLike = Partial<{\n\tinputs: Record<string, string[]>;\n\tbackgroundColor: Color | string;\n\tbackgroundImage: string | null;\n\tbackgroundShader: ZylemShader;\n\tgravity: Vector3;\n\tvariables: Record<string, any>;\n\t/** Physics update rate in Hz (default 60). */\n\tphysicsRate: number;\n\t/** Run physics in a Web Worker (default false). */\n\tusePhysicsWorker: boolean;\n\t/**\n\t * URL to the physics worker script. Required when `usePhysicsWorker` is true.\n\t * In a Vite app, use:\n\t * ```ts\n\t * physicsWorkerUrl: new URL('@zylem/game-lib/dist/physics-worker.js', import.meta.url)\n\t * ```\n\t */\n\tphysicsWorkerUrl: URL | string;\n}>;\n\n/**\n * Internal stage configuration class.\n */\nexport class StageConfig {\n\tconstructor(\n\t\tpublic inputs: Record<string, string[]>,\n\t\tpublic backgroundColor: Color | string,\n\t\tpublic backgroundImage: string | null,\n\t\tpublic backgroundShader: ZylemShader | null,\n\t\tpublic gravity: Vector3,\n\t\tpublic variables: Record<string, any>,\n\t\t/** Physics update rate in Hz (default 60). */\n\t\tpublic physicsRate: number = 60,\n\t\t/** Run physics in a Web Worker (default false). */\n\t\tpublic usePhysicsWorker: boolean = false,\n\t\t/** URL to the physics worker script. Required when usePhysicsWorker is true. */\n\t\tpublic physicsWorkerUrl: URL | string | undefined = undefined,\n\t) { }\n}\n\n/**\n * Create default stage configuration.\n */\nexport function createDefaultStageConfig(): StageConfig {\n\treturn new StageConfig(\n\t\t{\n\t\t\tp1: ['gamepad-1', 'keyboard-1'],\n\t\t\tp2: ['gamepad-2', 'keyboard-2'],\n\t\t},\n\t\tZylemBlueColor,\n\t\tnull,\n\t\tnull,\n\t\tnew Vector3(0, 0, 0),\n\t\t{},\n\t\t60,\n\t\tfalse,\n\t\tundefined,\n\t);\n}\n\n/**\n * Result of parsing stage options.\n */\nexport interface ParsedStageOptions {\n\tconfig: StageConfig;\n\tentities: BaseNode[];\n\tasyncEntities: Array<BaseNode | Promise<any> | (() => BaseNode | Promise<any>)>;\n\t/** @deprecated Use `cameras` array instead for multi-camera support */\n\tcamera?: CameraWrapper;\n\t/** All camera wrappers found in stage options */\n\tcameras: CameraWrapper[];\n}\n\n/**\n * Parse stage options array and resolve configuration.\n * Separates config objects, camera wrappers, and entity inputs.\n * \n * @param options Stage options array\n * @returns Parsed stage options with resolved config, entities, and camera\n */\nexport function parseStageOptions(options: any[] = []): ParsedStageOptions {\n\tconst defaults = createDefaultStageConfig();\n\tlet config: Partial<StageConfig> = {};\n\tconst entities: BaseNode[] = [];\n\tconst asyncEntities: Array<BaseNode | Promise<any> | (() => BaseNode | Promise<any>)> = [];\n\tconst cameras: CameraWrapper[] = [];\n\n\tfor (const item of options) {\n\t\tif (isCameraWrapper(item)) {\n\t\t\tcameras.push(item);\n\t\t} else if (isBaseNode(item)) {\n\t\t\tentities.push(item);\n\t\t} else if (isEntityInput(item) && !isBaseNode(item)) {\n\t\t\tasyncEntities.push(item);\n\t\t} else if (isConfigObject(item)) {\n\t\t\tconfig = { ...config, ...item };\n\t\t}\n\t}\n\n\t// Merge user config with defaults\n\tconst resolvedConfig = new StageConfig(\n\t\tconfig.inputs ?? defaults.inputs,\n\t\tconfig.backgroundColor ?? defaults.backgroundColor,\n\t\tconfig.backgroundImage ?? defaults.backgroundImage,\n\t\tconfig.backgroundShader ?? defaults.backgroundShader,\n\t\tconfig.gravity ?? defaults.gravity,\n\t\tconfig.variables ?? defaults.variables,\n\t\tconfig.physicsRate ?? defaults.physicsRate,\n\t\tconfig.usePhysicsWorker ?? defaults.usePhysicsWorker,\n\t\t(config as any).physicsWorkerUrl ?? defaults.physicsWorkerUrl,\n\t);\n\n\t// Backward compat: first camera is the legacy `camera` field\n\tconst camera = cameras.length > 0 ? cameras[0] : undefined;\n\n\treturn { config: resolvedConfig, entities, asyncEntities, camera, cameras };\n}\n\n/**\n * Factory for authoring stage configuration objects in user code.\n * Returns a plain object that can be passed to `createStage(...)`.\n */\nexport function stageConfig(config: StageConfigLike): StageConfigLike {\n\treturn { ...config };\n}\n","import { BaseNode } from '../base-node';\nimport { CameraWrapper } from '../../camera/camera';\n\n/**\n * Check if an item is a BaseNode (has a create function).\n */\nexport function isBaseNode(item: unknown): item is BaseNode {\n\treturn !!item && typeof item === 'object' && typeof (item as any).create === 'function';\n}\n\n/**\n * Check if an item is a Promise-like (thenable).\n */\nexport function isThenable(item: unknown): item is Promise<any> {\n\treturn !!item && typeof (item as any).then === 'function';\n}\n\n/**\n * Check if an item is a CameraWrapper.\n */\nexport function isCameraWrapper(item: unknown): item is CameraWrapper {\n\treturn !!item && typeof item === 'object' && (item as any).constructor?.name === 'CameraWrapper';\n}\n\n/**\n * Check if an item is a plain config object (not a special type).\n * Excludes BaseNode, CameraWrapper, functions, and promises.\n */\nexport function isConfigObject(item: unknown): boolean {\n\tif (!item || typeof item !== 'object') return false;\n\tif (isBaseNode(item)) return false;\n\tif (isCameraWrapper(item)) return false;\n\tif (isThenable(item)) return false;\n\tif (typeof (item as any).then === 'function') return false;\n\t// Must be a plain object\n\treturn (item as any).constructor === Object || (item as any).constructor?.name === 'Object';\n}\n\n/**\n * Check if an item is an entity input (BaseNode, Promise, or factory function).\n */\nexport function isEntityInput(item: unknown): boolean {\n\tif (!item) return false;\n\tif (isBaseNode(item)) return true;\n\tif (typeof item === 'function') return true;\n\tif (isThenable(item)) return true;\n\treturn false;\n}\n","import { RigidBody } from '@dimforge/rapier3d-compat';\nimport { TransformState } from './transform-store';\n\ninterface ComposedAxis {\n\tvalue: number;\n\ttouched: boolean;\n}\n\ninterface ComposedVelocity {\n\tx: ComposedAxis;\n\ty: ComposedAxis;\n\tz: ComposedAxis;\n}\n\ninterface ResolvedIntent {\n\tsourceId: string;\n\tmode: 'replace' | 'add';\n\tpriority: number;\n\tx?: number;\n\ty?: number;\n\tz?: number;\n}\n\nfunction sortIntents(a: ResolvedIntent, b: ResolvedIntent): number {\n\tif (a.priority !== b.priority) return a.priority - b.priority;\n\treturn a.sourceId.localeCompare(b.sourceId);\n}\n\nfunction composeAxis(\n\tcurrent: number,\n\tintents: ResolvedIntent[],\n\taxis: 'x' | 'y' | 'z',\n): ComposedAxis {\n\tlet touched = false;\n\tlet addSum = 0;\n\tlet hasReplace = false;\n\tlet replaceValue = current;\n\tlet replacePriority = Number.NEGATIVE_INFINITY;\n\n\tfor (const intent of intents) {\n\t\tconst axisValue = intent[axis];\n\t\tif (axisValue == null) continue;\n\t\ttouched = true;\n\n\t\tif (intent.mode === 'add') {\n\t\t\taddSum += axisValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!hasReplace || intent.priority >= replacePriority) {\n\t\t\thasReplace = true;\n\t\t\treplacePriority = intent.priority;\n\t\t\treplaceValue = axisValue;\n\t\t}\n\t}\n\n\treturn {\n\t\ttouched,\n\t\tvalue: (hasReplace ? replaceValue : 0) + addSum,\n\t};\n}\n\nfunction composeVelocity(current: { x: number; y: number; z: number }, intents: ResolvedIntent[]): ComposedVelocity {\n\treturn {\n\t\tx: composeAxis(current.x, intents, 'x'),\n\t\ty: composeAxis(current.y, intents, 'y'),\n\t\tz: composeAxis(current.z, intents, 'z'),\n\t};\n}\n\nfunction clearVelocityChannels(store: TransformState): void {\n\tfor (const sourceId in store.velocityChannels) {\n\t\tdelete store.velocityChannels[sourceId];\n\t}\n\tstore.dirty.velocityChannels = false;\n}\n\n/**\n * Entity that can have transformations applied from a store\n */\nexport interface TransformableEntity {\n\tbody: RigidBody | null;\n\ttransformStore?: TransformState;\n}\n\n/**\n * Apply accumulated transformations from the store to the physics body.\n * \n * This is called automatically after onUpdate() callbacks complete,\n * flushing all pending transformations to the physics engine in a single batch.\n * \n * Flow:\n * 1. Check dirty flags to see what changed\n * 2. Apply changes to RigidBody\n * 3. Reset store for next frame\n * \n * @param entity Entity with physics body and transform store\n * @param store Transform store containing pending changes\n */\nexport function applyTransformChanges(\n\tentity: TransformableEntity,\n\tstore: TransformState\n): void {\n\tif (!entity.body) return;\n\n\tconst hasPosition = store.dirty.position;\n\tconst hasRotation = store.dirty.rotation;\n\tconst hasAngularVelocity = store.dirty.angularVelocity;\n\tconst hasPerAxis = store.dirty.velocityX || store.dirty.velocityY || store.dirty.velocityZ;\n\tconst hasLegacyVelocity = store.dirty.velocity;\n\tconst hasChannels = store.dirty.velocityChannels;\n\n\tif (!hasPosition && !hasRotation && !hasAngularVelocity && !hasPerAxis && !hasLegacyVelocity && !hasChannels) {\n\t\treturn;\n\t}\n\n\tconst intents: ResolvedIntent[] = [];\n\tif (hasChannels) {\n\t\tfor (const sourceId in store.velocityChannels) {\n\t\t\tconst intent = store.velocityChannels[sourceId];\n\t\t\tintents.push({\n\t\t\t\tsourceId,\n\t\t\t\tmode: intent.mode ?? 'replace',\n\t\t\t\tpriority: intent.priority ?? 0,\n\t\t\t\tx: intent.x,\n\t\t\t\ty: intent.y,\n\t\t\t\tz: intent.z,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Legacy fallback mapped into the same composition pipeline.\n\tif (hasLegacyVelocity) {\n\t\tintents.push({\n\t\t\tsourceId: '__legacy_velocity__',\n\t\t\tmode: 'replace',\n\t\t\tpriority: -100,\n\t\t\tx: store.velocity.x,\n\t\t\ty: store.velocity.y,\n\t\t\tz: store.velocity.z,\n\t\t});\n\t} else if (hasPerAxis) {\n\t\tintents.push({\n\t\t\tsourceId: '__legacy_per_axis__',\n\t\t\tmode: 'replace',\n\t\t\tpriority: -100,\n\t\t\tx: store.dirty.velocityX ? store.velocity.x : undefined,\n\t\t\ty: store.dirty.velocityY ? store.velocity.y : undefined,\n\t\t\tz: store.dirty.velocityZ ? store.velocity.z : undefined,\n\t\t});\n\t}\n\n\tif (intents.length > 0) {\n\t\tconst current = entity.body.linvel();\n\t\tif (intents.length > 1) {\n\t\t\tintents.sort(sortIntents);\n\t\t}\n\t\tconst composed = composeVelocity(current, intents);\n\n\t\tentity.body.setLinvel(\n\t\t\t{\n\t\t\t\tx: composed.x.touched ? composed.x.value : current.x,\n\t\t\t\ty: composed.y.touched ? composed.y.value : current.y,\n\t\t\t\tz: composed.z.touched ? composed.z.value : current.z,\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t}\n\n\tif (hasRotation) {\n\t\tentity.body.setRotation(store.rotation, true);\n\t}\n\n\tif (hasAngularVelocity) {\n\t\tentity.body.setAngvel(store.angularVelocity, true);\n\t}\n\n\tif (hasPosition) {\n\t\tconst current = entity.body.translation();\n\t\tentity.body.setTranslation(\n\t\t\t{\n\t\t\t\tx: current.x + store.position.x,\n\t\t\t\ty: current.y + store.position.y,\n\t\t\t\tz: current.z + store.position.z,\n\t\t\t},\n\t\t\ttrue,\n\t\t);\n\t}\n\n\t// Reset dirty flags for next frame\n\tstore.dirty.position = false;\n\tstore.dirty.rotation = false;\n\tstore.dirty.velocity = false;\n\tstore.dirty.velocityX = false;\n\tstore.dirty.velocityY = false;\n\tstore.dirty.velocityZ = false;\n\tclearVelocityChannels(store);\n\tstore.dirty.angularVelocity = false;\n}\n","import { addEntity, removeEntity } from 'bitecs';\n\nimport { ZylemWorld } from '../collision/world';\nimport { ZylemScene } from '../graphics/zylem-scene';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { InstanceManager } from '../graphics/instance-manager';\nimport { clearVariables } from './stage-state';\nimport { debugState } from '../debug/debug-state';\nimport { getGlobals } from '../game/game-state';\nimport { BaseNode } from '../core/base-node';\nimport { GameEntity } from '../entities/entity';\nimport { ZylemActor } from '../entities/actor';\nimport { BaseEntityInterface } from '../types/entity-types';\nimport { StageLoadingDelegate } from './stage-loading-delegate';\nimport { StageEntityModelDelegate } from './stage-entity-model-delegate';\nimport { isBaseNode, isThenable } from '../core/utility/options-parser';\nimport type {\n\tBehaviorEntityLink,\n\tBehaviorSystem,\n\tBehaviorSystemFactory,\n} from '../behaviors/behavior-system';\nimport { Vessel } from '../core/vessel';\n\ntype NodeLike = { create: Function };\nexport type StageEntityInput = NodeLike | Promise<any> | (() => NodeLike | Promise<any>);\n\n/**\n * Runtime context provided by ZylemStage after scene and world are initialized.\n */\nexport interface EntityDelegateContext {\n\tscene: ZylemScene;\n\tworld: ZylemWorld;\n\tecs: ReturnType<typeof import('bitecs').createWorld>;\n\tinstanceManager: InstanceManager | null;\n\t/** Resolved camera for entity setup contexts. */\n\tcamera: ZylemCamera;\n}\n\n/**\n * Delegate responsible for entity spawning, tracking, queuing, removal, and lookup.\n *\n * Owns all entity-related state and exposes it to ZylemStage for orchestration\n * and to external consumers (debug delegate, transform system) via public getters.\n */\nexport class StageEntityDelegate {\n\tprivate static readonly EMPTY_BEHAVIOR_LINKS: readonly BehaviorEntityLink[] = [];\n\n\t/** Entities queued before load completes. */\n\tchildren: BaseNode[] = [];\n\n\t/** EID → BaseNode map of all live entities. */\n\treadonly childrenMap: Map<number, BaseNode> = new Map();\n\n\t/** UUID → BaseNode map populated when debug mode is active. */\n\treadonly debugMap: Map<string, BaseNode> = new Map();\n\n\t/** UUID → EID reverse lookup for O(1) removal. */\n\tprivate readonly uuidToEid: Map<string, number> = new Map();\n\n\tprivate pendingEntities: StageEntityInput[] = [];\n\tprivate pendingPromises: Promise<BaseNode>[] = [];\n\tprivate _isLoaded = false;\n\n\tprivate entityAddedHandlers: Array<(entity: BaseNode) => void> = [];\n\n\t/** ECS behavior systems auto-registered from entity refs or manually added. */\n\treadonly behaviorSystems: BehaviorSystem[] = [];\n\treadonly registeredSystemKeys: Set<symbol> = new Set();\n\treadonly behaviorEntityIndex: Map<symbol, Set<BehaviorEntityLink>> = new Map();\n\tprivate readonly behaviorLinksByUuid: Map<string, BehaviorEntityLink[]> = new Map();\n\n\t// Runtime context — set via attach() during stage load\n\tprivate scene: ZylemScene | null = null;\n\tprivate world: ZylemWorld | null = null;\n\tprivate ecs: ReturnType<typeof import('bitecs').createWorld> | null = null;\n\tprivate instanceManager: InstanceManager | null = null;\n\tprivate camera: ZylemCamera | null = null;\n\n\tprivate loadingDelegate: StageLoadingDelegate;\n\tprivate entityModelDelegate: StageEntityModelDelegate;\n\n\tconstructor(\n\t\tloadingDelegate: StageLoadingDelegate,\n\t\tentityModelDelegate: StageEntityModelDelegate,\n\t) {\n\t\tthis.loadingDelegate = loadingDelegate;\n\t\tthis.entityModelDelegate = entityModelDelegate;\n\t}\n\n\tget isLoaded(): boolean {\n\t\treturn this._isLoaded;\n\t}\n\n\tset isLoaded(value: boolean) {\n\t\tthis._isLoaded = value;\n\t}\n\n\t/**\n\t * Bind runtime context after scene and world are initialized.\n\t * Must be called before any spawn/enqueue operations.\n\t */\n\tattach(context: EntityDelegateContext): void {\n\t\tthis.scene = context.scene;\n\t\tthis.world = context.world;\n\t\tthis.ecs = context.ecs;\n\t\tthis.instanceManager = context.instanceManager;\n\t\tthis.camera = context.camera;\n\t}\n\n\t// ─── Spawning ────────────────────────────────────────────────────────────\n\n\t/**\n\t * Create, register, and add an entity to the scene/world.\n\t * Safe to call only after `attach` when scene/world exist.\n\t */\n\tasync spawnEntity(child: BaseNode): Promise<void> {\n\t\tif (!this.scene || !this.world || !this.ecs) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (child instanceof Vessel) {\n\t\t\tchild.create();\n\t\t\tfor (const childEntity of child.getChildren()) {\n\t\t\t\tif (childEntity instanceof BaseNode) {\n\t\t\t\t\tawait this.spawnEntity(childEntity);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst vesselEid = addEntity(this.ecs);\n\t\t\tchild.eid = vesselEid;\n\n\t\t\tchild.nodeSetup({\n\t\t\t\tme: child,\n\t\t\t\tglobals: getGlobals(),\n\t\t\t\tcamera: this.camera!,\n\t\t\t});\n\n\t\t\tthis.addEntityToStage(child);\n\t\t\treturn;\n\t\t}\n\n\t\tconst entity = child.create();\n\t\tconst eid = addEntity(this.ecs);\n\t\tentity.eid = eid;\n\n\t\t// Register behavior links and auto-register behavior systems once per key.\n\t\tthis.registerBehaviorLinks(entity);\n\n\t\tthis.maybeAttachEntityPhysics(entity);\n\n\t\tfor (const childNode of child.getChildren()) {\n\t\t\tif (childNode instanceof BaseNode) {\n\t\t\t\tawait this.spawnEntity(childNode);\n\t\t\t}\n\t\t}\n\n\t\tchild.nodeSetup({\n\t\t\tme: child,\n\t\t\tglobals: getGlobals(),\n\t\t\tcamera: this.camera!,\n\t\t});\n\n\t\tthis.scene.addEntityGroup(entity);\n\t\tthis.tryRegisterInstance(entity);\n\t\tthis.addEntityToStage(entity);\n\t\tthis.entityModelDelegate.observe(entity);\n\t}\n\n\thandleLateModelReady(entity: GameEntity<any>): void {\n\t\tif (!this.world || !this.scene || !this.uuidToEid.has(entity.uuid)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.maybeAttachEntityPhysics(entity);\n\t\tthis.tryRegisterInstance(entity);\n\t}\n\n\t// ─── Instance batching ───────────────────────────────────────────────────\n\n\t/**\n\t * Register an entity for instanced rendering if opted in with `batched: true`.\n\t */\n\tprivate tryRegisterInstance(entity: GameEntity<any>): void {\n\t\tif (!this.instanceManager) return;\n\t\tif (entity.isInstanced) return;\n\n\t\tconst options = entity.options as any;\n\t\tif (options?.batched !== true) return;\n\t\tif (!entity.mesh?.geometry || !entity.materials?.length) return;\n\n\t\tconst geometry = entity.mesh.geometry;\n\t\tconst material = entity.materials[0];\n\n\t\tconst entityType = (entity.constructor as any).type?.description || 'unknown';\n\t\tconst size = options.size || { x: 1, y: 1, z: 1 };\n\t\tconst matOptions = options.material || {};\n\n\t\tconst batchKey = InstanceManager.generateBatchKey({\n\t\t\tgeometryType: entityType,\n\t\t\tdimensions: { x: size.x, y: size.y, z: size.z },\n\t\t\tmaterialPath: matOptions.path || null,\n\t\t\tshaderType: matOptions.shader ? 'custom' : 'standard',\n\t\t\tcolorHex: matOptions.color?.getHex?.() || 0xffffff,\n\t\t});\n\n\t\tconst instanceId = this.instanceManager.register(entity, geometry, material, batchKey);\n\n\t\tif (instanceId >= 0) {\n\t\t\tentity.batchKey = batchKey;\n\t\t\tentity.instanceId = instanceId;\n\t\t\tentity.isInstanced = true;\n\n\t\t\tif (entity.mesh) {\n\t\t\t\tentity.mesh.visible = false;\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate maybeAttachEntityPhysics(entity: GameEntity<any>): void {\n\t\tif (!this.world || entity.physicsAttached || !entity.colliderDesc) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (entity instanceof ZylemActor) {\n\t\t\tif (entity.needsDeferredModelCollision()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tentity.synchronizeRuntimeCollider();\n\t\t}\n\n\t\tthis.world.addEntity(entity);\n\t}\n\n\t// ─── Stage registration ──────────────────────────────────────────────────\n\n\t/** Add the entity to internal maps and notify listeners. */\n\taddEntityToStage(entity: BaseNode): void {\n\t\tthis.childrenMap.set(entity.eid, entity);\n\t\tthis.uuidToEid.set(entity.uuid, entity.eid);\n\t\tif (debugState.enabled) {\n\t\t\tthis.debugMap.set(entity.uuid, entity);\n\t\t}\n\t\tfor (const handler of this.entityAddedHandlers) {\n\t\t\ttry {\n\t\t\t\thandler(entity);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.error('onEntityAdded handler failed', e);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ─── Removal ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Remove an entity and its resources by its UUID.\n\t * Uses a uuid→eid reverse map for O(1) lookup.\n\t * @returns true if removed, false if not found or stage not ready\n\t */\n\tremoveEntityByUuid(uuid: string): boolean {\n\t\tif (!this.scene || !this.world || !this.ecs) return false;\n\n\t\t// @ts-ignore - collisionMap is public Map<string, GameEntity<any>>\n\t\tconst mapEntity = this.world.collisionMap.get(uuid) as any | undefined;\n\t\tconst entity: any = mapEntity ?? this.debugMap.get(uuid);\n\t\tif (!entity) return false;\n\t\tthis.unregisterBehaviorLinks(entity);\n\n\t\tthis.entityModelDelegate.unobserve(uuid);\n\n\t\tif (entity.isInstanced && this.instanceManager) {\n\t\t\tthis.instanceManager.unregister(entity);\n\t\t}\n\n\t\tthis.world.destroyEntity(entity);\n\n\t\tif (entity.group) {\n\t\t\tthis.scene.scene.remove(entity.group);\n\t\t} else if (entity.mesh) {\n\t\t\tthis.scene.scene.remove(entity.mesh);\n\t\t}\n\n\t\tremoveEntity(this.ecs, entity.eid);\n\n\t\t// O(1) removal via reverse map\n\t\tconst eid = this.uuidToEid.get(uuid);\n\t\tif (eid !== undefined) {\n\t\t\tthis.childrenMap.delete(eid);\n\t\t\tthis.uuidToEid.delete(uuid);\n\t\t}\n\t\tthis.debugMap.delete(uuid);\n\t\treturn true;\n\t}\n\n\t// ─── Lookup ──────────────────────────────────────────────────────────────\n\n\t/** Get an entity by its name; returns null if not found. */\n\tgetEntityByName(name: string): BaseNode | null {\n\t\tfor (const child of this.childrenMap.values()) {\n\t\t\tif (child.name === name) return child;\n\t\t}\n\t\tconsole.warn(`Entity ${name} not found`);\n\t\treturn null;\n\t}\n\n\t/** Build a serializable state snapshot for an entity. */\n\tbuildEntityState(child: BaseNode): Partial<BaseEntityInterface> {\n\t\tif (child instanceof GameEntity) {\n\t\t\treturn { ...child.buildInfo() } as Partial<BaseEntityInterface>;\n\t\t}\n\t\treturn {\n\t\t\tuuid: child.uuid,\n\t\t\tname: child.name,\n\t\t\teid: child.eid,\n\t\t} as Partial<BaseEntityInterface>;\n\t}\n\n\t// ─── Subscriptions ───────────────────────────────────────────────────────\n\n\t/**\n\t * Subscribe to entity-added events.\n\t * @param callback Invoked for each entity when added\n\t * @param options.replayExisting If true and stage already loaded, replays existing entities\n\t * @returns Unsubscribe function\n\t */\n\tonEntityAdded(\n\t\tcallback: (entity: BaseNode) => void,\n\t\toptions?: { replayExisting?: boolean },\n\t): () => void {\n\t\tthis.entityAddedHandlers.push(callback);\n\t\tif (options?.replayExisting && this._isLoaded) {\n\t\t\tthis.childrenMap.forEach((entity) => {\n\t\t\t\ttry {\n\t\t\t\t\tcallback(entity);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.error('onEntityAdded replay failed', e);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn () => {\n\t\t\tthis.entityAddedHandlers = this.entityAddedHandlers.filter((h) => h !== callback);\n\t\t};\n\t}\n\n\t// ─── Queuing ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Enqueue items to be spawned. Items can be:\n\t * - BaseNode instances (immediate or deferred until load)\n\t * - Factory functions returning BaseNode or Promise<BaseNode>\n\t * - Promises resolving to BaseNode\n\t */\n\tenqueue(...items: StageEntityInput[]): void {\n\t\tfor (const item of items) {\n\t\t\tif (!item) continue;\n\t\t\tif (isBaseNode(item)) {\n\t\t\t\tthis.handleEntityImmediatelyOrQueue(item);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (typeof item === 'function') {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = (item as (() => BaseNode | Promise<any>))();\n\t\t\t\t\tif (isBaseNode(result)) {\n\t\t\t\t\t\tthis.handleEntityImmediatelyOrQueue(result);\n\t\t\t\t\t} else if (isThenable(result)) {\n\t\t\t\t\t\tthis.handlePromiseWithSpawnOnResolve(result as Promise<any>);\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error('Error executing entity factory', error);\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (isThenable(item)) {\n\t\t\t\tthis.handlePromiseWithSpawnOnResolve(item as Promise<any>);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleEntityImmediatelyOrQueue(entity: BaseNode): void {\n\t\tif (this._isLoaded) {\n\t\t\tthis.spawnEntity(entity);\n\t\t} else {\n\t\t\tthis.children.push(entity);\n\t\t}\n\t}\n\n\tprivate handlePromiseWithSpawnOnResolve(promise: Promise<any>): void {\n\t\tif (this._isLoaded) {\n\t\t\tpromise\n\t\t\t\t.then((entity) => this.spawnEntity(entity))\n\t\t\t\t.catch((e) => console.error('Failed to build async entity', e));\n\t\t} else {\n\t\t\tthis.pendingPromises.push(promise as Promise<BaseNode>);\n\t\t}\n\t}\n\n\t// ─── Loading generator ───────────────────────────────────────────────────\n\n\t/**\n\t * Generator that yields between entity loads for real-time progress updates.\n\t */\n\tprivate *entityLoadGenerator(): Generator<{ current: number; total: number; name: string }> {\n\t\tconst total = this.children.length + this.pendingEntities.length + this.pendingPromises.length;\n\t\tlet current = 0;\n\n\t\tfor (const child of this.children) {\n\t\t\tthis.spawnEntity(child);\n\t\t\tcurrent++;\n\t\t\tyield { current, total, name: child.name || 'unknown' };\n\t\t}\n\n\t\tif (this.pendingEntities.length) {\n\t\t\tthis.enqueue(...this.pendingEntities);\n\t\t\tcurrent += this.pendingEntities.length;\n\t\t\tthis.pendingEntities = [];\n\t\t\tyield { current, total, name: 'pending entities' };\n\t\t}\n\n\t\tif (this.pendingPromises.length) {\n\t\t\tfor (const promise of this.pendingPromises) {\n\t\t\t\tpromise.then((entity) => {\n\t\t\t\t\tthis.spawnEntity(entity);\n\t\t\t\t}).catch((e) => console.error('Failed to resolve pending stage entity', e));\n\t\t\t}\n\t\t\tcurrent += this.pendingPromises.length;\n\t\t\tthis.pendingPromises = [];\n\t\t\tyield { current, total, name: 'async entities' };\n\t\t}\n\t}\n\n\t/** Yields to the event loop via MessageChannel (~0.1ms vs ~4ms for setTimeout). */\n\tprivate yieldToEventLoop(): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst ch = new MessageChannel();\n\t\t\tch.port1.onmessage = () => resolve();\n\t\t\tch.port2.postMessage(undefined);\n\t\t});\n\t}\n\n\t/**\n\t * Runs the entity load generator, yielding to the event loop in batches.\n\t * Emits progress events through the loading delegate.\n\t */\n\tasync runEntityLoadGenerator(): Promise<void> {\n\t\tconst gen = this.entityLoadGenerator();\n\t\tlet i = 0;\n\t\tconst BATCH_SIZE = 5;\n\t\tfor (const progress of gen) {\n\t\t\tthis.loadingDelegate.emitProgress(`Loaded ${progress.name}`, progress.current, progress.total);\n\t\t\tif (++i % BATCH_SIZE === 0) {\n\t\t\t\tawait this.yieldToEventLoop();\n\t\t\t}\n\t\t}\n\t\tif (i % BATCH_SIZE !== 0) {\n\t\t\tawait this.yieldToEventLoop();\n\t\t}\n\t}\n\n\t// ─── Behavior systems ────────────────────────────────────────────────────\n\n\t/**\n\t * Register an ECS behavior system to run each frame.\n\t * @param systemOrFactory A BehaviorSystem instance or factory function\n\t */\n\tregisterSystem(systemOrFactory: BehaviorSystem | BehaviorSystemFactory): void {\n\t\tif (!this.world || !this.ecs || !this.scene) return;\n\t\tlet system: BehaviorSystem;\n\t\tif (typeof systemOrFactory === 'function') {\n\t\t\tsystem = systemOrFactory({\n\t\t\t\tworld: this.world,\n\t\t\t\tecs: this.ecs,\n\t\t\t\tscene: this.scene,\n\t\t\t\tgetBehaviorLinks: (key: symbol) =>\n\t\t\t\t\tthis.behaviorEntityIndex.get(key)\n\t\t\t\t\t?? StageEntityDelegate.EMPTY_BEHAVIOR_LINKS,\n\t\t\t});\n\t\t} else {\n\t\t\tsystem = systemOrFactory;\n\t\t}\n\t\tthis.behaviorSystems.push(system);\n\t}\n\n\t// ─── Cleanup ─────────────────────────────────────────────────────────────\n\n\t/**\n\t * Destroy all entities and clear internal state.\n\t * Called by ZylemStage._destroy().\n\t */\n\tdestroyAll(): void {\n\t\tfor (const system of this.behaviorSystems) {\n\t\t\tsystem.destroy?.(this.ecs!);\n\t\t}\n\t\tthis.behaviorSystems.length = 0;\n\t\tthis.registeredSystemKeys.clear();\n\t\tthis.behaviorEntityIndex.clear();\n\t\tthis.behaviorLinksByUuid.clear();\n\n\t\tthis.childrenMap.forEach((child) => {\n\t\t\ttry {\n\t\t\t\tchild.nodeDestroy({ me: child, globals: getGlobals() });\n\t\t\t} catch { /* noop */ }\n\t\t\tclearVariables(child);\n\t\t});\n\t\tthis.childrenMap.clear();\n\t\tthis.debugMap.clear();\n\t\tthis.uuidToEid.clear();\n\t\tthis.entityAddedHandlers = [];\n\n\t\tthis._isLoaded = false;\n\t\tthis.scene = null;\n\t\tthis.world = null;\n\t\tthis.ecs = null;\n\t\tthis.instanceManager = null;\n\t\tthis.camera = null;\n\t}\n\n\tprivate registerBehaviorLinks(entity: any): void {\n\t\tif (!this.world || !this.ecs || !this.scene) return;\n\t\tif (typeof entity?.getBehaviorRefs !== 'function') return;\n\n\t\tconst refs = entity.getBehaviorRefs();\n\t\tif (!Array.isArray(refs) || refs.length === 0) return;\n\n\t\tconst links: BehaviorEntityLink[] = [];\n\n\t\tfor (const ref of refs) {\n\t\t\tconst key = ref.descriptor.key;\n\t\t\tconst link: BehaviorEntityLink = { entity, ref };\n\t\t\tlinks.push(link);\n\n\t\t\tlet indexed = this.behaviorEntityIndex.get(key);\n\t\t\tif (!indexed) {\n\t\t\t\tindexed = new Set();\n\t\t\t\tthis.behaviorEntityIndex.set(key, indexed);\n\t\t\t}\n\t\t\tindexed.add(link);\n\n\t\t\tif (!this.registeredSystemKeys.has(key)) {\n\t\t\t\tconst system = ref.descriptor.systemFactory({\n\t\t\t\t\tworld: this.world,\n\t\t\t\t\tecs: this.ecs,\n\t\t\t\t\tscene: this.scene,\n\t\t\t\t\tgetBehaviorLinks: (behaviorKey: symbol) =>\n\t\t\t\t\t\tthis.behaviorEntityIndex.get(behaviorKey)\n\t\t\t\t\t\t?? StageEntityDelegate.EMPTY_BEHAVIOR_LINKS,\n\t\t\t\t});\n\t\t\t\tthis.behaviorSystems.push(system);\n\t\t\t\tthis.registeredSystemKeys.add(key);\n\t\t\t}\n\t\t}\n\n\t\tthis.behaviorLinksByUuid.set(entity.uuid, links);\n\t}\n\n\tprivate unregisterBehaviorLinks(entity: any): void {\n\t\tconst links = this.behaviorLinksByUuid.get(entity?.uuid);\n\t\tif (!links) return;\n\n\t\tfor (const link of links) {\n\t\t\tconst key = link.ref?.descriptor?.key as symbol | undefined;\n\t\t\tif (!key) continue;\n\t\t\tconst indexed = this.behaviorEntityIndex.get(key);\n\t\t\tif (!indexed) continue;\n\n\t\t\tindexed.delete(link);\n\t\t\tif (indexed.size === 0) {\n\t\t\t\tthis.behaviorEntityIndex.delete(key);\n\t\t\t}\n\t\t}\n\n\t\tthis.behaviorLinksByUuid.delete(entity.uuid);\n\t}\n}\n","import { BaseNode } from './base-node';\nimport {\n\tSetupContext,\n\tUpdateContext,\n\tDestroyContext,\n\tLoadedContext,\n\tCleanupContext,\n} from './base-node-life-cycle';\nimport type { NodeInterface } from './node-interface';\n\nconst VESSEL_TYPE = Symbol('vessel');\n\n/**\n * A Vessel is an empty container entity that holds child entities.\n * It has no geometry, physics, or rendering of its own, but propagates\n * lifecycle events to its children and provides a logical grouping mechanism.\n *\n * Child entities added to a Vessel will be individually spawned into the\n * stage's physics world and render scene when the Vessel is spawned.\n */\nexport class Vessel extends BaseNode<{}, Vessel> {\n\tstatic type = VESSEL_TYPE;\n\n\tprotected _setup(_params: SetupContext<this>): void { }\n\n\tprotected async _loaded(_params: LoadedContext<this>): Promise<void> { }\n\n\tprotected _update(_params: UpdateContext<this>): void { }\n\n\tprotected _destroy(_params: DestroyContext<this>): void { }\n\n\tprotected _cleanup(_params: CleanupContext<this>): void { }\n\n\tpublic create(): this {\n\t\treturn this;\n\t}\n\n\tpublic clone(): this {\n\t\tconst cloned = vessel() as this;\n\t\tthis.replayUserLifecycleRegistrationsTo(cloned);\n\t\tthis.cloneChildrenInto(cloned);\n\t\treturn cloned;\n\t}\n\n\t/**\n\t * Add one or more child entities to this vessel.\n\t * Overrides parent to support multiple arguments.\n\t * @returns this for chaining\n\t */\n\tpublic add(...nodes: NodeInterface[]): this {\n\t\tfor (const node of nodes) {\n\t\t\tsuper.add(node);\n\t\t}\n\t\treturn this;\n\t}\n}\n\n/**\n * Create a vessel containing the given child entities.\n * @param args Child BaseNode entities to add\n * @returns A new Vessel with the children added\n */\nexport function vessel(...args: Array<BaseNode>): Vessel {\n\tconst instance = new Vessel();\n\targs.forEach(arg => instance.add(arg));\n\tinstance.enableUserLifecycleTracking();\n\treturn instance;\n}\n","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 { proxy } from 'valtio/vanilla';\nimport { Vector3 } from 'three';\nimport type { StageOptions, ZylemStageConfig } from './zylem-stage';\nimport { ZylemBlueColor } from '../core/utility/vector';\n\n/**\n * Reactive defaults for building `Stage` instances. These values are applied\n * automatically by the `stage()` builder and can be changed at runtime to\n * influence future stage creations.\n */\nconst initialDefaults: Partial<ZylemStageConfig> = {\n\tbackgroundColor: ZylemBlueColor,\n\tbackgroundImage: null,\n\tinputs: {\n\t\tp1: ['gamepad-1', 'keyboard'],\n\t\tp2: ['gamepad-2', 'keyboard'],\n\t},\n\tgravity: new Vector3(0, 0, 0),\n\tvariables: {},\n};\n\nconst stageDefaultsState = proxy<Partial<ZylemStageConfig>>({\n\t...initialDefaults,\n});\n\n/** Replace multiple defaults at once (shallow merge). */\nfunction setStageDefaults(partial: Partial<ZylemStageConfig>): void {\n\tObject.assign(stageDefaultsState, partial);\n}\n\n/** Reset defaults back to library defaults. */\nfunction resetStageDefaults(): void {\n\tObject.assign(stageDefaultsState, initialDefaults);\n}\n\nexport function getStageOptions(options: StageOptions): StageOptions {\n\tconst defaults = getStageDefaultConfig();\n\tlet originalConfig = {};\n\tif (typeof options[0] === 'object') {\n\t\toriginalConfig = options.shift() ?? {};\n\t}\n\tconst combinedConfig = { ...defaults, ...originalConfig };\n\treturn [combinedConfig, ...options] as StageOptions;\n}\n\n/** Get a plain object copy of the current defaults. */\nfunction getStageDefaultConfig(): Partial<ZylemStageConfig> {\n\treturn {\n\t\tbackgroundColor: stageDefaultsState.backgroundColor,\n\t\tbackgroundImage: stageDefaultsState.backgroundImage ?? null,\n\t\tinputs: stageDefaultsState.inputs ? { ...stageDefaultsState.inputs } : undefined,\n\t\tgravity: stageDefaultsState.gravity,\n\t\tvariables: stageDefaultsState.variables ? { ...stageDefaultsState.variables } : undefined,\n\t};\n}\n\n\n","import { InputPlayer } from './input';\nimport { GameInputConfig, GameInputPlayerConfig, KeyboardMapping, MouseConfig } from '../game/game-interfaces';\n\n/**\n * Creates a GameInputConfig scoped to a single player.\n */\nfunction playerKeyMapping(player: InputPlayer, keyMapping: KeyboardMapping): GameInputConfig {\n\treturn { [player]: { key: keyMapping } } as GameInputConfig;\n}\n\n/**\n * Maps arrow keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useArrowsForAxes('p1'));\n */\nexport function useArrowsForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'ArrowLeft': ['axes.Left'],\n\t\t'ArrowRight': ['axes.Right'],\n\t\t'ArrowUp': ['axes.Up'],\n\t\t'ArrowDown': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps arrow keys to secondary axes for the given player.\n * @example stage.setInputConfiguration(useArrowsForSecondaryAxes('p1'));\n */\nexport function useArrowsForSecondaryAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'ArrowLeft': ['axes.SecondaryLeft'],\n\t\t'ArrowRight': ['axes.SecondaryRight'],\n\t\t'ArrowUp': ['axes.SecondaryUp'],\n\t\t'ArrowDown': ['axes.SecondaryDown'],\n\t});\n}\n\n/**\n * Maps arrow keys to directions (Up/Down/Left/Right) for the given player.\n * Useful when `includeDefaults` is false and you still want arrow-key directions.\n * @example stage.setInputConfiguration(useArrowsForDirections('p1'));\n */\nexport function useArrowsForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'ArrowLeft': ['directions.Left'],\n\t\t'ArrowRight': ['directions.Right'],\n\t\t'ArrowUp': ['directions.Up'],\n\t\t'ArrowDown': ['directions.Down'],\n\t});\n}\n\n/**\n * Maps W/A/S/D keys to directions (Up/Down/Left/Right) for the given player.\n * @example stage.setInputConfiguration(useWASDForDirections('p1'));\n */\nexport function useWASDForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'w': ['directions.Up'],\n\t\t's': ['directions.Down'],\n\t\t'a': ['directions.Left'],\n\t\t'd': ['directions.Right'],\n\t});\n}\n\n/**\n * Maps W/A/S/D keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useWASDForAxes('p1'));\n */\nexport function useWASDForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'a': ['axes.Left'],\n\t\t'd': ['axes.Right'],\n\t\t'w': ['axes.Up'],\n\t\t's': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps I/J/K/L keys to axes (Horizontal/Vertical) for the given player.\n * @example stage.setInputConfiguration(useIJKLForAxes('p1'));\n */\nexport function useIJKLForAxes(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'j': ['axes.Left'],\n\t\t'l': ['axes.Right'],\n\t\t'i': ['axes.Up'],\n\t\t'k': ['axes.Down'],\n\t});\n}\n\n/**\n * Maps I/J/K/L keys to directions (Up/Down/Left/Right) for the given player.\n * @example stage.setInputConfiguration(useIJKLForDirections('p1'));\n */\nexport function useIJKLForDirections(player: InputPlayer): GameInputConfig {\n\treturn playerKeyMapping(player, {\n\t\t'j': ['directions.Left'],\n\t\t'l': ['directions.Right'],\n\t\t'i': ['directions.Up'],\n\t\t'k': ['directions.Down'],\n\t});\n}\n\n/**\n * Enables mouse-look with pointer lock for the given player.\n * Mouse movement maps to SecondaryHorizontal/SecondaryVertical axes;\n * left click maps to LTrigger, right click to RTrigger.\n * @example stage.setInputConfiguration(useMouseLook('p1'));\n */\nexport function useMouseLook(player: InputPlayer, options?: { sensitivity?: number }): GameInputConfig {\n\treturn {\n\t\t[player]: {\n\t\t\tmouse: {\n\t\t\t\tpointerLock: true,\n\t\t\t\tsensitivity: options?.sensitivity,\n\t\t\t} satisfies MouseConfig,\n\t\t},\n\t} as GameInputConfig;\n}\n\n/**\n * Enables basic mouse input (no pointer lock) for the given player.\n * @example stage.setInputConfiguration(useMouse('p1'));\n */\nexport function useMouse(player: InputPlayer, options?: { sensitivity?: number }): GameInputConfig {\n\treturn {\n\t\t[player]: {\n\t\t\tmouse: {\n\t\t\t\tpointerLock: false,\n\t\t\t\tsensitivity: options?.sensitivity,\n\t\t\t} satisfies MouseConfig,\n\t\t},\n\t} as GameInputConfig;\n}\n\nconst INPUT_PLAYERS: (keyof GameInputConfig)[] = ['p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8'];\n\n/**\n * Deep-merges multiple GameInputConfig objects into one.\n * At the player level, configs are merged (both apply).\n * At the key level, later configs win on conflict.\n * @example mergeInputConfigs(useArrowsForAxes('p1'), useWASDForDirections('p1'));\n */\nexport function mergeInputConfigs(...configs: GameInputConfig[]): GameInputConfig {\n\tconst result: GameInputConfig = {};\n\n\tfor (const config of configs) {\n\t\tfor (const player of INPUT_PLAYERS) {\n\t\t\tconst source = config[player];\n\t\t\tif (!source) continue;\n\n\t\t\tconst target: GameInputPlayerConfig = result[player] ?? {};\n\t\t\tconst mergedMouse: MouseConfig | undefined =\n\t\t\t\t(target.mouse || source.mouse)\n\t\t\t\t\t? {\n\t\t\t\t\t\t...target.mouse,\n\t\t\t\t\t\t...source.mouse,\n\t\t\t\t\t\tmapping: { ...target.mouse?.mapping, ...source.mouse?.mapping },\n\t\t\t\t\t}\n\t\t\t\t\t: undefined;\n\t\t\tresult[player] = {\n\t\t\t\tkey: { ...target.key, ...source.key },\n\t\t\t\tmouse: mergedMouse,\n\t\t\t\tincludeDefaults: source.includeDefaults ?? target.includeDefaults,\n\t\t\t};\n\t\t}\n\t}\n\n\treturn result;\n}\n","import { BaseNode } from '../core/base-node';\nimport { DestroyFunction, SetupContext, SetupFunction, UpdateFunction } from '../core/base-node-life-cycle';\nimport { LoadingEvent, StageOptionItem, StageOptions, ZylemStage } from './zylem-stage';\nimport { ZylemCamera } from '../camera/zylem-camera';\nimport { CameraWrapper } from '../camera/camera';\nimport { RendererManager } from '../camera/renderer-manager';\nimport { stageState } from './stage-state';\nimport { getStageOptions } from './stage-default';\nimport { EntityTypeMap } from '../types/entity-type-map';\nimport { EventEmitterDelegate, zylemEventBus, type StageEvents } from '../events';\nimport { GameInputConfig } from '../game/game-interfaces';\nimport { mergeInputConfigs } from '../input/input-presets';\n\ntype NodeLike = { create: Function };\ntype AnyNode = NodeLike | Promise<NodeLike>;\ntype EntityInput = AnyNode | (() => AnyNode) | (() => Promise<any>);\n\nexport class Stage {\n\twrappedStage: ZylemStage | null;\n\toptions: StageOptionItem[] = [];\n\t// Entities added after construction, consumed on each load\n\tprivate _pendingEntities: BaseNode[] = [];\n\n\t// Lifecycle callback arrays\n\tprivate setupCallbacks: Array<SetupFunction<ZylemStage>> = [];\n\tprivate updateCallbacks: Array<UpdateFunction<ZylemStage>> = [];\n\tprivate destroyCallbacks: Array<DestroyFunction<ZylemStage>> = [];\n\tprivate pendingLoadingCallbacks: Array<(event: LoadingEvent) => void> = [];\n\n\t// Event delegate for dispatch/listen API\n\tprivate eventDelegate = new EventEmitterDelegate<StageEvents>();\n\n\t/** Per-stage input configuration overrides. Merged with game-level defaults on stage load. */\n\tinputConfig: GameInputConfig | null = null;\n\n\t/**\n\t * Callback set by the game to trigger input reconfiguration\n\t * when this stage's input config changes at runtime.\n\t * @internal\n\t */\n\tonInputConfigChanged: (() => void) | null = null;\n\n\tconstructor(options: StageOptions) {\n\t\tthis.options = options;\n\t\tthis.wrappedStage = null;\n\t}\n\n\t/**\n\t * Set composable input configuration for this stage.\n\t * Multiple configs are deep-merged (later configs win on key conflicts).\n\t * If this stage is currently active, the change takes effect immediately.\n\t * @example stage.setInputConfiguration(useArrowsForAxes('p1'), useWASDForDirections('p2'));\n\t */\n\tsetInputConfiguration(...configs: GameInputConfig[]): this {\n\t\tthis.inputConfig = mergeInputConfigs(...configs);\n\t\tif (this.onInputConfigChanged) {\n\t\t\tthis.onInputConfigChanged();\n\t\t}\n\t\treturn this;\n\t}\n\n\tasync load(id: string, camera?: ZylemCamera | CameraWrapper | null, rendererManager?: RendererManager | null) {\n\t\tstageState.entities = [];\n\t\t// Combine original options with pending entities, then clear pending\n\t\tconst loadOptions = [...this.options, ...this._pendingEntities] as StageOptions;\n\t\tthis._pendingEntities = [];\n\t\t\n\t\tthis.wrappedStage = new ZylemStage(loadOptions);\n\t\tthis.wrappedStage.wrapperRef = this;\n\n\t\t// Flush pending loading callbacks BEFORE load so we catch start/progress events\n\t\tthis.pendingLoadingCallbacks.forEach(cb => {\n\t\t\tthis.wrappedStage!.onLoading(cb);\n\t\t});\n\t\tthis.pendingLoadingCallbacks = [];\n\n\t\tconst zylemCamera = camera instanceof CameraWrapper ? camera.cameraRef : camera;\n\t\tawait this.wrappedStage!.load(id, zylemCamera, rendererManager);\n\n\t\tthis.wrappedStage!.onEntityAdded((child) => {\n\t\t\tconst next = this.wrappedStage!.buildEntityState(child);\n\t\t\tstageState.entities = [...stageState.entities, next];\n\t\t}, { replayExisting: true });\n\n\t\t// Apply lifecycle callbacks to wrapped stage\n\t\tthis.applyLifecycleCallbacks();\n\n\t}\n\n\tprivate applyLifecycleCallbacks() {\n\t\tif (!this.wrappedStage) return;\n\n\t\t// Compose setup callbacks into a single function\n\t\tif (this.setupCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.setup = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.setupCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\n\t\t// Compose update callbacks\n\t\tif (this.updateCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.update = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.updateCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\n\t\t// Compose destroy callbacks\n\t\tif (this.destroyCallbacks.length > 0) {\n\t\t\tthis.wrappedStage.destroy = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.destroyCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t}\n\n\tasync addEntities(entities: BaseNode[]) {\n\t\t// Store in pending, don't mutate options\n\t\tthis._pendingEntities.push(...entities);\n\t\tif (!this.wrappedStage) { return; }\n\t\tthis.wrappedStage!.enqueue(...entities);\n\t}\n\n\tadd(...inputs: Array<EntityInput>) {\n\t\tthis.addToBlueprints(...inputs);\n\t\tthis.addToStage(...inputs);\n\t}\n\n\tprivate addToBlueprints(...inputs: Array<EntityInput>) {\n\t\tif (this.wrappedStage) { return; }\n\t\t// Add to options (persistent) so they're available on reload\n\t\tthis.options.push(...(inputs as unknown as StageOptionItem[]));\n\t}\n\n\tprivate addToStage(...inputs: Array<EntityInput>) {\n\t\tif (!this.wrappedStage) { return; }\n\t\tthis.wrappedStage!.enqueue(...(inputs as any));\n\t}\n\n\tstart(params: SetupContext<ZylemStage>) {\n\t\tthis.wrappedStage?.nodeSetup(params);\n\t}\n\n\t// Fluent API for adding lifecycle callbacks\n\tonUpdate(...callbacks: UpdateFunction<ZylemStage>[]): this {\n\t\tthis.updateCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the update callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.update = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.updateCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonSetup(...callbacks: SetupFunction<ZylemStage>[]): this {\n\t\tthis.setupCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the setup callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.setup = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.setupCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonDestroy(...callbacks: DestroyFunction<ZylemStage>[]): this {\n\t\tthis.destroyCallbacks.push(...callbacks);\n\t\t// If already loaded, recompose the destroy callback\n\t\tif (this.wrappedStage) {\n\t\t\tthis.wrappedStage.destroy = (params) => {\n\t\t\t\tconst extended = { ...params, stage: this } as any;\n\t\t\t\tthis.destroyCallbacks.forEach(cb => cb(extended));\n\t\t\t};\n\t\t}\n\t\treturn this;\n\t}\n\n\tonLoading(callback: (event: LoadingEvent) => void) {\n\t\tif (!this.wrappedStage) { \n\t\t\tthis.pendingLoadingCallbacks.push(callback);\n\t\t\treturn () => {\n\t\t\t\tthis.pendingLoadingCallbacks = this.pendingLoadingCallbacks.filter(c => c !== callback);\n\t\t\t};\n\t\t}\n\t\treturn this.wrappedStage.onLoading(callback);\n\t}\n\n\t/**\n\t * Find an entity by name on the current stage.\n\t * @param name The name of the entity to find\n\t * @param type Optional type symbol for type inference (e.g., TEXT_TYPE, SPRITE_TYPE)\n\t * @returns The entity if found, or undefined\n\t * @example stage.getEntityByName('scoreText', TEXT_TYPE)\n\t */\n\tgetEntityByName<T extends symbol | void = void>(\n\t\tname: string,\n\t\ttype?: T\n\t): T extends keyof EntityTypeMap ? EntityTypeMap[T] | undefined : BaseNode | undefined {\n\t\tconst entity = this.wrappedStage?.getEntityByName(name);\n\t\treturn entity as any;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Camera management\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Add a camera to this stage.\n\t * @param camera The ZylemCamera or CameraWrapper to add\n\t * @param name Optional name for lookup\n\t */\n\taddCamera(camera: ZylemCamera | CameraWrapper, name?: string): string | null {\n\t\tconst zylemCam = camera instanceof CameraWrapper ? camera.cameraRef : camera;\n\t\treturn this.wrappedStage?.addCamera(zylemCam, name) ?? null;\n\t}\n\n\t/**\n\t * Remove a camera from this stage by name or reference.\n\t */\n\tremoveCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean {\n\t\tif (nameOrRef instanceof CameraWrapper) {\n\t\t\treturn this.wrappedStage?.removeCamera(nameOrRef.cameraRef) ?? false;\n\t\t}\n\t\treturn this.wrappedStage?.removeCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Set the active camera by name or reference.\n\t */\n\tsetActiveCamera(nameOrRef: string | ZylemCamera | CameraWrapper): boolean {\n\t\tif (nameOrRef instanceof CameraWrapper) {\n\t\t\treturn this.wrappedStage?.setActiveCamera(nameOrRef.cameraRef) ?? false;\n\t\t}\n\t\treturn this.wrappedStage?.setActiveCamera(nameOrRef) ?? false;\n\t}\n\n\t/**\n\t * Get a camera by name from the camera manager.\n\t */\n\tgetCamera(name: string): ZylemCamera | null {\n\t\treturn this.wrappedStage?.getCamera(name) ?? null;\n\t}\n\n\t// ─────────────────────────────────────────────────────────────────────────────\n\t// Events API\n\t// ─────────────────────────────────────────────────────────────────────────────\n\n\t/**\n\t * Dispatch an event from the stage.\n\t * Events are emitted both locally and to the global event bus.\n\t */\n\tdispatch<K extends keyof StageEvents>(event: K, payload: StageEvents[K]): void {\n\t\tthis.eventDelegate.dispatch(event, payload);\n\t\t(zylemEventBus as any).emit(event, payload);\n\t}\n\n\t/**\n\t * Listen for events on this stage instance.\n\t * @returns Unsubscribe function\n\t */\n\tlisten<K extends keyof StageEvents>(event: K, handler: (payload: StageEvents[K]) => void): () => void {\n\t\treturn this.eventDelegate.listen(event, handler);\n\t}\n\n\t/**\n\t * Clean up stage resources including event subscriptions.\n\t */\n\tdispose(): void {\n\t\tthis.eventDelegate.dispose();\n\t}\n}\n\n/**\n * Create a stage with optional camera\n */\nexport function createStage(...options: StageOptions): Stage {\n\tconst _options = getStageOptions(options);\n\treturn new Stage([..._options] as StageOptions);\n}","import { Euler, Quaternion, Vector2 } from \"three\";\nimport { GameEntity } from \"../entities\";\nimport { Stage } from \"./stage\";\n\nexport interface EntitySpawner {\n\tspawn: (stage: Stage, x: number, y: number) => Promise<GameEntity<any>>;\n\tspawnRelative: (source: any, stage: Stage, offset?: Vector2) => Promise<any | void>;\n}\n\nexport function entitySpawner(factory: (x: number, y: number) => Promise<any> | GameEntity<any>): EntitySpawner {\n\treturn {\n\t\tspawn: async (stage: Stage, x: number, y: number) => {\n\t\t\tconst instance = await Promise.resolve(factory(x, y));\n\t\t\tstage.add(instance);\n\t\t\treturn instance;\n\t\t},\n\t\tspawnRelative: async (source: any, stage: Stage, offset: Vector2 = new Vector2(0, 1)) => {\n\t\t\tif (!source.body) {\n\t\t\t\tconsole.warn('body missing for entity during spawnRelative');\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst { x, y, z } = source.body.translation();\n\t\t\tlet rz = (source as any)._rotation2DAngle ?? 0;\n\t\t\ttry {\n\t\t\t\tconst r = source.body.rotation();\n\t\t\t\tconst q = new Quaternion(r.x, r.y, r.z, r.w);\n\t\t\t\tconst e = new Euler().setFromQuaternion(q, 'XYZ');\n\t\t\t\trz = e.z;\n\t\t\t} catch { /* use fallback angle */ }\n\n\t\t\tconst offsetX = Math.sin(-rz) * (offset.x ?? 0);\n\t\t\tconst offsetY = Math.cos(-rz) * (offset.y ?? 0);\n\n\t\t\tconst instance = await Promise.resolve(factory(x + offsetX, y + offsetY));\n\t\t\tstage.add(instance);\n\t\t\treturn instance;\n\t\t}\n\t};\n}","import { subscribe } from 'valtio/vanilla';\nimport { stageState } from './stage-state';\nimport type { StageStateInterface } from '../types/stage-types';\n\n/**\n * Event name for stage state changes.\n * Dispatched when the stage state proxy is updated.\n */\nexport const STAGE_STATE_CHANGE = 'STAGE_STATE_CHANGE';\n\n/**\n * Event detail payload for STAGE_STATE_CHANGE events.\n */\nexport interface StageStateChangeEvent {\n\tentities: StageStateInterface['entities'];\n\tvariables: StageStateInterface['variables'];\n}\n\n/**\n * Initialize the stage state dispatcher.\n * Subscribes to stageState changes and dispatches STAGE_STATE_CHANGE events to the window.\n * \n * @returns Unsubscribe function to stop dispatching events.\n * \n * @example\n * // Start dispatching stage state changes\n * const unsubscribe = initStageStateDispatcher();\n * \n * // Later, stop dispatching\n * unsubscribe();\n */\nexport function initStageStateDispatcher(): () => void {\n\treturn subscribe(stageState, () => {\n\t\tconst detail: StageStateChangeEvent = {\n\t\t\tentities: stageState.entities,\n\t\t\tvariables: stageState.variables,\n\t\t};\n\t\twindow.dispatchEvent(new CustomEvent(STAGE_STATE_CHANGE, { detail }));\n\t});\n}\n\n/**\n * Manually dispatch the current stage state.\n * Useful for initial sync when a listener is added.\n */\nexport function dispatchStageState(): void {\n\tconst detail: StageStateChangeEvent = {\n\t\tentities: stageState.entities,\n\t\tvariables: stageState.variables,\n\t};\n\twindow.dispatchEvent(new CustomEvent(STAGE_STATE_CHANGE, { detail }));\n}\n"],"mappings":"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","names":["Color","Vector3","ActiveCollisionTypes","ColliderDesc","MeshStandardMaterial","Group","Vector3","Quaternion","position","rotation","Quaternion","all","Map","on","type","handler","handlers","get","push","set","off","splice","indexOf","emit","evt","slice","map","proxy","position","Vector3","Quaternion","Quaternion","Vector3","rotation","Vector3","Vector3","Color","Vector3","Vector3","Color","Mesh","Color","Vector2","Vector3","RepeatWrapping","ShaderMaterial","Vector3","position","ColliderDesc","ActiveCollisionTypes","Group","MeshStandardMaterial","scale","rotation","RigidBodyType","result","proxy","rotation","Color","Vector3","ShaderMaterial","Mesh","Texture","MeshBasicNodeMaterial","proxy","state","Color","MeshBasicNodeMaterial","ShaderMaterial","Mesh","Texture","position","Vector3","Matrix4","Vector3","Quaternion","Matrix4","Vector3","Quaternion","scale","rotation","Color","Vector3","proxy","subscribe","Color","Vector3","Vector3","Vector3","proxy","Color","nanoid","BufferAttribute","BufferGeometry","LineBasicMaterial","LineSegments","Vector2","subscribe","subscribe","subscribe","Box3","BoxGeometry","Color","Group","Mesh","Vector3","Vector2","subscribe","LineSegments","BufferGeometry","LineBasicMaterial","BufferAttribute","hoveredUuid","Vector2","PerspectiveCamera","Vector3","WebGLRenderTarget","Vector3","state","Vector2","WebGLRenderer","Vector2","WebGLRenderer","Vector3","Quaternion","MathUtils","Vector3","Quaternion","position","Vector3","Quaternion","DEFAULTS","Vector3","Quaternion","Euler","MathUtils","DEFAULTS","position","rotation","Vector3","PerspectiveCamera","WebGLRenderTarget","position","Vector2","Vector2","Vector2","Vector3","Vector3","nanoid","Vector3","Color","Vector2","Vector3","proxy","Vector3","Vector3","proxy","Euler","Quaternion","Vector2","subscribe","subscribe"]}