@series-inc/rundot-3d-engine 0.3.0

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 (38) hide show
  1. package/LICENSE.txt +6 -0
  2. package/README.md +80 -0
  3. package/dist/ComponentRegistry-V_7WauAE.d.ts +448 -0
  4. package/dist/chunk-ZNDJR3RD.js +5623 -0
  5. package/dist/chunk-ZNDJR3RD.js.map +1 -0
  6. package/dist/index.d.ts +1484 -0
  7. package/dist/index.js +1390 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/systems/index.d.ts +3356 -0
  10. package/dist/systems/index.js +9652 -0
  11. package/dist/systems/index.js.map +1 -0
  12. package/docs/core/Component.md +321 -0
  13. package/docs/core/GameObject.md +204 -0
  14. package/docs/core/VenusGame.md +316 -0
  15. package/docs/patterns/ComponentCommunication.md +337 -0
  16. package/docs/patterns/CreatingGameObjects.md +290 -0
  17. package/docs/patterns/MeshColliders.md +338 -0
  18. package/docs/patterns/MeshLoading.md +316 -0
  19. package/docs/physics/Colliders.md +249 -0
  20. package/docs/physics/PhysicsSystem.md +151 -0
  21. package/docs/physics/RigidBodyComponent.md +201 -0
  22. package/docs/rendering/AssetManager.md +308 -0
  23. package/docs/rendering/InstancedRenderer.md +286 -0
  24. package/docs/rendering/MeshRenderer.md +286 -0
  25. package/docs/rendering/SkeletalRenderer.md +308 -0
  26. package/docs/systems/AnimationSystem.md +75 -0
  27. package/docs/systems/AudioSystem.md +79 -0
  28. package/docs/systems/InputManager.md +101 -0
  29. package/docs/systems/LightingSystem.md +101 -0
  30. package/docs/systems/NavigationSystem.md +246 -0
  31. package/docs/systems/ParticleSystem.md +44 -0
  32. package/docs/systems/PrefabSystem.md +60 -0
  33. package/docs/systems/SplineSystem.md +194 -0
  34. package/docs/systems/StowKitSystem.md +77 -0
  35. package/docs/systems/TweenSystem.md +132 -0
  36. package/docs/systems/UISystem.md +73 -0
  37. package/package.json +62 -0
  38. package/scripts/postinstall.mjs +51 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/systems/physics/BoxColliderComponent.ts","../../src/systems/physics/MeshColliderComponent.ts","../../src/systems/debug/RenderingDebugger.ts","../../src/systems/debug/DebugPanelThree.ts","../../src/systems/navigation/DynamicNavSystem.ts","../../src/systems/navigation/NavigationGrid.ts","../../src/systems/navigation/NavGridDebugDisplayThree.ts","../../src/systems/navigation/PathVisualizationThree.ts","../../src/systems/spline/SplineDebugManager.ts","../../src/systems/spline/SplineDebugRendererThree.ts","../../src/systems/lighting/DirectionalLightComponentThree.ts","../../src/systems/lighting/AmbientLightComponentThree.ts","../../src/systems/materials/MaterialUtils.ts","../../src/systems/navigation/NavAgent.ts","../../src/systems/ui/UIUtils.ts","../../src/systems/ui/UISystem.ts","../../src/systems/ui/UILoadingScreen.ts","../../src/systems/particle-system/index.ts","../../src/systems/particle-system/Particle.ts","../../src/systems/particle-system/curve.ts","../../src/systems/particle-system/ParticleSystemPrefabComponent.ts","../../src/systems/animatrix/animatrix.ts","../../src/systems/animatrix/animation-library.ts","../../src/systems/animatrix/SharedAnimationManager.ts","../../src/systems/animatrix/AnimationGraphComponent.ts","../../src/systems/animatrix/visualizer.ts","../../src/systems/animatrix/AnimationControllerComponent.ts","../../src/systems/animatrix/AnimationLibraryComponent.ts","../../src/systems/animatrix/AnimationVisualizerComponent.ts","../../src/systems/animatrix/AnimationConsoleFilter.ts","../../src/systems/animatrix/AnimationPerformance.ts","../../src/systems/spline/SplineThree.ts"],"sourcesContent":["import * as THREE from \"three\"\nimport { Component } from \"@engine/core\"\nimport { PrefabComponent } from \"../prefabs/PrefabComponent\"\nimport type { ComponentJSON, PrefabNode } from \"../prefabs\"\nimport { ColliderShape, RigidBodyComponentThree, RigidBodyType } from \"./RigidBodyComponentThree\"\n\ninterface BoxComponentJSON extends ComponentJSON {\n type: \"box\"\n isCollider?: boolean\n size: number[]\n offset: number[]\n}\n\n@PrefabComponent(\"box\")\nexport class BoxColliderComponent extends Component {\n static fromPrefabJSON(json: BoxComponentJSON, _node: PrefabNode): BoxColliderComponent | null {\n if (!json.isCollider) {\n return null\n }\n\n const size = new THREE.Vector3(json.size[0], json.size[1], json.size[2])\n const offset = new THREE.Vector3(json.offset[0], json.offset[1], json.offset[2])\n return new BoxColliderComponent(size, offset)\n }\n\n private rigidBody: RigidBodyComponentThree | null = null\n private readonly size: THREE.Vector3\n private readonly offset: THREE.Vector3\n\n constructor(size: THREE.Vector3, offset: THREE.Vector3) {\n super()\n this.size = size\n this.offset = offset\n }\n\n protected onCreate(): void {\n this.rigidBody = new RigidBodyComponentThree({\n type: RigidBodyType.STATIC,\n shape: ColliderShape.BOX,\n size: this.size,\n centerOffset: this.offset,\n })\n this.gameObject.addComponent(this.rigidBody)\n }\n\n public getRigidBody(): RigidBodyComponentThree | null {\n return this.rigidBody\n }\n}\n","import { Component } from \"@engine/core\"\nimport { PrefabComponent } from \"../prefabs/PrefabComponent\"\nimport type { ComponentJSON, PrefabNode } from \"../prefabs\"\nimport { StowKitSystem } from \"../stowkit/StowKitSystem\"\nimport { ColliderShape, RigidBodyComponentThree, RigidBodyType } from \"./RigidBodyComponentThree\"\n\ninterface MeshColliderJSON extends ComponentJSON {\n type: \"mesh_collider\"\n colliderType: \"bounding_box\"\n}\n\ninterface StowMeshJSON extends ComponentJSON {\n type: \"stow_mesh\"\n mesh: {\n pack: string\n assetId: string\n }\n}\n\n@PrefabComponent(\"mesh_collider\")\nexport class MeshColliderComponent extends Component {\n static fromPrefabJSON(json: MeshColliderJSON, node: PrefabNode): MeshColliderComponent | null {\n if (json.colliderType !== \"bounding_box\") {\n console.warn(`Unknown mesh collider type: ${json.colliderType}`)\n return null\n }\n\n const stowMeshComponent = node.components.find((c) => c.type === \"stow_mesh\") as\n | StowMeshJSON\n | undefined\n if (!stowMeshComponent) {\n console.warn(\"MeshColliderComponent requires a stow_mesh component on the same node\")\n return null\n }\n\n return new MeshColliderComponent(stowMeshComponent.mesh.assetId)\n }\n\n private rigidBody: RigidBodyComponentThree | null = null\n private readonly meshName: string\n\n constructor(meshName: string) {\n super()\n this.meshName = meshName\n }\n\n protected onCreate(): void {\n const stowkit = StowKitSystem.getInstance()\n const scale = this.gameObject.scale.clone()\n\n stowkit.getMesh(this.meshName).then((meshGroup) => {\n const bounds = stowkit.getBounds(meshGroup)\n\n if (bounds) {\n const scaledBounds = bounds.clone().multiply(scale)\n this.rigidBody = RigidBodyComponentThree.fromBounds(scaledBounds, {\n type: RigidBodyType.STATIC,\n shape: ColliderShape.BOX,\n })\n this.gameObject.addComponent(this.rigidBody)\n }\n })\n }\n\n public getRigidBody(): RigidBodyComponentThree | null {\n return this.rigidBody\n }\n}\n","import * as THREE from \"three\"\nimport { AssetManager } from \"@engine/assets/AssetManager\"\n\n/**\n * Debug utility for analyzing rendering performance and GPU instancing\n * Contains all debugging functionality separate from core rendering classes\n */\nexport class RenderingDebugger {\n /**\n * Get comprehensive rendering statistics from AssetManager\n */\n public static getRenderingStats(): any {\n const globalStats = AssetManager.getGlobalInstanceStats()\n\n return {\n totalInstances: globalStats.totalInstances,\n gpuInstances: globalStats.gpuInstances,\n gpuBatches: globalStats.gpuBatches,\n sharedInstances: globalStats.sharedInstances,\n clonedInstances: globalStats.clonedInstances,\n brokenInstances: globalStats.brokenInstances,\n geometryReuse: globalStats.geometryReuse,\n materialReuse: globalStats.materialReuse,\n }\n }\n\n /**\n * Print comprehensive rendering report\n */\n public static printRenderingReport(): void {\n const stats = RenderingDebugger.getRenderingStats()\n\n console.log(\"đŸŽŦ === RENDERING PERFORMANCE REPORT ===\")\n console.log(`📊 Total Instances: ${stats.totalInstances}`)\n console.log(\n `🚀 GPU Instances: ${stats.gpuInstances} in ${stats.gpuBatches} batches (${Math.round((stats.gpuInstances / Math.max(stats.totalInstances, 1)) * 100)}%)`\n )\n console.log(\n `🔗 Shared Instances: ${stats.sharedInstances} (${Math.round((stats.sharedInstances / Math.max(stats.totalInstances, 1)) * 100)}%)`\n )\n console.log(\n `📋 Cloned Instances: ${stats.clonedInstances} (${Math.round((stats.clonedInstances / Math.max(stats.totalInstances, 1)) * 100)}%)`\n )\n console.log(\n `âš ī¸ Broken Instances: ${stats.brokenInstances} (${Math.round((stats.brokenInstances / Math.max(stats.totalInstances, 1)) * 100)}%)`\n )\n console.log(`â™ģī¸ Geometry Reuse: ${stats.geometryReuse}x`)\n console.log(`🎨 Material Reuse: ${stats.materialReuse}x`)\n\n if (stats.gpuInstances === stats.totalInstances) {\n console.log(\"✅ PERFECT: 100% GPU instancing - optimal performance!\")\n } else if (stats.gpuInstances > stats.totalInstances * 0.8) {\n console.log(\"đŸŽ¯ EXCELLENT: >80% GPU instancing - great performance!\")\n } else if (stats.gpuInstances > stats.totalInstances * 0.5) {\n console.log(\"👍 GOOD: >50% GPU instancing - decent performance\")\n } else {\n console.log(\"âš ī¸ WARNING: Low GPU instancing usage - performance could be improved\")\n console.log(\"💡 Consider using RenderingMode.GPU_INSTANCING for more objects\")\n }\n }\n\n /**\n * Analyze what's causing high draw calls\n */\n public static analyzeDrawCalls(): void {\n console.log(\"🔍 === DRAW CALL ANALYSIS ===\")\n\n // Get global scene reference\n const scene =\n (window as any).renderer?.scene || (window as any).game?.scene || (window as any).scene\n const renderer = (window as any).renderer\n\n if (!scene) {\n console.log(\"❌ No scene found. Try: window.scene = yourScene\")\n return\n }\n\n if (!renderer) {\n console.log(\"❌ No renderer found. Try: window.renderer = yourRenderer\")\n return\n }\n\n console.log(\"📊 === RENDERER INFO ===\")\n console.log(`Draw calls: ${renderer.info.render.calls}`)\n console.log(`Triangles: ${renderer.info.render.triangles.toLocaleString()}`)\n console.log(`Points: ${renderer.info.render.points}`)\n console.log(`Lines: ${renderer.info.render.lines}`)\n console.log(`Geometries: ${renderer.info.memory.geometries}`)\n console.log(`Textures: ${renderer.info.memory.textures}`)\n\n console.log(\"đŸ“Ļ === SCENE BREAKDOWN ===\")\n console.log(`Total scene children: ${scene.children.length}`)\n\n let instancedMeshCount = 0\n let regularMeshCount = 0\n let groupCount = 0\n let lightCount = 0\n let cameraCount = 0\n let helperCount = 0\n let totalMeshes = 0\n\n scene.children.forEach((child: any, i: number) => {\n if (i < 20) {\n // Log first 20 objects to avoid spam\n console.log(\n `${i}: ${child.type} - \"${child.name}\" (${child.children?.length || 0} children)`\n )\n }\n\n // Count meshes in this child\n let meshCount = 0\n child.traverse((obj: any) => {\n if (obj.isMesh) {\n meshCount++\n totalMeshes++\n\n if (i < 10 && meshCount <= 3) {\n // Log details for first few objects only\n if (obj.isInstancedMesh) {\n console.log(` ├─ InstancedMesh: \"${obj.name}\" (${obj.count} instances)`)\n } else {\n console.log(` ├─ Regular Mesh: \"${obj.name}\"`)\n }\n }\n }\n })\n\n // Categorize objects\n if (child.isInstancedMesh) {\n instancedMeshCount++\n } else if (child.isMesh) {\n regularMeshCount++\n } else if (child.isGroup) {\n groupCount++\n } else if (child.isLight) {\n lightCount++\n } else if (child.isCamera) {\n cameraCount++\n } else if (child.name?.includes(\"Helper\") || child.name?.includes(\"Debug\")) {\n helperCount++\n }\n\n if (i < 20 && meshCount > 0) {\n console.log(` └─ Contains ${meshCount} total meshes`)\n }\n })\n\n console.log(\"📈 === OBJECT SUMMARY ===\")\n console.log(`InstancedMesh objects: ${instancedMeshCount}`)\n console.log(`Regular meshes: ${regularMeshCount}`)\n console.log(`Groups: ${groupCount}`)\n console.log(`Lights: ${lightCount}`)\n console.log(`Cameras: ${cameraCount}`)\n console.log(`Helpers/Debug: ${helperCount}`)\n console.log(`Total meshes in scene: ${totalMeshes}`)\n\n console.log(\"🔍 === DRAW CALL ANALYSIS ===\")\n const expectedDrawCalls = instancedMeshCount + regularMeshCount\n console.log(`Expected draw calls (geometry): ${expectedDrawCalls}`)\n console.log(`Actual draw calls: ${renderer.info.render.calls}`)\n console.log(`Extra draw calls: ${renderer.info.render.calls - expectedDrawCalls}`)\n\n if (renderer.info.render.calls > expectedDrawCalls) {\n console.log(\"🤔 POSSIBLE CAUSES OF EXTRA DRAW CALLS:\")\n console.log(\" â€ĸ Post-processing effects (SSAA, Bloom, etc.)\")\n console.log(\" â€ĸ Shadow mapping passes\")\n console.log(\" â€ĸ UI rendering\")\n console.log(\" â€ĸ Debug visualization\")\n console.log(\" â€ĸ Transparency sorting\")\n console.log(\" â€ĸ Material incompatibilities breaking batching\")\n }\n\n // Check for post-processing\n if ((window as any).postProcessing || renderer.domElement?.style?.filter) {\n console.log(\"📸 Post-processing detected - this adds multiple render passes\")\n }\n\n console.log(\"💡 Run this function again after toggling post-processing to compare\")\n }\n\n /**\n * Test frustum culling with current camera\n */\n public static testFrustumCulling(): void {\n const camera = (window as any).camera || (window as any).game?.camera\n\n if (!camera) {\n console.log(\"❌ No camera found. Try: window.camera = yourCamera\")\n return\n }\n\n console.log(\"đŸŽ¯ === TESTING FRUSTUM CULLING ===\")\n\n const renderer = (window as any).renderer\n if (renderer) {\n // Reset renderer info and force a render to get baseline\n renderer.info.reset()\n renderer.render((window as any).scene, camera)\n const trianglesBefore = renderer.info.render.triangles\n console.log(`📊 Triangle count BEFORE frustum culling: ${trianglesBefore.toLocaleString()}`)\n\n // Apply frustum culling\n console.log(\"🔄 Applying frustum culling to all GPU batches...\")\n AssetManager.updateAllGPUBatches(camera, true) // Enable debug logging\n\n // Reset and render again to get new count\n renderer.info.reset()\n renderer.render((window as any).scene, camera)\n const trianglesAfter = renderer.info.render.triangles\n const reduction = trianglesBefore - trianglesAfter\n const percentReduction =\n trianglesBefore > 0 ? Math.round((reduction / trianglesBefore) * 100) : 0\n\n console.log(`📊 Triangle count AFTER frustum culling: ${trianglesAfter.toLocaleString()}`)\n console.log(\n `📉 Triangle reduction: ${reduction.toLocaleString()} triangles (${percentReduction}% reduction)`\n )\n\n if (reduction > 0) {\n console.log(\n \"✅ Frustum culling is working! Try moving the camera to see different results.\"\n )\n } else {\n console.log(\"â„šī¸ No triangle reduction - all instances are currently visible to the camera.\")\n }\n } else {\n console.log(\"❌ No renderer found for triangle counting\")\n }\n\n console.log(\n \"💡 Move the camera around and call testFrustumCulling() again to see the difference!\"\n )\n }\n\n /**\n * Debug frustum culling for a specific asset type\n * @param assetPath Asset to debug (e.g., 'tree.obj')\n */\n public static debugFrustumCullingForAsset(assetPath: string): void {\n const camera = (window as any).camera || (window as any).game?.camera\n\n if (!camera) {\n console.log(\"❌ No camera found\")\n return\n }\n\n console.log(`🔍 === DEBUGGING FRUSTUM CULLING FOR '${assetPath}' ===`)\n\n // Get the GPU batches for this asset\n const batches = (AssetManager as any)._gpuBatches?.get(assetPath)\n\n if (!batches || batches.length === 0) {\n console.log(`❌ No GPU batches found for '${assetPath}'`)\n return\n }\n\n const batch = batches[0] // Use first batch\n console.log(`đŸ“Ļ Found batch with ${batch.instances.length} instances`)\n\n console.log(\n `đŸ”ĩ Culling radius: ${batch.cullingRadius.toFixed(2)} (encompasses entire geometry)`\n )\n\n // Test frustum culling for each instance\n const frustum = new THREE.Frustum()\n const cameraMatrix = new THREE.Matrix4().multiplyMatrices(\n camera.projectionMatrix,\n camera.matrixWorldInverse\n )\n frustum.setFromProjectionMatrix(cameraMatrix)\n\n let visibleCount = 0\n let culledCount = 0\n\n batch.instances.forEach((instance: any, index: number) => {\n const position = new THREE.Vector3().setFromMatrixPosition(instance.matrix)\n const scale = new THREE.Vector3().setFromMatrixScale(instance.matrix)\n const maxScale = Math.max(scale.x, scale.y, scale.z)\n\n const actualRadius = batch.cullingRadius * maxScale\n const paddedRadius = actualRadius * 1.2\n const isVisible = frustum.intersectsSphere(new THREE.Sphere(position, paddedRadius))\n\n if (index < 5) {\n // Log details for first 5 instances\n console.log(\n ` Instance ${index}: pos(${position.x.toFixed(1)}, ${position.z.toFixed(1)}), radius: ${paddedRadius.toFixed(2)}, visible: ${isVisible}`\n )\n }\n\n if (isVisible) {\n visibleCount++\n } else {\n culledCount++\n }\n })\n\n console.log(`đŸ‘ī¸ Visible instances: ${visibleCount}/${batch.instances.length}`)\n console.log(`âœ‚ī¸ Culled instances: ${culledCount}/${batch.instances.length}`)\n\n if (culledCount === 0) {\n console.log(\n \"💡 No instances are being culled. This might explain why you see objects on screen being culled incorrectly.\"\n )\n console.log(\"💡 Try moving the camera to point away from the objects to test culling.\")\n }\n }\n\n /**\n * Inspect scene objects to detect duplicate rendering\n */\n public static inspectScene(): void {\n const scene =\n (window as any).renderer?.scene || (window as any).game?.scene || (window as any).scene\n\n if (!scene) {\n console.log(\"❌ No scene available for inspection\")\n return\n }\n\n console.log(\"🔍 === SCENE INSPECTION ===\")\n console.log(`đŸ“Ļ Total scene children: ${scene.children.length}`)\n\n let instancedMeshCount = 0\n let regularMeshCount = 0\n let groupCount = 0\n let otherCount = 0\n\n const assetGroups: string[] = []\n const instancedMeshes: string[] = []\n\n scene.children.forEach((child: any, index: number) => {\n if (child.name.includes(\"_gpu_batch_\")) {\n instancedMeshCount++\n instancedMeshes.push(child.name)\n } else if (child.name.includes(\"_group\") || child.name.includes(\".obj\")) {\n groupCount++\n assetGroups.push(child.name)\n } else if (child.type === \"Mesh\") {\n regularMeshCount++\n } else {\n otherCount++\n }\n\n if (index < 15) {\n // Log first 15 objects\n console.log(\n ` ${index}: ${child.type} - \"${child.name}\" (${child.children?.length || 0} children)`\n )\n }\n })\n\n console.log(\"📊 SCENE OBJECT BREAKDOWN:\")\n console.log(` đŸŽ¯ InstancedMesh objects: ${instancedMeshCount}`)\n console.log(` đŸ“Ļ Asset groups: ${groupCount}`)\n console.log(` đŸ”ŗ Regular meshes: ${regularMeshCount}`)\n console.log(` 📝 Other objects: ${otherCount}`)\n\n if (assetGroups.length > 0) {\n console.log(\"âš ī¸ POTENTIAL DUPLICATE RENDERING DETECTED!\")\n console.log(\"đŸ“Ļ Asset groups in scene (these may cause duplicate rendering):\")\n assetGroups.slice(0, 10).forEach((name) => console.log(` - ${name}`)) // Limit to first 10\n if (assetGroups.length > 10) {\n console.log(` ... and ${assetGroups.length - 10} more`)\n }\n }\n\n if (instancedMeshes.length > 0) {\n console.log(\"✅ InstancedMesh objects in scene:\")\n instancedMeshes.forEach((name) => console.log(` - ${name}`))\n }\n }\n\n /**\n * Make all debug functions globally available\n */\n public static makeGloballyAvailable(): void {\n ;(window as any).printRenderingReport = RenderingDebugger.printRenderingReport\n ;(window as any).analyzeDrawCalls = RenderingDebugger.analyzeDrawCalls\n ;(window as any).testFrustumCulling = RenderingDebugger.testFrustumCulling\n ;(window as any).inspectScene = RenderingDebugger.inspectScene\n ;(window as any).getRenderingStats = RenderingDebugger.getRenderingStats\n ;(window as any).debugFrustumCulling = RenderingDebugger.debugFrustumCullingForAsset\n ;(window as any).setFrustumPadding = AssetManager.setFrustumCullingPadding\n ;(window as any).getFrustumPadding = AssetManager.getFrustumCullingPadding\n ;(window as any).debugBatchTypes = AssetManager.debugBatchTypes\n }\n}\n","import * as THREE from \"three\"\nimport { PhysicsSystem } from \"../physics/PhysicsSystem\"\nimport { DynamicNavSystem } from \"../navigation/DynamicNavSystem\"\nimport { NavGridDebugDisplayThree } from \"../navigation/NavGridDebugDisplayThree\"\nimport { PathVisualizationThree } from \"../navigation/PathVisualizationThree\"\nimport { SplineDebugManager } from \"../spline/SplineDebugManager\"\nimport { AssetManager } from \"@engine/assets/AssetManager\"\nimport { VenusGame } from \"@engine/core/VenusGame\"\n\n/**\n * Debug option interface for tracking state\n */\ninterface DebugOption {\n label: string\n checked: boolean\n onChange: (checked: boolean) => void\n element?: HTMLElement\n}\n\n/**\n * Base Debug panel for Three.js applications\n * Can be extended by specific game implementations to add custom debug options\n */\nexport class DebugPanelThree {\n // Static variable to always hide debug panel for release builds\n public static alwaysHide: boolean = false\n\n protected container!: HTMLElement\n protected contentContainer!: HTMLElement\n protected options: DebugOption[] = []\n protected isVisible: boolean = true\n protected contentsExpanded: boolean = true\n protected performanceStats: { fps: number; frameTime: number } = {\n fps: 0,\n frameTime: 0,\n }\n protected performanceElement?: HTMLElement\n protected playerPositionElement?: HTMLElement\n protected renderer?: any // Three.js renderer for draw call stats\n protected playerGameObject?: any // Player GameObject for position tracking\n\n constructor() {\n this.createPanel()\n this.setupKeyboardToggle()\n this.setupPerformanceMonitoring()\n this.addCoreOptions()\n\n // Hide the panel immediately if alwaysHide is enabled\n if (DebugPanelThree.alwaysHide) {\n this.hide()\n }\n }\n\n /**\n * Set the Three.js renderer for draw call tracking\n * Should be called by the game implementation\n */\n public setRenderer(renderer: any): void {\n this.renderer = renderer\n }\n\n /**\n * Set the player GameObject for position tracking\n * Should be called by the game implementation\n */\n public setPlayerGameObject(playerGameObject: any): void {\n this.playerGameObject = playerGameObject\n }\n\n /**\n * Create the main debug panel HTML structure\n */\n protected createPanel(): void {\n // Create main container\n this.container = document.createElement(\"div\")\n this.container.id = \"debug-panel-three\"\n this.container.style.cssText = `\n position: absolute;\n top: 20px;\n left: 20px;\n width: 240px;\n min-width: 240px;\n background: rgba(0, 0, 0, 0.8);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 8px;\n padding: 10px;\n font-family: 'Courier New', monospace;\n font-size: 14px;\n color: white;\n z-index: 1000;\n display: block;\n backdrop-filter: blur(10px);\n transition: width 0.3s ease-out;\n pointer-events: auto;\n `\n\n // Create title with expand/collapse functionality\n const titleContainer = document.createElement(\"div\")\n titleContainer.style.cssText = `\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: 10px;\n padding-bottom: 8px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n cursor: pointer;\n `\n\n const titleText = document.createElement(\"span\")\n titleText.textContent = \"Debug\"\n titleText.style.cssText = `\n font-weight: bold;\n color: #5B9AE8;\n `\n\n const expandCheckbox = document.createElement(\"input\")\n expandCheckbox.type = \"checkbox\"\n expandCheckbox.checked = this.contentsExpanded\n expandCheckbox.style.cssText = `\n margin-left: 10px;\n cursor: pointer;\n `\n\n titleContainer.appendChild(titleText)\n titleContainer.appendChild(expandCheckbox)\n this.container.appendChild(titleContainer)\n\n // Create content container\n this.contentContainer = document.createElement(\"div\")\n this.contentContainer.style.display = this.contentsExpanded ? \"block\" : \"none\"\n this.container.appendChild(this.contentContainer)\n\n // Add expand/collapse functionality\n const toggleContents = () => {\n this.contentsExpanded = !this.contentsExpanded\n expandCheckbox.checked = this.contentsExpanded\n this.contentContainer.style.display = this.contentsExpanded ? \"block\" : \"none\"\n\n // Adjust panel width and styling based on expanded state\n if (this.contentsExpanded) {\n this.container.style.width = \"240px\" // Full width when expanded\n this.container.style.minWidth = \"240px\"\n titleContainer.style.borderBottom = \"1px solid rgba(255, 255, 255, 0.2)\" // Show divider\n titleContainer.style.marginBottom = \"10px\"\n titleContainer.style.paddingBottom = \"8px\"\n } else {\n this.container.style.width = \"auto\" // Narrow width when collapsed\n this.container.style.minWidth = \"90px\"\n titleContainer.style.borderBottom = \"none\" // Hide divider\n titleContainer.style.marginBottom = \"0\"\n titleContainer.style.paddingBottom = \"0\"\n }\n }\n\n titleContainer.addEventListener(\"click\", toggleContents)\n expandCheckbox.addEventListener(\"click\", (e) => {\n e.stopPropagation()\n toggleContents()\n })\n\n // Add panel to UISystem container if available, otherwise document.body\n const uiContainer = document.getElementById(\"ui-system-three\")\n if (uiContainer) {\n uiContainer.appendChild(this.container)\n } else {\n // Fallback to document.body if UISystem is not initialized\n document.body.appendChild(this.container)\n }\n\n // Set initial width and styling based on expanded state\n if (this.contentsExpanded) {\n this.container.style.width = \"240px\"\n this.container.style.minWidth = \"240px\"\n titleContainer.style.borderBottom = \"1px solid rgba(255, 255, 255, 0.2)\"\n titleContainer.style.marginBottom = \"10px\"\n titleContainer.style.paddingBottom = \"8px\"\n } else {\n this.container.style.width = \"auto\"\n this.container.style.minWidth = \"90px\"\n titleContainer.style.borderBottom = \"none\"\n titleContainer.style.marginBottom = \"0\"\n titleContainer.style.paddingBottom = \"0\"\n }\n }\n\n /**\n * Add core debug options that all implementations should have\n * Can be overridden by implementations to add custom options\n */\n protected addCoreOptions(): void {\n // Add performance stats as the first option\n this.addOption(\"Performance Stats\", false, (checked) => {\n if (this.performanceElement) {\n this.performanceElement.style.display = checked ? \"block\" : \"none\"\n }\n })\n\n // Create performance stats display\n this.createPerformanceDisplay()\n\n // Add common debug options with working implementations\n this.addCommonDebugOptions()\n }\n\n /**\n * Add common debug options that most Three.js games will need\n * These have working implementations using dynamic imports\n */\n protected addCommonDebugOptions(): void {\n // Add physics debug toggle with working implementation\n this.addOption(\"Physics Debug\", false, (checked) => {\n PhysicsSystem.setDebugEnabled(checked)\n })\n\n // Add navigation debug toggle with working implementation\n this.addOption(\"Navigation Debug\", false, (checked) => {\n if (checked) {\n DynamicNavSystem.debugNavigation()\n } else {\n NavGridDebugDisplayThree.clearDebugLines()\n }\n })\n\n // Add path visualization toggle with working implementation\n this.addOption(\"Path Visualization\", false, (checked) => {\n PathVisualizationThree.setVisualizationEnabled(checked)\n // Path visualization toggled\n })\n\n // Add spline debug toggle with working implementation\n this.addOption(\"Spline Debug\", false, (checked) => {\n SplineDebugManager.getInstance().setDebugEnabled(checked)\n })\n\n // Post-processing option removed - using pure Three.js rendering\n\n // Add instancing report command (one-time action)\n this.addOption(\"Print Instance Report\", false, (checked) => {\n if (checked) {\n const report = AssetManager.getInstanceReport()\n console.log(report)\n\n // Also expose to global for easy access\n ;(window as any).getInstanceReport = () => AssetManager.getInstanceReport()\n console.log(\"💡 Use getInstanceReport() in console for updated reports\")\n\n // Remove this option after use (reset checkbox)\n setTimeout(() => {\n const checkbox = document.querySelector(\n `input[type=\"checkbox\"][data-label=\"Print Instance Report\"]`\n ) as HTMLInputElement\n if (checkbox) {\n checkbox.checked = false\n }\n }, 100)\n }\n })\n\n // Toggle to hide skinned meshes (for performance testing)\n this.addOption(\"Hide Skinned Meshes\", false, (checked) => {\n const scene = this.findScene()\n if (!scene) return\n scene.traverse((obj: THREE.Object3D) => {\n if (obj instanceof THREE.SkinnedMesh) {\n obj.visible = !checked\n }\n })\n })\n\n // Toggle to hide transparent objects (for performance testing)\n // DISABLED: Breaks purchase area displays which use transparent materials\n /*\n this.addOption(\"Hide Transparent\", false, (checked) => {\n const scene = this.findScene()\n if (!scene) return\n let count = 0\n scene.traverse((obj: THREE.Object3D) => {\n if (obj instanceof THREE.Mesh && !(obj instanceof THREE.SkinnedMesh)) {\n const mat = obj.material as THREE.Material\n if (mat && mat.transparent) {\n obj.visible = !checked\n count++\n }\n }\n })\n if (checked) console.log(`Hidden ${count} transparent objects`)\n })\n */\n\n // Toggle to hide blob shadows specifically\n this.addOption(\"Hide Blob Shadows\", false, (checked) => {\n const scene = this.findScene()\n if (!scene) return\n let count = 0\n scene.traverse((obj: THREE.Object3D) => {\n if (\n obj.name?.toLowerCase().includes(\"shadow\") ||\n obj.name?.toLowerCase().includes(\"blob\")\n ) {\n obj.visible = !checked\n count++\n }\n })\n if (checked) console.log(`Hidden ${count} blob shadows`)\n })\n\n // Toggle to use real shadows on characters instead of blob shadows\n this.addOption(\"Real Character Shadows\", false, (checked) => {\n const scene = this.findScene()\n if (!scene) return\n let skinnedCount = 0\n let blobCount = 0\n\n scene.traverse((obj: THREE.Object3D) => {\n // Enable/disable real shadows on skinned meshes\n if (obj instanceof THREE.SkinnedMesh) {\n obj.castShadow = checked\n skinnedCount++\n }\n // Hide/show blob shadows (opposite of real shadows)\n if (\n obj.name?.toLowerCase().includes(\"shadow\") ||\n obj.name?.toLowerCase().includes(\"blob\")\n ) {\n obj.visible = !checked\n blobCount++\n }\n })\n\n if (checked) {\n console.log(\n `Enabled real shadows on ${skinnedCount} skinned meshes, hidden ${blobCount} blob shadows`\n )\n } else {\n console.log(`Disabled real shadows, restored ${blobCount} blob shadows`)\n }\n })\n\n // Toggle to hide UI canvases (sprites/planes with canvas textures)\n // DISABLED: Breaks UI elements like purchase areas, indicators, etc.\n /*\n this.addOption(\"Hide UI Canvases\", false, (checked) => {\n const scene = this.findScene()\n if (!scene) return\n let count = 0\n scene.traverse((obj: THREE.Object3D) => {\n // Check for sprites\n if (obj instanceof THREE.Sprite) {\n obj.visible = !checked\n count++\n return\n }\n // Check for meshes with canvas textures or UI-like names\n if (obj instanceof THREE.Mesh) {\n const isUI = obj.name?.toLowerCase().includes('ui') ||\n obj.name?.toLowerCase().includes('canvas') ||\n obj.name?.toLowerCase().includes('label') ||\n obj.name?.toLowerCase().includes('text') ||\n obj.name?.toLowerCase().includes('indicator')\n if (isUI) {\n obj.visible = !checked\n count++\n return\n }\n // Check for CanvasTexture\n const mat = obj.material as THREE.MeshBasicMaterial\n if (mat?.map && (mat.map as any).isCanvasTexture) {\n obj.visible = !checked\n count++\n }\n }\n })\n if (checked) console.log(`Hidden ${count} UI canvas elements`)\n })\n */\n\n // Bake instancing for duplicate meshes (one-time performance optimization)\n this.addOption(\"Bake Instancing\", false, (checked) => {\n if (checked) {\n this.bakeInstancing()\n // Reset checkbox after running\n setTimeout(() => {\n const checkbox = document.querySelector(\n `input[type=\"checkbox\"][data-label=\"Bake Instancing\"]`\n ) as HTMLInputElement\n if (checkbox) {\n checkbox.checked = false\n }\n }, 100)\n }\n })\n\n // Add scene analysis command (one-time action)\n this.addOption(\"Run Scene Analysis\", false, (checked) => {\n if (checked) {\n this.runSceneAnalysis()\n // Reset checkbox after running\n setTimeout(() => {\n const checkbox = document.querySelector(\n `input[type=\"checkbox\"][data-label=\"Run Scene Analysis\"]`\n ) as HTMLInputElement\n if (checkbox) {\n checkbox.checked = false\n }\n }, 100)\n }\n })\n\n // Add render cost analysis command (one-time action)\n this.addOption(\"Run Render Cost Analysis\", false, (checked) => {\n if (checked) {\n this.runRenderCostAnalysis()\n // Reset checkbox after running\n setTimeout(() => {\n const checkbox = document.querySelector(\n `input[type=\"checkbox\"][data-label=\"Run Render Cost Analysis\"]`\n ) as HTMLInputElement\n if (checkbox) {\n checkbox.checked = false\n }\n }, 100)\n }\n })\n }\n\n /**\n * Run scene analysis to find instancing opportunities\n */\n protected runSceneAnalysis(): void {\n const scene = this.findScene()\n if (!scene) {\n console.warn(\"Scene not found for analysis\")\n return\n }\n\n console.log(\"%c=== SCENE ANALYSIS ===\", \"font-size: 16px; font-weight: bold; color: #00ff00\")\n\n const geometryGroups: Map<\n string,\n { count: number; name: string; triangles: number; examples: string[] }\n > = new Map()\n const nameGroups: Map<string, number> = new Map()\n let skinnedMeshCount = 0\n let totalMeshes = 0\n\n scene.traverse((obj: THREE.Object3D) => {\n if (obj instanceof THREE.SkinnedMesh) {\n skinnedMeshCount++\n totalMeshes++\n } else if (obj instanceof THREE.Mesh && obj.visible) {\n totalMeshes++\n const geomId = obj.geometry.uuid\n const triangles = obj.geometry.index\n ? obj.geometry.index.count / 3\n : (obj.geometry.attributes.position?.count || 0) / 3\n\n if (!geometryGroups.has(geomId)) {\n geometryGroups.set(geomId, {\n count: 0,\n name: obj.geometry.name || obj.name || \"unnamed\",\n triangles: Math.floor(triangles),\n examples: [],\n })\n }\n const group = geometryGroups.get(geomId)!\n group.count++\n if (group.examples.length < 3) {\n group.examples.push(obj.name || obj.parent?.name || \"unnamed\")\n }\n\n const baseName = (obj.name || \"unnamed\").replace(/[0-9_]+$/, \"\").trim() || \"unnamed\"\n nameGroups.set(baseName, (nameGroups.get(baseName) || 0) + 1)\n }\n })\n\n const instanceCandidates = [...geometryGroups.entries()]\n .filter(([_, data]) => data.count > 1)\n .sort((a, b) => b[1].count - a[1].count)\n .slice(0, 15)\n\n console.log(\"%cđŸ“Ļ TOP INSTANCING CANDIDATES:\", \"font-weight: bold; color: #ffff00\")\n console.table(\n instanceCandidates.map(([id, data]) => ({\n Geometry: data.name.substring(0, 30),\n Count: data.count,\n \"Triangles Each\": data.triangles,\n \"Potential Savings\": `${data.count - 1} draw calls`,\n Examples: data.examples.join(\", \").substring(0, 40),\n }))\n )\n\n console.log(\"%c📊 SUMMARY:\", \"font-weight: bold; color: #ff00ff\")\n console.table({\n \"Total Visible Meshes\": totalMeshes,\n \"Skinned Meshes (animated)\": skinnedMeshCount,\n \"Regular Meshes\": totalMeshes - skinnedMeshCount,\n \"Unique Geometries\": geometryGroups.size,\n \"Potential Draw Call Savings\": instanceCandidates.reduce(\n (sum, [_, d]) => sum + d.count - 1,\n 0\n ),\n })\n }\n\n /**\n * Run render cost analysis to identify bottlenecks\n */\n protected runRenderCostAnalysis(): void {\n const scene = this.findScene()\n if (!scene) {\n console.warn(\"Scene not found for analysis\")\n return\n }\n\n console.log(\n \"%c=== RENDER COST BREAKDOWN ===\",\n \"font-size: 16px; font-weight: bold; color: #ff6600\"\n )\n\n let staticCandidates = 0\n let alreadyStatic = 0\n let skinnedMeshes = 0\n let skinnedBoneCount = 0\n let shadowCasters = 0\n let shadowReceivers = 0\n let transparentObjects = 0\n let totalObjects = 0\n\n scene.traverse((obj: THREE.Object3D) => {\n totalObjects++\n\n if (obj.matrixAutoUpdate) {\n if (\n !(obj instanceof THREE.SkinnedMesh) &&\n !(obj.parent instanceof THREE.SkinnedMesh) &&\n !obj.name.toLowerCase().includes(\"player\")\n ) {\n staticCandidates++\n }\n } else {\n alreadyStatic++\n }\n\n if (obj instanceof THREE.SkinnedMesh) {\n skinnedMeshes++\n if (obj.skeleton) {\n skinnedBoneCount += obj.skeleton.bones.length\n }\n }\n\n if (obj instanceof THREE.Mesh || obj instanceof THREE.SkinnedMesh) {\n if (obj.castShadow) shadowCasters++\n if (obj.receiveShadow) shadowReceivers++\n\n const mat = obj.material as THREE.Material\n if (mat && mat.transparent) {\n transparentObjects++\n }\n }\n })\n\n let shadowLights = 0\n scene.traverse((obj: THREE.Object3D) => {\n if (obj instanceof THREE.Light && (obj as any).castShadow) {\n shadowLights++\n }\n })\n\n console.log(\"%c🔄 MATRIX UPDATES:\", \"font-weight: bold; color: #ffff00\")\n console.table({\n \"Total Objects\": totalObjects,\n \"With matrixAutoUpdate ON\": staticCandidates + skinnedMeshes,\n \"Could be static\": staticCandidates,\n \"Already static\": alreadyStatic,\n \"Potential CPU savings\": `${staticCandidates} matrix calcs/frame`,\n })\n\n console.log(\"%cđŸĻ´ SKINNED MESH (Animation) COST:\", \"font-weight: bold; color: #ff00ff\")\n console.table({\n \"Skinned Meshes\": skinnedMeshes,\n \"Total Bones\": skinnedBoneCount,\n \"Avg Bones per Character\":\n skinnedMeshes > 0 ? Math.round(skinnedBoneCount / skinnedMeshes) : 0,\n Impact: skinnedBoneCount > 500 ? \"âš ī¸ HIGH\" : \"✅ Reasonable\",\n })\n\n console.log(\"%c🌑 SHADOW COST:\", \"font-weight: bold; color: #00ffff\")\n console.table({\n \"Shadow-casting Lights\": shadowLights,\n \"Shadow Casters\": shadowCasters,\n \"Shadow Receivers\": shadowReceivers,\n Impact: shadowLights > 1 ? \"âš ī¸ Multiple shadow maps\" : \"✅ OK\",\n })\n\n console.log(\"%c🔮 TRANSPARENCY:\", \"font-weight: bold; color: #00ff00\")\n console.table({\n \"Transparent Objects\": transparentObjects,\n Impact: transparentObjects > 50 ? \"âš ī¸ Sorting overhead\" : \"✅ OK\",\n })\n\n console.log(\"%c📋 PRIORITY ACTIONS:\", \"font-weight: bold; color: #ffffff; background: #333\")\n const priorities: string[] = []\n if (staticCandidates > 50)\n priorities.push(`â€ĸ Set ${staticCandidates} objects to matrixAutoUpdate=false`)\n if (skinnedBoneCount > 300)\n priorities.push(`â€ĸ Consider LOD for characters (${skinnedBoneCount} bones)`)\n if (shadowCasters > 50) priorities.push(`â€ĸ Reduce shadow casters (${shadowCasters})`)\n if (transparentObjects > 30)\n priorities.push(`â€ĸ Reduce transparent objects (${transparentObjects})`)\n console.log(priorities.length > 0 ? priorities.join(\"\\n\") : \"✅ No major issues\")\n }\n\n /**\n * Get the scene from VenusGame\n */\n protected findScene(): THREE.Scene | null {\n try {\n return VenusGame.scene\n } catch {\n return null\n }\n }\n\n /**\n * Bake duplicate meshes into InstancedMeshes for better performance.\n * Finds meshes with the same geometry and replaces them with a single InstancedMesh.\n */\n protected bakeInstancing(): void {\n const scene = this.findScene()\n if (!scene) {\n console.warn(\"Scene not found for instancing\")\n return\n }\n\n console.log(\n \"%c=== BAKING INSTANCED MESHES ===\",\n \"font-size: 16px; font-weight: bold; color: #00ff00\"\n )\n\n // Group meshes by geometry UUID\n const geometryGroups: Map<string, THREE.Mesh[]> = new Map()\n\n scene.traverse((obj: THREE.Object3D) => {\n // Skip skinned meshes and instanced meshes\n if (obj instanceof THREE.SkinnedMesh) return\n if (obj instanceof THREE.InstancedMesh) return\n\n if (obj instanceof THREE.Mesh && obj.visible) {\n const geomId = obj.geometry.uuid\n if (!geometryGroups.has(geomId)) {\n geometryGroups.set(geomId, [])\n }\n geometryGroups.get(geomId)!.push(obj)\n }\n })\n\n // Find groups with 3+ meshes (worth instancing)\n let totalInstanced = 0\n let totalSaved = 0\n\n for (const [geomId, meshes] of geometryGroups) {\n if (meshes.length < 3) continue\n\n const firstMesh = meshes[0]\n const geometry = firstMesh.geometry\n const material = firstMesh.material\n\n // Skip if mesh has multiple materials (complex case)\n if (Array.isArray(material)) continue\n\n // Create InstancedMesh\n const instancedMesh = new THREE.InstancedMesh(geometry, material, meshes.length)\n instancedMesh.name = `Instanced_${firstMesh.name || \"unnamed\"}`\n instancedMesh.castShadow = firstMesh.castShadow\n instancedMesh.receiveShadow = firstMesh.receiveShadow\n\n // Set transforms for each instance\n const matrix = new THREE.Matrix4()\n for (let i = 0; i < meshes.length; i++) {\n const mesh = meshes[i]\n mesh.updateWorldMatrix(true, false)\n matrix.copy(mesh.matrixWorld)\n instancedMesh.setMatrixAt(i, matrix)\n }\n instancedMesh.instanceMatrix.needsUpdate = true\n\n // Add instanced mesh to scene\n scene.add(instancedMesh)\n\n // Remove original meshes\n for (const mesh of meshes) {\n if (mesh.parent) {\n mesh.parent.remove(mesh)\n }\n }\n\n console.log(\n `✅ Instanced ${meshes.length}x \"${firstMesh.name || \"unnamed\"}\" → 1 draw call (saved ${meshes.length - 1})`\n )\n totalInstanced += meshes.length\n totalSaved += meshes.length - 1\n }\n\n console.log(\"%c📊 INSTANCING COMPLETE:\", \"font-weight: bold; color: #ff00ff\")\n console.log(` Meshes instanced: ${totalInstanced}`)\n console.log(` Draw calls saved: ${totalSaved}`)\n }\n\n // Post-processing callback method removed - post-processing disabled\n\n /**\n * Add a debug option to the panel\n */\n public addOption(\n label: string,\n defaultValue: boolean,\n onChange: (checked: boolean) => void\n ): void {\n const optionContainer = document.createElement(\"div\")\n optionContainer.style.cssText = `\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px;\n margin: 4px 0;\n background: ${defaultValue ? \"rgba(91, 154, 232, 0.2)\" : \"rgba(255, 255, 255, 0.1)\"};\n border-radius: 4px;\n transition: background-color 0.2s;\n `\n\n const labelElement = document.createElement(\"span\")\n labelElement.textContent = label\n labelElement.style.cssText = `\n color: white;\n font-size: 13px;\n `\n\n const checkbox = document.createElement(\"input\")\n checkbox.type = \"checkbox\"\n checkbox.checked = defaultValue\n checkbox.setAttribute(\"data-label\", label) // Add data attribute for identification\n checkbox.style.cssText = `\n cursor: pointer;\n accent-color: #5B9AE8;\n `\n\n optionContainer.appendChild(labelElement)\n optionContainer.appendChild(checkbox)\n this.contentContainer.appendChild(optionContainer)\n\n // Store option data\n const option: DebugOption = {\n label,\n checked: defaultValue,\n onChange,\n element: optionContainer,\n }\n\n this.options.push(option)\n\n // Set up event handler\n checkbox.addEventListener(\"change\", () => {\n option.checked = checkbox.checked\n optionContainer.style.background = checkbox.checked\n ? \"rgba(91, 154, 232, 0.2)\"\n : \"rgba(255, 255, 255, 0.1)\"\n onChange(checkbox.checked)\n })\n\n // Trigger initial state\n onChange(defaultValue)\n }\n\n /**\n * Add a numeric slider to the panel\n */\n public addSlider(\n label: string,\n defaultValue: number,\n min: number,\n max: number,\n onChange: (value: number) => void\n ): void {\n const optionContainer = document.createElement(\"div\")\n optionContainer.style.cssText = `\n display: flex;\n flex-direction: column;\n padding: 8px;\n margin: 4px 0;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n `\n\n const labelContainer = document.createElement(\"div\")\n labelContainer.style.cssText = `\n display: flex;\n justify-content: space-between;\n margin-bottom: 4px;\n `\n\n const labelElement = document.createElement(\"span\")\n labelElement.textContent = label\n labelElement.style.cssText = `\n color: white;\n font-size: 13px;\n `\n\n const valueElement = document.createElement(\"span\")\n valueElement.textContent = defaultValue.toFixed(3)\n valueElement.style.cssText = `\n color: #5B9AE8;\n font-size: 12px;\n `\n\n const slider = document.createElement(\"input\")\n slider.type = \"range\"\n slider.min = min.toString()\n slider.max = max.toString()\n slider.step = ((max - min) / 100).toString()\n slider.value = defaultValue.toString()\n slider.style.cssText = `\n width: 100%;\n cursor: pointer;\n accent-color: #5B9AE8;\n `\n\n labelContainer.appendChild(labelElement)\n labelContainer.appendChild(valueElement)\n optionContainer.appendChild(labelContainer)\n optionContainer.appendChild(slider)\n this.contentContainer.appendChild(optionContainer)\n\n // Set up event handler\n slider.addEventListener(\"input\", () => {\n const value = parseFloat(slider.value)\n valueElement.textContent = value.toFixed(3)\n onChange(value)\n })\n\n // Trigger initial value\n onChange(defaultValue)\n }\n\n /**\n * Create performance stats display\n */\n protected createPerformanceDisplay(): void {\n this.performanceElement = document.createElement(\"div\")\n this.performanceElement.style.cssText = `\n padding: 8px;\n margin: 4px 0;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n font-size: 11px;\n display: none;\n line-height: 1.4;\n `\n\n this.performanceElement.innerHTML = `\n <div style=\"font-weight: bold; margin-bottom: 4px; color: #5B9AE8;\">Performance:</div>\n <div id=\"fps-display\">FPS: --</div>\n <div id=\"frame-time-display\">Frame Time: -- ms</div>\n \n <div style=\"font-weight: bold; margin: 6px 0 2px 0; color: #5B9AE8;\">Rendering:</div>\n <div id=\"draw-calls-display\">Draw Calls: --</div>\n <div id=\"triangles-display\">Triangles: --</div>\n \n <div style=\"font-weight: bold; margin: 6px 0 2px 0; color: #5B9AE8;\">Instancing:</div>\n <div id=\"total-instances-display\">Total: --</div>\n <div id=\"gpu-instances-display\">GPU: --</div>\n <div id=\"shared-instances-display\">Shared: --</div>\n <div id=\"cloned-instances-display\">Cloned: --</div>\n <div id=\"broken-instances-display\">Broken: --</div>\n <div id=\"geometry-reuse-display\">Geo Reuse: --x</div>\n `\n\n this.contentContainer.appendChild(this.performanceElement)\n }\n\n /**\n * Create player position display\n */\n protected createPlayerPositionDisplay(): void {\n this.playerPositionElement = document.createElement(\"div\")\n this.playerPositionElement.style.cssText = `\n padding: 8px;\n margin: 4px 0;\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n font-size: 11px;\n display: none;\n line-height: 1.4;\n `\n\n this.playerPositionElement.innerHTML = `\n <div style=\"font-weight: bold; margin-bottom: 4px; color: #5B9AE8;\">Player Position:</div>\n <div id=\"player-x-display\">X: --</div>\n <div id=\"player-y-display\">Y: --</div>\n <div id=\"player-z-display\">Z: --</div>\n `\n\n this.contentContainer.appendChild(this.playerPositionElement)\n }\n\n /**\n * Set up performance monitoring\n */\n protected setupPerformanceMonitoring(): void {\n let lastTime = performance.now()\n let frameCount = 0\n let fpsUpdateTime = performance.now()\n\n const updatePerformance = () => {\n const currentTime = performance.now()\n const deltaTime = currentTime - lastTime\n lastTime = currentTime\n\n frameCount++\n\n // Update FPS every second\n if (currentTime - fpsUpdateTime >= 1000) {\n this.performanceStats.fps = Math.round(frameCount / ((currentTime - fpsUpdateTime) / 1000))\n frameCount = 0\n fpsUpdateTime = currentTime\n }\n\n this.performanceStats.frameTime = Math.round(deltaTime * 100) / 100\n\n // Update display\n this.updatePerformanceDisplay()\n this.updatePlayerPositionDisplay()\n\n requestAnimationFrame(updatePerformance)\n }\n\n requestAnimationFrame(updatePerformance)\n }\n\n /**\n * Update all performance metrics in the display\n */\n protected updatePerformanceDisplay(): void {\n // Basic performance metrics\n const fpsDisplay = document.getElementById(\"fps-display\")\n const frameTimeDisplay = document.getElementById(\"frame-time-display\")\n\n if (fpsDisplay) fpsDisplay.textContent = `FPS: ${this.performanceStats.fps}`\n if (frameTimeDisplay)\n frameTimeDisplay.textContent = `Frame Time: ${this.performanceStats.frameTime} ms`\n\n // Three.js rendering metrics\n if (this.renderer && this.renderer.info) {\n const info = this.renderer.info\n\n const drawCallsDisplay = document.getElementById(\"draw-calls-display\")\n const trianglesDisplay = document.getElementById(\"triangles-display\")\n\n if (drawCallsDisplay) {\n const drawCalls = info.render?.calls || 0\n drawCallsDisplay.textContent = `Draw Calls: ${drawCalls}`\n\n // Color code draw calls (green = good, yellow = ok, red = bad)\n if (drawCalls < 50) {\n drawCallsDisplay.style.color = \"#4CAF50\" // Green\n } else if (drawCalls < 100) {\n drawCallsDisplay.style.color = \"#FF9800\" // Orange\n } else {\n drawCallsDisplay.style.color = \"#F44336\" // Red\n }\n }\n\n if (trianglesDisplay) {\n const triangles = info.render?.triangles || 0\n const trianglesK = Math.round(triangles / 1000)\n trianglesDisplay.textContent = `Triangles: ${trianglesK}K`\n\n // Color code triangles\n if (triangles < 50000) {\n trianglesDisplay.style.color = \"#4CAF50\" // Green\n } else if (triangles < 100000) {\n trianglesDisplay.style.color = \"#FF9800\" // Orange\n } else {\n trianglesDisplay.style.color = \"#F44336\" // Red\n }\n }\n\n // Manually reset renderer info if autoReset is disabled\n // This prevents accumulation of draw calls/triangles\n if (!info.autoReset) {\n info.reset()\n }\n }\n\n // Instancing statistics (import dynamically to avoid circular dependencies)\n const instanceStats = AssetManager.getGlobalInstanceStats()\n\n const totalDisplay = document.getElementById(\"total-instances-display\")\n const gpuDisplay = document.getElementById(\"gpu-instances-display\")\n const sharedDisplay = document.getElementById(\"shared-instances-display\")\n const clonedDisplay = document.getElementById(\"cloned-instances-display\")\n const brokenDisplay = document.getElementById(\"broken-instances-display\")\n const geoReuseDisplay = document.getElementById(\"geometry-reuse-display\")\n\n if (totalDisplay) totalDisplay.textContent = `Total: ${instanceStats.totalInstances}`\n\n if (gpuDisplay) {\n gpuDisplay.textContent = `GPU: ${instanceStats.gpuInstances}`\n\n // Color code GPU instances (higher is better for performance)\n const gpuPercent =\n instanceStats.totalInstances > 0\n ? Math.round((instanceStats.gpuInstances / instanceStats.totalInstances) * 100)\n : 0\n\n if (gpuPercent > 70) {\n gpuDisplay.style.color = \"#4CAF50\" // Green - excellent GPU usage\n } else if (gpuPercent > 40) {\n gpuDisplay.style.color = \"#FF9800\" // Orange - moderate GPU usage\n } else {\n gpuDisplay.style.color = \"#F44336\" // Red - poor GPU usage\n }\n }\n\n if (sharedDisplay) {\n const sharedPercent =\n instanceStats.totalInstances > 0\n ? Math.round((instanceStats.sharedInstances / instanceStats.totalInstances) * 100)\n : 0\n sharedDisplay.textContent = `Shared: ${instanceStats.sharedInstances} (${sharedPercent}%)`\n\n // Color code shared instances (higher % is better)\n if (sharedPercent > 70) {\n sharedDisplay.style.color = \"#4CAF50\" // Green\n } else if (sharedPercent > 40) {\n sharedDisplay.style.color = \"#FF9800\" // Orange\n } else {\n sharedDisplay.style.color = \"#F44336\" // Red\n }\n }\n\n if (clonedDisplay) {\n const clonedPercent =\n instanceStats.totalInstances > 0\n ? Math.round((instanceStats.clonedInstances / instanceStats.totalInstances) * 100)\n : 0\n clonedDisplay.textContent = `Cloned: ${instanceStats.clonedInstances} (${clonedPercent}%)`\n }\n\n if (brokenDisplay) {\n brokenDisplay.textContent = `Broken: ${instanceStats.brokenInstances}`\n\n // Color code broken instances (fewer is better)\n if (instanceStats.brokenInstances === 0) {\n brokenDisplay.style.color = \"#4CAF50\" // Green\n } else if (instanceStats.brokenInstances < 5) {\n brokenDisplay.style.color = \"#FF9800\" // Orange\n } else {\n brokenDisplay.style.color = \"#F44336\" // Red\n }\n }\n\n if (geoReuseDisplay) {\n geoReuseDisplay.textContent = `Geo Reuse: ${instanceStats.geometryReuse}x`\n\n // Color code geometry reuse (higher is better for instancing)\n if (instanceStats.geometryReuse > 3) {\n geoReuseDisplay.style.color = \"#4CAF50\" // Green\n } else if (instanceStats.geometryReuse > 1.5) {\n geoReuseDisplay.style.color = \"#FF9800\" // Orange\n } else {\n geoReuseDisplay.style.color = \"#F44336\" // Red\n }\n }\n }\n\n /**\n * Update player position display\n */\n protected updatePlayerPositionDisplay(): void {\n if (!this.playerGameObject) {\n // Set displays to show no data available\n const xDisplay = document.getElementById(\"player-x-display\")\n const yDisplay = document.getElementById(\"player-y-display\")\n const zDisplay = document.getElementById(\"player-z-display\")\n\n if (xDisplay) xDisplay.textContent = `X: --`\n if (yDisplay) yDisplay.textContent = `Y: --`\n if (zDisplay) zDisplay.textContent = `Z: --`\n return\n }\n\n try {\n // Get world position of the player\n const worldPos = new THREE.Vector3()\n this.playerGameObject.getWorldPosition(worldPos)\n\n // Update the position displays\n const xDisplay = document.getElementById(\"player-x-display\")\n const yDisplay = document.getElementById(\"player-y-display\")\n const zDisplay = document.getElementById(\"player-z-display\")\n\n if (xDisplay) xDisplay.textContent = `X: ${worldPos.x.toFixed(2)}`\n if (yDisplay) yDisplay.textContent = `Y: ${worldPos.y.toFixed(2)}`\n if (zDisplay) zDisplay.textContent = `Z: ${worldPos.z.toFixed(2)}`\n } catch (error) {\n // Silently handle errors when player object is not available\n const xDisplay = document.getElementById(\"player-x-display\")\n const yDisplay = document.getElementById(\"player-y-display\")\n const zDisplay = document.getElementById(\"player-z-display\")\n\n if (xDisplay) xDisplay.textContent = `X: --`\n if (yDisplay) yDisplay.textContent = `Y: --`\n if (zDisplay) zDisplay.textContent = `Z: --`\n }\n }\n\n /**\n * Set up keyboard toggle for debug panel\n */\n protected setupKeyboardToggle(): void {\n document.addEventListener(\"keydown\", (event) => {\n if (event.key === \"`\" || event.key === \"~\") {\n // Backtick or tilde key\n this.toggle()\n event.preventDefault()\n } else if (event.key === \"Tab\") {\n // Tab key - complete visibility toggle for marketing purposes\n this.toggle()\n event.preventDefault()\n }\n })\n }\n\n /**\n * Show the debug panel\n */\n public show(): void {\n // Don't show if always hidden for release builds\n if (DebugPanelThree.alwaysHide) {\n return\n }\n\n this.isVisible = true\n this.container.style.display = \"block\"\n }\n\n /**\n * Hide the debug panel\n */\n public hide(): void {\n this.isVisible = false\n this.container.style.display = \"none\"\n }\n\n /**\n * Toggle the debug panel visibility\n */\n public toggle(): void {\n // Don't toggle if always hidden for release builds\n if (DebugPanelThree.alwaysHide) {\n return\n }\n\n if (this.isVisible) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n /**\n * Get current visibility state\n */\n public getVisibility(): boolean {\n return this.isVisible\n }\n\n /**\n * Dispose of the debug panel\n */\n public dispose(): void {\n if (this.container && this.container.parentNode) {\n this.container.parentNode.removeChild(this.container)\n }\n this.options = []\n }\n}\n","import * as THREE from \"three\"\nimport { NavigationGrid, Footprint } from \"./NavigationGrid\"\nimport { NavGridDebugDisplayThree } from \"./NavGridDebugDisplayThree\"\nimport { GameObject } from \"@engine/core\"\nimport { RigidBodyComponentThree } from \"@systems/physics\"\n\nexport interface Waypoint {\n x: number\n z: number\n}\n\nexport interface PathfindingResult {\n success: boolean\n waypoints: Waypoint[]\n distance: number\n}\n\ninterface PathNode {\n col: number\n row: number\n gCost: number // Distance from start\n hCost: number // Heuristic distance to end\n fCost: number // gCost + hCost\n parent: PathNode | null\n}\n\n/**\n * Three.js version of DynamicNavSystem\n * Uses Three.js Vector2/Vector3 instead of Babylon.js types\n * Clean static API with no scene dependency needed\n */\nexport class DynamicNavSystem {\n private static navigationGrid: NavigationGrid | null = null\n private static scene: THREE.Scene | null = null\n private static isInitialized: boolean = false\n private static obstacleRegistry = new Map<string, Footprint>()\n\n /**\n * Initialize the navigation system (must be called before use)\n * Scene parameter is optional - only needed for debug visualization\n */\n public static initialize(\n scene?: THREE.Scene,\n worldWidth: number = 200,\n worldDepth: number = 200,\n gridSize: number = 2\n ): void {\n if (DynamicNavSystem.isInitialized) {\n console.warn(\"DynamicNavSystem already initialized\")\n return\n }\n\n DynamicNavSystem.scene = scene || null\n DynamicNavSystem.navigationGrid = new NavigationGrid(worldWidth, worldDepth, gridSize)\n DynamicNavSystem.isInitialized = true\n\n // Initialize debug display system if scene is provided\n if (scene) {\n NavGridDebugDisplayThree.initialize(scene)\n }\n\n // DynamicNavSystem initialized\n }\n\n /**\n * Check if the system is initialized\n */\n public static getIsInitialized(): boolean {\n return DynamicNavSystem.isInitialized\n }\n\n /**\n * Dispose of the navigation system\n */\n public static dispose(): void {\n if (DynamicNavSystem.isInitialized) {\n //NavGridDebugDisplayThree.dispose()\n DynamicNavSystem.navigationGrid = null\n DynamicNavSystem.scene = null\n DynamicNavSystem.isInitialized = false\n console.log(\"DynamicNavSystem disposed\")\n }\n }\n\n /**\n * Add an obstacle to the navigation grid\n */\n public static addObstacle(footprint: Footprint): void {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return\n }\n\n DynamicNavSystem.navigationGrid.addObstacle(footprint)\n }\n\n /**\n * Remove an obstacle from the navigation grid\n */\n public static removeObstacle(footprint: Footprint): void {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return\n }\n\n DynamicNavSystem.navigationGrid.removeObstacle(footprint)\n }\n\n /**\n * Check if a position is walkable\n */\n public static isWalkable(x: number, z: number): boolean {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return false\n }\n\n const gridPos = DynamicNavSystem.navigationGrid.worldToGrid(x, z)\n return DynamicNavSystem.navigationGrid.isWalkable(gridPos.col, gridPos.row)\n }\n\n /**\n * Convert world coordinates to grid coordinates\n */\n public static worldToGrid(x: number, z: number): { col: number; row: number } | null {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return null\n }\n\n return DynamicNavSystem.navigationGrid.worldToGrid(x, z)\n }\n\n /**\n * Convert grid coordinates to world coordinates\n */\n public static gridToWorld(col: number, row: number): { x: number; z: number } | null {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return null\n }\n\n return DynamicNavSystem.navigationGrid.gridToWorld(col, row)\n }\n\n /**\n * Debug method to print current navigation state\n */\n public static debugNavigation(): void {\n NavGridDebugDisplayThree.debugNavigation(DynamicNavSystem.navigationGrid)\n }\n\n /**\n * Add a box obstacle to the navigation grid\n * @param x World X position (center)\n * @param z World Z position (center)\n * @param width Width of the obstacle\n * @param depth Depth of the obstacle\n */\n public static addBoxObstacle(x: number, z: number, width: number, depth: number): void {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return\n }\n\n // Create a polygon footprint for the box\n const halfWidth = width * 0.5\n const halfDepth = depth * 0.5\n\n const footprint: Footprint = {\n type: \"polygon\",\n vertices: [\n new THREE.Vector3(x - halfWidth, 0, z - halfDepth),\n new THREE.Vector3(x + halfWidth, 0, z - halfDepth),\n new THREE.Vector3(x + halfWidth, 0, z + halfDepth),\n new THREE.Vector3(x - halfWidth, 0, z + halfDepth),\n ],\n }\n\n DynamicNavSystem.navigationGrid.addObstacle(footprint)\n // Box obstacle added (logging disabled)\n }\n\n /**\n * Remove a box obstacle from the navigation grid\n * @param x World X position (center)\n * @param z World Z position (center)\n * @param width Width of the obstacle\n * @param depth Depth of the obstacle\n */\n public static removeBoxObstacle(x: number, z: number, width: number, depth: number): void {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return\n }\n\n // Create a polygon footprint for the box (same as addBoxObstacle)\n const halfWidth = width * 0.5\n const halfDepth = depth * 0.5\n\n const footprint: Footprint = {\n type: \"polygon\",\n vertices: [\n new THREE.Vector3(x - halfWidth, 0, z - halfDepth),\n new THREE.Vector3(x + halfWidth, 0, z - halfDepth),\n new THREE.Vector3(x + halfWidth, 0, z + halfDepth),\n new THREE.Vector3(x - halfWidth, 0, z + halfDepth),\n ],\n }\n\n DynamicNavSystem.navigationGrid.removeObstacle(footprint)\n console.log(`🚧 Removed box obstacle at (${x}, ${z}) with size ${width}x${depth}`)\n }\n\n public static addBoxObstacleFromRigidBody(gameObject: GameObject): void {\n const rigidBody = gameObject.getComponent(RigidBodyComponentThree)\n if (!rigidBody) return\n\n const bounds = rigidBody.getBounds()\n const boundsSize = bounds.getSize(new THREE.Vector3())\n DynamicNavSystem.addBoxObstacleFromBounds(gameObject, boundsSize)\n }\n\n /**\n * Add a box obstacle from a GameObject and its bounds size\n * @param gameObject The GameObject to get world position from\n * @param boundsSize The size from renderer bounds (uses X and Z for navigation)\n */\n public static addBoxObstacleFromBounds(gameObject: GameObject, boundsSize: THREE.Vector3): void {\n // Get world position of the object\n const worldPos = gameObject.getWorldPosition(new THREE.Vector3())\n\n // Get the Y rotation to determine if dimensions need to be swapped\n const worldRotation = gameObject.getWorldQuaternion(new THREE.Quaternion())\n const euler = new THREE.Euler().setFromQuaternion(worldRotation)\n const rotationY = euler.y\n\n // Use X and Z dimensions for navigation (ignore Y/height)\n let width = boundsSize.x\n let depth = boundsSize.z\n\n // For 90° and 270° rotations, swap width and depth\n // Normalize rotation to 0-2Ī€ range to handle negative values\n let normalizedRotation = rotationY % (Math.PI * 2)\n if (normalizedRotation < 0) normalizedRotation += Math.PI * 2\n\n const is90Degrees = Math.abs(normalizedRotation - Math.PI * 0.5) < 0.1\n const is270Degrees = Math.abs(normalizedRotation - Math.PI * 1.5) < 0.1\n\n if (is90Degrees || is270Degrees) {\n // Swap dimensions for rotated objects\n const temp = width\n width = depth\n depth = temp\n }\n\n // Add obstacle to navigation system\n DynamicNavSystem.addBoxObstacle(worldPos.x, worldPos.z, width, depth)\n // Navigation obstacle added (logging disabled)\n }\n\n /**\n * Add a rotated box obstacle from bounds and track it by GameObject ID\n * @param gameObject The GameObject to get world transform from\n * @param boundsSize The size from bounds (uses X and Z for navigation)\n * @returns The ID used to track this obstacle (GameObject UUID)\n */\n public static addRotatedBoxObstacle(gameObject: GameObject, boundsSize: THREE.Vector3): string {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return \"\"\n }\n\n // Update world matrices to ensure accurate transforms\n gameObject.updateMatrixWorld(true)\n\n // Get world position and rotation\n const worldPos = gameObject.getWorldPosition(new THREE.Vector3())\n const worldRotation = gameObject.getWorldQuaternion(new THREE.Quaternion())\n\n // Calculate the 4 corners of the box in local space\n const halfWidth = boundsSize.x * 0.5\n const halfDepth = boundsSize.z * 0.5\n\n const corners = [\n new THREE.Vector3(-halfWidth, 0, -halfDepth),\n new THREE.Vector3(halfWidth, 0, -halfDepth),\n new THREE.Vector3(halfWidth, 0, halfDepth),\n new THREE.Vector3(-halfWidth, 0, halfDepth),\n ]\n\n // Rotate and translate corners to world space\n const rotatedCorners = corners.map((corner) => {\n const rotated = corner.clone()\n rotated.applyQuaternion(worldRotation)\n rotated.add(worldPos)\n return rotated\n })\n\n // Create polygon footprint\n const footprint: Footprint = {\n type: \"polygon\",\n vertices: rotatedCorners,\n }\n\n // Add obstacle\n DynamicNavSystem.navigationGrid.addObstacle(footprint)\n\n // Store in registry using GameObject UUID\n const id = gameObject.uuid\n DynamicNavSystem.obstacleRegistry.set(id, footprint)\n\n return id\n }\n\n /**\n * Remove an obstacle by GameObject ID\n * @param id The ID returned from addRotatedBoxObstacle (GameObject UUID)\n * @returns true if obstacle was found and removed\n */\n public static removeObstacleById(id: string): boolean {\n if (!DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return false\n }\n\n const footprint = DynamicNavSystem.obstacleRegistry.get(id)\n if (!footprint) {\n return false\n }\n\n // Remove from navigation grid\n DynamicNavSystem.navigationGrid.removeObstacle(footprint)\n\n // Remove from registry\n DynamicNavSystem.obstacleRegistry.delete(id)\n\n return true\n }\n\n /**\n * Remove an obstacle by GameObject\n * @param gameObject The GameObject whose obstacle should be removed\n * @returns true if obstacle was found and removed\n */\n public static removeObstacleByGameObject(gameObject: GameObject): boolean {\n return DynamicNavSystem.removeObstacleById(gameObject.uuid)\n }\n\n // ========================================\n // PATHFINDING METHODS\n // ========================================\n\n /**\n * Find a path from start position to end position using A* pathfinding\n * @param startPos Start position as THREE.Vector2 (x, z)\n * @param endPos End position as THREE.Vector2 (x, z)\n */\n public static findPath(startPos: THREE.Vector2, endPos: THREE.Vector2): PathfindingResult\n\n /**\n * Find a path from start position to end position using A* pathfinding\n * @param startPos Start position as THREE.Vector3 (uses x, z components)\n * @param endPos End position as THREE.Vector3 (uses x, z components)\n */\n public static findPath(startPos: THREE.Vector3, endPos: THREE.Vector3): PathfindingResult\n\n /**\n * Implementation for findPath - main logic using THREE.Vector2\n */\n public static findPath(\n startPos: THREE.Vector2 | THREE.Vector3,\n endPos: THREE.Vector2 | THREE.Vector3\n ): PathfindingResult {\n // Convert inputs to THREE.Vector2\n let start: THREE.Vector2, end: THREE.Vector2\n\n if (startPos instanceof THREE.Vector3) {\n start = new THREE.Vector2(startPos.x, startPos.z)\n } else {\n start = startPos\n }\n\n if (endPos instanceof THREE.Vector3) {\n end = new THREE.Vector2(endPos.x, endPos.z)\n } else {\n end = endPos\n }\n\n // Main pathfinding implementation\n if (!DynamicNavSystem.isInitialized || !DynamicNavSystem.navigationGrid) {\n console.warn(\"DynamicNavSystem not initialized\")\n return { success: false, waypoints: [], distance: 0 }\n }\n\n // Convert world coordinates to grid coordinates\n const startGrid = DynamicNavSystem.navigationGrid.worldToGrid(start.x, start.y)\n const endGrid = DynamicNavSystem.navigationGrid.worldToGrid(end.x, end.y)\n\n // Check if start and end positions are valid\n if (!DynamicNavSystem.navigationGrid.isWalkable(startGrid.col, startGrid.row)) {\n // Find the closest walkable cell to the start position\n const closestWalkableStartCell = DynamicNavSystem.findClosestWalkableCell(startGrid)\n if (!closestWalkableStartCell) {\n console.warn(`No walkable position found near start position (${start.x}, ${start.y})`)\n return { success: false, waypoints: [], distance: 0 }\n }\n\n // Update the start to the closest walkable cell\n startGrid.col = closestWalkableStartCell.col\n startGrid.row = closestWalkableStartCell.row\n // Adjusted start position (logging disabled)\n }\n\n if (!DynamicNavSystem.navigationGrid.isWalkable(endGrid.col, endGrid.row)) {\n // Find the closest walkable cell to the target\n const closestWalkableCell = DynamicNavSystem.findClosestWalkableCell(endGrid)\n if (!closestWalkableCell) {\n return { success: false, waypoints: [], distance: 0 }\n }\n\n // Update the target to the closest walkable cell\n endGrid.col = closestWalkableCell.col\n endGrid.row = closestWalkableCell.row\n }\n\n // Run A* pathfinding on the grid\n const gridPath = DynamicNavSystem.findPathAStar(startGrid, endGrid)\n\n if (gridPath.length === 0) {\n return { success: false, waypoints: [], distance: 0 }\n }\n\n // Convert grid path to world waypoints\n const worldPath = gridPath.map((node) => {\n const worldPos = DynamicNavSystem.navigationGrid!.gridToWorld(node.col, node.row)\n return { x: worldPos.x, z: worldPos.z }\n })\n\n // Simplify path to reduce waypoints (remove unnecessary intermediate points)\n const simplifiedPath = DynamicNavSystem.simplifyPath(worldPath)\n\n // CRITICAL: Use exact target position instead of grid center for final waypoint (like Babylon.js)\n if (simplifiedPath.length > 0 && gridPath.length > 0) {\n const finalPathCell = gridPath[gridPath.length - 1]\n // If pathfinding reached the target cell, use exact target position\n if (finalPathCell.col === endGrid.col && finalPathCell.row === endGrid.row) {\n // Check if target was redirected to a different cell\n const originalTargetGrid = DynamicNavSystem.navigationGrid!.worldToGrid(end.x, end.y)\n if (endGrid.col === originalTargetGrid.col && endGrid.row === originalTargetGrid.row) {\n // Target wasn't redirected, use exact position\n simplifiedPath[simplifiedPath.length - 1] = {\n x: end.x,\n z: end.y,\n }\n } else {\n // Target was redirected, find closest point in the reachable cell to original target\n const cellWorldPos = DynamicNavSystem.navigationGrid!.gridToWorld(\n endGrid.col,\n endGrid.row\n )\n const gridSize = DynamicNavSystem.navigationGrid!.getDimensions().gridSize\n const halfGrid = gridSize / 2\n\n // Clamp original target to be within the reachable cell bounds\n const clampedX = Math.max(\n cellWorldPos.x - halfGrid,\n Math.min(cellWorldPos.x + halfGrid, end.x)\n )\n const clampedZ = Math.max(\n cellWorldPos.z - halfGrid,\n Math.min(cellWorldPos.z + halfGrid, end.y)\n )\n\n simplifiedPath[simplifiedPath.length - 1] = {\n x: clampedX,\n z: clampedZ,\n }\n }\n }\n }\n\n // Calculate total distance\n const distance = DynamicNavSystem.calculatePathDistance(simplifiedPath)\n\n return {\n success: true,\n waypoints: simplifiedPath,\n distance: distance,\n }\n }\n\n /**\n * Find the closest walkable cell to a given position\n */\n private static findClosestWalkableCell(targetPos: {\n col: number\n row: number\n }): { col: number; row: number } | null {\n if (!DynamicNavSystem.navigationGrid) return null\n\n const maxSearchRadius = 10\n const gridInfo = DynamicNavSystem.navigationGrid.getDimensions()\n\n for (let radius = 1; radius <= maxSearchRadius; radius++) {\n for (let dx = -radius; dx <= radius; dx++) {\n for (let dz = -radius; dz <= radius; dz++) {\n // Skip inner cells (already checked in smaller radius)\n if (Math.abs(dx) < radius && Math.abs(dz) < radius) continue\n\n const checkCol = targetPos.col + dx\n const checkRow = targetPos.row + dz\n\n // Check bounds\n if (\n checkCol < 0 ||\n checkCol >= gridInfo.cols ||\n checkRow < 0 ||\n checkRow >= gridInfo.rows\n ) {\n continue\n }\n\n if (DynamicNavSystem.navigationGrid.isWalkable(checkCol, checkRow)) {\n return { col: checkCol, row: checkRow }\n }\n }\n }\n }\n\n return null\n }\n\n /**\n * A* pathfinding algorithm implementation\n * Returns array of grid nodes representing the path\n */\n private static findPathAStar(\n start: { col: number; row: number },\n end: { col: number; row: number }\n ): PathNode[] {\n const openSet: PathNode[] = []\n const closedSet: Set<string> = new Set()\n const gridInfo = DynamicNavSystem.navigationGrid!.getDimensions()\n\n // Create start node\n const startNode: PathNode = {\n col: start.col,\n row: start.row,\n gCost: 0,\n hCost: DynamicNavSystem.getDistance(start.col, start.row, end.col, end.row),\n fCost: 0,\n parent: null,\n }\n startNode.fCost = startNode.gCost + startNode.hCost\n\n openSet.push(startNode)\n\n while (openSet.length > 0) {\n // Find node with lowest fCost\n let currentNode = openSet[0]\n let currentIndex = 0\n\n for (let i = 1; i < openSet.length; i++) {\n if (\n openSet[i].fCost < currentNode.fCost ||\n (openSet[i].fCost === currentNode.fCost && openSet[i].hCost < currentNode.hCost)\n ) {\n currentNode = openSet[i]\n currentIndex = i\n }\n }\n\n // Remove current node from open set\n openSet.splice(currentIndex, 1)\n const nodeKey = `${currentNode.col},${currentNode.row}`\n closedSet.add(nodeKey)\n\n // Check if we reached the target\n if (currentNode.col === end.col && currentNode.row === end.row) {\n return DynamicNavSystem.reconstructPath(currentNode)\n }\n\n // Check all neighbors (8-directional movement)\n const neighbors = [\n { col: -1, row: -1 },\n { col: 0, row: -1 },\n { col: 1, row: -1 },\n { col: -1, row: 0 },\n { col: 1, row: 0 },\n { col: -1, row: 1 },\n { col: 0, row: 1 },\n { col: 1, row: 1 },\n ]\n\n for (const neighborOffset of neighbors) {\n const neighborCol = currentNode.col + neighborOffset.col\n const neighborRow = currentNode.row + neighborOffset.row\n const neighborKey = `${neighborCol},${neighborRow}`\n\n // Skip if out of bounds\n if (\n neighborCol < 0 ||\n neighborCol >= gridInfo.cols ||\n neighborRow < 0 ||\n neighborRow >= gridInfo.rows\n ) {\n continue\n }\n\n // Skip if not walkable or already in closed set\n if (\n !DynamicNavSystem.navigationGrid!.isWalkable(neighborCol, neighborRow) ||\n closedSet.has(neighborKey)\n ) {\n continue\n }\n\n // Calculate movement cost (diagonal movement costs more)\n const isDiagonal = neighborOffset.col !== 0 && neighborOffset.row !== 0\n const movementCost = isDiagonal ? 1.414 : 1.0 // sqrt(2) for diagonal\n const tentativeGCost = currentNode.gCost + movementCost\n\n // Check if this neighbor is already in open set\n let neighborNode = openSet.find(\n (node) => node.col === neighborCol && node.row === neighborRow\n )\n\n if (!neighborNode) {\n // Create new node\n neighborNode = {\n col: neighborCol,\n row: neighborRow,\n gCost: tentativeGCost,\n hCost: DynamicNavSystem.getDistance(neighborCol, neighborRow, end.col, end.row),\n fCost: 0,\n parent: currentNode,\n }\n neighborNode.fCost = neighborNode.gCost + neighborNode.hCost\n openSet.push(neighborNode)\n } else if (tentativeGCost < neighborNode.gCost) {\n // Update existing node with better path\n neighborNode.gCost = tentativeGCost\n neighborNode.fCost = neighborNode.gCost + neighborNode.hCost\n neighborNode.parent = currentNode\n }\n }\n }\n\n return [] // No path found\n }\n\n /**\n * Reconstruct path from the end node back to start\n */\n private static reconstructPath(endNode: PathNode): PathNode[] {\n const path: PathNode[] = []\n let current: PathNode | null = endNode\n\n while (current !== null) {\n path.unshift(current)\n current = current.parent\n }\n\n return path\n }\n\n /**\n * Calculate distance between two grid positions (Manhattan distance with diagonal support)\n */\n private static getDistance(col1: number, row1: number, col2: number, row2: number): number {\n const dx = Math.abs(col1 - col2)\n const dy = Math.abs(row1 - row2)\n\n // Use diagonal distance calculation for better heuristic\n const diagonalSteps = Math.min(dx, dy)\n const straightSteps = Math.max(dx, dy) - diagonalSteps\n\n return diagonalSteps * 1.414 + straightSteps * 1.0\n }\n\n /**\n * Simplify path by removing unnecessary waypoints using line-of-sight optimization\n */\n private static simplifyPath(waypoints: Waypoint[]): Waypoint[] {\n if (waypoints.length <= 2) {\n return waypoints\n }\n\n const simplified: Waypoint[] = [waypoints[0]] // Always include start point\n let currentIndex = 0\n\n while (currentIndex < waypoints.length - 1) {\n let farthestReachable = currentIndex + 1\n\n // Find the farthest point we can reach in a straight line\n for (let testIndex = currentIndex + 2; testIndex < waypoints.length; testIndex++) {\n if (DynamicNavSystem.hasLineOfSight(waypoints[currentIndex], waypoints[testIndex])) {\n farthestReachable = testIndex\n } else {\n break\n }\n }\n\n simplified.push(waypoints[farthestReachable])\n currentIndex = farthestReachable\n }\n\n return simplified\n }\n\n /**\n * Check if there's a clear line of sight between two waypoints\n */\n private static hasLineOfSight(start: Waypoint, end: Waypoint): boolean {\n if (!DynamicNavSystem.navigationGrid) return false\n\n // Convert to grid coordinates\n const startGrid = DynamicNavSystem.navigationGrid.worldToGrid(start.x, start.z)\n const endGrid = DynamicNavSystem.navigationGrid.worldToGrid(end.x, end.z)\n\n // Use Bresenham's line algorithm to check each grid cell along the line\n const dx = Math.abs(endGrid.col - startGrid.col)\n const dz = Math.abs(endGrid.row - startGrid.row)\n let x = startGrid.col\n let z = startGrid.row\n const xInc = startGrid.col < endGrid.col ? 1 : -1\n const zInc = startGrid.row < endGrid.row ? 1 : -1\n let error = dx - dz\n\n for (let i = 0; i <= dx + dz; i++) {\n // Check if current cell is walkable\n if (!DynamicNavSystem.navigationGrid.isWalkable(x, z)) {\n return false\n }\n\n if (x === endGrid.col && z === endGrid.row) {\n break\n }\n\n const error2 = error * 2\n if (error2 > -dz) {\n error -= dz\n x += xInc\n }\n if (error2 < dx) {\n error += dx\n z += zInc\n }\n }\n\n return true\n }\n\n /**\n * Calculate total distance of a path (like Babylon.js version)\n */\n private static calculatePathDistance(waypoints: Waypoint[]): number {\n let totalDistance = 0\n for (let i = 0; i < waypoints.length - 1; i++) {\n const dx = waypoints[i + 1].x - waypoints[i].x\n const dz = waypoints[i + 1].z - waypoints[i].z\n totalDistance += Math.sqrt(dx * dx + dz * dz)\n }\n return totalDistance\n }\n\n /**\n * Check if a path exists between two positions (faster than full pathfinding)\n */\n public static canReach(startX: number, startZ: number, endX: number, endZ: number): boolean {\n if (!DynamicNavSystem.isInitialized || !DynamicNavSystem.navigationGrid) {\n return false\n }\n\n // Quick checks first\n if (!DynamicNavSystem.isWalkable(startX, startZ) || !DynamicNavSystem.isWalkable(endX, endZ)) {\n return false\n }\n\n // If very close, just check line of sight\n const distance = Math.sqrt((endX - startX) ** 2 + (endZ - startZ) ** 2)\n if (distance <= DynamicNavSystem.navigationGrid.getDimensions().gridSize * 2) {\n return DynamicNavSystem.hasLineOfSight({ x: startX, z: startZ }, { x: endX, z: endZ })\n }\n\n // For longer distances, use simplified A* with early exit\n const result = DynamicNavSystem.findPath(\n new THREE.Vector2(startX, startZ),\n new THREE.Vector2(endX, endZ)\n )\n return result.success\n }\n}\n","import { Vector3 } from \"three\"\n\nexport interface Footprint {\n type: \"polygon\" | \"circle\"\n vertices?: Vector3[]\n x?: number\n z?: number\n radius?: number\n}\n\nexport interface AABB {\n minX: number\n minZ: number\n maxX: number\n maxZ: number\n}\n\n/**\n * A fast 2D navigation grid using reference counting for obstacle management\n * OPTIMIZED for high-performance incremental add/remove operations\n */\nexport class NavigationGrid {\n private grid: number[][]\n private worldWidth: number\n private worldDepth: number\n private gridSize: number\n private cols: number\n private rows: number\n\n // Performance optimization: Pre-calculated frequently used values\n private halfWorldWidth: number\n private halfWorldDepth: number\n private halfGridSize: number\n private gridSizeInv: number // 1/gridSize for fast division\n\n // Debug mode flag - disable for production performance\n private static DEBUG_MODE: boolean = false\n\n constructor(worldWidth: number, worldDepth: number, gridSize: number) {\n this.worldWidth = worldWidth\n this.worldDepth = worldDepth\n this.gridSize = gridSize\n\n this.cols = Math.ceil(worldWidth / gridSize)\n this.rows = Math.ceil(worldDepth / gridSize)\n\n // Pre-calculate frequently used values for performance\n this.halfWorldWidth = worldWidth * 0.5\n this.halfWorldDepth = worldDepth * 0.5\n this.halfGridSize = gridSize * 0.5\n this.gridSizeInv = 1.0 / gridSize\n\n // Initialize grid: each cell stores a reference count\n this.grid = Array(this.rows)\n .fill(null)\n .map(() => Array(this.cols).fill(0))\n\n if (NavigationGrid.DEBUG_MODE) {\n console.log(\n `NavigationGrid: Initialized ${this.cols}x${this.rows} grid, cellSize=${gridSize}`\n )\n }\n }\n\n /**\n * OPTIMIZED: Converts world X, Z coordinates to grid column, row\n * Uses pre-calculated values for maximum performance\n */\n public worldToGrid(x: number, z: number): { col: number; row: number } {\n return {\n col: Math.floor((x + this.halfWorldWidth) * this.gridSizeInv),\n row: Math.floor((z + this.halfWorldDepth) * this.gridSizeInv),\n }\n }\n\n /**\n * Converts grid column, row to world X, Z center coordinates\n * Uses centered coordinate system where (0,0) world = center of grid\n */\n public gridToWorld(col: number, row: number): { x: number; z: number } {\n return {\n x: col * this.gridSize - this.worldWidth / 2 + this.gridSize / 2,\n z: row * this.gridSize - this.worldDepth / 2 + this.gridSize / 2,\n }\n }\n\n /**\n * Point-in-Polygon test using ray casting algorithm for 2D XZ plane\n */\n private isPointInPolygon(px: number, pz: number, polygonVertices: Vector3[]): boolean {\n let isInside = false\n for (let i = 0, j = polygonVertices.length - 1; i < polygonVertices.length; j = i++) {\n const xi = polygonVertices[i].x,\n zi = polygonVertices[i].z\n const xj = polygonVertices[j].x,\n zj = polygonVertices[j].z\n\n const intersect = zi > pz !== zj > pz && px < ((xj - xi) * (pz - zi)) / (zj - zi) + xi\n if (intersect) isInside = !isInside\n }\n return isInside\n }\n\n /**\n * Point-in-Circle test for 2D XZ plane\n */\n private isPointInCircle(\n px: number,\n pz: number,\n circleX: number,\n circleZ: number,\n circleRadius: number\n ): boolean {\n const dx = px - circleX\n const dz = pz - circleZ\n return dx * dx + dz * dz <= circleRadius * circleRadius\n }\n\n /**\n * Check if a polygon intersects with a grid cell (not just contains the center)\n * This is crucial for thin obstacles like walls that might span multiple cells\n * but not contain the cell centers\n */\n private doesPolygonIntersectCell(\n cellCenterX: number,\n cellCenterZ: number,\n cellSize: number,\n polygonVertices: Vector3[]\n ): boolean {\n // First check if the cell center is inside the polygon (most common case)\n if (this.isPointInPolygon(cellCenterX, cellCenterZ, polygonVertices)) {\n return true\n }\n\n // If center is not inside, check if polygon intersects the cell area\n // Define the 4 corners of the grid cell\n const halfSize = cellSize / 2\n const cellCorners = [\n { x: cellCenterX - halfSize, z: cellCenterZ - halfSize }, // Bottom-left\n { x: cellCenterX + halfSize, z: cellCenterZ - halfSize }, // Bottom-right\n { x: cellCenterX + halfSize, z: cellCenterZ + halfSize }, // Top-right\n { x: cellCenterX - halfSize, z: cellCenterZ + halfSize }, // Top-left\n ]\n\n // Check if any polygon vertex is inside the cell\n for (const vertex of polygonVertices) {\n if (\n vertex.x >= cellCenterX - halfSize &&\n vertex.x <= cellCenterX + halfSize &&\n vertex.z >= cellCenterZ - halfSize &&\n vertex.z <= cellCenterZ + halfSize\n ) {\n return true\n }\n }\n\n // Check if any cell corner is inside the polygon\n for (const corner of cellCorners) {\n if (this.isPointInPolygon(corner.x, corner.z, polygonVertices)) {\n return true\n }\n }\n\n // Check if any polygon edge intersects any cell edge\n const cellEdges = [\n [cellCorners[0], cellCorners[1]], // Bottom edge\n [cellCorners[1], cellCorners[2]], // Right edge\n [cellCorners[2], cellCorners[3]], // Top edge\n [cellCorners[3], cellCorners[0]], // Left edge\n ]\n\n for (let i = 0; i < polygonVertices.length; i++) {\n const j = (i + 1) % polygonVertices.length\n const polyEdge = [\n { x: polygonVertices[i].x, z: polygonVertices[i].z },\n { x: polygonVertices[j].x, z: polygonVertices[j].z },\n ]\n\n for (const cellEdge of cellEdges) {\n if (this.doLineSegmentsIntersect(polyEdge[0], polyEdge[1], cellEdge[0], cellEdge[1])) {\n return true\n }\n }\n }\n\n return false\n }\n\n /**\n * Check if two line segments intersect\n */\n private doLineSegmentsIntersect(\n p1: { x: number; z: number },\n p2: { x: number; z: number },\n p3: { x: number; z: number },\n p4: { x: number; z: number }\n ): boolean {\n const d1 = this.direction(p3, p4, p1)\n const d2 = this.direction(p3, p4, p2)\n const d3 = this.direction(p1, p2, p3)\n const d4 = this.direction(p1, p2, p4)\n\n if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {\n return true\n }\n\n // Check for collinear points\n if (d1 === 0 && this.onSegment(p3, p4, p1)) return true\n if (d2 === 0 && this.onSegment(p3, p4, p2)) return true\n if (d3 === 0 && this.onSegment(p1, p2, p3)) return true\n if (d4 === 0 && this.onSegment(p1, p2, p4)) return true\n\n return false\n }\n\n /**\n * Calculate the direction/orientation of three points\n */\n private direction(\n a: { x: number; z: number },\n b: { x: number; z: number },\n c: { x: number; z: number }\n ): number {\n return (c.x - a.x) * (b.z - a.z) - (b.x - a.x) * (c.z - a.z)\n }\n\n /**\n * Check if point p lies on line segment ab\n */\n private onSegment(\n a: { x: number; z: number },\n b: { x: number; z: number },\n p: { x: number; z: number }\n ): boolean {\n return (\n p.x >= Math.min(a.x, b.x) &&\n p.x <= Math.max(a.x, b.x) &&\n p.z >= Math.min(a.z, b.z) &&\n p.z <= Math.max(a.z, b.z)\n )\n }\n\n /**\n * OPTIMIZED: Fast polygon-cell intersection using simplified approach\n * Much faster than full line-segment intersection for reference counting\n */\n private fastPolygonIntersectCell(\n cellCenterX: number,\n cellCenterZ: number,\n polygonVertices: Vector3[]\n ): boolean {\n // Fast check: If cell center is inside polygon, we're done\n if (this.isPointInPolygon(cellCenterX, cellCenterZ, polygonVertices)) {\n return true\n }\n\n // Fast check: If any polygon vertex is in cell bounds, we intersect\n const halfSize = this.halfGridSize\n const minX = cellCenterX - halfSize\n const maxX = cellCenterX + halfSize\n const minZ = cellCenterZ - halfSize\n const maxZ = cellCenterZ + halfSize\n\n for (let i = 0; i < polygonVertices.length; i++) {\n const v = polygonVertices[i]\n if (v.x >= minX && v.x <= maxX && v.z >= minZ && v.z <= maxZ) {\n return true\n }\n }\n\n // For thin objects, simplified AABB overlap test\n // This is much faster than line-segment intersection\n let polyMinX = polygonVertices[0].x,\n polyMaxX = polygonVertices[0].x\n let polyMinZ = polygonVertices[0].z,\n polyMaxZ = polygonVertices[0].z\n\n for (let i = 1; i < polygonVertices.length; i++) {\n const v = polygonVertices[i]\n if (v.x < polyMinX) polyMinX = v.x\n else if (v.x > polyMaxX) polyMaxX = v.x\n if (v.z < polyMinZ) polyMinZ = v.z\n else if (v.z > polyMaxZ) polyMaxZ = v.z\n }\n\n // Check if polygon AABB overlaps cell AABB\n return !(polyMaxX < minX || polyMinX > maxX || polyMaxZ < minZ || polyMinZ > maxZ)\n }\n\n /**\n * OPTIMIZED: Calculate AABB with minimal overhead\n */\n private calculateAABB(footprint: Footprint): AABB {\n if (footprint.type === \"circle\") {\n const r = footprint.radius!\n return {\n minX: footprint.x! - r,\n minZ: footprint.z! - r,\n maxX: footprint.x! + r,\n maxZ: footprint.z! + r,\n }\n } else {\n const vertices = footprint.vertices!\n let minX = vertices[0].x,\n minZ = vertices[0].z\n let maxX = vertices[0].x,\n maxZ = vertices[0].z\n\n for (let i = 1; i < vertices.length; i++) {\n const v = vertices[i]\n if (v.x < minX) minX = v.x\n else if (v.x > maxX) maxX = v.x\n if (v.z < minZ) minZ = v.z\n else if (v.z > maxZ) maxZ = v.z\n }\n return { minX, minZ, maxX, maxZ }\n }\n }\n\n /**\n * OPTIMIZED: Add obstacle with maximum performance - INCREMENTAL reference counting only\n * Only touches cells affected by THIS obstacle - no global rebaking\n */\n public addObstacle(footprint: Footprint): void {\n const aabb = this.calculateAABB(footprint)\n\n // FAST: Inline grid bounds calculation without object allocations\n const minCol = Math.max(0, Math.floor((aabb.minX + this.halfWorldWidth) * this.gridSizeInv))\n const maxCol = Math.min(\n this.cols - 1,\n Math.floor((aabb.maxX + this.halfWorldWidth) * this.gridSizeInv)\n )\n const minRow = Math.max(0, Math.floor((aabb.minZ + this.halfWorldDepth) * this.gridSizeInv))\n const maxRow = Math.min(\n this.rows - 1,\n Math.floor((aabb.maxZ + this.halfWorldDepth) * this.gridSizeInv)\n )\n\n if (NavigationGrid.DEBUG_MODE) {\n console.log(\n `🔍 NavigationGrid: Adding ${footprint.type} obstacle, grid area: rows ${minRow}-${maxRow}, cols ${minCol}-${maxCol}`\n )\n }\n\n let cellsAffected = 0\n\n // Pre-calculate values outside loops for maximum performance\n const isCircle = footprint.type === \"circle\"\n const circleX = isCircle ? footprint.x! : 0\n const circleZ = isCircle ? footprint.z! : 0\n const radiusSquared = isCircle ? footprint.radius! * footprint.radius! : 0\n const vertices = !isCircle ? footprint.vertices! : null\n\n // OPTIMIZED: Inline cell world coordinate calculation to avoid function calls\n for (let r = minRow; r <= maxRow; r++) {\n const cellWorldZ = r * this.gridSize - this.halfWorldDepth + this.halfGridSize\n\n for (let c = minCol; c <= maxCol; c++) {\n const cellWorldX = c * this.gridSize - this.halfWorldWidth + this.halfGridSize\n\n let isCovered = false\n if (isCircle) {\n // FAST: Pre-calculated squared radius avoids sqrt\n const dx = cellWorldX - circleX\n const dz = cellWorldZ - circleZ\n isCovered = dx * dx + dz * dz <= radiusSquared\n } else {\n // FAST: Use optimized polygon intersection\n isCovered = this.fastPolygonIntersectCell(cellWorldX, cellWorldZ, vertices!)\n }\n\n if (isCovered) {\n this.grid[r][c]++ // INCREMENTAL: Only increment affected cells\n cellsAffected++\n }\n }\n }\n\n if (NavigationGrid.DEBUG_MODE) {\n console.log(`🔍 NavigationGrid: ${footprint.type} obstacle affected ${cellsAffected} cells`)\n }\n }\n\n /**\n * OPTIMIZED: Remove obstacle with maximum performance - INCREMENTAL reference counting only\n * Only touches cells affected by THIS obstacle - no global rebaking\n */\n public removeObstacle(footprint: Footprint): void {\n const aabb = this.calculateAABB(footprint)\n\n // FAST: Inline grid bounds calculation (same as addObstacle for consistency)\n const minCol = Math.max(0, Math.floor((aabb.minX + this.halfWorldWidth) * this.gridSizeInv))\n const maxCol = Math.min(\n this.cols - 1,\n Math.floor((aabb.maxX + this.halfWorldWidth) * this.gridSizeInv)\n )\n const minRow = Math.max(0, Math.floor((aabb.minZ + this.halfWorldDepth) * this.gridSizeInv))\n const maxRow = Math.min(\n this.rows - 1,\n Math.floor((aabb.maxZ + this.halfWorldDepth) * this.gridSizeInv)\n )\n\n // Pre-calculate values outside loops (same as addObstacle for consistency)\n const isCircle = footprint.type === \"circle\"\n const circleX = isCircle ? footprint.x! : 0\n const circleZ = isCircle ? footprint.z! : 0\n const radiusSquared = isCircle ? footprint.radius! * footprint.radius! : 0\n const vertices = !isCircle ? footprint.vertices! : null\n\n // OPTIMIZED: Same performance optimizations as addObstacle\n for (let r = minRow; r <= maxRow; r++) {\n const cellWorldZ = r * this.gridSize - this.halfWorldDepth + this.halfGridSize\n\n for (let c = minCol; c <= maxCol; c++) {\n const cellWorldX = c * this.gridSize - this.halfWorldWidth + this.halfGridSize\n\n let isCovered = false\n if (isCircle) {\n // FAST: Same optimized circle test\n const dx = cellWorldX - circleX\n const dz = cellWorldZ - circleZ\n isCovered = dx * dx + dz * dz <= radiusSquared\n } else {\n // FAST: Same optimized polygon intersection\n isCovered = this.fastPolygonIntersectCell(cellWorldX, cellWorldZ, vertices!)\n }\n\n if (isCovered) {\n this.grid[r][c]-- // INCREMENTAL: Only decrement affected cells\n if (this.grid[r][c] < 0) {\n this.grid[r][c] = 0\n if (NavigationGrid.DEBUG_MODE) {\n console.warn(`Grid count for cell (${c},${r}) went negative. Check logic.`)\n }\n }\n }\n }\n }\n }\n\n /**\n * Check if a grid cell is walkable (reference count is zero)\n */\n public isWalkable(col: number, row: number): boolean {\n if (row < 0 || row >= this.rows || col < 0 || col >= this.cols) {\n return false // Out of bounds\n }\n return this.grid[row][col] === 0\n }\n\n /**\n * Get grid dimensions\n */\n public getDimensions(): {\n cols: number\n rows: number\n worldWidth: number\n worldDepth: number\n gridSize: number\n } {\n return {\n cols: this.cols,\n rows: this.rows,\n worldWidth: this.worldWidth,\n worldDepth: this.worldDepth,\n gridSize: this.gridSize,\n }\n }\n\n /**\n * Debug helper to print the grid state\n */\n public printGrid(): void {\n console.log(\"Navigation Grid State:\")\n console.log(\n `Grid: ${this.cols}x${this.rows}, World: ${this.worldWidth}x${this.worldDepth}, Cell Size: ${this.gridSize}`\n )\n console.log(\"🧭 NORTH (positive Z) at bottom, SOUTH (negative Z) at top\")\n\n // Print all rows from 0 to rows-1 (so north appears at bottom)\n for (let r = 0; r < this.rows; r++) {\n let rowString = \"\"\n for (let c = 0; c < this.cols; c++) {\n rowString += this.grid[r][c] === 0 ? \".\" : \"#\"\n }\n\n // Add row number and world Z coordinate for reference\n const worldZ = this.gridToWorld(0, r).z\n console.log(`${r.toString().padStart(2)} (Z=${worldZ.toFixed(1)}): ${rowString}`)\n }\n console.log(\"🧭 SOUTH ← → NORTH (Z coordinates)\")\n }\n\n /**\n * Get the raw grid data (for debugging or visualization)\n */\n public getGridData(): number[][] {\n return this.grid\n }\n\n /**\n * Enable/disable debug logging for performance tuning\n * Set to false for production performance\n */\n public static setDebugMode(enabled: boolean): void {\n NavigationGrid.DEBUG_MODE = enabled\n if (enabled) {\n console.log(\"NavigationGrid: Debug mode ENABLED (performance impact)\")\n } else {\n console.log(\"NavigationGrid: Debug mode DISABLED (production performance)\")\n }\n }\n\n /**\n * Get current debug mode status\n */\n public static isDebugMode(): boolean {\n return NavigationGrid.DEBUG_MODE\n }\n}\n","import * as THREE from \"three\"\nimport { NavigationGrid } from \"./NavigationGrid\"\n\n/**\n * Debug visualization for NavigationGrid in Three.js\n * Shows grid lines and blocked areas\n */\nexport class NavGridDebugDisplayThree {\n private static isInitialized: boolean = false\n private static scene: THREE.Scene | null = null\n private static debugLines: THREE.LineSegments | null = null\n private static blockedCubes: THREE.Group | null = null // Group to hold all blocked area cubes\n\n /**\n * Initialize the debug display system\n */\n public static initialize(scene: THREE.Scene): void {\n if (NavGridDebugDisplayThree.isInitialized) {\n console.warn(\"NavGridDebugDisplayThree already initialized\")\n return\n }\n\n NavGridDebugDisplayThree.scene = scene\n NavGridDebugDisplayThree.isInitialized = true\n\n // NavGridDebugDisplayThree initialized\n }\n\n /**\n * Dispose of the debug display system\n */\n public static dispose(): void {\n if (NavGridDebugDisplayThree.isInitialized) {\n NavGridDebugDisplayThree.clearDebugLines()\n NavGridDebugDisplayThree.scene = null\n NavGridDebugDisplayThree.isInitialized = false\n console.log(\"NavGridDebugDisplayThree disposed\")\n }\n }\n\n /**\n * Debug method to visualize the navigation grid with blocked areas\n */\n public static debugNavigation(navigationGrid: NavigationGrid | null): void {\n if (\n !NavGridDebugDisplayThree.isInitialized ||\n !NavGridDebugDisplayThree.scene ||\n !navigationGrid\n ) {\n console.warn(\"NavGridDebugDisplayThree not initialized or no grid provided\")\n return\n }\n\n // Clear existing debug visualization\n NavGridDebugDisplayThree.clearDebugLines()\n\n // Create debug visualization\n const dimensions = navigationGrid.getDimensions()\n const gridData = navigationGrid.getGridData()\n\n // Create grid lines\n NavGridDebugDisplayThree.createGridLines(navigationGrid, dimensions)\n\n // Create blocked area visualization\n NavGridDebugDisplayThree.createBlockedAreas(navigationGrid, dimensions, gridData)\n\n // Log statistics\n let walkableCount = 0\n let blockedCount = 0\n\n for (let row = 0; row < dimensions.rows; row++) {\n for (let col = 0; col < dimensions.cols; col++) {\n if (navigationGrid.isWalkable(col, row)) {\n walkableCount++\n } else {\n blockedCount++\n }\n }\n }\n\n // Navigation grid debug ready\n }\n\n /**\n * Create grid lines for the navigation grid\n */\n private static createGridLines(navigationGrid: NavigationGrid, dimensions: any): void {\n const points: THREE.Vector3[] = []\n\n // Create grid lines\n for (let row = 0; row <= dimensions.rows; row++) {\n for (let col = 0; col <= dimensions.cols; col++) {\n const worldPos = navigationGrid.gridToWorld(col, row)\n\n // Horizontal lines\n if (col < dimensions.cols) {\n const nextWorldPos = navigationGrid.gridToWorld(col + 1, row)\n points.push(new THREE.Vector3(worldPos.x, 0.1, worldPos.z))\n points.push(new THREE.Vector3(nextWorldPos.x, 0.1, nextWorldPos.z))\n }\n\n // Vertical lines\n if (row < dimensions.rows) {\n const nextWorldPos = navigationGrid.gridToWorld(col, row + 1)\n points.push(new THREE.Vector3(worldPos.x, 0.1, worldPos.z))\n points.push(new THREE.Vector3(nextWorldPos.x, 0.1, nextWorldPos.z))\n }\n }\n }\n\n // Create geometry and material for grid lines\n const geometry = new THREE.BufferGeometry().setFromPoints(points)\n const material = new THREE.LineBasicMaterial({\n color: 0x00ff00, // Green for walkable grid\n transparent: true,\n opacity: 0.3,\n })\n\n // Create line segments\n NavGridDebugDisplayThree.debugLines = new THREE.LineSegments(geometry, material)\n NavGridDebugDisplayThree.scene!.add(NavGridDebugDisplayThree.debugLines)\n }\n\n /**\n * Create red cubes for blocked areas\n */\n private static createBlockedAreas(\n navigationGrid: NavigationGrid,\n dimensions: any,\n gridData: number[][]\n ): void {\n // Create a group to hold all blocked cubes\n NavGridDebugDisplayThree.blockedCubes = new THREE.Group()\n NavGridDebugDisplayThree.scene!.add(NavGridDebugDisplayThree.blockedCubes)\n\n // Create geometry and material for blocked cubes (reuse for performance)\n const cubeGeometry = new THREE.BoxGeometry(\n dimensions.gridSize * 0.8,\n 0.2,\n dimensions.gridSize * 0.8\n )\n const blockedMaterial = new THREE.MeshBasicMaterial({\n color: 0xff0000, // Red for blocked areas\n transparent: true,\n opacity: 0.7,\n })\n\n // Create cubes for blocked cells\n for (let row = 0; row < dimensions.rows; row++) {\n for (let col = 0; col < dimensions.cols; col++) {\n if (!navigationGrid.isWalkable(col, row)) {\n const worldPos = navigationGrid.gridToWorld(col, row)\n\n // Create cube mesh\n const cube = new THREE.Mesh(cubeGeometry, blockedMaterial)\n cube.position.set(worldPos.x, 0.1, worldPos.z)\n\n NavGridDebugDisplayThree.blockedCubes.add(cube)\n }\n }\n }\n\n // Created blocked area cubes\n }\n\n /**\n * Clear debug lines and blocked cubes from the scene\n */\n public static clearDebugLines(): void {\n // Clear grid lines\n if (NavGridDebugDisplayThree.debugLines && NavGridDebugDisplayThree.scene) {\n NavGridDebugDisplayThree.scene.remove(NavGridDebugDisplayThree.debugLines)\n NavGridDebugDisplayThree.debugLines.geometry.dispose()\n ;(NavGridDebugDisplayThree.debugLines.material as THREE.Material).dispose()\n NavGridDebugDisplayThree.debugLines = null\n }\n\n // Clear blocked cubes\n if (NavGridDebugDisplayThree.blockedCubes && NavGridDebugDisplayThree.scene) {\n NavGridDebugDisplayThree.scene.remove(NavGridDebugDisplayThree.blockedCubes)\n\n // Dispose of all cube geometries and materials\n NavGridDebugDisplayThree.blockedCubes.children.forEach((child) => {\n if (child instanceof THREE.Mesh) {\n child.geometry.dispose()\n if (child.material instanceof THREE.Material) {\n child.material.dispose()\n }\n }\n })\n\n NavGridDebugDisplayThree.blockedCubes = null\n }\n\n // Debug visualization cleared\n }\n}\n","import * as THREE from \"three\"\nimport { DynamicNavSystem, Waypoint, PathfindingResult } from \"./DynamicNavSystem\"\n\n/**\n * Three.js visualization system for pathfinding results\n * Shows waypoints as spheres and paths as lines for debugging\n */\nexport class PathVisualizationThree {\n private static scene: THREE.Scene | null = null\n private static isInitialized: boolean = false\n\n // Global control for path visualization\n private static visualizationEnabled: boolean = false\n\n // Materials\n private static pathMaterial: THREE.LineBasicMaterial | null = null\n private static waypointMaterial: THREE.MeshBasicMaterial | null = null\n private static startMaterial: THREE.MeshBasicMaterial | null = null\n private static endMaterial: THREE.MeshBasicMaterial | null = null\n\n // Multiple path support\n private static pathVisualizations: Map<\n string,\n {\n pathLines: THREE.Line[]\n waypointSpheres: THREE.Mesh[]\n startMarker: THREE.Mesh | null\n endMarker: THREE.Mesh | null\n }\n > = new Map()\n\n // Legacy support\n private static currentPath: PathfindingResult | null = null\n\n /**\n * Initialize the path visualization system\n */\n public static initialize(scene: THREE.Scene): void {\n if (PathVisualizationThree.isInitialized) {\n return\n }\n\n PathVisualizationThree.scene = scene\n PathVisualizationThree.createMaterials()\n PathVisualizationThree.isInitialized = true\n\n // PathVisualizationThree initialized\n }\n\n /**\n * Create materials for different visual elements\n */\n private static createMaterials(): void {\n // Path line material (bright yellow)\n PathVisualizationThree.pathMaterial = new THREE.LineBasicMaterial({\n color: 0xffff00, // Bright yellow\n linewidth: 3,\n transparent: true,\n opacity: 0.8,\n })\n\n // Waypoint sphere material (orange)\n PathVisualizationThree.waypointMaterial = new THREE.MeshBasicMaterial({\n color: 0xff8000, // Orange\n transparent: true,\n opacity: 0.9,\n })\n\n // Start position material (green)\n PathVisualizationThree.startMaterial = new THREE.MeshBasicMaterial({\n color: 0x00ff00, // Bright green\n transparent: true,\n opacity: 0.9,\n })\n\n // End position material (red)\n PathVisualizationThree.endMaterial = new THREE.MeshBasicMaterial({\n color: 0xff0000, // Bright red\n transparent: true,\n opacity: 0.9,\n })\n }\n\n /**\n * Enable or disable path visualization globally\n */\n public static setVisualizationEnabled(enabled: boolean): void {\n PathVisualizationThree.visualizationEnabled = enabled\n\n if (!enabled) {\n // Clear all visualizations when disabled\n PathVisualizationThree.clearVisualization()\n }\n\n // Path visualization toggled\n }\n\n /**\n * Check if path visualization is globally enabled\n */\n public static isVisualizationEnabled(): boolean {\n return PathVisualizationThree.visualizationEnabled\n }\n\n /**\n * Add a path visualization with optional ID for later removal\n */\n public static addPath(\n pathId: string,\n result: PathfindingResult,\n startX?: number,\n startZ?: number,\n endX?: number,\n endZ?: number\n ): boolean {\n if (!PathVisualizationThree.isInitialized || !PathVisualizationThree.scene) {\n console.warn(\"PathVisualizationThree not initialized\")\n return false\n }\n\n if (!result.success || result.waypoints.length === 0) {\n // No path data to visualize\n return false\n }\n\n // Check if visualization is globally enabled\n if (!PathVisualizationThree.visualizationEnabled) {\n // Path visualization disabled\n return false\n }\n\n // Remove existing path with same ID if it exists\n PathVisualizationThree.removePath(pathId)\n\n console.log(\n `đŸ›¤ī¸ Adding path visualization '${pathId}' with ${result.waypoints.length} waypoints, distance: ${result.distance.toFixed(1)}`\n )\n\n const visualization = {\n pathLines: [] as THREE.Line[],\n waypointSpheres: [] as THREE.Mesh[],\n startMarker: null as THREE.Mesh | null,\n endMarker: null as THREE.Mesh | null,\n }\n\n // If start/end coordinates aren't provided, infer them from waypoints\n const inferredStartX = startX ?? result.waypoints[0]?.x\n const inferredStartZ = startZ ?? result.waypoints[0]?.z\n const inferredEndX = endX ?? result.waypoints[result.waypoints.length - 1]?.x\n const inferredEndZ = endZ ?? result.waypoints[result.waypoints.length - 1]?.z\n\n // Create start and end markers if positions are available\n if (inferredStartX !== undefined && inferredStartZ !== undefined) {\n visualization.startMarker = PathVisualizationThree.createStartMarker(\n pathId,\n inferredStartX,\n inferredStartZ\n )\n }\n\n if (inferredEndX !== undefined && inferredEndZ !== undefined) {\n visualization.endMarker = PathVisualizationThree.createEndMarker(\n pathId,\n inferredEndX,\n inferredEndZ\n )\n }\n\n // Create waypoint spheres\n visualization.waypointSpheres = PathVisualizationThree.createWaypointSpheres(\n pathId,\n result.waypoints\n )\n\n // Create path lines\n visualization.pathLines = PathVisualizationThree.createPathLines(pathId, result.waypoints)\n\n // Store the visualization\n PathVisualizationThree.pathVisualizations.set(pathId, visualization)\n PathVisualizationThree.currentPath = result\n\n return true\n }\n\n /**\n * Add a path visualization (simplified API - infers start/end from waypoints)\n */\n public static addPathSimple(pathId: string, result: PathfindingResult): boolean {\n return PathVisualizationThree.addPath(pathId, result)\n }\n\n /**\n * Remove a specific path visualization by ID\n */\n public static removePath(pathId: string): boolean {\n const visualization = PathVisualizationThree.pathVisualizations.get(pathId)\n if (!visualization) {\n return false\n }\n\n // Remove from scene and dispose\n visualization.pathLines.forEach((line) => {\n PathVisualizationThree.scene?.remove(line)\n line.geometry.dispose()\n })\n visualization.waypointSpheres.forEach((sphere) => {\n PathVisualizationThree.scene?.remove(sphere)\n sphere.geometry.dispose()\n })\n if (visualization.startMarker) {\n PathVisualizationThree.scene?.remove(visualization.startMarker)\n visualization.startMarker.geometry.dispose()\n }\n if (visualization.endMarker) {\n PathVisualizationThree.scene?.remove(visualization.endMarker)\n visualization.endMarker.geometry.dispose()\n }\n\n // Remove from map\n PathVisualizationThree.pathVisualizations.delete(pathId)\n\n console.log(`đŸ›¤ī¸ Removed path visualization '${pathId}'`)\n return true\n }\n\n /**\n * Visualize a pathfinding result (legacy method - uses default ID)\n */\n public static visualizePath(\n result: PathfindingResult,\n startX?: number,\n startZ?: number,\n endX?: number,\n endZ?: number\n ): void {\n PathVisualizationThree.addPath(\"default\", result, startX, startZ, endX, endZ)\n }\n\n /**\n * Create visual marker for start position\n */\n private static createStartMarker(pathId: string, x: number, z: number): THREE.Mesh | null {\n if (!PathVisualizationThree.scene || !PathVisualizationThree.startMaterial) return null\n\n const geometry = new THREE.SphereGeometry(0.5, 16, 16)\n const marker = new THREE.Mesh(geometry, PathVisualizationThree.startMaterial)\n\n marker.position.set(x, 0.5, z)\n marker.name = `PathStartMarker_${pathId}`\n\n PathVisualizationThree.scene.add(marker)\n return marker\n }\n\n /**\n * Create visual marker for end position\n */\n private static createEndMarker(pathId: string, x: number, z: number): THREE.Mesh | null {\n if (!PathVisualizationThree.scene || !PathVisualizationThree.endMaterial) return null\n\n const geometry = new THREE.SphereGeometry(0.5, 16, 16)\n const marker = new THREE.Mesh(geometry, PathVisualizationThree.endMaterial)\n\n marker.position.set(x, 0.5, z)\n marker.name = `PathEndMarker_${pathId}`\n\n PathVisualizationThree.scene.add(marker)\n return marker\n }\n\n /**\n * Create spheres to mark waypoints along the path\n */\n private static createWaypointSpheres(pathId: string, waypoints: Waypoint[]): THREE.Mesh[] {\n if (!PathVisualizationThree.scene || !PathVisualizationThree.waypointMaterial) return []\n\n const spheres: THREE.Mesh[] = []\n\n waypoints.forEach((waypoint, index) => {\n const geometry = new THREE.SphereGeometry(0.3, 12, 12)\n const sphere = new THREE.Mesh(geometry, PathVisualizationThree.waypointMaterial!)\n\n sphere.position.set(waypoint.x, 0.3, waypoint.z)\n sphere.name = `PathWaypoint_${pathId}_${index}`\n\n PathVisualizationThree.scene!.add(sphere)\n spheres.push(sphere)\n })\n\n return spheres\n }\n\n /**\n * Create lines connecting waypoints to show the path\n */\n private static createPathLines(pathId: string, waypoints: Waypoint[]): THREE.Line[] {\n if (\n !PathVisualizationThree.scene ||\n !PathVisualizationThree.pathMaterial ||\n waypoints.length < 2\n )\n return []\n\n const lines: THREE.Line[] = []\n\n // Create lines between consecutive waypoints\n for (let i = 0; i < waypoints.length - 1; i++) {\n const start = waypoints[i]\n const end = waypoints[i + 1]\n\n const points = [\n new THREE.Vector3(start.x, 0.2, start.z),\n new THREE.Vector3(end.x, 0.2, end.z),\n ]\n\n const geometry = new THREE.BufferGeometry().setFromPoints(points)\n const line = new THREE.Line(geometry, PathVisualizationThree.pathMaterial)\n line.name = `PathLine_${pathId}_${i}`\n\n PathVisualizationThree.scene.add(line)\n lines.push(line)\n }\n\n return lines\n }\n\n /**\n * Clear all path visualizations\n */\n public static clearVisualization(): void {\n // Clear all paths\n const pathIds = Array.from(PathVisualizationThree.pathVisualizations.keys())\n pathIds.forEach((pathId) => PathVisualizationThree.removePath(pathId))\n\n PathVisualizationThree.currentPath = null\n // Path visualizations cleared\n }\n\n /**\n * Get list of active path IDs\n */\n public static getActivePathIds(): string[] {\n return Array.from(PathVisualizationThree.pathVisualizations.keys())\n }\n\n /**\n * Check if any path is currently being visualized\n */\n public static hasActiveVisualization(): boolean {\n return PathVisualizationThree.pathVisualizations.size > 0\n }\n\n /**\n * Get current path result (legacy support)\n */\n public static getCurrentPath(): PathfindingResult | null {\n return PathVisualizationThree.currentPath\n }\n\n /**\n * Console helper function for manual testing\n */\n public static testPath(startX: number, startZ: number, endX: number, endZ: number): void {\n console.log(`đŸ›¤ī¸ Testing path from (${startX}, ${startZ}) to (${endX}, ${endZ})`)\n\n if (!DynamicNavSystem.getIsInitialized()) {\n console.warn(\"❌ DynamicNavSystem not initialized\")\n return\n }\n\n PathVisualizationThree.initialize(PathVisualizationThree.scene!)\n\n const result = DynamicNavSystem.findPath(\n new THREE.Vector2(startX, startZ),\n new THREE.Vector2(endX, endZ)\n )\n\n if (result.success) {\n console.log(\n `✅ Path found! ${result.waypoints.length} waypoints, distance: ${result.distance.toFixed(1)} units`\n )\n result.waypoints.forEach((waypoint, index) => {\n console.log(` ${index + 1}. (${waypoint.x.toFixed(1)}, ${waypoint.z.toFixed(1)})`)\n })\n PathVisualizationThree.visualizePath(result, startX, startZ, endX, endZ)\n } else {\n console.log(\"❌ No path found!\")\n PathVisualizationThree.clearVisualization()\n }\n }\n\n /**\n * Dispose of the path visualization system\n */\n public static dispose(): void {\n if (PathVisualizationThree.isInitialized) {\n PathVisualizationThree.clearVisualization()\n\n // Dispose materials\n if (PathVisualizationThree.pathMaterial) PathVisualizationThree.pathMaterial.dispose()\n if (PathVisualizationThree.waypointMaterial) PathVisualizationThree.waypointMaterial.dispose()\n if (PathVisualizationThree.startMaterial) PathVisualizationThree.startMaterial.dispose()\n if (PathVisualizationThree.endMaterial) PathVisualizationThree.endMaterial.dispose()\n\n PathVisualizationThree.scene = null\n PathVisualizationThree.isInitialized = false\n\n console.log(\"đŸ›¤ī¸ PathVisualizationThree disposed\")\n }\n }\n}\n\n// Make functions available globally for console testing\ndeclare global {\n interface Window {\n testPathThree: (startX: number, startZ: number, endX: number, endZ: number) => void\n clearPathThree: () => void\n addPathThree: (\n pathId: string,\n startX: number,\n startZ: number,\n endX: number,\n endZ: number\n ) => void\n removePathThree: (pathId: string) => void\n listPathsThree: () => void\n }\n}\n\n// Add to window for browser console access\nif (typeof window !== \"undefined\") {\n window.testPathThree = (startX: number, startZ: number, endX: number, endZ: number) => {\n PathVisualizationThree.testPath(startX, startZ, endX, endZ)\n }\n\n window.clearPathThree = () => {\n PathVisualizationThree.clearVisualization()\n console.log(\"đŸ›¤ī¸ Path visualization cleared\")\n }\n\n window.addPathThree = (\n pathId: string,\n startX: number,\n startZ: number,\n endX: number,\n endZ: number\n ) => {\n const result = DynamicNavSystem.findPath(\n new THREE.Vector2(startX, startZ),\n new THREE.Vector2(endX, endZ)\n )\n if (result.success) {\n PathVisualizationThree.addPath(pathId, result, startX, startZ, endX, endZ)\n console.log(`đŸ›¤ī¸ Added path '${pathId}'`)\n } else {\n console.log(`❌ Failed to find path for '${pathId}'`)\n }\n }\n\n window.removePathThree = (pathId: string) => {\n const removed = PathVisualizationThree.removePath(pathId)\n if (!removed) {\n console.log(`❌ Path '${pathId}' not found`)\n }\n }\n\n window.listPathsThree = () => {\n const paths = PathVisualizationThree.getActivePathIds()\n console.log(`đŸ›¤ī¸ Active paths: ${paths.length > 0 ? paths.join(\", \") : \"none\"}`)\n }\n}\n","import * as THREE from \"three\"\nimport { GameObject } from \"@engine/core/GameObject\"\nimport { SplineThree } from \"./SplineThree\"\nimport { SplineDebugRendererThree } from \"./SplineDebugRendererThree\"\n\n/**\n * Configuration for spline debug visualization\n */\nexport interface SplineDebugConfig {\n showWaypoints?: boolean\n showCurve?: boolean\n showDirection?: boolean\n waypointSize?: number\n waypointColor?: THREE.Color\n curveColor?: THREE.Color\n}\n\n/**\n * Internal registration entry for a spline\n */\ninterface SplineRegistration {\n spline: SplineThree\n debugGameObject: GameObject | null\n debugRenderer: SplineDebugRendererThree | null\n config: SplineDebugConfig\n}\n\n/**\n * Global manager for spline debug visualization\n * Allows centralized control of debug rendering for all splines\n */\nexport class SplineDebugManager {\n private static instance: SplineDebugManager | null = null\n private registrations: Map<SplineThree, SplineRegistration> = new Map()\n private debugEnabled: boolean = false\n private defaultConfig: SplineDebugConfig = {\n showWaypoints: true,\n showCurve: true,\n showDirection: false,\n waypointSize: 0.4,\n waypointColor: new THREE.Color(0xff0000),\n curveColor: new THREE.Color(0xffff00),\n }\n\n private constructor() {}\n\n /**\n * Get the singleton instance\n */\n public static getInstance(): SplineDebugManager {\n if (!SplineDebugManager.instance) {\n SplineDebugManager.instance = new SplineDebugManager()\n }\n return SplineDebugManager.instance\n }\n\n /**\n * Register a spline for debug visualization\n */\n public registerSpline(spline: SplineThree, config: SplineDebugConfig = {}): void {\n if (this.registrations.has(spline)) {\n return\n }\n\n const mergedConfig = { ...this.defaultConfig, ...config }\n\n this.registrations.set(spline, {\n spline,\n debugGameObject: null,\n debugRenderer: null,\n config: mergedConfig,\n })\n\n // If debug is already enabled, create visualization immediately\n if (this.debugEnabled) {\n this.createDebugVisualization(spline)\n }\n }\n\n /**\n * Unregister a spline from debug visualization\n */\n public unregisterSpline(spline: SplineThree): void {\n const registration = this.registrations.get(spline)\n if (!registration) {\n return\n }\n\n this.destroyDebugVisualization(spline)\n this.registrations.delete(spline)\n }\n\n /**\n * Enable debug visualization for all registered splines\n */\n public setDebugEnabled(enabled: boolean): void {\n if (this.debugEnabled === enabled) {\n return\n }\n\n this.debugEnabled = enabled\n\n if (enabled) {\n this.registrations.forEach((_, spline) => {\n this.createDebugVisualization(spline)\n })\n } else {\n this.registrations.forEach((_, spline) => {\n this.destroyDebugVisualization(spline)\n })\n }\n }\n\n /**\n * Check if debug is currently enabled\n */\n public isDebugEnabled(): boolean {\n return this.debugEnabled\n }\n\n /**\n * Get the number of registered splines\n */\n public getRegisteredCount(): number {\n return this.registrations.size\n }\n\n /**\n * Create debug visualization for a specific spline\n */\n private createDebugVisualization(spline: SplineThree): void {\n const registration = this.registrations.get(spline)\n if (!registration || registration.debugGameObject) {\n return\n }\n\n const debugGameObject = new GameObject(\"SplineDebug\")\n debugGameObject.position.set(0, 0.5, 0) // Slightly elevated\n\n const debugRenderer = new SplineDebugRendererThree(spline, registration.config)\n debugGameObject.addComponent(debugRenderer)\n\n registration.debugGameObject = debugGameObject\n registration.debugRenderer = debugRenderer\n }\n\n /**\n * Destroy debug visualization for a specific spline\n */\n private destroyDebugVisualization(spline: SplineThree): void {\n const registration = this.registrations.get(spline)\n if (!registration || !registration.debugGameObject) {\n return\n }\n\n registration.debugGameObject.dispose()\n registration.debugGameObject = null\n registration.debugRenderer = null\n }\n\n /**\n * Update configuration for the default debug visualization\n */\n public setDefaultConfig(config: SplineDebugConfig): void {\n this.defaultConfig = { ...this.defaultConfig, ...config }\n }\n\n /**\n * Clear all registrations (useful for cleanup/testing)\n */\n public clear(): void {\n this.registrations.forEach((_, spline) => {\n this.destroyDebugVisualization(spline)\n })\n this.registrations.clear()\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core/GameObject\"\nimport { SplineThree } from \"./SplineThree\"\n\nexport interface SplineDebugOptionsThree {\n showWaypoints?: boolean\n showCurve?: boolean\n showDirection?: boolean\n waypointSize?: number\n waypointColor?: THREE.Color\n curveColor?: THREE.Color\n directionColor?: THREE.Color\n directionLength?: number\n directionSpacing?: number\n}\n\n/**\n * Three.js component for debugging and visualizing splines\n */\nexport class SplineDebugRendererThree extends Component {\n private spline: SplineThree\n private options: Required<SplineDebugOptionsThree>\n\n // Visual elements\n private waypointMeshes: THREE.Mesh[] = []\n private curveLine: THREE.Line | null = null\n private directionArrows: THREE.Group[] = []\n private parentGroup: THREE.Group\n\n constructor(spline: SplineThree, options: SplineDebugOptionsThree = {}) {\n super()\n\n this.spline = spline\n this.options = {\n showWaypoints: options.showWaypoints ?? true,\n showCurve: options.showCurve ?? true,\n showDirection: options.showDirection ?? false,\n waypointSize: options.waypointSize ?? 0.5,\n waypointColor: options.waypointColor ?? new THREE.Color(0xff0000),\n curveColor: options.curveColor ?? new THREE.Color(0xffff00),\n directionColor: options.directionColor ?? new THREE.Color(0x00ff00),\n directionLength: options.directionLength ?? 2.0,\n directionSpacing: options.directionSpacing ?? 0.1,\n }\n\n this.parentGroup = new THREE.Group()\n }\n\n protected onCreate(): void {\n if (!this.gameObject) return\n\n // Add the parent group to the scene through the gameObject\n this.gameObject.add(this.parentGroup)\n\n this.createDebugVisualization()\n }\n\n protected onCleanup(): void {\n this.clearVisualization()\n\n if (this.parentGroup && this.gameObject) {\n this.gameObject.remove(this.parentGroup)\n }\n }\n\n public update(deltaTime: number): void {\n // Debug visualization is static - no updates needed\n }\n\n /**\n * Update the visualization (call this if the spline changes)\n */\n public refresh(): void {\n this.clearVisualization()\n this.createDebugVisualization()\n }\n\n /**\n * Show or hide waypoints\n */\n public setShowWaypoints(show: boolean): void {\n this.options.showWaypoints = show\n this.waypointMeshes.forEach((mesh) => {\n mesh.visible = show\n })\n }\n\n /**\n * Show or hide the curve\n */\n public setShowCurve(show: boolean): void {\n this.options.showCurve = show\n if (this.curveLine) {\n this.curveLine.visible = show\n }\n }\n\n /**\n * Show or hide direction arrows\n */\n public setShowDirection(show: boolean): void {\n this.options.showDirection = show\n this.directionArrows.forEach((arrow) => {\n arrow.visible = show\n })\n }\n\n /**\n * Create all debug visualization elements\n */\n private createDebugVisualization(): void {\n if (this.options.showWaypoints) {\n this.createWaypoints()\n }\n\n if (this.options.showCurve) {\n this.createCurve()\n }\n\n if (this.options.showDirection) {\n this.createDirectionArrows()\n }\n }\n\n /**\n * Create waypoint spheres\n */\n private createWaypoints(): void {\n const geometry = new THREE.SphereGeometry(this.options.waypointSize, 8, 6)\n const material = new THREE.MeshBasicMaterial({\n color: this.options.waypointColor,\n depthTest: false,\n transparent: true,\n opacity: 0.8,\n })\n\n // Use original waypoints, not interpolated points\n const waypoints = this.spline.getWaypoints()\n\n waypoints.forEach((waypoint, index) => {\n const mesh = new THREE.Mesh(geometry, material.clone())\n mesh.position.copy(waypoint)\n mesh.renderOrder = 1000 // Render on top\n\n this.waypointMeshes.push(mesh)\n this.parentGroup.add(mesh)\n })\n }\n\n /**\n * Create the curve line\n */\n private createCurve(): void {\n const points = this.spline.getInterpolatedPoints()\n\n if (points.length < 2) return\n\n const geometry = new THREE.BufferGeometry().setFromPoints(points)\n const material = new THREE.LineBasicMaterial({\n color: this.options.curveColor,\n linewidth: 2,\n transparent: true,\n opacity: 0.8,\n })\n\n this.curveLine = new THREE.Line(geometry, material)\n this.curveLine.renderOrder = 999 // Render below waypoints\n this.parentGroup.add(this.curveLine)\n }\n\n /**\n * Create direction arrows along the spline\n */\n private createDirectionArrows(): void {\n const spacing = this.options.directionSpacing\n const length = this.options.directionLength\n\n for (let t = 0; t <= 1; t += spacing) {\n const position = this.spline.getPointAt(t)\n const direction = this.spline.getDirectionAt(t)\n\n if (direction.length() < 0.001) continue\n\n const arrow = this.createArrow(position, direction, length)\n this.directionArrows.push(arrow)\n this.parentGroup.add(arrow)\n }\n }\n\n /**\n * Create a single direction arrow\n */\n private createArrow(\n position: THREE.Vector3,\n direction: THREE.Vector3,\n length: number\n ): THREE.Group {\n const group = new THREE.Group()\n\n // Arrow shaft\n const shaftGeometry = new THREE.CylinderGeometry(0.02, 0.02, length * 0.8, 4)\n const shaftMaterial = new THREE.MeshBasicMaterial({\n color: this.options.directionColor,\n })\n const shaft = new THREE.Mesh(shaftGeometry, shaftMaterial)\n\n // Arrow head\n const headGeometry = new THREE.ConeGeometry(0.08, length * 0.2, 6)\n const headMaterial = new THREE.MeshBasicMaterial({\n color: this.options.directionColor,\n })\n const head = new THREE.Mesh(headGeometry, headMaterial)\n head.position.y = length * 0.4\n\n group.add(shaft)\n group.add(head)\n\n // Position and orient the arrow\n group.position.copy(position)\n group.position.y += 0.1 // Slightly above ground\n\n // Orient to face the direction\n const up = new THREE.Vector3(0, 1, 0)\n const quaternion = new THREE.Quaternion().setFromUnitVectors(up, direction.normalize())\n group.setRotationFromQuaternion(quaternion)\n\n return group\n }\n\n /**\n * Clear all visualization elements\n */\n private clearVisualization(): void {\n // Remove waypoints\n this.waypointMeshes.forEach((mesh) => {\n this.parentGroup.remove(mesh)\n mesh.geometry.dispose()\n if (Array.isArray(mesh.material)) {\n mesh.material.forEach((mat) => mat.dispose())\n } else {\n mesh.material.dispose()\n }\n })\n this.waypointMeshes = []\n\n // Remove curve\n if (this.curveLine) {\n this.parentGroup.remove(this.curveLine)\n this.curveLine.geometry.dispose()\n if (Array.isArray(this.curveLine.material)) {\n this.curveLine.material.forEach((mat) => mat.dispose())\n } else {\n this.curveLine.material.dispose()\n }\n this.curveLine = null\n }\n\n // Remove direction arrows\n this.directionArrows.forEach((arrow) => {\n this.parentGroup.remove(arrow)\n arrow.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n child.geometry.dispose()\n if (Array.isArray(child.material)) {\n child.material.forEach((mat) => mat.dispose())\n } else {\n child.material.dispose()\n }\n }\n })\n })\n this.directionArrows = []\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core/GameObject\"\nimport { VenusGame } from \"@engine/core/VenusGame\"\n\n/**\n * Simple Three.js directional light component\n * No complex shadow management - just Three.js native properties\n */\nexport class DirectionalLightComponent extends Component {\n private light: THREE.DirectionalLight\n\n constructor(\n options: {\n color?: THREE.ColorRepresentation\n intensity?: number\n castShadow?: boolean\n shadowMapSize?: number\n shadowCamera?: {\n left?: number\n right?: number\n top?: number\n bottom?: number\n near?: number\n far?: number\n }\n } = {}\n ) {\n super()\n\n // Create the light with Three.js defaults\n this.light = new THREE.DirectionalLight(options.color || 0xffffff, options.intensity || 1)\n\n // Set up shadows if requested - Three.js native approach\n if (options.castShadow) {\n this.light.castShadow = true\n\n // Configure shadow map\n if (options.shadowMapSize) {\n this.light.shadow.mapSize.width = options.shadowMapSize\n this.light.shadow.mapSize.height = options.shadowMapSize\n }\n\n // Configure shadow camera\n if (options.shadowCamera) {\n const cam = this.light.shadow.camera\n if (options.shadowCamera.left !== undefined) cam.left = options.shadowCamera.left\n if (options.shadowCamera.right !== undefined) cam.right = options.shadowCamera.right\n if (options.shadowCamera.top !== undefined) cam.top = options.shadowCamera.top\n if (options.shadowCamera.bottom !== undefined) cam.bottom = options.shadowCamera.bottom\n if (options.shadowCamera.near !== undefined) cam.near = options.shadowCamera.near\n if (options.shadowCamera.far !== undefined) cam.far = options.shadowCamera.far\n }\n }\n }\n\n protected onCreate(): void {\n // Add light to the scene via this GameObject\n this.gameObject.add(this.light)\n\n // Set light position from GameObject position\n this.light.position.copy(this.gameObject.position)\n\n // Set light target to look at origin by default (can be changed with setTarget)\n this.light.target.position.set(0, 0, 0)\n\n // Add target to scene so light direction works properly\n VenusGame.scene.add(this.light.target)\n }\n\n protected onCleanup(): void {\n // Remove light from the scene\n this.gameObject.remove(this.light)\n }\n\n /**\n * Get the Three.js light for direct access\n */\n public getLight(): THREE.DirectionalLight {\n return this.light\n }\n\n /**\n * Set light position\n */\n public setPosition(x: number, y: number, z: number): void {\n this.light.position.set(x, y, z)\n }\n\n /**\n * Set light target position\n */\n public setTarget(x: number, y: number, z: number): void {\n this.light.target.position.set(x, y, z)\n }\n\n /**\n * Set light intensity\n */\n public setIntensity(intensity: number): void {\n this.light.intensity = intensity\n }\n\n /**\n * Set light color\n */\n public setColor(color: THREE.ColorRepresentation): void {\n this.light.color.set(color)\n }\n\n /**\n * Enable/disable shadow casting\n */\n public setCastShadow(enabled: boolean): void {\n this.light.castShadow = enabled\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core/GameObject\"\n\n/**\n * Enhanced Three.js ambient light component that mimics Babylon.js HemisphericLight\n * Provides directional ambient lighting with ground color support\n */\nexport class AmbientLightComponent extends Component {\n private ambientLight!: THREE.AmbientLight\n private hemisphereLight: THREE.HemisphereLight | null = null\n private useHemispheric: boolean = false\n\n constructor(\n options: {\n color?: THREE.ColorRepresentation\n intensity?: number\n groundColor?: THREE.ColorRepresentation // If provided, creates hemispheric lighting\n direction?: THREE.Vector3 // For hemispheric lighting\n } = {}\n ) {\n super()\n\n // If ground color is provided, use hemispheric lighting (like Babylon.js)\n if (options.groundColor !== undefined) {\n this.useHemispheric = true\n this.hemisphereLight = new THREE.HemisphereLight(\n options.color || 0xffffff, // sky color\n options.groundColor, // ground color\n options.intensity || 0.4\n )\n\n // Set direction if provided\n if (options.direction) {\n this.hemisphereLight.position.copy(options.direction)\n }\n } else {\n // Use simple ambient light\n this.ambientLight = new THREE.AmbientLight(\n options.color || 0x404040,\n options.intensity || 0.4\n )\n }\n }\n\n protected onCreate(): void {\n // Add the appropriate light to the scene via this GameObject\n if (this.useHemispheric && this.hemisphereLight) {\n this.gameObject.add(this.hemisphereLight)\n } else {\n this.gameObject.add(this.ambientLight)\n }\n }\n\n protected onCleanup(): void {\n // Remove light from the scene\n if (this.useHemispheric && this.hemisphereLight) {\n this.gameObject.remove(this.hemisphereLight)\n } else {\n this.gameObject.remove(this.ambientLight)\n }\n }\n\n /**\n * Get the Three.js light for direct access\n */\n public getLight(): THREE.Light {\n return this.useHemispheric && this.hemisphereLight ? this.hemisphereLight : this.ambientLight\n }\n\n /**\n * Set light intensity\n */\n public setIntensity(intensity: number): void {\n if (this.useHemispheric && this.hemisphereLight) {\n this.hemisphereLight.intensity = intensity\n } else {\n this.ambientLight.intensity = intensity\n }\n }\n\n /**\n * Set sky color (main color)\n */\n public setColor(color: THREE.ColorRepresentation): void {\n if (this.useHemispheric && this.hemisphereLight) {\n this.hemisphereLight.color.set(color)\n } else {\n this.ambientLight.color.set(color)\n }\n }\n\n /**\n * Set ground color (only works with hemispheric lighting)\n */\n public setGroundColor(color: THREE.ColorRepresentation): void {\n if (this.useHemispheric && this.hemisphereLight) {\n this.hemisphereLight.groundColor.set(color)\n }\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Simple Three.js material utilities\n * Provides common material patterns without complex abstractions\n */\nexport class MaterialUtils {\n // Centralized default path for the toon gradient ramp used by toon materials\n public static readonly DEFAULT_TOON_GRADIENT_PATH = \"assets/cozy_game_general/threeTone.jpg\"\n private static textureLoader = new THREE.TextureLoader()\n private static cachedGradientMap: THREE.Texture | null = null\n\n /**\n * Create a standard PBR material with common settings\n */\n static createStandardMaterial(\n options: {\n color?: THREE.ColorRepresentation\n map?: THREE.Texture\n mapPath?: string // Path to diffuse texture\n roughness?: number\n metalness?: number\n normalMap?: THREE.Texture\n normalMapPath?: string // Path to normal map\n transparent?: boolean\n opacity?: number\n } = {}\n ): THREE.MeshStandardMaterial {\n // Only include defined properties to avoid warnings\n const materialOptions: any = {\n color: options.color || 0xffffff,\n roughness: options.roughness !== undefined ? options.roughness : 0.5,\n metalness: options.metalness !== undefined ? options.metalness : 0.0,\n transparent: options.transparent || false,\n opacity: options.opacity !== undefined ? options.opacity : 1.0,\n }\n\n // Load textures if paths are provided\n if (options.mapPath) {\n materialOptions.map = MaterialUtils.textureLoader.load(options.mapPath)\n } else if (options.map) {\n materialOptions.map = options.map\n }\n\n if (options.normalMapPath) {\n materialOptions.normalMap = MaterialUtils.textureLoader.load(options.normalMapPath)\n } else if (options.normalMap) {\n materialOptions.normalMap = options.normalMap\n }\n\n return new THREE.MeshStandardMaterial(materialOptions)\n }\n\n /**\n * Create a basic material with a color\n */\n static createBasicMaterial(color: THREE.ColorRepresentation): THREE.MeshBasicMaterial {\n return new THREE.MeshBasicMaterial({ color })\n }\n\n /**\n * Create a Lambert material (good for low-poly/stylized looks)\n */\n static createLambertMaterial(\n options: {\n color?: THREE.ColorRepresentation\n map?: THREE.Texture\n } = {}\n ): THREE.MeshLambertMaterial {\n return new THREE.MeshLambertMaterial({\n color: options.color || 0xffffff,\n map: options.map,\n })\n }\n\n /**\n * Create a material with texture\n */\n static createTexturedMaterial(\n textureUrl: string,\n options: {\n color?: THREE.ColorRepresentation\n roughness?: number\n metalness?: number\n } = {}\n ): THREE.MeshStandardMaterial {\n const texture = new THREE.TextureLoader().load(textureUrl)\n\n return new THREE.MeshStandardMaterial({\n color: options.color || 0xffffff,\n map: texture,\n roughness: options.roughness || 0.5,\n metalness: options.metalness || 0.0,\n })\n }\n\n /**\n * Create a simple shared material for prototyping\n */\n static createSharedMaterial(\n color: THREE.ColorRepresentation = 0xffffff\n ): THREE.MeshStandardMaterial {\n return new THREE.MeshStandardMaterial({\n color,\n roughness: 0.7,\n metalness: 0.1,\n })\n }\n\n /**\n * Get or load the toon gradient map (ramp) texture.\n * The texture is cached after first load. Uses nearest filtering and disables mipmaps\n * to preserve crisp banding of the ramp.\n */\n static getToonGradientMap(\n gradientPath: string = MaterialUtils.DEFAULT_TOON_GRADIENT_PATH\n ): THREE.Texture {\n if (MaterialUtils.cachedGradientMap) {\n return MaterialUtils.cachedGradientMap\n }\n\n const tex = MaterialUtils.textureLoader.load(gradientPath)\n tex.minFilter = THREE.NearestFilter\n tex.magFilter = THREE.NearestFilter\n tex.generateMipmaps = false\n ;(tex as any).colorSpace = THREE.SRGBColorSpace\n MaterialUtils.cachedGradientMap = tex\n return tex\n }\n\n /**\n * Create a MeshToonMaterial with optional albedo map and the shared gradient ramp.\n */\n static createToonMaterial(\n options: {\n color?: THREE.ColorRepresentation\n map?: THREE.Texture\n mapPath?: string\n transparent?: boolean\n opacity?: number\n gradientPath?: string\n emissive?: THREE.ColorRepresentation\n } = {}\n ): THREE.MeshToonMaterial {\n const params: any = {\n color: options.color ?? 0xffffff,\n transparent: options.transparent ?? false,\n opacity: options.opacity ?? 1.0,\n gradientMap: MaterialUtils.getToonGradientMap(options.gradientPath),\n }\n\n if (options.map) params.map = options.map\n if (options.mapPath) params.map = MaterialUtils.textureLoader.load(options.mapPath)\n if (options.emissive !== undefined) params.emissive = options.emissive\n\n return new THREE.MeshToonMaterial(params)\n }\n\n /**\n * Convert an arbitrary THREE.Material into a MeshToonMaterial while\n * preserving common properties like color, map and transparency.\n */\n static convertToToon(material: THREE.Material, gradientPath?: string): THREE.MeshToonMaterial {\n const baseMat = material as any\n\n const toon = new THREE.MeshToonMaterial({\n color: baseMat.color ? baseMat.color.clone() : new THREE.Color(0xffffff),\n map: baseMat.map ?? undefined,\n transparent: baseMat.transparent ?? false,\n opacity: baseMat.opacity ?? 1.0,\n alphaTest: baseMat.alphaTest ?? 0,\n gradientMap: MaterialUtils.getToonGradientMap(gradientPath),\n emissive: baseMat.emissive ? baseMat.emissive.clone() : undefined,\n })\n // Preserve material name so downstream logic (e.g., appearance randomizer) keeps working\n if (baseMat.name) {\n toon.name = baseMat.name\n }\n return toon\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core\"\nimport { PathfindingResult, DynamicNavSystem } from \"./DynamicNavSystem\"\n//import { PathVisualizationThree } from \"./PathVisualizationThree\"\n\n/**\n * Three.js version of NavAgent\n * Transform-based navigation agent for AI entities\n * Moves the gameObject position directly without physics for smooth movement\n * Uses waypoint-based pathfinding for all movement\n * Perfect for entities that don't need collision detection (like customers)\n *\n * Handles pathfinding and visualization automatically!\n */\nexport class NavAgent extends Component {\n // Public movement parameters - can be adjusted directly\n public moveSpeed: number = 5.0\n public acceleration: number = 15.0\n public deceleration: number = 10.0\n public arrivalDistance: number = 0.5\n public angularAcceleration: number = 8.0 // How fast to rotate towards movement direction\n\n // Waypoint following\n private waypoints: THREE.Vector3[] = []\n private currentWaypointIndex: number = 0\n\n // Smooth movement interpolation\n private currentVelocity: THREE.Vector3 = new THREE.Vector3()\n private maxSpeed: number = 5.0\n\n // Target tracking\n private currentTarget: THREE.Vector3 | null = null\n private isMoving: boolean = false\n\n // Visualization management\n private pathVisualizationId: string\n private isVisualizationEnabled: boolean = true\n\n constructor() {\n super()\n this.pathVisualizationId = `nav_${Math.random().toString(36).substr(2, 9)}`\n }\n\n /**\n * Move to a target position using pathfinding\n * Handles pathfinding and visualization automatically\n * Returns true if pathfinding succeeded, false otherwise\n */\n public moveTo(targetPosition: THREE.Vector3 | THREE.Vector2): boolean {\n // Update maxSpeed to match current moveSpeed\n this.maxSpeed = this.moveSpeed\n\n // Convert Vector2 to Vector3 if needed\n const target3D =\n targetPosition instanceof THREE.Vector2\n ? new THREE.Vector3(targetPosition.x, 0, targetPosition.y)\n : targetPosition\n\n // Clear any existing path visualization\n this.clearVisualization()\n\n // Find path using DynamicNavSystem\n const result = DynamicNavSystem.findPath(this.gameObject.position, target3D)\n\n if (result.success) {\n // Set the path\n this.setPath(result)\n this.currentTarget = target3D.clone()\n this.isMoving = true\n\n // Add visualization if enabled\n if (this.isVisualizationEnabled) {\n //PathVisualizationThree.addPath(this.pathVisualizationId, result)\n }\n\n return true\n } else {\n // Try to find closest reachable point for fallback\n const currentPos = this.gameObject.position\n const targetDistance = currentPos.distanceTo(target3D)\n\n if (targetDistance < 5.0) {\n // Target is close, try direct movement\n this.setWaypoints([target3D.clone()])\n this.currentTarget = target3D.clone()\n this.isMoving = true\n return true\n }\n\n return false\n }\n }\n\n /**\n * Check if the agent has reached its target (matches Babylon.js NavAgent exactly)\n */\n public hasReachedTarget(): boolean {\n // Must have waypoints and be at the final target position\n if (this.waypoints.length === 0 || !this.currentTarget) {\n return false\n }\n\n // Check if we've completed all waypoints AND are close to the final target\n const hasCompletedPath = this.currentWaypointIndex >= this.waypoints.length\n const distanceToFinalTarget = this.gameObject.position.distanceTo(this.currentTarget)\n const isCloseToTarget = distanceToFinalTarget <= this.arrivalDistance\n\n return hasCompletedPath && isCloseToTarget\n }\n\n /**\n * Check if the agent is currently in motion\n * Returns true if the agent has a target or is still moving (velocity > threshold)\n */\n public isInMotion(): boolean {\n // Check if we have an active target\n if (this.currentTarget !== null) {\n return true\n }\n\n // Check if we're still moving (velocity magnitude)\n const velocityMagnitude = this.currentVelocity.length()\n return velocityMagnitude > 0.1\n }\n\n /**\n * Get the current movement speed as a normalized value (0-1)\n * 0 = stopped, 1 = moving at max speed\n * Useful for animation blending\n */\n public getMovementSpeedNormalized(): number {\n const currentSpeed = this.currentVelocity.length()\n return Math.min(currentSpeed / this.maxSpeed, 1.0)\n }\n\n /**\n * Get the current movement speed (units per second)\n */\n public getMovementSpeed(): number {\n return this.currentVelocity.length()\n }\n\n /**\n * Enable or disable path visualization\n */\n public setVisualizationEnabled(enabled: boolean): void {\n this.isVisualizationEnabled = enabled\n if (!enabled) {\n this.clearVisualization()\n }\n }\n\n /**\n * Get current movement speed\n */\n public getCurrentSpeed(): number {\n return this.currentVelocity.length()\n }\n\n /**\n * Get current waypoints\n */\n public getWaypoints(): THREE.Vector3[] {\n return [...this.waypoints]\n }\n\n /**\n * Stop current movement (matches Babylon.js NavAgent)\n */\n public stop(): void {\n this.clearTarget()\n }\n\n /**\n * Set path from pathfinding result (used internally by moveTo)\n */\n private setPath(pathResult: PathfindingResult): boolean {\n if (!pathResult.success || pathResult.waypoints.length === 0) {\n console.warn(\"NavAgent: Invalid path result provided\")\n this.clearTarget()\n return false\n }\n\n // Convert waypoints to Vector3 array internally\n const waypoints = pathResult.waypoints.map((wp) => new THREE.Vector3(wp.x, 0, wp.z))\n this.setWaypoints(waypoints)\n\n return true\n }\n\n /**\n * Set waypoints to follow (used internally)\n */\n private setWaypoints(waypoints: THREE.Vector3[]): void {\n this.waypoints = [...waypoints]\n\n // CRITICAL: Always skip first waypoint since it's just the starting grid cell center\n // This matches the original Babylon.js NavAgent behavior\n this.currentWaypointIndex = waypoints.length > 1 ? 1 : 0\n }\n\n /**\n * Clear the current target (stops movement) - matches Babylon.js NavAgent exactly\n */\n private clearTarget(): void {\n this.waypoints = []\n this.currentWaypointIndex = 0\n this.currentVelocity.set(0, 0, 0)\n this.currentTarget = null\n this.isMoving = false\n this.clearVisualization()\n }\n\n /**\n * Clear path visualization\n */\n private clearVisualization(): void {\n //PathVisualizationThree.removePath(this.pathVisualizationId)\n }\n\n /**\n * Update movement along waypoints (called automatically by component system)\n */\n public update(deltaTime: number): void {\n // Handle end of path\n if (this.handlePathComplete(deltaTime)) {\n return\n }\n\n // Move toward current waypoint\n this.moveTowardPosition(deltaTime)\n\n // Handle waypoint reached\n this.checkWaypointReached()\n }\n\n /**\n * Handle stopping when path is complete\n * Returns true if path is complete\n */\n private handlePathComplete(deltaTime: number): boolean {\n if (this.currentWaypointIndex >= this.waypoints.length) {\n // Stop moving with smooth deceleration\n this.currentVelocity.lerp(new THREE.Vector3(), this.deceleration * deltaTime)\n this.applyMovement(deltaTime)\n\n if (this.currentVelocity.length() < 0.1) {\n this.isMoving = false\n this.currentVelocity.set(0, 0, 0)\n this.clearVisualization()\n }\n return true\n }\n return false\n }\n\n /**\n * Check if current waypoint is reached and advance if so\n */\n private checkWaypointReached(): void {\n if (this.currentWaypointIndex >= this.waypoints.length) return\n\n const currentWaypoint = this.waypoints[this.currentWaypointIndex]\n const distance = this.gameObject.position.distanceTo(currentWaypoint)\n\n if (distance <= this.arrivalDistance) {\n this.currentWaypointIndex++\n }\n }\n\n /**\n * Move toward a specific position with smooth acceleration/deceleration\n */\n private moveTowardPosition(deltaTime: number): void {\n if (this.currentWaypointIndex >= this.waypoints.length) return\n\n const targetPos = this.waypoints[this.currentWaypointIndex]\n const direction = targetPos.clone().sub(this.gameObject.position)\n direction.y = 0 // Only move on XZ plane\n\n const distance = direction.length()\n if (distance > 0.01) {\n direction.normalize()\n\n // Handle rotation - only rotate when not at the final waypoint or when far from final target\n const isLastWaypoint = this.currentWaypointIndex === this.waypoints.length - 1\n const shouldRotate = !isLastWaypoint || distance > this.arrivalDistance * 2\n\n if (shouldRotate) {\n this.rotateTowardsDirection(direction, deltaTime)\n }\n\n const desiredVelocity = direction.multiplyScalar(this.maxSpeed)\n this.currentVelocity.lerp(desiredVelocity, this.acceleration * deltaTime)\n }\n\n this.applyMovement(deltaTime)\n }\n\n /**\n * Apply the current velocity to the gameObject position\n */\n private applyMovement(deltaTime: number): void {\n const movement = this.currentVelocity.clone().multiplyScalar(deltaTime)\n this.gameObject.position.add(movement)\n }\n\n /**\n * Rotate towards movement direction\n */\n private rotateTowardsDirection(direction: THREE.Vector3, deltaTime: number): void {\n // Calculate target rotation from direction\n const targetRotationY = Math.atan2(direction.x, direction.z)\n\n // Get current rotation Y\n const currentRotationY = this.gameObject.rotation.y\n\n // Calculate the shortest angular distance\n let angleDifference = targetRotationY - currentRotationY\n\n // Normalize angle difference to [-Ī€, Ī€] range\n while (angleDifference > Math.PI) angleDifference -= 2 * Math.PI\n while (angleDifference < -Math.PI) angleDifference += 2 * Math.PI\n\n // Apply angular acceleration with smooth interpolation\n const rotationSpeed = this.angularAcceleration * deltaTime\n const maxRotationThisFrame = rotationSpeed\n\n // Clamp rotation to prevent overshooting\n const rotationDelta =\n Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationThisFrame)\n\n // Apply rotation\n this.gameObject.rotation.y += rotationDelta\n\n // Normalize rotation to [0, 2Ī€] range for consistency\n while (this.gameObject.rotation.y < 0) this.gameObject.rotation.y += 2 * Math.PI\n while (this.gameObject.rotation.y >= 2 * Math.PI) this.gameObject.rotation.y -= 2 * Math.PI\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Three.js UI utilities for creating consistent world-space UI components\n * Simplified to provide consistent text sizing based on world units\n */\nexport class UIUtils {\n /**\n * Create world-space UI plane with consistent text sizing\n * Text sizes in pixels directly translate to world units via pixelsPerUnit\n *\n * @param worldWidth Width of the plane in world units\n * @param worldHeight Height of the plane in world units\n * @param options Configuration options\n * @returns Object containing the plane mesh, canvas, context, and texture\n */\n public static createWorldUI(\n worldWidth: number,\n worldHeight: number,\n options: {\n /** Resolution (pixels per world unit) - use same value across all UI for consistent text size */\n pixelsPerUnit?: number\n /** Height above ground (default: 0.05) */\n heightOffset?: number\n /** Rotate 180 degrees for correct text orientation (default: true) */\n flipOrientation?: boolean\n } = {}\n ): {\n plane: THREE.Mesh\n canvas: HTMLCanvasElement\n ctx: CanvasRenderingContext2D\n texture: THREE.CanvasTexture\n worldSize: { width: number; height: number }\n pixelsPerUnit: number\n } {\n const { pixelsPerUnit = 128, heightOffset = 0.05, flipOrientation = true } = options\n\n // Canvas size = world units * pixels per unit\n // This ensures consistent pixel density across all world UI\n const canvasWidth = Math.round(worldWidth * pixelsPerUnit)\n const canvasHeight = Math.round(worldHeight * pixelsPerUnit)\n\n // Create canvas\n const canvas = document.createElement(\"canvas\")\n canvas.width = canvasWidth\n canvas.height = canvasHeight\n\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) {\n throw new Error(\"Failed to get 2D context from canvas\")\n }\n\n // Set default text rendering settings\n ctx.textBaseline = \"middle\"\n ctx.textAlign = \"center\"\n ctx.imageSmoothingEnabled = true\n ctx.imageSmoothingQuality = \"high\"\n\n // Create texture\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace // Canvas content is sRGB\n texture.minFilter = THREE.LinearFilter\n texture.magFilter = THREE.LinearFilter\n texture.wrapS = THREE.ClampToEdgeWrapping\n texture.wrapT = THREE.ClampToEdgeWrapping\n texture.flipY = true\n texture.generateMipmaps = false\n\n // Create ground plane geometry and unlit shader material\n const geometry = new THREE.PlaneGeometry(worldWidth, worldHeight)\n\n // Unlit shader material for consistent appearance\n const material = new THREE.ShaderMaterial({\n transparent: true,\n side: THREE.DoubleSide,\n fog: false,\n depthWrite: false,\n uniforms: {\n map: { value: texture },\n opacity: { value: 1.0 },\n },\n vertexShader: `\n varying vec2 vUv;\n void main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n `,\n fragmentShader: `\n uniform sampler2D map;\n uniform float opacity;\n varying vec2 vUv;\n void main() {\n vec4 texColor = texture2D(map, vUv);\n gl_FragColor = vec4(texColor.rgb, texColor.a * opacity);\n }\n `,\n })\n\n const plane = new THREE.Mesh(geometry, material)\n plane.rotation.x = -Math.PI / 2 // Lay flat on ground\n if (flipOrientation) {\n plane.rotation.z = Math.PI // Rotate 180 degrees for correct orientation\n }\n plane.position.y = heightOffset\n\n return {\n plane,\n canvas,\n ctx,\n texture,\n worldSize: { width: worldWidth, height: worldHeight },\n pixelsPerUnit,\n }\n }\n\n /**\n * Helper function to draw rounded rectangles on canvas\n */\n public static drawRoundedRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n width: number,\n height: number,\n radius: number\n ): void {\n ctx.beginPath()\n ctx.moveTo(x + radius, y)\n ctx.lineTo(x + width - radius, y)\n ctx.quadraticCurveTo(x + width, y, x + width, y + radius)\n ctx.lineTo(x + width, y + height - radius)\n ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)\n ctx.lineTo(x + radius, y + height)\n ctx.quadraticCurveTo(x, y + height, x, y + height - radius)\n ctx.lineTo(x, y + radius)\n ctx.quadraticCurveTo(x, y, x + radius, y)\n ctx.closePath()\n }\n\n // Common UI colors\n public static readonly COLORS = {\n SUCCESS: \"#008200\",\n PRIMARY: \"#3b82f6\",\n WARNING: \"#f59e0b\",\n DANGER: \"#ef4444\",\n WHITE: \"#ffffff\",\n BLACK: \"#000000\",\n GRAY: \"#6b7280\",\n BACKGROUND: \"rgba(0, 0, 0, 0.4)\",\n BORDER: \"#ffffff\",\n }\n\n // Default font family for game UI - single source of truth\n public static readonly FONT_FAMILY = \"'Palanquin Dark', sans-serif\"\n\n /**\n * Initialize CSS variables for UI styling\n * Call this once at app startup (UISystem.initialize() calls this automatically)\n */\n public static initializeCSSVariables(): void {\n document.documentElement.style.setProperty(\"--game-font\", UIUtils.FONT_FAMILY)\n }\n}\n","import * as THREE from \"three\"\nimport { UIUtils } from \"./UIUtils\"\n\n/**\n * HTML/CSS-based UI system for Three.js\n * Provides overlay elements for HUD, interaction prompts, menus, and dialogs\n * Uses modern CSS and HTML instead of canvas-based UI\n *\n * The system uses two separate containers:\n * - Main container: For HUD, menus, etc. Respects safe area insets\n * - World container: For world-space UI (indicators above 3D objects). Not affected by safe areas\n */\nexport class UISystem {\n private static container: HTMLElement | null = null\n private static worldContainer: HTMLElement | null = null // Separate container for world UI\n private static isInitialized: boolean = false\n private static activeElements: Map<string, UIElement> = new Map()\n private static lastMoneyAmount: number = -1 // Track last money amount for animation\n\n // Unity-style Canvas Scaler system with \"Match Width Or Height\" support\n // Reference resolution is the screen size at which UI appears at 100% scale\n // matchWidthOrHeight: 0 = match width only, 1 = match height only, 0.5 = blend both\n private static referenceWidth: number = 1920 // Reference resolution width (Full HD)\n private static referenceHeight: number = 1080 // Reference resolution height (Full HD)\n private static matchWidthOrHeight: number = 0.5 // 0=width, 1=height, 0.5=blend (like Unity)\n private static minScale: number = 0.5 // Minimum scale\n private static maxScale: number = 1.5 // Maximum scale\n private static currentScale: number = 1.0 // Calculated scale\n\n /**\n * Reset the UISystem state - useful for page refreshes or reinitialization\n */\n public static reset(): void {\n if (UISystem.container) {\n UISystem.container.remove()\n UISystem.container = null\n }\n if (UISystem.worldContainer) {\n UISystem.worldContainer.remove()\n UISystem.worldContainer = null\n }\n UISystem.activeElements.clear()\n UISystem.isInitialized = false\n console.log(`[UISystem] System reset`)\n }\n\n public static setInsets(insets: {\n left: number\n top: number\n right: number\n bottom: number\n }): void {\n UISystem.initialize()\n\n const container = UISystem.container\n if (!container) {\n console.warn(\"UISystem container missing\")\n return\n }\n\n console.log(`[UISystem] Setting safe area insets:`, insets)\n\n // Apply safe area insets only to the main UI container\n // World UI container is not affected by safe areas to maintain accurate 3D positioning\n container.style.left = insets.left + \"px\"\n container.style.top = insets.top + \"px\"\n container.style.right = insets.right + \"px\"\n container.style.bottom = insets.bottom + \"px\"\n }\n\n /**\n * Initialize the UI system\n */\n public static initialize(): void {\n if (UISystem.isInitialized) {\n return\n }\n\n // Initialize CSS variables (font family, etc.)\n UIUtils.initializeCSSVariables()\n\n // Create the main UI container (for HUD, menus, etc. - respects safe areas)\n UISystem.container = document.createElement(\"div\")\n UISystem.container.id = \"ui-system-three\"\n UISystem.container.style.cssText = `\n position: absolute;\n top: 0px;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 1000;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n `\n document.body.appendChild(UISystem.container)\n\n // Create a separate container for world-space UI (doesn't respect safe areas)\n UISystem.worldContainer = document.createElement(\"div\")\n UISystem.worldContainer.id = \"ui-world-system-three\"\n UISystem.worldContainer.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n pointer-events: none;\n z-index: 999;\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n `\n document.body.appendChild(UISystem.worldContainer)\n\n // Add global CSS styles\n UISystem.addGlobalStyles()\n\n UISystem.isInitialized = true\n\n // Add CSS custom properties for responsive scaling\n UISystem.updateResponsiveScale()\n\n // Update responsive scale on window resize\n window.addEventListener(\"resize\", UISystem.updateResponsiveScale)\n\n // Add debug functions\n ;(window as any).refreshUIStyles = () => {\n console.log(\"đŸ§Ē Forcing UI styles refresh...\")\n const existing = document.getElementById(\"ui-system-three-styles\")\n if (existing) {\n existing.remove()\n }\n UISystem.addGlobalStyles()\n console.log(\"đŸ§Ē UI styles refreshed\")\n }\n ;(window as any).cleanupUIElements = () => {\n const elements = document.querySelectorAll(\".ui-max-indicator\")\n console.log(`đŸ§Ē Found ${elements.length} MAX indicators, cleaning up...`)\n elements.forEach((el, index) => {\n const rect = el.getBoundingClientRect()\n console.log(`Element ${index} position:`, rect)\n if (rect.left === 0 && rect.top === 0) {\n console.log(`đŸ§Ē Removing element ${index} (at origin)`)\n el.remove()\n }\n })\n }\n ;(window as any).resetUISystem = () => {\n console.log(\"🔄 Resetting UI system...\")\n UISystem.reset()\n UISystem.initialize()\n console.log(\"✅ UI system reset complete\")\n }\n\n // UI debug functions available\n }\n\n /**\n * Add global CSS styles for UI elements\n */\n private static addGlobalStyles(): void {\n const style = document.createElement(\"style\")\n style.textContent = `\n .ui-element {\n position: absolute;\n pointer-events: auto;\n user-select: none;\n }\n \n .ui-hud {\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 12px;\n border-radius: 8px;\n font-size: 14px;\n backdrop-filter: blur(4px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n }\n \n .ui-interaction-prompt {\n background: rgba(74, 222, 128, 0.9);\n color: white;\n padding: 8px 16px;\n border-radius: 20px;\n font-size: 14px;\n font-weight: bold;\n text-align: center;\n backdrop-filter: blur(4px);\n border: 2px solid rgba(255, 255, 255, 0.3);\n animation: ui-pulse 2s infinite;\n }\n \n .ui-money-display {\n background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%);\n color: white;\n padding: 12px 20px;\n border-radius: 25px;\n font-size: 20px;\n font-weight: 700;\n box-shadow: 0 6px 0 #16a34a, 0 8px 20px rgba(34, 197, 94, 0.4);\n font-family: var(--game-font);\n text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);\n transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);\n opacity: 0.9;\n }\n \n .ui-progress-bar {\n background: rgba(0, 0, 0, 0.7);\n border-radius: 4px;\n overflow: hidden;\n border: 1px solid rgba(255, 255, 255, 0.2);\n }\n \n .ui-progress-fill {\n height: 100%;\n background: linear-gradient(90deg, #10b981, #34d399);\n transition: width 0.3s ease;\n }\n \n .ui-button {\n background: rgba(59, 130, 246, 0.9);\n color: white;\n border: none;\n padding: 10px 20px;\n border-radius: 6px;\n font-size: 14px;\n font-weight: bold;\n cursor: pointer;\n transition: all 0.2s ease;\n border: 1px solid rgba(255, 255, 255, 0.2);\n }\n \n .ui-button:hover {\n background: rgba(79, 70, 229, 0.9);\n transform: translateY(-1px);\n }\n \n .ui-button:active {\n transform: translateY(0);\n }\n \n .ui-modal {\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 24px;\n border-radius: 12px;\n backdrop-filter: blur(8px);\n border: 1px solid rgba(255, 255, 255, 0.1);\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);\n }\n \n .ui-tooltip {\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 12px;\n pointer-events: none;\n border: 1px solid rgba(255, 255, 255, 0.2);\n }\n \n @keyframes ui-pulse {\n 0%, 100% { transform: scale(1); opacity: 1; }\n 50% { transform: scale(1.05); opacity: 0.9; }\n }\n \n @keyframes ui-fade-in {\n from { opacity: 0; transform: translateY(-10px); }\n to { opacity: 1; transform: translateY(0); }\n }\n \n .ui-fade-in {\n animation: ui-fade-in 0.3s ease;\n }\n \n /* Purchase Area Styles */\n .purchase-area-world-ui {\n position: absolute;\n transform: translate(-50%, -50%);\n pointer-events: none;\n z-index: 1000;\n }\n \n .purchase-area-ui {\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 12px 20px;\n border-radius: 8px;\n text-align: center;\n border: 2px solid #4ade80;\n box-shadow: 0 4px 16px rgba(74, 222, 128, 0.3);\n min-width: 120px;\n }\n \n .purchase-label {\n font-size: 18px;\n font-weight: bold;\n margin-bottom: 4px;\n color: #4ade80;\n }\n \n .purchase-progress {\n font-size: 14px;\n margin-bottom: 2px;\n color: #ffffff;\n }\n \n .purchase-percent {\n font-size: 16px;\n font-weight: bold;\n color: #4ade80;\n }\n \n /* MAX Indicator Styles - Moved to world-ui.css */\n /* Commented out to use external CSS file without !important overrides */\n \n /* Table Warning Styles - Moved to world-ui.css */\n /* Commented out to use external CSS file without !important overrides */\n \n @keyframes ui-max-pulse {\n 0%, 100% { \n opacity: 1;\n transform: scale(1);\n }\n 50% { \n opacity: 0.8;\n transform: scale(1.05);\n }\n }\n \n @keyframes bounce-pulse {\n 0%, 100% {\n transform: translateY(0) scale(1);\n }\n 25% {\n transform: translateY(-4px) scale(1.05);\n }\n 50% {\n transform: translateY(0) scale(1.1);\n }\n 75% {\n transform: translateY(-2px) scale(1.05);\n }\n }\n \n @keyframes gentle-bounce {\n 0%, 100% {\n transform: translateY(0);\n }\n 50% {\n transform: translateY(-3px);\n }\n }\n \n @keyframes money-pulse {\n 0%, 100% {\n transform: scale(1) rotate(0deg);\n }\n 25% {\n transform: scale(1.02) rotate(1deg);\n }\n 50% {\n transform: scale(1.05) rotate(-1deg);\n }\n 75% {\n transform: scale(1.02) rotate(1deg);\n }\n }\n \n @keyframes money-juice {\n 0% {\n transform: scale(1) rotate(0deg);\n }\n 10% {\n transform: scale(1.3) rotate(-5deg);\n }\n 20% {\n transform: scale(1.15) rotate(5deg);\n }\n 30% {\n transform: scale(1.25) rotate(-3deg);\n }\n 40% {\n transform: scale(1.1) rotate(3deg);\n }\n 50% {\n transform: scale(1.15) rotate(-2deg);\n }\n 60% {\n transform: scale(1.05) rotate(2deg);\n }\n 70% {\n transform: scale(1.08) rotate(-1deg);\n }\n 80% {\n transform: scale(1.02) rotate(1deg);\n }\n 90% {\n transform: scale(1.01) rotate(0deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n }\n }\n \n /* Order Indicator Styles - Moved to world-ui.css */\n /* Commented out to use external CSS file without !important overrides */\n\n /* Car Order Indicator Styles - Moved to world-ui.css */\n /* Commented out to use external CSS file without !important overrides */\n `\n document.head.appendChild(style)\n }\n\n /**\n * Create a HUD element (money display, health bar, etc.)\n */\n public static createHUD(\n id: string,\n content: string,\n position: { x: number; y: number },\n options: { className?: string; style?: string } = {}\n ): UIElement {\n const element = UISystem.createElement(id, \"hud\", content, position, options)\n element.element.classList.add(\"ui-hud\")\n return element\n }\n\n /**\n * Create an interaction prompt (Press E to interact, etc.)\n */\n public static createInteractionPrompt(\n id: string,\n text: string,\n position: { x: number; y: number }\n ): UIElement {\n const element = UISystem.createElement(id, \"interaction\", text, position)\n element.element.classList.add(\"ui-interaction-prompt\")\n return element\n }\n\n /**\n * Create a progress bar (cooking progress, etc.)\n */\n public static createProgressBar(\n id: string,\n position: { x: number; y: number },\n size: { width: number; height: number },\n progress: number = 0\n ): UIProgressBar {\n const container = document.createElement(\"div\")\n container.className = \"ui-element ui-progress-bar\"\n container.style.cssText = `\n left: ${position.x}px;\n top: ${position.y}px;\n width: ${size.width}px;\n height: ${size.height}px;\n `\n\n const fill = document.createElement(\"div\")\n fill.className = \"ui-progress-fill\"\n fill.style.width = `${progress * 100}%`\n container.appendChild(fill)\n\n UISystem.container!.appendChild(container)\n\n const progressBar: UIProgressBar = {\n id,\n type: \"progress\",\n element: container,\n fillElement: fill,\n setProgress: (value: number) => {\n fill.style.width = `${Math.max(0, Math.min(1, value)) * 100}%`\n },\n show: () => {\n container.style.display = \"block\"\n },\n hide: () => {\n container.style.display = \"none\"\n },\n remove: () => {\n container.remove()\n UISystem.activeElements.delete(id)\n },\n }\n\n UISystem.activeElements.set(id, progressBar)\n return progressBar\n }\n\n /**\n * Create a button\n */\n public static createButton(\n id: string,\n text: string,\n position: { x: number; y: number },\n onClick: () => void\n ): UIElement {\n const element = UISystem.createElement(id, \"button\", text, position)\n element.element.classList.add(\"ui-button\")\n element.element.addEventListener(\"click\", onClick)\n return element\n }\n\n /**\n * Create a modal dialog\n */\n public static createModal(\n id: string,\n content: string,\n options: {\n title?: string\n buttons?: Array<{ text: string; onClick: () => void }>\n width?: number\n height?: number\n fullScreenOverlay?: boolean // If true, backdrop will ignore safe areas and cover the full screen\n } = {}\n ): UIElement {\n const modal = document.createElement(\"div\")\n modal.className = \"ui-element ui-modal ui-fade-in\"\n let style = `\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n width: ${options.width || 400}px;\n z-index: 1100;\n `\n if (typeof options.height === \"number\") {\n style += `max-height: ${options.height}px;`\n }\n modal.style.cssText = style\n // Avoid one-frame position/size flicker by rendering hidden and revealing next frame\n ;(modal as HTMLElement).style.visibility = \"hidden\"\n\n let html = \"\"\n if (options.title) {\n html += `<h3 style=\"margin: 0 0 16px 0; color: #10b981;\">${options.title}</h3>`\n }\n html += `<div style=\"margin-bottom: 16px;\">${content}</div>`\n\n if (options.buttons) {\n html += '<div style=\"display: flex; gap: 8px; justify-content: flex-end;\">'\n options.buttons.forEach((button, index) => {\n html += `<button class=\"ui-button\" data-button-index=\"${index}\">${button.text}</button>`\n })\n html += \"</div>\"\n }\n\n modal.innerHTML = html\n\n // Add button event listeners\n if (options.buttons) {\n options.buttons.forEach((button, index) => {\n const buttonElement = modal.querySelector(`[data-button-index=\"${index}\"]`) as HTMLElement\n if (buttonElement) {\n buttonElement.addEventListener(\"click\", button.onClick)\n }\n })\n }\n\n // Add backdrop\n const backdrop = document.createElement(\"div\")\n backdrop.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.5);\n z-index: 1099;\n `\n\n // Use worldContainer for full-screen overlays that ignore safe areas, otherwise use main container\n const backdropContainer = options.fullScreenOverlay\n ? UISystem.worldContainer!\n : UISystem.container!\n backdropContainer.appendChild(backdrop)\n\n UISystem.container!.appendChild(modal)\n requestAnimationFrame(() => {\n ;(modal as HTMLElement).style.visibility = \"visible\"\n })\n\n const element: UIElement = {\n id,\n type: \"modal\",\n element: modal,\n show: () => {\n modal.style.display = \"block\"\n backdrop.style.display = \"block\"\n },\n hide: () => {\n modal.style.display = \"none\"\n backdrop.style.display = \"none\"\n },\n remove: () => {\n modal.remove()\n backdrop.remove()\n UISystem.activeElements.delete(id)\n },\n }\n\n UISystem.activeElements.set(id, element)\n return element\n }\n\n /**\n * Update money display (special HUD element)\n */\n public static updateMoneyDisplay(amount: number): void {\n // Money display update requested\n\n const existing = UISystem.activeElements.get(\"money-display\")\n if (existing) {\n // Check if money increased for juice animation\n const shouldJuice = UISystem.lastMoneyAmount >= 0 && amount > UISystem.lastMoneyAmount\n\n // Money display updated\n existing.element.innerHTML = `<span class=\"money-display-icon\"></span>${amount.toLocaleString()}`\n\n // Apply juice animation if money increased\n if (shouldJuice) {\n // Remove any existing animation\n existing.element.style.animation = \"none\"\n\n // Dispatch custom event for sound system to hook into\n window.dispatchEvent(\n new CustomEvent(\"moneyIncreased\", {\n detail: { oldAmount: UISystem.lastMoneyAmount, newAmount: amount },\n })\n )\n\n // No more animations - let MoneyChangeIndicator handle attention-grabbing\n }\n\n UISystem.lastMoneyAmount = amount\n } else {\n // Creating money display\n\n const money = UISystem.createHUD(\n \"money-display\",\n `<span class=\"money-display-icon\"></span>${amount.toLocaleString()}`,\n { x: window.innerWidth - 150, y: 20 } // Top-right positioning\n )\n money.element.classList.add(\"ui-money-display\")\n\n // Add money display specific styles - define colors here (will be centralized later if needed)\n money.element.style.cssText += `\n position: absolute !important;\n top: 20px !important;\n right: 20px !important;\n left: auto !important;\n background: linear-gradient(135deg, #4ade80 0%, #22c55e 100%) !important;\n color: white !important;\n padding: 12px 20px !important;\n border-radius: 25px !important;\n font-weight: 700 !important;\n font-size: 22px !important;\n box-shadow: 0 6px 0 #16a34a, 0 8px 20px rgba(34, 197, 94, 0.4) !important;\n z-index: 9999 !important;\n display: flex !important;\n align-items: center !important;\n gap: 10px !important;\n font-family: var(--game-font) !important;\n text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3) !important;\n /* No animation - stable money display */\n transform-origin: center !important;\n opacity: 0.9 !important;\n `\n\n // Add money icon styles if not already added\n if (!document.querySelector(\"#money-display-icon-style\")) {\n const iconStyle = document.createElement(\"style\")\n iconStyle.id = \"money-display-icon-style\"\n iconStyle.textContent = `\n .money-display-icon {\n width: 30px;\n height: 30px;\n background-image: url('assets/cozy_game_general/money_icon.png');\n background-size: contain;\n background-repeat: no-repeat;\n background-position: center;\n display: inline-block;\n flex-shrink: 0;\n filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.4));\n }\n `\n document.head.appendChild(iconStyle)\n }\n\n // Money display created\n UISystem.lastMoneyAmount = amount\n }\n }\n\n /**\n * Create a world-space UI element that follows a 3D position\n */\n public static createWorldSpaceUI(\n id: string,\n content: string,\n worldPosition: THREE.Vector3,\n camera: THREE.Camera,\n options: { offset?: { x: number; y: number }; className?: string } = {}\n ): UIWorldElement {\n const element = document.createElement(\"div\")\n element.className = `ui-element ${options.className || \"ui-tooltip\"}`\n element.innerHTML = content\n element.style.position = \"absolute\"\n\n // Use world container instead of regular container to avoid safe area issues\n UISystem.worldContainer!.appendChild(element)\n\n const worldElement: UIWorldElement = {\n id,\n type: \"world\",\n element,\n worldPosition: worldPosition.clone(),\n update: (camera: THREE.Camera) => {\n // Project 3D position to screen coordinates\n const screenPosition = worldPosition.clone().project(camera)\n\n // Convert to pixel coordinates\n const x = (screenPosition.x * 0.5 + 0.5) * window.innerWidth\n const y = (screenPosition.y * -0.5 + 0.5) * window.innerHeight\n\n // Apply offset\n const offsetX = options.offset?.x || 0\n const offsetY = options.offset?.y || -30\n\n element.style.left = `${x + offsetX}px`\n element.style.top = `${y + offsetY}px`\n element.style.transform = \"translate(-50%, -50%)\" // Center the element on the position\n element.style.transformOrigin = \"center\"\n\n // Hide if behind camera\n element.style.display = screenPosition.z > 1 ? \"none\" : \"block\"\n },\n show: () => {\n element.style.display = \"block\"\n },\n hide: () => {\n element.style.display = \"none\"\n },\n remove: () => {\n element.remove()\n UISystem.activeElements.delete(id)\n },\n }\n\n UISystem.activeElements.set(id, worldElement)\n return worldElement\n }\n\n /**\n * Update all world-space UI elements\n */\n public static updateWorldSpaceElements(camera: THREE.Camera): void {\n UISystem.activeElements.forEach((element) => {\n if (element.type === \"world\" && \"update\" in element) {\n ;(element as UIWorldElement).update(camera)\n }\n })\n }\n\n /**\n * Unity-style Canvas Scaler with \"Match Width Or Height\" support\n *\n * How it works:\n * - Reference resolution (e.g., 800x600) - screen size where UI is 100% scale\n * - matchWidthOrHeight: 0 = match width, 1 = match height, 0.5 = blend both\n * - UI components use CSS: transform: scale(var(--ui-scale, 1))\n *\n * The blend formula (same as Unity):\n * scale = widthScale^(1-match) * heightScale^match\n *\n * This means on portrait mobile (narrow width, tall height):\n * - Width-only (match=0): very small UI\n * - Height-only (match=1): large UI\n * - Blend (match=0.5): balanced UI that looks good\n */\n public static updateResponsiveScale(): void {\n const screenWidth = window.innerWidth\n const screenHeight = window.innerHeight\n\n // Calculate scale factors for width and height\n const widthScale = screenWidth / UISystem.referenceWidth\n const heightScale = screenHeight / UISystem.referenceHeight\n\n // Unity's blend formula: scale = widthScale^(1-match) * heightScale^match\n const match = UISystem.matchWidthOrHeight\n const rawScale = Math.pow(widthScale, 1 - match) * Math.pow(heightScale, match)\n\n // Clamp the scale to prevent extremes\n const prevScale = UISystem.currentScale\n UISystem.currentScale = Math.max(UISystem.minScale, Math.min(UISystem.maxScale, rawScale))\n\n // Log scale changes for debugging\n if (Math.abs(prevScale - UISystem.currentScale) > 0.01) {\n console.log(\n `[UISystem] Canvas Scale: ${UISystem.currentScale.toFixed(2)} (screen: ${screenWidth}x${screenHeight}, ref: ${UISystem.referenceWidth}x${UISystem.referenceHeight}, match: ${match})`\n )\n }\n\n // Set CSS custom property that UI components use via: transform: scale(var(--ui-scale, 1))\n document.documentElement.style.setProperty(\"--ui-scale\", UISystem.currentScale.toString())\n document.documentElement.style.setProperty(\"--screen-width\", `${screenWidth}px`)\n document.documentElement.style.setProperty(\"--screen-height\", `${screenHeight}px`)\n }\n\n /**\n * Create a HUD element with responsive anchor-based positioning\n */\n public static createResponsiveHUD(\n id: string,\n content: string,\n anchor: { x: number; y: number }, // 0-1 values (0 = left/top, 1 = right/bottom)\n offset: { x: number; y: number } = { x: 0, y: 0 }, // Pixel offset from anchor\n options: { className?: string; style?: string } = {}\n ): UIElement {\n const element = document.createElement(\"div\")\n element.className = `ui-element ui-responsive ${options.className || \"\"}`\n element.innerHTML = content\n\n // Use CSS positioning with calc() for responsive anchoring\n element.style.position = \"absolute\"\n element.style.left = `calc(${anchor.x * 100}% + ${offset.x}px)`\n element.style.top = `calc(${anchor.y * 100}% + ${offset.y}px)`\n element.style.transform = `translate(-${anchor.x * 100}%, -${anchor.y * 100}%) scale(var(--ui-scale, 1))`\n element.style.transformOrigin = \"center\"\n element.style.pointerEvents = \"none\"\n element.style.zIndex = \"1000\"\n\n if (options.style) {\n element.style.cssText += options.style\n }\n\n UISystem.container!.appendChild(element)\n\n const uiElement: UIElement = {\n id,\n type: \"hud\",\n element,\n show: () => {\n element.style.display = \"block\"\n },\n hide: () => {\n element.style.display = \"none\"\n },\n remove: () => {\n element.remove()\n UISystem.activeElements.delete(id)\n },\n }\n\n UISystem.activeElements.set(id, uiElement)\n return uiElement\n }\n\n /**\n * Get an element by ID\n */\n public static getElement(id: string): UIElement | undefined {\n return UISystem.activeElements.get(id)\n }\n\n /**\n * Remove an element\n */\n public static removeElement(id: string): void {\n const element = UISystem.activeElements.get(id)\n if (element) {\n element.remove()\n }\n }\n\n /**\n * Clear all UI elements\n */\n public static clear(): void {\n UISystem.activeElements.forEach((element) => element.remove())\n UISystem.activeElements.clear()\n }\n\n /**\n * Show/hide the entire UI system\n */\n public static setVisible(visible: boolean): void {\n if (UISystem.container) {\n UISystem.container.style.display = visible ? \"block\" : \"none\"\n }\n if (UISystem.worldContainer) {\n UISystem.worldContainer.style.display = visible ? \"block\" : \"none\"\n }\n }\n\n /**\n * Generic element creation helper\n */\n private static createElement(\n id: string,\n type: string,\n content: string,\n position: { x: number; y: number },\n options: { className?: string; style?: string } = {}\n ): UIElement {\n const element = document.createElement(\"div\")\n element.className = `ui-element ${options.className || \"\"}`\n element.innerHTML = content\n element.style.cssText = `\n left: ${position.x}px;\n top: ${position.y}px;\n ${options.style || \"\"}\n `\n\n UISystem.container!.appendChild(element)\n\n const uiElement: UIElement = {\n id,\n type,\n element,\n show: () => {\n element.style.display = \"block\"\n },\n hide: () => {\n element.style.display = \"none\"\n },\n remove: () => {\n element.remove()\n UISystem.activeElements.delete(id)\n },\n }\n\n UISystem.activeElements.set(id, uiElement)\n return uiElement\n }\n\n /**\n * Configure the reference resolution for UI scaling (like Unity's Canvas Scaler)\n * @param referenceWidth - The width at which UI is designed (default: 1920 Full HD)\n * @param referenceHeight - The height at which UI is designed (default: 1080 Full HD)\n * @param matchWidthOrHeight - 0 = match width, 1 = match height, 0.5 = blend both (recommended)\n * @param minScale - Minimum scale factor (prevents UI from getting too small)\n * @param maxScale - Maximum scale factor (prevents UI from getting too large)\n */\n public static configureScaling(\n referenceWidth: number = 1920,\n referenceHeight: number = 1080,\n matchWidthOrHeight: number = 0.5,\n minScale: number = 0.5,\n maxScale: number = 1.5\n ): void {\n UISystem.referenceWidth = referenceWidth\n UISystem.referenceHeight = referenceHeight\n UISystem.matchWidthOrHeight = Math.max(0, Math.min(1, matchWidthOrHeight))\n UISystem.minScale = minScale\n UISystem.maxScale = maxScale\n UISystem.updateResponsiveScale()\n }\n\n /**\n * Get the current calculated UI scale factor\n */\n public static getUIScale(): number {\n return UISystem.currentScale\n }\n\n /**\n * Get the reference width used for scaling calculations\n */\n public static getReferenceWidth(): number {\n return UISystem.referenceWidth\n }\n\n /**\n * Dispose of the UI system\n */\n public static dispose(): void {\n UISystem.clear()\n window.removeEventListener(\"resize\", UISystem.updateResponsiveScale)\n if (UISystem.container) {\n UISystem.container.remove()\n UISystem.container = null\n }\n if (UISystem.worldContainer) {\n UISystem.worldContainer.remove()\n UISystem.worldContainer = null\n }\n UISystem.isInitialized = false\n }\n}\n\n// UI Element interfaces\nexport interface UIElement {\n id: string\n type: string\n element: HTMLElement\n show: () => void\n hide: () => void\n remove: () => void\n}\n\nexport interface UIProgressBar extends UIElement {\n fillElement: HTMLElement\n setProgress: (value: number) => void\n}\n\nexport interface UIWorldElement extends UIElement {\n worldPosition: THREE.Vector3\n update: (camera: THREE.Camera) => void\n}\n","īģŋexport class UILoadingScreen {\n private static loadingScreenElement: HTMLDivElement | null = null\n\n /**\n * Show the loading screen with a spinner\n * @param message Optional loading message to display\n * @param backgroundColor Optional background color (default: #1a1a1a)\n */\n static showLoadingScreen(\n message: string = \"Loading...\",\n backgroundColor: string = \"#1a1a1a\"\n ): void {\n // Prevent multiple loading screens\n if (this.loadingScreenElement) {\n return\n }\n\n const loadingScreen = document.createElement(\"div\")\n loadingScreen.id = \"loadingScreen\"\n\n // Apply styles\n Object.assign(loadingScreen.style, {\n position: \"fixed\",\n left: \"0\",\n right: \"0\",\n top: \"0\",\n bottom: \"0\",\n backgroundColor: backgroundColor,\n zIndex: \"9999\",\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n fontFamily: \"Arial, sans-serif\",\n })\n\n // Create spinner\n const spinner = document.createElement(\"div\")\n spinner.className = \"spinner\"\n Object.assign(spinner.style, {\n width: \"60px\",\n height: \"60px\",\n border: \"6px solid rgba(255, 255, 255, 0.2)\",\n borderTop: \"6px solid #ffffff\",\n borderRadius: \"50%\",\n animation: \"spin 1s linear infinite\",\n })\n\n // Create loading text\n // const loadingText = document.createElement(\"p\");\n // loadingText.textContent = message;\n // Object.assign(loadingText.style, {\n // color: \"#ffffff\",\n // fontSize: \"18px\",\n // marginTop: \"20px\",\n // fontWeight: \"500\",\n // });\n\n // Add CSS animation\n this.addSpinnerAnimation()\n\n // Append elements\n loadingScreen.appendChild(spinner)\n // loadingScreen.appendChild(loadingText);\n document.body.appendChild(loadingScreen)\n\n this.loadingScreenElement = loadingScreen\n }\n\n /**\n * Hide and remove the loading screen\n * @param fadeOut Optional fade out animation (default: true)\n */\n static hideLoadingScreen(fadeOut: boolean = true): void {\n if (!this.loadingScreenElement) {\n return\n }\n\n if (fadeOut) {\n this.loadingScreenElement.style.transition = \"opacity 0.3s ease-out\"\n this.loadingScreenElement.style.opacity = \"0\"\n\n setTimeout(() => {\n this.removeLoadingScreen()\n }, 300)\n } else {\n this.removeLoadingScreen()\n }\n }\n\n /**\n * Remove the loading screen from DOM\n */\n private static removeLoadingScreen(): void {\n if (this.loadingScreenElement) {\n this.loadingScreenElement.remove()\n this.loadingScreenElement = null\n }\n }\n\n /**\n * Add spinner animation to the document\n */\n private static addSpinnerAnimation(): void {\n // Check if animation already exists\n if (document.getElementById(\"spinner-animation\")) {\n return\n }\n\n const style = document.createElement(\"style\")\n style.id = \"spinner-animation\"\n style.textContent = `\n @keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n `\n document.head.appendChild(style)\n }\n}\n","import * as THREE from \"three\"\n\n// Re-export the ParticleEmitterComponent\nexport { Particle } from \"./Particle\"\n\n// Import curve types and evaluation functions\nexport type { CurveKeyframe, AnimationCurve, CurveableValue } from \"./curve\"\nexport {\n evaluateCurve,\n evaluateCurveableValue,\n createKeyframe,\n createCurveFromPoints,\n CurvePresets,\n cloneCurve,\n addKeyframe,\n removeKeyframe,\n updateKeyframe,\n} from \"./curve\"\nimport type { CurveableValue } from \"./curve\"\nimport { evaluateCurveableValue } from \"./curve\"\n\nexport type ParticleSystem = {\n object: THREE.InstancedMesh\n update: (dt: number, camera: THREE.Camera, emitterWorldMatrix?: THREE.Matrix4) => void\n burst: (origin: THREE.Vector3, count?: number) => void\n setSpawnRate: (rate: number) => void\n setOrigin: (origin: THREE.Vector3) => void\n config: EmitterConfig\n setTexture?: (texture: THREE.Texture) => void\n // Playback controls\n play: () => void\n stop: () => void\n restart: () => void\n isPlaying: () => boolean\n getElapsed: () => number\n // Internal methods (no cascade) - used by parent cascade\n playInternal?: () => void\n stopInternal?: () => void\n restartInternal?: () => void\n}\n\nexport type NumRange = number | readonly [number, number]\ntype Vec3Range = THREE.Vector3 | { min: THREE.Vector3; max: THREE.Vector3 }\ntype Vec4Range = THREE.Vector4 | { min: THREE.Vector4; max: THREE.Vector4 }\n\nfunction randRange(r: NumRange): number {\n if (Array.isArray(r)) return r[0] + Math.random() * (r[1] - r[0])\n return r as number\n}\nfunction randVec3(r: Vec3Range, out: THREE.Vector3): THREE.Vector3 {\n if (r instanceof THREE.Vector3) {\n out.copy(r)\n return out\n }\n const { min, max } = r\n out.set(\n min.x + Math.random() * (max.x - min.x),\n min.y + Math.random() * (max.y - min.y),\n min.z + Math.random() * (max.z - min.z)\n )\n return out\n}\nfunction randVec4(r: Vec4Range, out: THREE.Vector4): THREE.Vector4 {\n if (r instanceof THREE.Vector4) {\n out.copy(r)\n return out\n }\n const { min, max } = r\n out.set(\n min.x + Math.random() * (max.x - min.x),\n min.y + Math.random() * (max.y - min.y),\n min.z + Math.random() * (max.z - min.z),\n min.w + Math.random() * (max.w - min.w)\n )\n return out\n}\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t\n}\nfunction lerpVec4(\n a: THREE.Vector4,\n b: THREE.Vector4,\n t: number,\n out: THREE.Vector4\n): THREE.Vector4 {\n out.set(lerp(a.x, b.x, t), lerp(a.y, b.y, t), lerp(a.z, b.z, t), lerp(a.w, b.w, t))\n return out\n}\n\nexport function range(min: number, max: number): readonly [number, number] {\n return [min, max] as const\n}\n\n// ============================================================================\n// Simplex Noise Implementation (2D/3D)\n// Based on Stefan Gustavson's implementation, optimized for particles\n// ============================================================================\n\n// Permutation table (doubled for wrapping)\nconst perm = new Uint8Array(512)\nconst permMod12 = new Uint8Array(512)\n\n// Initialize permutation tables with a fixed seed for deterministic results\n;(function initNoise() {\n const p = [\n 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69,\n 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219,\n 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,\n 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230,\n 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76,\n 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186,\n 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59,\n 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70,\n 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178,\n 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,\n 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115,\n 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195,\n 78, 66, 215, 61, 156, 180,\n ]\n for (let i = 0; i < 256; i++) {\n perm[i] = perm[i + 256] = p[i]\n permMod12[i] = permMod12[i + 256] = p[i] % 12\n }\n})()\n\n// Gradient vectors for 3D\nconst grad3 = [\n [1, 1, 0],\n [-1, 1, 0],\n [1, -1, 0],\n [-1, -1, 0],\n [1, 0, 1],\n [-1, 0, 1],\n [1, 0, -1],\n [-1, 0, -1],\n [0, 1, 1],\n [0, -1, 1],\n [0, 1, -1],\n [0, -1, -1],\n]\n\n// Skewing factors for 2D and 3D\nconst F2 = 0.5 * (Math.sqrt(3) - 1)\nconst G2 = (3 - Math.sqrt(3)) / 6\nconst F3 = 1 / 3\nconst G3 = 1 / 6\n\n/**\n * 2D Simplex noise - returns value in range [-1, 1]\n */\nfunction simplex2D(x: number, y: number): number {\n // Skew input to determine which simplex cell we're in\n const s = (x + y) * F2\n const i = Math.floor(x + s)\n const j = Math.floor(y + s)\n\n // Unskew back to (x,y) space\n const t = (i + j) * G2\n const X0 = i - t\n const Y0 = j - t\n const x0 = x - X0\n const y0 = y - Y0\n\n // Determine which simplex we're in\n let i1: number, j1: number\n if (x0 > y0) {\n i1 = 1\n j1 = 0\n } else {\n i1 = 0\n j1 = 1\n }\n\n const x1 = x0 - i1 + G2\n const y1 = y0 - j1 + G2\n const x2 = x0 - 1 + 2 * G2\n const y2 = y0 - 1 + 2 * G2\n\n // Hash coordinates of the three corners\n const ii = i & 255\n const jj = j & 255\n const gi0 = permMod12[ii + perm[jj]]\n const gi1 = permMod12[ii + i1 + perm[jj + j1]]\n const gi2 = permMod12[ii + 1 + perm[jj + 1]]\n\n // Calculate contribution from three corners\n let n0 = 0,\n n1 = 0,\n n2 = 0\n\n let t0 = 0.5 - x0 * x0 - y0 * y0\n if (t0 >= 0) {\n t0 *= t0\n n0 = t0 * t0 * (grad3[gi0][0] * x0 + grad3[gi0][1] * y0)\n }\n\n let t1 = 0.5 - x1 * x1 - y1 * y1\n if (t1 >= 0) {\n t1 *= t1\n n1 = t1 * t1 * (grad3[gi1][0] * x1 + grad3[gi1][1] * y1)\n }\n\n let t2 = 0.5 - x2 * x2 - y2 * y2\n if (t2 >= 0) {\n t2 *= t2\n n2 = t2 * t2 * (grad3[gi2][0] * x2 + grad3[gi2][1] * y2)\n }\n\n // Scale to [-1, 1]\n return 70 * (n0 + n1 + n2)\n}\n\n/**\n * 3D Simplex noise - returns value in range [-1, 1]\n */\nfunction simplex3D(x: number, y: number, z: number): number {\n // Skew input space\n const s = (x + y + z) * F3\n const i = Math.floor(x + s)\n const j = Math.floor(y + s)\n const k = Math.floor(z + s)\n\n // Unskew back\n const t = (i + j + k) * G3\n const X0 = i - t\n const Y0 = j - t\n const Z0 = k - t\n const x0 = x - X0\n const y0 = y - Y0\n const z0 = z - Z0\n\n // Determine which simplex we're in\n let i1: number, j1: number, k1: number\n let i2: number, j2: number, k2: number\n\n if (x0 >= y0) {\n if (y0 >= z0) {\n i1 = 1\n j1 = 0\n k1 = 0\n i2 = 1\n j2 = 1\n k2 = 0\n } else if (x0 >= z0) {\n i1 = 1\n j1 = 0\n k1 = 0\n i2 = 1\n j2 = 0\n k2 = 1\n } else {\n i1 = 0\n j1 = 0\n k1 = 1\n i2 = 1\n j2 = 0\n k2 = 1\n }\n } else {\n if (y0 < z0) {\n i1 = 0\n j1 = 0\n k1 = 1\n i2 = 0\n j2 = 1\n k2 = 1\n } else if (x0 < z0) {\n i1 = 0\n j1 = 1\n k1 = 0\n i2 = 0\n j2 = 1\n k2 = 1\n } else {\n i1 = 0\n j1 = 1\n k1 = 0\n i2 = 1\n j2 = 1\n k2 = 0\n }\n }\n\n const x1 = x0 - i1 + G3\n const y1 = y0 - j1 + G3\n const z1 = z0 - k1 + G3\n const x2 = x0 - i2 + 2 * G3\n const y2 = y0 - j2 + 2 * G3\n const z2 = z0 - k2 + 2 * G3\n const x3 = x0 - 1 + 3 * G3\n const y3 = y0 - 1 + 3 * G3\n const z3 = z0 - 1 + 3 * G3\n\n // Hash coordinates\n const ii = i & 255\n const jj = j & 255\n const kk = k & 255\n const gi0 = permMod12[ii + perm[jj + perm[kk]]]\n const gi1 = permMod12[ii + i1 + perm[jj + j1 + perm[kk + k1]]]\n const gi2 = permMod12[ii + i2 + perm[jj + j2 + perm[kk + k2]]]\n const gi3 = permMod12[ii + 1 + perm[jj + 1 + perm[kk + 1]]]\n\n // Calculate contributions\n let n0 = 0,\n n1 = 0,\n n2 = 0,\n n3 = 0\n\n let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0\n if (t0 >= 0) {\n t0 *= t0\n n0 = t0 * t0 * (grad3[gi0][0] * x0 + grad3[gi0][1] * y0 + grad3[gi0][2] * z0)\n }\n\n let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1\n if (t1 >= 0) {\n t1 *= t1\n n1 = t1 * t1 * (grad3[gi1][0] * x1 + grad3[gi1][1] * y1 + grad3[gi1][2] * z1)\n }\n\n let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2\n if (t2 >= 0) {\n t2 *= t2\n n2 = t2 * t2 * (grad3[gi2][0] * x2 + grad3[gi2][1] * y2 + grad3[gi2][2] * z2)\n }\n\n let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3\n if (t3 >= 0) {\n t3 *= t3\n n3 = t3 * t3 * (grad3[gi3][0] * x3 + grad3[gi3][1] * y3 + grad3[gi3][2] * z3)\n }\n\n return 32 * (n0 + n1 + n2 + n3)\n}\n\n/**\n * Fractal Brownian Motion (FBM) - layered noise with octaves\n * Returns value roughly in range [-1, 1]\n */\nfunction fbm2D(x: number, y: number, octaves: number): number {\n let value = 0\n let amplitude = 1\n let frequency = 1\n let maxValue = 0\n\n for (let i = 0; i < octaves; i++) {\n value += amplitude * simplex2D(x * frequency, y * frequency)\n maxValue += amplitude\n amplitude *= 0.5\n frequency *= 2\n }\n\n return value / maxValue\n}\n\nfunction fbm3D(x: number, y: number, z: number, octaves: number): number {\n let value = 0\n let amplitude = 1\n let frequency = 1\n let maxValue = 0\n\n for (let i = 0; i < octaves; i++) {\n value += amplitude * simplex3D(x * frequency, y * frequency, z * frequency)\n maxValue += amplitude\n amplitude *= 0.5\n frequency *= 2\n }\n\n return value / maxValue\n}\n\nexport const EmitterShape = {\n CONE: \"cone\",\n SPHERE: \"sphere\",\n BOX: \"box\",\n POINT: \"point\",\n} as const\nexport type EmitterShapeKey = (typeof EmitterShape)[keyof typeof EmitterShape]\n\nexport type BurstConfig = {\n time: number // When to burst (seconds from start)\n count: number // How many particles to spawn\n cycles?: number // How many times to repeat (1 = once, default)\n interval?: number // Time between cycles\n}\n\nexport type EmissionConfig = {\n mode: \"constant\" | \"burst\"\n rateOverTime?: number // For constant mode (particles per second)\n bursts?: BurstConfig[] // For burst mode\n}\n\nexport type NoiseConfig = {\n enabled?: boolean\n // What to affect\n positionAmount?: number // How much noise affects position (world units)\n rotationAmount?: number // How much noise affects rotation (radians)\n sizeAmount?: number // How much noise affects size (multiplier, 0-1 range typically)\n // Noise parameters\n frequency?: number // How fast the noise changes spatially (default 1)\n scrollSpeed?: number // How fast noise scrolls over time (default 0)\n octaves?: number // Number of noise layers for detail (1-4, default 1)\n strengthX?: number // Noise strength multiplier for X axis (default 1)\n strengthY?: number // Noise strength multiplier for Y axis (default 1)\n}\n\nexport type FlipConfig = {\n x?: number // Probability (0-1) of flipping particle horizontally\n y?: number // Probability (0-1) of flipping particle vertically\n}\n\nexport type RenderMode = \"billboard\" | \"quad\"\n\nexport type EmitterConfig = {\n maxParticles?: number\n\n // Playback control\n duration?: number // System duration in seconds (0 = infinite)\n looping?: boolean // Restart after duration ends\n playOnAwake?: boolean // Start playing immediately on creation\n\n // Emission\n emission?: EmissionConfig\n\n // Shape\n shape?: EmitterShapeKey\n coneAngle?: NumRange\n coneDirection?: THREE.Vector3\n radius?: number\n boxSize?: THREE.Vector3\n sphereRadius?: number\n\n // Particle properties\n lifetime?: NumRange\n size?: { start: NumRange; end: NumRange }\n speed?: NumRange\n gravity?: THREE.Vector3\n damping?: number // Velocity damping over lifetime (0 = no damping, higher = more drag)\n\n // Orbital velocity - particles orbit around axes (radians per second)\n orbital?: {\n x?: number // Orbit around X axis (rotation in YZ plane)\n y?: number // Orbit around Y axis (rotation in XZ plane)\n z?: number // Orbit around Z axis (rotation in XY plane)\n }\n alignment?: {\n velocityScale?: number\n enableVelocityStretch?: boolean\n enableVelocityAlignment?: boolean\n }\n\n rotation?: { angle?: NumRange; velocity?: NumRange }\n\n // Curves - \"over lifetime\" multipliers (all default to 1.0 constant)\n sizeOverLifetime?: CurveableValue // Multiplier applied to interpolated size\n speedOverLifetime?: CurveableValue // Multiplier applied to velocity magnitude\n opacityOverLifetime?: CurveableValue // Direct alpha value (0-1), overrides color alpha\n rotationOverLifetime?: CurveableValue // Multiplier applied to angular velocity\n\n // Noise - affects position, rotation, and size over lifetime\n noise?: NoiseConfig\n\n // Rendering\n color?: {\n start: Vec4Range\n startList?: THREE.Vector4[] // Random start colors to pick from\n useStartAsEnd?: boolean // If true, end color matches start (for no-fade when using random colors)\n mid?: Vec4Range\n end: Vec4Range\n }\n blending?: THREE.Blending\n premultipliedAlpha?: boolean\n maskFromLuminance?: boolean\n flip?: FlipConfig // Probability of flipping particles on X/Y axes\n renderMode?: RenderMode // 'billboard' (default) or 'quad' (uses emitter rotation)\n\n // Collision\n collision?: {\n enabled?: boolean\n planeY?: number\n restitution?: number\n friction?: number\n killAfterBounces?: number\n }\n\n // Sprite sheets\n spriteSheet?: {\n rows: number\n columns: number\n frameCount?: number\n timeMode?: \"fps\" | \"startLifetime\" // fps = animate at fps rate, startLifetime = fixed frame based on lifetime value\n fps?: number\n loop?: boolean\n randomStartFrame?: boolean // If true, each particle starts at a random frame in the animation\n }\n\n debug?: boolean\n debugVelocities?: boolean\n}\n\nexport type EmitterAssets = {\n texture?: THREE.Texture\n textureUrl?: string\n material?: THREE.MeshBasicMaterial\n}\n\nexport function createParticleEmitter(\n cfg: EmitterConfig = {},\n assets: EmitterAssets = {}\n): ParticleSystem {\n cfg.alignment = { ...(cfg.alignment ?? {}) }\n cfg.collision = { ...(cfg.collision ?? {}) }\n const particleCount = cfg.maxParticles ?? 300\n const baseBillboardSize = 0.35\n const baseSizeX = baseBillboardSize\n const baseSizeY = baseBillboardSize\n let velocityScaleFactor = cfg.alignment?.velocityScale ?? 0.4\n\n const texture = assets.texture\n ? assets.texture\n : assets.textureUrl\n ? new THREE.TextureLoader().load(assets.textureUrl)\n : (cfg as any).textureUrl\n ? new THREE.TextureLoader().load((cfg as any).textureUrl)\n : new THREE.TextureLoader().load(\"assets/particle_tex.jpg\")\n texture.flipY = false\n texture.wrapS = THREE.ClampToEdgeWrapping\n texture.wrapT = THREE.ClampToEdgeWrapping\n texture.minFilter = THREE.NearestFilter\n texture.magFilter = THREE.NearestFilter\n texture.generateMipmaps = false\n texture.needsUpdate = true\n const material = new THREE.RawShaderMaterial({\n uniforms: {\n map: { value: texture },\n spriteSheetEnabled: { value: cfg.spriteSheet ? 1.0 : 0.0 },\n spriteGrid: {\n value: new THREE.Vector2(cfg.spriteSheet?.columns ?? 1, cfg.spriteSheet?.rows ?? 1),\n },\n spriteTotalFrames: {\n value: cfg.spriteSheet\n ? (cfg.spriteSheet.frameCount ??\n (cfg.spriteSheet.columns ?? 1) * (cfg.spriteSheet.rows ?? 1))\n : 1,\n },\n spriteCurrentFrame: { value: 0 },\n spritePerParticle: { value: 1.0 },\n spritePad: { value: new THREE.Vector2(0.002, 0.002) },\n useMaskFromLuminance: {\n value: (cfg.maskFromLuminance ?? false) ? 1.0 : 0.0,\n },\n },\n vertexShader: `\n precision highp float;\n precision highp int;\n uniform mat4 modelViewMatrix;\n uniform mat4 projectionMatrix;\n attribute vec3 position;\n attribute vec2 uv;\n attribute mat4 instanceMatrix;\n attribute vec3 instanceColor;\n attribute float instanceOpacity;\n attribute float instanceFrame;\n varying vec2 vUv;\n varying vec3 vColor;\n varying float vOpacity;\n varying float vFrame;\n void main() {\n vUv = uv;\n vColor = instanceColor;\n vOpacity = instanceOpacity;\n vFrame = instanceFrame;\n gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);\n }\n `,\n fragmentShader: `\n precision highp float;\n uniform sampler2D map;\n uniform float spriteSheetEnabled;\n uniform vec2 spriteGrid;\n uniform float spriteTotalFrames;\n uniform float spriteCurrentFrame;\n uniform float spritePerParticle;\n uniform vec2 spritePad;\n uniform float useMaskFromLuminance;\n varying vec2 vUv;\n varying vec3 vColor;\n varying float vOpacity;\n varying float vFrame;\n void main() {\n vec2 uvFrame = vUv;\n if (spriteSheetEnabled > 0.5) {\n float tilesX = spriteGrid.x;\n float tilesY = spriteGrid.y;\n float total = max(1.0, spriteTotalFrames);\n float frame = spritePerParticle > 0.5 ? vFrame : spriteCurrentFrame;\n frame = mod(floor(frame), total);\n float col = mod(frame, tilesX);\n float row = floor(frame / tilesX);\n vec2 tileSize = vec2(1.0 / tilesX, 1.0 / tilesY);\n vec2 pad = spritePad * tileSize;\n vec2 offset = vec2(col, row) * tileSize + pad;\n // Flip V within tile to correct sprite orientation\n vec2 uvInTile = vec2(vUv.x, 1.0 - vUv.y) * (tileSize - 2.0 * pad);\n uvFrame = offset + uvInTile;\n } else {\n // Flip V coordinate for regular (non-sprite-sheet) textures\n uvFrame = vec2(vUv.x, 1.0 - vUv.y);\n }\n vec4 texel = texture2D(map, uvFrame);\n float alpha = texel.a;\n if (useMaskFromLuminance > 0.5) {\n // Use luminance as alpha mask (ignore texel RGB for color)\n alpha = dot(texel.rgb, vec3(0.299, 0.587, 0.114));\n float outA = alpha * vOpacity;\n vec3 outRGB = vColor * outA; // premultiply\n gl_FragColor = vec4(outRGB, outA);\n } else {\n gl_FragColor = vec4(texel.rgb * vColor, alpha * vOpacity);\n }\n }\n `,\n transparent: true,\n depthWrite: false,\n blending: cfg.blending ?? THREE.AdditiveBlending,\n side: THREE.DoubleSide,\n })\n // Set premultiplied alpha mode if requested (works best with NormalBlending)\n ;(material as THREE.RawShaderMaterial).premultipliedAlpha = cfg.premultipliedAlpha ?? false\n\n const geometry = new THREE.PlaneGeometry(1, 1)\n const mesh = new THREE.InstancedMesh(geometry, material, particleCount)\n\n const instanceColors = new Float32Array(particleCount * 3)\n for (let i = 0; i < particleCount * 3; i++) instanceColors[i] = 1.0\n mesh.instanceColor = new THREE.InstancedBufferAttribute(instanceColors, 3)\n\n const instanceOpacity = new Float32Array(particleCount)\n geometry.setAttribute(\"instanceOpacity\", new THREE.InstancedBufferAttribute(instanceOpacity, 1))\n const instanceFrame = new Float32Array(particleCount)\n geometry.setAttribute(\"instanceFrame\", new THREE.InstancedBufferAttribute(instanceFrame, 1))\n\n const positions = new Float32Array(particleCount * 3)\n const velocities = new Float32Array(particleCount * 3)\n const ages = new Float32Array(particleCount)\n const lifetimes = new Float32Array(particleCount)\n const bounceCount = new Float32Array(particleCount)\n const sizeStart = new Float32Array(particleCount)\n const sizeEnd = new Float32Array(particleCount)\n const spinAngle = new Float32Array(particleCount)\n const spinVelocity = new Float32Array(particleCount)\n const frameOffset = new Float32Array(particleCount) // Random start frame offset per particle\n const color0 = new Float32Array(particleCount * 4)\n const color1 = new Float32Array(particleCount * 4)\n const color2 = new Float32Array(particleCount * 4)\n const noiseSeed = new Float32Array(particleCount * 2) // Per-particle noise seed (x, y offset)\n const flipState = new Uint8Array(particleCount) // Per-particle flip state (bit 0 = flipX, bit 1 = flipY)\n\n // Flip configuration (probability 0-1 for each axis)\n const flipX = Math.max(0, Math.min(1, cfg.flip?.x ?? 0))\n const flipY = Math.max(0, Math.min(1, cfg.flip?.y ?? 0))\n\n // Noise configuration\n const noiseCfg = cfg.noise ?? {}\n const noiseEnabled = noiseCfg.enabled ?? false\n const noisePositionAmount = noiseCfg.positionAmount ?? 0\n const noiseRotationAmount = noiseCfg.rotationAmount ?? 0\n const noiseSizeAmount = noiseCfg.sizeAmount ?? 0\n const noiseFrequency = noiseCfg.frequency ?? 1\n const noiseScrollSpeed = noiseCfg.scrollSpeed ?? 0\n const noiseOctaves = Math.max(1, Math.min(4, Math.round(noiseCfg.octaves ?? 1)))\n const noiseStrengthX = noiseCfg.strengthX ?? 1\n const noiseStrengthY = noiseCfg.strengthY ?? 1\n\n const gravity = cfg.gravity ? cfg.gravity.clone() : new THREE.Vector3(0, -9.8, 0)\n const damping = cfg.damping ?? 0\n\n // Orbital velocity (radians per second around each axis)\n const orbitalX = cfg.orbital?.x ?? 0\n const orbitalY = cfg.orbital?.y ?? 0\n const orbitalZ = cfg.orbital?.z ?? 0\n const hasOrbital = orbitalX !== 0 || orbitalY !== 0 || orbitalZ !== 0\n\n const emitterRadius = cfg.radius ?? 0.25\n\n // Emission config\n const emission = cfg.emission ?? { mode: \"constant\" as const, rateOverTime: 50 }\n let currentSpawnRate = emission.mode === \"constant\" ? (emission.rateOverTime ?? 50) : 0\n\n const shape: EmitterShapeKey = cfg.shape ?? EmitterShape.CONE\n const coneDirection = (cfg.coneDirection ?? new THREE.Vector3(0, 1, 0)).clone().normalize()\n const coneAngleRange: NumRange = cfg.coneAngle ?? [Math.PI / 16, Math.PI / 12]\n const speedRange: NumRange = cfg.speed ?? [1.0, 3.0]\n const lifeRange: NumRange = cfg.lifetime ?? [1.5, 3.0]\n const sizeRangeStart: NumRange = cfg.size?.start ?? [0.8, 1.2]\n const sizeRangeEnd: NumRange = cfg.size?.end ?? [0.2, 0.5]\n // When rotation is disabled (undefined), use zero angle and velocity so particles don't rotate\n const rotAngleRange: NumRange = cfg.rotation ? (cfg.rotation.angle ?? [0, Math.PI * 2]) : [0, 0]\n const rotVelRange: NumRange = cfg.rotation ? (cfg.rotation.velocity ?? [-6.0, 6.0]) : [0, 0]\n const colorStartRange: Vec4Range = cfg.color?.start ?? new THREE.Vector4(1, 0.8, 0.2, 1)\n const colorStartList: THREE.Vector4[] | undefined = cfg.color?.startList\n const colorUseStartAsEnd: boolean = cfg.color?.useStartAsEnd ?? false\n const colorMidRange: Vec4Range | undefined = cfg.color?.mid\n const colorEndRange: Vec4Range = cfg.color?.end ?? new THREE.Vector4(0.8, 0.1, 0.02, 0)\n\n const collisionCfg = cfg.collision ?? {}\n const floorCollisionEnabled = collisionCfg.enabled ?? true\n const floorY = collisionCfg.planeY ?? 0\n const floorBounceRestitution = collisionCfg.restitution ?? 0.7\n const floorFriction = collisionCfg.friction ?? 0.5\n const killAfterBounces = collisionCfg.killAfterBounces ?? 2\n\n let burstOrigin = new THREE.Vector3()\n let spawnAccumulator = 0\n\n // Playback state\n let isPlayingState = cfg.playOnAwake ?? true\n let elapsed = 0\n let systemComplete = false\n\n // Burst tracking (for burst mode with cycles)\n const bursts = emission.mode === \"burst\" ? (emission.bursts ?? []) : []\n const burstCycleCount: number[] = bursts.map(() => 0)\n const nextBurstTime: number[] = bursts.map((b) => b.time)\n\n function resetBurstTracking() {\n for (let i = 0; i < bursts.length; i++) {\n burstCycleCount[i] = 0\n nextBurstTime[i] = bursts[i].time\n }\n }\n\n let currentVelocityScale = velocityScaleFactor\n\n let spriteFrameAcc = 0\n let anyAliveLastFrame = false\n\n let debugGroup: THREE.Group | null = null\n let debugVelSegments: THREE.LineSegments | null = null\n if (cfg.debug && shape === EmitterShape.CONE) {\n debugGroup = new THREE.Group()\n const L = 2.0\n const minA = Array.isArray(coneAngleRange) ? coneAngleRange[0] : coneAngleRange\n const maxA = Array.isArray(coneAngleRange) ? coneAngleRange[1] : coneAngleRange\n const axis = coneDirection\n const u = new THREE.Vector3()\n const v = new THREE.Vector3()\n if (Math.abs(axis.x) < 0.9) u.set(1, 0, 0)\n else u.set(0, 1, 0)\n u.cross(axis).normalize()\n v.copy(axis).cross(u).normalize()\n\n function ring(angle: number, color: number) {\n const r = Math.tan(angle) * L\n const pts: THREE.Vector3[] = []\n for (let i = 0; i <= 64; i++) {\n const t = (i / 64) * Math.PI * 2\n const p = new THREE.Vector3()\n .copy(axis)\n .multiplyScalar(L)\n .addScaledVector(u, Math.cos(t) * r)\n .addScaledVector(v, Math.sin(t) * r)\n pts.push(p)\n }\n const geom = new THREE.BufferGeometry().setFromPoints(pts)\n const mat = new THREE.LineBasicMaterial({\n color,\n transparent: true,\n opacity: 0.6,\n })\n return new THREE.Line(geom, mat)\n }\n\n const axisGeom = new THREE.BufferGeometry().setFromPoints([\n new THREE.Vector3(0, 0, 0),\n new THREE.Vector3().copy(axis).multiplyScalar(L),\n ])\n debugGroup.add(new THREE.Line(axisGeom, new THREE.LineBasicMaterial({ color: 0x66ccff })))\n debugGroup.add(ring(minA, 0x44ff44))\n debugGroup.add(ring(maxA, 0xff4444))\n ;(mesh as THREE.Object3D).add(debugGroup)\n }\n if (cfg.debugVelocities) {\n const maxLines = Math.min(64, particleCount)\n const linePos = new Float32Array(maxLines * 2 * 3)\n const geom = new THREE.BufferGeometry()\n geom.setAttribute(\"position\", new THREE.BufferAttribute(linePos, 3))\n const mat = new THREE.LineBasicMaterial({\n color: 0xffff66,\n transparent: true,\n opacity: 0.85,\n })\n debugVelSegments = new THREE.LineSegments(geom, mat)\n ;(mesh as THREE.Object3D).add(debugVelSegments)\n }\n\n const m4 = new THREE.Matrix4()\n const invWorldMatrix = new THREE.Matrix4()\n const pos = new THREE.Vector3()\n const right = new THREE.Vector3()\n const up = new THREE.Vector3()\n const forward = new THREE.Vector3()\n const rightRot = new THREE.Vector3()\n const upRot = new THREE.Vector3()\n const viewDir = new THREE.Vector3()\n const prevPos = new THREE.Vector3()\n const prevNdc = new THREE.Vector3()\n const currNdc = new THREE.Vector3()\n const tmp4a = new THREE.Vector4()\n const tmp4b = new THREE.Vector4()\n const tmp4c = new THREE.Vector4()\n const tmpColor = new THREE.Color()\n const tmpVec3A = new THREE.Vector3()\n const tmpVec3B = new THREE.Vector3()\n const tmpVec3C = new THREE.Vector3()\n const tmpVec3D = new THREE.Vector3()\n const tmpVec3E = new THREE.Vector3()\n\n function sampleDirection(spawnPos: THREE.Vector3, out: THREE.Vector3): THREE.Vector3 {\n switch (shape) {\n case EmitterShape.CONE: {\n tmpVec3A.copy(spawnPos).sub(burstOrigin).normalize()\n const angle = randRange(coneAngleRange)\n const cosA = Math.cos(angle)\n const sinA = Math.sin(angle)\n out.copy(coneDirection).multiplyScalar(cosA).addScaledVector(tmpVec3A, sinA).normalize()\n return out\n }\n case EmitterShape.SPHERE:\n case EmitterShape.POINT: {\n out.set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1).normalize()\n return out\n }\n default:\n out.set(0, 1, 0)\n return out\n }\n }\n\n // Pre-computed box size to avoid allocation\n const defaultBoxSize = new THREE.Vector3(1, 1, 1)\n const boxSize = cfg.boxSize ?? defaultBoxSize\n\n function sampleSpawnPosition(origin: THREE.Vector3, out: THREE.Vector3): THREE.Vector3 {\n switch (shape) {\n case EmitterShape.CONE:\n case EmitterShape.POINT: {\n const r = emitterRadius * Math.sqrt(Math.random())\n const t = Math.random() * Math.PI * 2\n const axis = coneDirection\n if (Math.abs(axis.x) < 0.9) tmpVec3B.set(1, 0, 0)\n else tmpVec3B.set(0, 1, 0)\n tmpVec3B.cross(axis).normalize()\n tmpVec3C.copy(axis).cross(tmpVec3B).normalize()\n out\n .copy(origin)\n .addScaledVector(tmpVec3B, Math.cos(t) * r)\n .addScaledVector(tmpVec3C, Math.sin(t) * r)\n return out\n }\n case EmitterShape.SPHERE: {\n tmpVec3B\n .set(Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1)\n .normalize()\n const r = (cfg.sphereRadius ?? emitterRadius) * Math.cbrt(Math.random())\n out.copy(origin).addScaledVector(tmpVec3B, r)\n return out\n }\n case EmitterShape.BOX: {\n out.set(\n origin.x + (Math.random() - 0.5) * boxSize.x,\n origin.y + (Math.random() - 0.5) * boxSize.y,\n origin.z + (Math.random() - 0.5) * boxSize.z\n )\n return out\n }\n default:\n out.copy(origin)\n return out\n }\n }\n\n // Pre-compute sprite settings\n const spriteTotalFrames = cfg.spriteSheet\n ? (cfg.spriteSheet.frameCount ?? (cfg.spriteSheet.columns ?? 1) * (cfg.spriteSheet.rows ?? 1))\n : 1\n const spriteFps = cfg.spriteSheet?.fps ?? 15\n const spriteLoop = cfg.spriteSheet?.loop ?? true\n const spriteTimeMode = cfg.spriteSheet?.timeMode ?? \"fps\"\n const spriteRandomStartFrame = cfg.spriteSheet?.randomStartFrame ?? false\n\n function respawn(i: number, origin: THREE.Vector3 = burstOrigin) {\n const idx = i * 3\n sampleSpawnPosition(origin, tmpVec3D)\n positions[idx + 0] = tmpVec3D.x\n positions[idx + 1] = tmpVec3D.y\n positions[idx + 2] = tmpVec3D.z\n\n sampleDirection(tmpVec3D, tmpVec3E)\n const speed = randRange(speedRange)\n velocities[idx + 0] = tmpVec3E.x * speed\n velocities[idx + 1] = tmpVec3E.y * speed\n velocities[idx + 2] = tmpVec3E.z * speed\n\n ages[i] = 0\n lifetimes[i] = Math.max(0.0001, randRange(lifeRange))\n bounceCount[i] = 0\n\n sizeStart[i] = randRange(sizeRangeStart)\n sizeEnd[i] = randRange(sizeRangeEnd)\n spinAngle[i] = randRange(rotAngleRange)\n spinVelocity[i] = randRange(rotVelRange)\n\n // Set random start frame offset if enabled\n frameOffset[i] = spriteRandomStartFrame ? Math.random() * spriteTotalFrames : 0\n\n // Set random noise seed for this particle (used to give each particle unique noise pattern)\n const seedBase = i * 2\n noiseSeed[seedBase + 0] = Math.random() * 1000\n noiseSeed[seedBase + 1] = Math.random() * 1000\n\n // Determine flip state based on probability (random check against flipX/flipY values)\n let flip = 0\n if (flipX > 0 && Math.random() < flipX) flip |= 1 // bit 0 = flip X\n if (flipY > 0 && Math.random() < flipY) flip |= 2 // bit 1 = flip Y\n flipState[i] = flip\n\n // Write colors directly to typed arrays without allocating Vector4\n const base = i * 4\n // If startList exists and has colors, pick one randomly; otherwise use start range\n if (colorStartList && colorStartList.length > 0) {\n const picked = colorStartList[Math.floor(Math.random() * colorStartList.length)]\n tmp4a.copy(picked)\n } else {\n randVec4(colorStartRange, tmp4a)\n }\n color0[base + 0] = tmp4a.x\n color0[base + 1] = tmp4a.y\n color0[base + 2] = tmp4a.z\n color0[base + 3] = tmp4a.w\n\n if (colorMidRange) {\n randVec4(colorMidRange, tmp4b)\n color1[base + 0] = tmp4b.x\n color1[base + 1] = tmp4b.y\n color1[base + 2] = tmp4b.z\n color1[base + 3] = tmp4b.w\n } else {\n color1[base + 0] = tmp4a.x\n color1[base + 1] = tmp4a.y\n color1[base + 2] = tmp4a.z\n color1[base + 3] = tmp4a.w\n }\n\n // If useStartAsEnd is true, copy start color to end (no fade effect)\n // This ensures random start colors stay constant when colorOverLifetime is disabled\n if (colorUseStartAsEnd) {\n color2[base + 0] = tmp4a.x\n color2[base + 1] = tmp4a.y\n color2[base + 2] = tmp4a.z\n color2[base + 3] = tmp4a.w\n } else {\n randVec4(colorEndRange, tmp4c)\n color2[base + 0] = tmp4c.x\n color2[base + 1] = tmp4c.y\n color2[base + 2] = tmp4c.z\n color2[base + 3] = tmp4c.w\n }\n }\n\n for (let i = 0; i < particleCount; i++) {\n ages[i] = 10\n lifetimes[i] = 0\n }\n\n // Check if all particles are dead\n function allParticlesDead(): boolean {\n for (let i = 0; i < particleCount; i++) {\n if (ages[i] < lifetimes[i]) return false\n }\n return true\n }\n\n // Kill all particles (used by stop)\n function despawnAll(): void {\n for (let i = 0; i < particleCount; i++) {\n ages[i] = lifetimes[i] + 1\n }\n mesh.count = 0\n }\n\n // Render mode configuration\n const renderMode = cfg.renderMode ?? \"billboard\"\n\n // Reusable vectors for emitter orientation (quad mode)\n const emitterRight = new THREE.Vector3()\n const emitterUp = new THREE.Vector3()\n const emitterForward = new THREE.Vector3()\n\n const update = (dt: number, camera: THREE.Camera, emitterWorldMatrix?: THREE.Matrix4) => {\n if (debugGroup) debugGroup.position.copy(burstOrigin)\n if (debugVelSegments) {\n const attr = debugVelSegments.geometry.getAttribute(\"position\") as THREE.BufferAttribute\n const arr = attr.array as Float32Array\n let w = 0\n const scale = 0.25\n const maxLines = arr.length / 6\n for (let i = 0; i < particleCount && w / 6 < maxLines; i++) {\n if (ages[i] >= lifetimes[i]) continue\n const idx = i * 3\n const x = positions[idx + 0]\n const y = positions[idx + 1]\n const z = positions[idx + 2]\n const vx = velocities[idx + 0]\n const vy = velocities[idx + 1]\n const vz = velocities[idx + 2]\n arr[w++] = x\n arr[w++] = y\n arr[w++] = z\n arr[w++] = x + vx * scale\n arr[w++] = y + vy * scale\n arr[w++] = z + vz * scale\n }\n for (; w < arr.length; w++) arr[w] = 0\n attr.needsUpdate = true\n }\n\n // Handle playback state\n const duration = cfg.duration ?? 0\n const withinDuration = duration <= 0 || elapsed < duration\n\n if (isPlayingState && !systemComplete) {\n elapsed += dt\n\n // Handle emission based on mode\n if (emission.mode === \"constant\" && withinDuration) {\n // Constant emission - spawn over time\n if (currentSpawnRate > 0) {\n spawnAccumulator += currentSpawnRate * dt\n const toSpawn = Math.floor(spawnAccumulator)\n if (toSpawn > 0) {\n spawnAccumulator -= toSpawn\n let spawned = 0\n for (let i = 0; i < particleCount && spawned < toSpawn; i++) {\n if (ages[i] >= lifetimes[i]) {\n respawn(i, burstOrigin)\n spawned++\n }\n }\n }\n }\n } else if (emission.mode === \"burst\" && withinDuration) {\n // Burst emission - process burst triggers\n for (let bi = 0; bi < bursts.length; bi++) {\n const b = bursts[bi]\n const cyclesCompleted = burstCycleCount[bi]\n const maxCycles = b.cycles ?? 1\n\n if (cyclesCompleted >= maxCycles) continue\n\n if (elapsed >= nextBurstTime[bi]) {\n // Trigger burst\n burst(burstOrigin, b.count)\n\n // Schedule next cycle\n burstCycleCount[bi]++\n if (burstCycleCount[bi] < maxCycles) {\n nextBurstTime[bi] = elapsed + (b.interval ?? 0)\n }\n }\n }\n }\n\n // Check for system completion (only when duration is set)\n if (duration > 0 && elapsed >= duration) {\n if (cfg.looping) {\n // Restart the system immediately - don't wait for particles to die\n elapsed = 0\n resetBurstTracking()\n } else if (!withinDuration) {\n // Non-looping system past duration - stop spawning but let particles live\n // Only mark complete when all particles are dead\n if (allParticlesDead()) {\n systemComplete = true\n isPlayingState = false\n }\n }\n }\n }\n\n // Extract camera vectors (always needed for billboard mode and velocity alignment)\n right.setFromMatrixColumn(camera.matrixWorld, 0).normalize()\n up.setFromMatrixColumn(camera.matrixWorld, 1).normalize()\n forward.setFromMatrixColumn(camera.matrixWorld, 2).normalize()\n viewDir.copy(forward).negate()\n\n // Transform billboard vectors from world space to emitter's local space\n // This ensures billboards face the camera correctly even when emitter has rotated parents\n if (emitterWorldMatrix) {\n invWorldMatrix.copy(emitterWorldMatrix).invert()\n right.transformDirection(invWorldMatrix)\n up.transformDirection(invWorldMatrix)\n forward.transformDirection(invWorldMatrix)\n viewDir.transformDirection(invWorldMatrix)\n }\n\n // For quad mode, use local/identity vectors since the parent hierarchy\n // already applies the emitter's world transform to the instanced mesh\n const isQuadMode = renderMode === \"quad\"\n if (isQuadMode) {\n // Use identity axes - parent transform handles the rotation\n emitterRight.set(1, 0, 0)\n emitterUp.set(0, 1, 0)\n emitterForward.set(0, 0, 1)\n }\n\n // Cache alignment config lookups\n const velAlign = cfg.alignment?.enableVelocityAlignment ?? false\n const velStretchEnabled = cfg.alignment?.enableVelocityStretch ?? false\n const velScaleConfig = cfg.alignment?.velocityScale ?? velocityScaleFactor\n\n // GPU write index - alive particles are packed contiguously for rendering\n let writeIdx = 0\n\n for (let i = 0; i < particleCount; i++) {\n // Early exit for dead particles - skip all processing\n if (ages[i] >= lifetimes[i]) continue\n\n const idx = i * 3\n\n // Calculate life ratio for curve evaluation (needed early for speed/rotation curves)\n const preLifeRatio = ages[i] / lifetimes[i]\n\n // Evaluate speed and rotation curves\n const speedCurveMultiplier = evaluateCurveableValue(cfg.speedOverLifetime, preLifeRatio, 1)\n const rotationCurveMultiplier = evaluateCurveableValue(\n cfg.rotationOverLifetime,\n preLifeRatio,\n 1\n )\n\n // Physics update\n velocities[idx + 0] += gravity.x * dt\n velocities[idx + 1] += gravity.y * dt\n velocities[idx + 2] += gravity.z * dt\n\n // Apply damping (velocity reduction over time)\n if (damping > 0) {\n const dampFactor = 1 - damping * dt\n const clampedDamp = Math.max(0, dampFactor)\n velocities[idx + 0] *= clampedDamp\n velocities[idx + 1] *= clampedDamp\n velocities[idx + 2] *= clampedDamp\n }\n\n // Apply orbital velocity (rotation around axes)\n // This rotates both position and velocity around each axis, creating orbital motion\n // Velocity must also be rotated so alignment to velocity works correctly\n if (hasOrbital) {\n // Orbital X: rotate in YZ plane around X axis\n if (orbitalX !== 0) {\n const cosX = Math.cos(orbitalX * dt)\n const sinX = Math.sin(orbitalX * dt)\n // Rotate position\n const py = positions[idx + 1]\n const pz = positions[idx + 2]\n positions[idx + 1] = py * cosX - pz * sinX\n positions[idx + 2] = py * sinX + pz * cosX\n // Rotate velocity\n const vy = velocities[idx + 1]\n const vz = velocities[idx + 2]\n velocities[idx + 1] = vy * cosX - vz * sinX\n velocities[idx + 2] = vy * sinX + vz * cosX\n }\n\n // Orbital Y: rotate in XZ plane around Y axis\n if (orbitalY !== 0) {\n const cosY = Math.cos(orbitalY * dt)\n const sinY = Math.sin(orbitalY * dt)\n // Rotate position\n const px = positions[idx + 0]\n const pz = positions[idx + 2]\n positions[idx + 0] = px * cosY + pz * sinY\n positions[idx + 2] = -px * sinY + pz * cosY\n // Rotate velocity\n const vx = velocities[idx + 0]\n const vz = velocities[idx + 2]\n velocities[idx + 0] = vx * cosY + vz * sinY\n velocities[idx + 2] = -vx * sinY + vz * cosY\n }\n\n // Orbital Z: rotate in XY plane around Z axis\n if (orbitalZ !== 0) {\n const cosZ = Math.cos(orbitalZ * dt)\n const sinZ = Math.sin(orbitalZ * dt)\n // Rotate position\n const px = positions[idx + 0]\n const py = positions[idx + 1]\n positions[idx + 0] = px * cosZ - py * sinZ\n positions[idx + 1] = px * sinZ + py * cosZ\n // Rotate velocity\n const vx = velocities[idx + 0]\n const vy = velocities[idx + 1]\n velocities[idx + 0] = vx * cosZ - vy * sinZ\n velocities[idx + 1] = vx * sinZ + vy * cosZ\n }\n }\n\n // Apply speed curve multiplier to position update\n const effectiveSpeedMult = speedCurveMultiplier\n positions[idx + 0] += velocities[idx + 0] * dt * effectiveSpeedMult\n positions[idx + 1] += velocities[idx + 1] * dt * effectiveSpeedMult\n positions[idx + 2] += velocities[idx + 2] * dt * effectiveSpeedMult\n ages[i] += dt\n\n // Apply rotation curve multiplier to angular velocity\n spinAngle[i] += spinVelocity[i] * dt * rotationCurveMultiplier\n\n // Floor collision\n if (floorCollisionEnabled && positions[idx + 1] <= floorY && velocities[idx + 1] < 0) {\n positions[idx + 1] = floorY\n velocities[idx + 1] = -velocities[idx + 1] * floorBounceRestitution\n velocities[idx + 0] *= floorFriction\n velocities[idx + 2] *= floorFriction\n bounceCount[i]++\n if (bounceCount[i] >= killAfterBounces) {\n lifetimes[i] = ages[i]\n continue // Particle just died, skip rendering\n }\n }\n\n // Check if particle died this frame from age\n if (ages[i] >= lifetimes[i]) continue\n\n pos.set(positions[idx + 0], positions[idx + 1], positions[idx + 2])\n\n // Apply noise offsets for position, rotation, and size\n let noiseRotOffset = 0\n let noiseSizeMultiplier = 1\n if (noiseEnabled) {\n const seedBase = i * 2\n const seedX = noiseSeed[seedBase + 0]\n const seedY = noiseSeed[seedBase + 1]\n const timeOffset = ages[i] * noiseScrollSpeed\n\n // Sample noise at particle's unique seed + time offset\n const noiseX =\n noiseOctaves > 1\n ? fbm2D((seedX + timeOffset) * noiseFrequency, seedY * noiseFrequency, noiseOctaves)\n : simplex2D((seedX + timeOffset) * noiseFrequency, seedY * noiseFrequency)\n const noiseY =\n noiseOctaves > 1\n ? fbm2D(\n (seedX + 100 + timeOffset) * noiseFrequency,\n (seedY + 100) * noiseFrequency,\n noiseOctaves\n )\n : simplex2D((seedX + 100 + timeOffset) * noiseFrequency, (seedY + 100) * noiseFrequency)\n const noiseZ =\n noiseOctaves > 1\n ? fbm2D(\n (seedX + 200 + timeOffset) * noiseFrequency,\n (seedY + 200) * noiseFrequency,\n noiseOctaves\n )\n : simplex2D((seedX + 200 + timeOffset) * noiseFrequency, (seedY + 200) * noiseFrequency)\n\n // Apply position noise with strength modifiers\n if (noisePositionAmount > 0) {\n pos.x += noiseX * noisePositionAmount * noiseStrengthX\n pos.y += noiseY * noisePositionAmount * noiseStrengthY\n pos.z += noiseZ * noisePositionAmount * noiseStrengthX // Z uses X strength (horizontal)\n }\n\n // Calculate rotation noise offset\n if (noiseRotationAmount > 0) {\n const noiseRot =\n noiseOctaves > 1\n ? fbm2D(\n (seedX + 300 + timeOffset) * noiseFrequency,\n (seedY + 300) * noiseFrequency,\n noiseOctaves\n )\n : simplex2D(\n (seedX + 300 + timeOffset) * noiseFrequency,\n (seedY + 300) * noiseFrequency\n )\n noiseRotOffset = noiseRot * noiseRotationAmount\n }\n\n // Calculate size noise multiplier (centered around 1)\n if (noiseSizeAmount > 0) {\n const noiseSz =\n noiseOctaves > 1\n ? fbm2D(\n (seedX + 400 + timeOffset) * noiseFrequency,\n (seedY + 400) * noiseFrequency,\n noiseOctaves\n )\n : simplex2D(\n (seedX + 400 + timeOffset) * noiseFrequency,\n (seedY + 400) * noiseFrequency\n )\n // noiseSz is [-1, 1], map to [1-amount, 1+amount]\n noiseSizeMultiplier = 1 + noiseSz * noiseSizeAmount\n }\n }\n\n let angle = 0\n if (velAlign && !isQuadMode) {\n // Velocity alignment only makes sense in billboard mode\n // Calculate effective velocity including orbital tangential velocity\n let effVelX = velocities[idx + 0]\n let effVelY = velocities[idx + 1]\n let effVelZ = velocities[idx + 2]\n\n // Add orbital tangential velocity: v_tangent = Ή × position\n // For rotation around X axis: vy += -ΉX * z, vz += ΉX * y\n // For rotation around Y axis: vx += ΉY * z, vz += -ΉY * x\n // For rotation around Z axis: vx += -ΉZ * y, vy += ΉZ * x\n if (hasOrbital) {\n const px = positions[idx + 0]\n const py = positions[idx + 1]\n const pz = positions[idx + 2]\n if (orbitalX !== 0) {\n effVelY += -orbitalX * pz\n effVelZ += orbitalX * py\n }\n if (orbitalY !== 0) {\n effVelX += orbitalY * pz\n effVelZ += -orbitalY * px\n }\n if (orbitalZ !== 0) {\n effVelX += -orbitalZ * py\n effVelY += orbitalZ * px\n }\n }\n\n prevPos.set(\n positions[idx + 0] - effVelX * dt,\n positions[idx + 1] - effVelY * dt,\n positions[idx + 2] - effVelZ * dt\n )\n prevNdc.copy(prevPos).project(camera)\n currNdc.copy(pos).project(camera)\n const dx = currNdc.x - prevNdc.x\n const dy = currNdc.y - prevNdc.y\n angle = Math.atan2(dy, dx) - Math.PI * 0.5\n }\n angle += spinAngle[i] + noiseRotOffset\n const cosA = Math.cos(angle)\n const sinA = Math.sin(angle)\n\n if (isQuadMode) {\n // Quad mode: use emitter's orientation, apply spin around local forward axis\n rightRot.set(\n emitterRight.x * cosA + emitterUp.x * sinA,\n emitterRight.y * cosA + emitterUp.y * sinA,\n emitterRight.z * cosA + emitterUp.z * sinA\n )\n upRot.set(\n -emitterRight.x * sinA + emitterUp.x * cosA,\n -emitterRight.y * sinA + emitterUp.y * cosA,\n -emitterRight.z * sinA + emitterUp.z * cosA\n )\n } else {\n // Billboard mode: use camera's orientation\n rightRot.set(\n right.x * cosA + up.x * sinA,\n right.y * cosA + up.y * sinA,\n right.z * cosA + up.z * sinA\n )\n upRot.set(\n -right.x * sinA + up.x * cosA,\n -right.y * sinA + up.y * cosA,\n -right.z * sinA + up.z * cosA\n )\n }\n\n currentVelocityScale = velStretchEnabled ? velScaleConfig : 0\n const vmag = Math.hypot(velocities[idx + 0], velocities[idx + 1], velocities[idx + 2])\n const stretch = 1 + vmag * currentVelocityScale\n // No artificial attenuation - perspective camera handles depth scaling naturally\n\n const lifeRatio = ages[i] / lifetimes[i]\n\n // Evaluate curve multipliers for this particle's lifetime\n const sizeCurveMultiplier = evaluateCurveableValue(cfg.sizeOverLifetime, lifeRatio, 1)\n const opacityCurveValue =\n cfg.opacityOverLifetime !== undefined\n ? evaluateCurveableValue(cfg.opacityOverLifetime, lifeRatio, 1)\n : null // null means use color alpha interpolation\n\n const s =\n lerp(sizeStart[i], sizeEnd[i], lifeRatio) * noiseSizeMultiplier * sizeCurveMultiplier\n let sx = baseSizeX * s\n let sy = baseSizeY * s * stretch\n\n // Apply flip (negate scale to flip the particle)\n const flip = flipState[i]\n if (flip & 1) sx = -sx // flip X (horizontal)\n if (flip & 2) sy = -sy // flip Y (vertical)\n\n // Color interpolation\n const colorBase = i * 4\n tmp4a.set(\n color0[colorBase + 0],\n color0[colorBase + 1],\n color0[colorBase + 2],\n color0[colorBase + 3]\n )\n tmp4b.set(\n color2[colorBase + 0],\n color2[colorBase + 1],\n color2[colorBase + 2],\n color2[colorBase + 3]\n )\n if (colorMidRange) {\n tmp4c.set(\n color1[colorBase + 0],\n color1[colorBase + 1],\n color1[colorBase + 2],\n color1[colorBase + 3]\n )\n if (lifeRatio < 0.5) {\n lerpVec4(tmp4a, tmp4c, lifeRatio * 2, tmp4a)\n } else {\n lerpVec4(tmp4c, tmp4b, (lifeRatio - 0.5) * 2, tmp4a)\n }\n } else {\n lerpVec4(tmp4a, tmp4b, lifeRatio, tmp4a)\n }\n\n // Write GPU data at writeIdx (packed contiguously)\n tmpColor.setRGB(tmp4a.x, tmp4a.y, tmp4a.z)\n mesh.setColorAt(writeIdx, tmpColor)\n // Use opacity curve if defined, otherwise use interpolated color alpha\n instanceOpacity[writeIdx] = opacityCurveValue !== null ? opacityCurveValue : tmp4a.w\n\n // Use emitter forward for quad mode, camera view direction for billboard\n const normal = isQuadMode ? emitterForward : viewDir\n m4.set(\n rightRot.x * sx,\n upRot.x * sy,\n normal.x,\n pos.x,\n rightRot.y * sx,\n upRot.y * sy,\n normal.y,\n pos.y,\n rightRot.z * sx,\n upRot.z * sy,\n normal.z,\n pos.z,\n 0,\n 0,\n 0,\n 1\n )\n mesh.setMatrixAt(writeIdx, m4)\n\n // Per-particle sprite frame\n if (cfg.spriteSheet) {\n let frameF: number\n if (spriteTimeMode === \"startLifetime\") {\n // Frame is fixed based on particle's assigned lifetime value (normalized within range)\n // Particles with shorter lifetimes get lower frames, longer lifetimes get higher frames\n const lifeMin = Array.isArray(lifeRange) ? lifeRange[0] : (lifeRange as number)\n const lifeMax = Array.isArray(lifeRange) ? lifeRange[1] : (lifeRange as number)\n const normalizedLife =\n lifeMax > lifeMin ? (lifetimes[i] - lifeMin) / (lifeMax - lifeMin) : 0\n // Use spriteTotalFrames (not -1) because normalizedLife is in [0,1) due to Math.random()\n // This ensures all frames including the last one can be selected\n frameF = normalizedLife * spriteTotalFrames\n } else {\n // FPS-based animation with optional random start offset\n frameF = ages[i] * spriteFps + frameOffset[i]\n if (spriteLoop) {\n frameF = frameF % spriteTotalFrames\n } else {\n frameF = Math.min(frameF, spriteTotalFrames - 0.01)\n }\n }\n instanceFrame[writeIdx] = frameF\n }\n\n writeIdx++\n }\n\n // Set instance count to only render alive particles\n mesh.count = writeIdx\n ;(mesh.instanceMatrix as unknown as THREE.InstancedBufferAttribute).needsUpdate = true\n if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true\n const op = geometry.getAttribute(\"instanceOpacity\") as THREE.InstancedBufferAttribute\n if (op) op.needsUpdate = true\n const ifr = geometry.getAttribute(\"instanceFrame\") as THREE.InstancedBufferAttribute\n if (ifr) ifr.needsUpdate = true\n\n const spriteCfg = cfg.spriteSheet\n const shaderMat = material as THREE.RawShaderMaterial\n if (shaderMat && spriteCfg) {\n const gridX = spriteCfg.columns\n const gridY = spriteCfg.rows\n const total = spriteCfg.frameCount ?? gridX * gridY\n shaderMat.uniforms.spriteSheetEnabled.value = 1.0\n ;(shaderMat.uniforms.spriteGrid.value as THREE.Vector2).set(gridX, gridY)\n shaderMat.uniforms.spriteTotalFrames.value = total\n shaderMat.uniforms.spriteCurrentFrame.value = 0\n shaderMat.uniforms.spritePerParticle.value = 1.0\n } else if (shaderMat) {\n shaderMat.uniforms.spriteSheetEnabled.value = 0.0\n }\n }\n\n const burst = (origin: THREE.Vector3, count: number = 50) => {\n burstOrigin.copy(origin)\n // Do not reset global sprite frame; per-particle frames are derived from age\n let spawned = 0\n for (let i = 0; i < particleCount && spawned < count; i++) {\n if (ages[i] >= lifetimes[i]) {\n respawn(i, origin)\n spawned++\n }\n }\n }\n\n const setTexture = (tex: THREE.Texture) => {\n const m = material as THREE.RawShaderMaterial\n if (m.uniforms.map) m.uniforms.map.value = tex\n tex.needsUpdate = true\n m.needsUpdate = true\n }\n\n const setSpawnRate = (rate: number) => {\n currentSpawnRate = Math.max(0, rate || 0)\n }\n\n const setOrigin = (origin: THREE.Vector3) => {\n burstOrigin.copy(origin)\n }\n\n // Internal playback controls (no cascade - used by parent's cascade)\n const playInternal = () => {\n isPlayingState = true\n systemComplete = false\n }\n\n const stopInternal = () => {\n isPlayingState = false\n elapsed = 0\n systemComplete = false\n spawnAccumulator = 0\n resetBurstTracking()\n despawnAll()\n }\n\n const restartInternal = () => {\n stopInternal()\n playInternal()\n }\n\n // Helper to cascade action to child particle emitters\n const cascadeToChildren = (action: \"play\" | \"stop\" | \"restart\") => {\n // Get the parent object (the one that owns this particle system)\n const parent = mesh.parent\n if (!parent) return\n\n // Traverse all descendants and trigger INTERNAL action (no re-cascade)\n parent.traverse((child) => {\n // Skip self (the mesh itself)\n if (child === mesh) return\n // Check if child has a particle emitter\n const childEmitter = child.userData.__particleEmitter as ParticleSystem | undefined\n if (childEmitter) {\n // Call internal methods to avoid infinite recursion\n if (action === \"play\") childEmitter.playInternal?.()\n else if (action === \"stop\") childEmitter.stopInternal?.()\n else if (action === \"restart\") childEmitter.restartInternal?.()\n }\n })\n }\n\n // Playback controls - cascade to children\n const play = () => {\n playInternal()\n cascadeToChildren(\"play\")\n }\n\n const stop = () => {\n stopInternal()\n cascadeToChildren(\"stop\")\n }\n\n const restart = () => {\n restartInternal()\n cascadeToChildren(\"restart\")\n }\n\n const isPlaying = () => isPlayingState\n\n const getElapsed = () => elapsed\n\n return {\n object: mesh,\n update,\n burst,\n setSpawnRate,\n setOrigin,\n config: cfg,\n setTexture,\n // Playback controls\n play,\n stop,\n restart,\n isPlaying,\n getElapsed,\n // Internal methods (no cascade) - used by parent cascade\n playInternal,\n stopInternal,\n restartInternal,\n }\n}\n\nexport * from \"./ParticleSystemPrefabComponent\"\n","import * as THREE from \"three\"\nimport { Component, VenusGame } from \"@engine/core\"\nimport { createParticleEmitter, EmitterConfig, EmitterAssets, ParticleSystem } from \"./index\"\n\n/**\n * A reusable particle emitter component that can be attached to any GameObject.\n * The particle system becomes a child of the GameObject and follows it automatically.\n */\nexport class Particle extends Component {\n private emitter: ParticleSystem | null = null\n private config: EmitterConfig\n private assets: EmitterAssets\n\n // Reusable vector to avoid allocation on trigger\n private static readonly _tempOrigin = new THREE.Vector3()\n\n /**\n * Creates a new particle emitter component\n * @param config - The emitter configuration\n * @param assets - The assets (textures) for the particles\n */\n constructor(config: EmitterConfig, assets: EmitterAssets) {\n super()\n this.config = config\n this.assets = assets\n }\n\n protected onCreate(): void {\n // Create the particle emitter\n this.emitter = createParticleEmitter(this.config, this.assets)\n\n // Add the particle mesh as a child of the GameObject\n // This makes it follow the GameObject's transform automatically\n if (this.emitter?.object && this.gameObject) {\n this.gameObject.add(this.emitter.object)\n // Keep particles at local origin so they spawn at GameObject's position\n this.emitter.object.position.set(0, 0, 0)\n // Disable frustum culling to ensure particles are always rendered\n this.emitter.object.frustumCulled = false\n }\n }\n\n /**\n * Trigger a burst of particles at the current GameObject position\n * @param count - Number of particles to emit\n */\n public trigger(count: number = 10): void {\n if (!this.emitter) return\n\n // Since the particle mesh is a child of the GameObject,\n // we use local position (0,0,0) to spawn at the GameObject's position\n const localOrigin = Particle._tempOrigin.set(0, 0, 0)\n this.emitter.setOrigin(localOrigin)\n this.emitter.burst(localOrigin, count)\n }\n\n /**\n * Update the particle system\n * @param deltaTime - Time since last frame in seconds\n */\n public update(deltaTime: number): void {\n if (!this.emitter) return\n\n // Update the particle system\n this.emitter.update(deltaTime, VenusGame.camera)\n }\n\n /**\n * Get the underlying particle system\n */\n public getEmitter(): ParticleSystem | null {\n return this.emitter\n }\n\n /**\n * Clean up the particle system\n */\n protected onCleanup(): void {\n // Remove particle mesh from GameObject (it will be disposed with the GameObject)\n if (this.emitter?.object && this.gameObject) {\n this.gameObject.remove(this.emitter.object)\n }\n this.emitter = null\n }\n}\n","/**\n * Animation Curve System for Particle Effects\n *\n * Provides cubic Hermite interpolation similar to Unity's AnimationCurve.\n * Used for \"X over Lifetime\" properties like size, speed, opacity, rotation.\n */\n\n/**\n * A single keyframe on an animation curve.\n */\nexport interface CurveKeyframe {\n /** Time position on the curve (0-1 normalized) */\n time: number\n /** Output value at this keyframe */\n value: number\n /** Left tangent slope (controls curve shape approaching this point) */\n inTangent: number\n /** Right tangent slope (controls curve shape leaving this point) */\n outTangent: number\n}\n\n/**\n * An animation curve defined by keyframes with tangent handles.\n */\nexport interface AnimationCurve {\n /** Sorted array of keyframes (by time) */\n keys: CurveKeyframe[]\n}\n\n/**\n * CurveableValue - a property that can be either a constant or a curve.\n * Used in EmitterConfig for properties that support \"over lifetime\" curves.\n */\nexport type CurveableValue = number | { curve: AnimationCurve }\n\n/**\n * Evaluates an animation curve at a given time using cubic Hermite interpolation.\n *\n * @param curve - The animation curve to evaluate\n * @param t - Time value (typically 0-1 for particle lifetime)\n * @returns The interpolated value at time t\n */\nexport function evaluateCurve(curve: AnimationCurve, t: number): number {\n const keys = curve.keys\n\n // Handle edge cases\n if (keys.length === 0) {\n return 0\n }\n\n if (keys.length === 1) {\n return keys[0].value\n }\n\n // Clamp t to curve range\n const firstKey = keys[0]\n const lastKey = keys[keys.length - 1]\n\n if (t <= firstKey.time) {\n return firstKey.value\n }\n\n if (t >= lastKey.time) {\n return lastKey.value\n }\n\n // Find the segment containing t using binary search\n let left = 0\n let right = keys.length - 1\n\n while (right - left > 1) {\n const mid = Math.floor((left + right) / 2)\n if (keys[mid].time <= t) {\n left = mid\n } else {\n right = mid\n }\n }\n\n const k0 = keys[left]\n const k1 = keys[right]\n\n // Compute normalized position within segment\n const dt = k1.time - k0.time\n const u = dt > 0 ? (t - k0.time) / dt : 0\n\n // Cubic Hermite interpolation\n // H(u) = (2uÂŗ - 3u² + 1)p0 + (uÂŗ - 2u² + u)m0 + (-2uÂŗ + 3u²)p1 + (uÂŗ - u²)m1\n // where p0, p1 are values and m0, m1 are tangents scaled by segment duration\n\n const u2 = u * u\n const u3 = u2 * u\n\n const h00 = 2 * u3 - 3 * u2 + 1 // Hermite basis function for p0\n const h10 = u3 - 2 * u2 + u // Hermite basis function for m0\n const h01 = -2 * u3 + 3 * u2 // Hermite basis function for p1\n const h11 = u3 - u2 // Hermite basis function for m1\n\n // Scale tangents by segment duration\n const m0 = k0.outTangent * dt\n const m1 = k1.inTangent * dt\n\n return h00 * k0.value + h10 * m0 + h01 * k1.value + h11 * m1\n}\n\n/**\n * Evaluates a CurveableValue (constant or curve) at a given time.\n *\n * @param value - Either a constant number or an object with a curve\n * @param t - Time value (0-1 for particle lifetime)\n * @param defaultValue - Value to return if value is undefined\n * @returns The evaluated value\n */\nexport function evaluateCurveableValue(\n value: CurveableValue | undefined,\n t: number,\n defaultValue: number = 1\n): number {\n if (value === undefined) {\n return defaultValue\n }\n\n if (typeof value === \"number\") {\n return value\n }\n\n return evaluateCurve(value.curve, t)\n}\n\n/**\n * Creates a keyframe with auto-calculated tangents for smooth interpolation.\n */\nexport function createKeyframe(\n time: number,\n value: number,\n inTangent: number = 0,\n outTangent: number = 0\n): CurveKeyframe {\n return { time, value, inTangent, outTangent }\n}\n\n/**\n * Creates a simple curve from an array of [time, value] pairs.\n * Tangents are automatically calculated for smooth interpolation.\n */\nexport function createCurveFromPoints(points: Array<[number, number]>): AnimationCurve {\n if (points.length === 0) {\n return { keys: [createKeyframe(0, 1, 0, 0)] }\n }\n\n if (points.length === 1) {\n return { keys: [createKeyframe(points[0][0], points[0][1], 0, 0)] }\n }\n\n // Sort points by time\n const sorted = [...points].sort((a, b) => a[0] - b[0])\n\n // Create keyframes with auto-smooth tangents\n const keys: CurveKeyframe[] = sorted.map((point, i) => {\n const [time, value] = point\n\n // Calculate tangent using Catmull-Rom style\n let tangent = 0\n\n if (i === 0) {\n // First point: use slope to next point\n const next = sorted[i + 1]\n tangent = (next[1] - value) / (next[0] - time || 1)\n } else if (i === sorted.length - 1) {\n // Last point: use slope from previous point\n const prev = sorted[i - 1]\n tangent = (value - prev[1]) / (time - prev[0] || 1)\n } else {\n // Middle point: average of slopes\n const prev = sorted[i - 1]\n const next = sorted[i + 1]\n const slopeBefore = (value - prev[1]) / (time - prev[0] || 1)\n const slopeAfter = (next[1] - value) / (next[0] - time || 1)\n tangent = (slopeBefore + slopeAfter) / 2\n }\n\n return createKeyframe(time, value, tangent, tangent)\n })\n\n return { keys }\n}\n\n/**\n * Preset curve factories for common curve shapes.\n */\nexport const CurvePresets = {\n /**\n * Linear curve from 0 to 1\n */\n linear(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 1, 1), createKeyframe(1, 1, 1, 1)],\n }\n },\n\n /**\n * Linear curve from 1 to 0 (inverse)\n */\n linearInverse(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 1, -1, -1), createKeyframe(1, 0, -1, -1)],\n }\n },\n\n /**\n * Constant value curve\n */\n constant(value: number = 1): AnimationCurve {\n return {\n keys: [createKeyframe(0, value, 0, 0), createKeyframe(1, value, 0, 0)],\n }\n },\n\n /**\n * Ease-in curve (slow start, fast end)\n */\n easeIn(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 0, 0), createKeyframe(1, 1, 2, 2)],\n }\n },\n\n /**\n * Ease-out curve (fast start, slow end)\n */\n easeOut(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 2, 2), createKeyframe(1, 1, 0, 0)],\n }\n },\n\n /**\n * Ease-in-out curve (smooth S-curve)\n */\n easeInOut(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 0, 0), createKeyframe(1, 1, 0, 0)],\n }\n },\n\n /**\n * Bell curve (starts at 0, peaks at 1 in middle, returns to 0)\n */\n bell(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 0, 2), createKeyframe(0.5, 1, 0, 0), createKeyframe(1, 0, -2, 0)],\n }\n },\n\n /**\n * Fade-in curve (0 to 1 with smooth ramp)\n */\n fadeIn(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 0, 0, 0), createKeyframe(0.3, 1, 2, 0), createKeyframe(1, 1, 0, 0)],\n }\n },\n\n /**\n * Fade-out curve (1 to 0 with smooth ramp)\n */\n fadeOut(): AnimationCurve {\n return {\n keys: [createKeyframe(0, 1, 0, 0), createKeyframe(0.7, 1, 0, -2), createKeyframe(1, 0, 0, 0)],\n }\n },\n\n /**\n * Bounce curve (oscillating decay)\n */\n bounce(): AnimationCurve {\n return {\n keys: [\n createKeyframe(0, 1, 0, -4),\n createKeyframe(0.25, 0.3, 0, 0),\n createKeyframe(0.5, 0.7, 0, 0),\n createKeyframe(0.75, 0.5, 0, 0),\n createKeyframe(1, 0.6, 0, 0),\n ],\n }\n },\n}\n\n/**\n * Clones an animation curve (deep copy).\n */\nexport function cloneCurve(curve: AnimationCurve): AnimationCurve {\n return {\n keys: curve.keys.map((k) => ({ ...k })),\n }\n}\n\n/**\n * Adds a keyframe to a curve at the specified time.\n * The curve is re-sorted after insertion.\n */\nexport function addKeyframe(curve: AnimationCurve, keyframe: CurveKeyframe): AnimationCurve {\n const newKeys = [...curve.keys, keyframe].sort((a, b) => a.time - b.time)\n return { keys: newKeys }\n}\n\n/**\n * Removes a keyframe at the specified index.\n */\nexport function removeKeyframe(curve: AnimationCurve, index: number): AnimationCurve {\n if (curve.keys.length <= 1) {\n // Don't remove the last keyframe\n return curve\n }\n const newKeys = curve.keys.filter((_, i) => i !== index)\n return { keys: newKeys }\n}\n\n/**\n * Updates a keyframe at the specified index.\n */\nexport function updateKeyframe(\n curve: AnimationCurve,\n index: number,\n updates: Partial<CurveKeyframe>\n): AnimationCurve {\n const newKeys = curve.keys.map((k, i) => (i === index ? { ...k, ...updates } : k))\n // Re-sort if time changed\n if (updates.time !== undefined) {\n newKeys.sort((a, b) => a.time - b.time)\n }\n return { keys: newKeys }\n}\n","import * as THREE from \"three\"\nimport { Component, VenusGame } from \"@engine/core\"\nimport { PrefabComponent } from \"../prefabs/PrefabComponent\"\nimport type { ComponentJSON, PrefabNode } from \"../prefabs\"\nimport { StowKitSystem } from \"../stowkit/StowKitSystem\"\nimport { createParticleEmitter } from \"./index\"\nimport type { EmitterConfig, EmitterAssets, ParticleSystem } from \"./index\"\n\n// ============================================================================\n// Prefab JSON Type Definitions\n// ============================================================================\n\ninterface CurvePropertyValue {\n mode: \"constant\" | \"curve\"\n constant?: number\n curve?: { keys: { time: number; value: number; inTangent: number; outTangent: number }[] }\n}\n\ninterface ParticleSystemJSON extends ComponentJSON {\n type: \"particle_system\"\n main: {\n duration: number\n looping: boolean\n startLifetimeMin: number\n startLifetimeMax: number\n startSpeedMin: number\n startSpeedMax: number\n startSizeMin: number\n startSizeMax: number\n gravityModifier: number\n maxParticles: number\n startColor: number[]\n useRandomStartColors?: boolean\n randomStartColors?: number[][]\n colorOverLifetime: boolean\n endColor: number[]\n useMidColor?: boolean\n midColor?: number[]\n opacityOverLifetime?: CurvePropertyValue\n }\n emission: {\n enabled: boolean\n mode: \"constant\" | \"burst\"\n rateOverTime: number\n burstCount?: number\n burstCycles?: number\n burstInterval?: number\n }\n shape: {\n enabled: boolean\n shape: \"cone\" | \"sphere\" | \"box\" | \"point\"\n radius: number\n coneAngleMin?: number\n coneAngleMax?: number\n coneDirection?: number[]\n boxSize?: number[]\n sphereRadius?: number\n }\n velocity: {\n enabled: boolean\n gravity: number[]\n damping?: number\n speedOverLifetime?: CurvePropertyValue\n orbitalX?: number\n orbitalY?: number\n orbitalZ?: number\n }\n size: {\n value?: {\n enabled?: boolean\n endSizeMin?: number\n endSizeMax?: number\n }\n enabled?: boolean\n endSizeMin: number\n endSizeMax: number\n sizeOverLifetime?: CurvePropertyValue\n }\n rotation: {\n enabled: boolean\n startAngleMin: number\n startAngleMax: number\n angularVelocityMin: number\n angularVelocityMax: number\n rotationOverLifetime?: CurvePropertyValue\n }\n noise?: {\n enabled: boolean\n positionAmount?: number\n rotationAmount?: number\n sizeAmount?: number\n frequency?: number\n scrollSpeed?: number\n octaves?: number\n }\n textureSheet: {\n enabled: boolean\n timeMode?: \"fps\" | \"startLifetime\"\n rows: number\n columns: number\n fps: number\n loop: boolean\n randomStartFrame?: boolean\n }\n collision: {\n enabled: boolean\n planeY?: number\n restitution?: number\n friction?: number\n killAfterBounces?: number\n }\n renderer: {\n texture: {\n pack: string\n assetId: string\n }\n renderMode?: \"billboard\" | \"quad\"\n blending: \"additive\" | \"normal\"\n premultipliedAlpha: boolean\n maskFromLuminance: boolean\n velocityScale: number\n stretchWithVelocity: boolean\n alignToVelocity: boolean\n flipX?: number\n flipY?: number\n }\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\n/**\n * Unwrap SerializedProperty values from a module\n */\nfunction unwrapModule(module: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {}\n for (const key in module) {\n const value = module[key]\n result[key] = value?.value ?? value\n }\n return result\n}\n\nfunction degToRad(degrees: number): number {\n return degrees * (Math.PI / 180)\n}\n\nfunction isEnabled(val: any, defaultEnabled: boolean = true): boolean {\n if (val === true) return true\n if (val === false) return false\n return defaultEnabled\n}\n\nfunction getBlendingMode(mode: string): THREE.Blending {\n switch (mode) {\n case \"additive\":\n return THREE.AdditiveBlending\n case \"multiply\":\n return THREE.MultiplyBlending\n case \"normal\":\n default:\n return THREE.NormalBlending\n }\n}\n\n/**\n * Deeply unwrap SerializedProperty values from a nested object\n */\nfunction deepUnwrap(value: any): any {\n // Unwrap SerializedProperty (object with only a 'value' property)\n if (value && typeof value === \"object\" && \"value\" in value && Object.keys(value).length === 1) {\n return deepUnwrap(value.value)\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => deepUnwrap(item))\n }\n\n if (value !== null && typeof value === \"object\") {\n const result: Record<string, any> = {}\n for (const key in value) {\n result[key] = deepUnwrap(value[key])\n }\n return result\n }\n\n return value\n}\n\n/**\n * Convert editor CurvePropertyValue to engine CurveableValue format\n */\nfunction convertCurvePropertyToEngine(\n propValue: any,\n defaultValue: number = 1\n): number | { curve: { keys: any[] } } | undefined {\n if (!propValue) return undefined\n\n // Deeply unwrap all SerializedProperty wrappers\n const value = deepUnwrap(propValue)\n\n if (!value || typeof value !== \"object\") return undefined\n\n // Check if it's a CurvePropertyValue\n if (value.mode === \"constant\") {\n const constantVal = value.constant ?? defaultValue\n // Only return if different from default to avoid unnecessary curve evaluation\n if (constantVal !== defaultValue) {\n return constantVal\n }\n return undefined\n }\n\n // Handle curve mode\n if (value.mode === \"curve\" && value.curve && Array.isArray(value.curve.keys)) {\n return { curve: value.curve }\n }\n\n return undefined\n}\n\n// ============================================================================\n// ParticleSystemPrefabComponent\n// ============================================================================\n\n/**\n * Prefab component for particle systems.\n * Directly creates particle emitter like the editor does.\n */\n@PrefabComponent(\"particle_system\")\nexport class ParticleSystemPrefabComponent extends Component {\n private emitter: ParticleSystem | null = null\n private json: ParticleSystemJSON\n\n // Reusable vector to avoid allocation on trigger\n private static readonly _tempOrigin = new THREE.Vector3()\n\n /**\n * Create a ParticleSystemPrefabComponent from prefab JSON\n */\n static fromPrefabJSON(\n json: ParticleSystemJSON,\n _node: PrefabNode\n ): ParticleSystemPrefabComponent | null {\n return new ParticleSystemPrefabComponent(json)\n }\n\n constructor(json: ParticleSystemJSON) {\n super()\n this.json = json\n }\n\n protected onCreate(): void {\n // Build config exactly like the editor does\n const config = this.buildEmitterConfig()\n const assets = this.buildEmitterAssets()\n\n // Create the particle emitter directly (like editor does)\n this.emitter = createParticleEmitter(config, assets)\n\n // Add to the object (like editor does)\n if (this.emitter?.object && this.gameObject) {\n this.gameObject.add(this.emitter.object)\n this.emitter.object.position.set(0, 0, 0)\n this.emitter.object.frustumCulled = false\n // Store emitter reference in userData for cascade functionality\n // This allows parent particle systems to find and control child emitters\n this.gameObject.userData.__particleEmitter = this.emitter\n }\n\n // Load texture asynchronously and update material (like editor does)\n this.loadTextureAsync()\n }\n\n /**\n * Load texture on-demand and update the emitter's material\n * This matches how the editor loads textures asynchronously\n */\n private async loadTextureAsync(): Promise<void> {\n const textureRef = this.json.renderer?.texture\n if (!textureRef?.pack || !textureRef?.assetId) return\n if (!this.emitter) return\n\n const stowkit = StowKitSystem.getInstance()\n // Load VFX texture\n const tex = await stowkit.getTexture(textureRef.assetId)\n\n // Configure for particle shaders\n tex.colorSpace = THREE.NoColorSpace\n tex.flipY = false\n tex.needsUpdate = true\n\n if (this.emitter) {\n // Update the emitter's material texture (like editor does)\n const material = this.emitter.object.material as THREE.ShaderMaterial\n if (material?.uniforms?.map) {\n material.uniforms.map.value = tex\n material.needsUpdate = true\n }\n }\n }\n\n /**\n * Build EmitterConfig from prefab JSON - matches editor's buildEmitterConfigFromComponentData\n */\n private buildEmitterConfig(): EmitterConfig {\n // Use unwrapModule exactly like the editor does\n const main = unwrapModule(this.json.main || {})\n const emission = unwrapModule(this.json.emission || {})\n const shape = unwrapModule(this.json.shape || {})\n const velocity = unwrapModule(this.json.velocity || {})\n const size = unwrapModule(this.json.size || {})\n const rotation = unwrapModule(this.json.rotation || {})\n const noise = unwrapModule(this.json.noise || {})\n const textureSheet = unwrapModule(this.json.textureSheet || {})\n const collision = unwrapModule(this.json.collision || {})\n const renderer = unwrapModule(this.json.renderer || {})\n\n // Apply gravity modifier to base gravity (like editor)\n const gravityModifier = main.gravityModifier ?? 1.0\n const baseGravity = velocity.gravity || [0, -9.8, 0]\n\n // Build emission config based on mode (like editor)\n const emissionEnabled = isEnabled(emission.enabled)\n const isBurst = emission.mode === \"burst\"\n\n const config = {\n maxParticles: main.maxParticles ?? 300,\n\n // Playback control\n duration: main.duration ?? 5,\n looping: main.looping ?? true,\n playOnAwake: false,\n\n // Emission (like editor)\n emission: emissionEnabled\n ? {\n mode: isBurst ? \"burst\" : \"constant\",\n rateOverTime: emission.rateOverTime ?? 50,\n bursts: isBurst\n ? [\n {\n time: 0,\n count: emission.burstCount ?? 30,\n cycles: emission.burstCycles ?? 1,\n interval: emission.burstInterval ?? 0.5,\n },\n ]\n : undefined,\n }\n : { mode: \"constant\", rateOverTime: 0 },\n\n // Lifetime from main module\n lifetime: [main.startLifetimeMin ?? 1.5, main.startLifetimeMax ?? 3.0],\n\n // Speed from main module\n speed: [main.startSpeedMin ?? 1.0, main.startSpeedMax ?? 3.0],\n\n // Shape (like editor)\n shape: isEnabled(shape.enabled) ? (shape.shape ?? \"cone\") : \"point\",\n radius: shape.radius ?? 0.25,\n coneAngle: [degToRad(shape.coneAngleMin ?? 15), degToRad(shape.coneAngleMax ?? 30)],\n coneDirection: new THREE.Vector3(\n shape.coneDirection?.[0] ?? 0,\n shape.coneDirection?.[1] ?? 1,\n shape.coneDirection?.[2] ?? 0\n ),\n boxSize: new THREE.Vector3(\n shape.boxSize?.[0] ?? 1,\n shape.boxSize?.[1] ?? 1,\n shape.boxSize?.[2] ?? 1\n ),\n sphereRadius: shape.sphereRadius ?? 1,\n\n // Velocity - apply gravity modifier (like editor)\n gravity: isEnabled(velocity.enabled)\n ? new THREE.Vector3(\n (baseGravity[0] ?? 0) * gravityModifier,\n (baseGravity[1] ?? -9.8) * gravityModifier,\n (baseGravity[2] ?? 0) * gravityModifier\n )\n : new THREE.Vector3(0, 0, 0),\n\n // Damping\n damping: isEnabled(velocity.enabled) ? (velocity.damping ?? 0) : 0,\n\n // Size - start from main, end from size module (like editor)\n size: isEnabled(size.enabled)\n ? {\n start: [main.startSizeMin ?? 0.8, main.startSizeMax ?? 1.2],\n end: [size.endSizeMin ?? 0.2, size.endSizeMax ?? 0.5],\n }\n : {\n start: [main.startSizeMin ?? 1, main.startSizeMax ?? 1],\n end: [main.startSizeMin ?? 1, main.startSizeMax ?? 1],\n },\n\n // Rotation (disabled by default, like editor)\n rotation: isEnabled(rotation.enabled, false)\n ? {\n angle: [degToRad(rotation.startAngleMin ?? 0), degToRad(rotation.startAngleMax ?? 360)],\n velocity: [\n degToRad(rotation.angularVelocityMin ?? -180),\n degToRad(rotation.angularVelocityMax ?? 180),\n ],\n }\n : undefined,\n\n // Noise (disabled by default, like editor)\n noise: isEnabled(noise.enabled, false)\n ? {\n enabled: true,\n positionAmount: noise.positionAmount ?? 0,\n rotationAmount: degToRad(noise.rotationAmount ?? 0),\n sizeAmount: noise.sizeAmount ?? 0,\n frequency: noise.frequency ?? 1,\n scrollSpeed: noise.scrollSpeed ?? 0,\n octaves: Math.round(noise.octaves ?? 1),\n }\n : undefined,\n\n // Color (like editor)\n color: {\n start: new THREE.Vector4(\n main.startColor?.[0] ?? 1,\n main.startColor?.[1] ?? 1,\n main.startColor?.[2] ?? 1,\n main.startColor?.[3] ?? 1\n ),\n // Random start colors list - convert array of [r,g,b,a] to Vector4 array\n startList:\n isEnabled(main.useRandomStartColors, false) &&\n Array.isArray(main.randomStartColors) &&\n main.randomStartColors.length > 0\n ? main.randomStartColors.map(\n (c: [number, number, number, number]) =>\n new THREE.Vector4(c[0] ?? 1, c[1] ?? 1, c[2] ?? 1, c[3] ?? 1)\n )\n : undefined,\n // When colorOverLifetime is disabled, use start color as end (no fade)\n // This ensures random start colors stay constant throughout particle lifetime\n useStartAsEnd: !isEnabled(main.colorOverLifetime, false),\n mid:\n isEnabled(main.colorOverLifetime, false) && isEnabled(main.useMidColor, false)\n ? new THREE.Vector4(\n main.midColor?.[0] ?? 0.8,\n main.midColor?.[1] ?? 0.8,\n main.midColor?.[2] ?? 0.8,\n main.midColor?.[3] ?? 0.7\n )\n : undefined,\n end: isEnabled(main.colorOverLifetime, false)\n ? new THREE.Vector4(\n main.endColor?.[0] ?? 0.5,\n main.endColor?.[1] ?? 0.5,\n main.endColor?.[2] ?? 0.5,\n main.endColor?.[3] ?? 0\n )\n : new THREE.Vector4(\n main.startColor?.[0] ?? 1,\n main.startColor?.[1] ?? 1,\n main.startColor?.[2] ?? 1,\n main.startColor?.[3] ?? 1\n ),\n },\n\n // Renderer (like editor)\n renderMode: (renderer.renderMode ?? \"billboard\") as \"billboard\" | \"quad\",\n blending: getBlendingMode(renderer.blending ?? \"additive\"),\n premultipliedAlpha: renderer.premultipliedAlpha ?? false,\n maskFromLuminance: renderer.maskFromLuminance ?? false,\n flip: {\n x: renderer.flipX ?? 0,\n y: renderer.flipY ?? 0,\n },\n\n // Texture Sheet Animation (disabled by default, like editor)\n spriteSheet: isEnabled(textureSheet.enabled, false)\n ? {\n rows: Math.round(textureSheet.rows ?? 4),\n columns: Math.round(textureSheet.columns ?? 4),\n timeMode: (textureSheet.timeMode ?? \"fps\") as \"fps\" | \"startLifetime\",\n fps: textureSheet.fps ?? 15,\n loop: textureSheet.loop ?? true,\n randomStartFrame: textureSheet.randomStartFrame ?? false,\n }\n : undefined,\n\n // Collision (disabled by default, like editor)\n collision: {\n enabled: isEnabled(collision.enabled, false),\n planeY: collision.planeY ?? 0,\n restitution: collision.restitution ?? 0.7,\n friction: collision.friction ?? 0.5,\n killAfterBounces: Math.round(collision.killAfterBounces ?? 2),\n },\n\n // Alignment (like editor)\n alignment: {\n velocityScale: renderer.velocityScale ?? 0.4,\n enableVelocityStretch: renderer.stretchWithVelocity ?? false,\n enableVelocityAlignment: renderer.alignToVelocity ?? false,\n },\n\n // Curve over lifetime properties (like editor)\n sizeOverLifetime: convertCurvePropertyToEngine(size.sizeOverLifetime, 1),\n speedOverLifetime: convertCurvePropertyToEngine(velocity.speedOverLifetime, 1),\n opacityOverLifetime: convertCurvePropertyToEngine(main.opacityOverLifetime, 1),\n rotationOverLifetime: convertCurvePropertyToEngine(rotation.rotationOverLifetime, 1),\n\n // Orbital velocity - rotation around axes (radians/sec)\n orbital:\n isEnabled(velocity.enabled) && (velocity.orbitalX || velocity.orbitalY || velocity.orbitalZ)\n ? {\n x: velocity.orbitalX ?? 0,\n y: velocity.orbitalY ?? 0,\n z: velocity.orbitalZ ?? 0,\n }\n : undefined,\n } as EmitterConfig\n\n return config\n }\n\n /**\n * Build EmitterAssets from prefab JSON\n * Starts with procedural texture - actual texture is loaded asynchronously in loadTextureAsync()\n */\n private buildEmitterAssets(): EmitterAssets {\n // Create procedural fallback texture (like editor does)\n const size = 64\n const canvas = document.createElement(\"canvas\")\n canvas.width = size\n canvas.height = size\n const ctx = canvas.getContext(\"2d\")!\n const gradient = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2)\n gradient.addColorStop(0, \"rgba(255, 255, 255, 1)\")\n gradient.addColorStop(0.5, \"rgba(255, 255, 255, 0.5)\")\n gradient.addColorStop(1, \"rgba(255, 255, 255, 0)\")\n ctx.fillStyle = gradient\n ctx.fillRect(0, 0, size, size)\n const texture = new THREE.CanvasTexture(canvas)\n texture.needsUpdate = true\n\n return { texture }\n }\n\n /**\n * Trigger a burst of particles\n */\n public trigger(count: number = 10): void {\n if (!this.emitter) return\n const localOrigin = ParticleSystemPrefabComponent._tempOrigin.set(0, 0, 0)\n this.emitter.setOrigin(localOrigin)\n this.emitter.burst(localOrigin, count)\n }\n\n /**\n * Play the particle system\n */\n public play(): void {\n ;(this.emitter as any)?.play?.()\n }\n\n /**\n * Stop the particle system\n */\n public stop(): void {\n ;(this.emitter as any)?.stop?.()\n }\n\n /**\n * Update the particle system\n */\n public update(deltaTime: number): void {\n if (!this.emitter) return\n this.emitter.update(deltaTime, VenusGame.camera, this.gameObject?.matrixWorld)\n }\n\n /**\n * Get the underlying particle system\n */\n public getEmitter(): ParticleSystem | null {\n return this.emitter\n }\n\n protected onCleanup(): void {\n if (this.emitter?.object && this.gameObject) {\n this.gameObject.remove(this.emitter.object)\n // Clean up the userData reference\n delete this.gameObject.userData.__particleEmitter\n }\n this.emitter = null\n }\n}\n","export enum ParameterType {\n BOOL = \"bool\",\n FLOAT = \"float\",\n INT = \"int\",\n TRIGGER = \"trigger\",\n}\n\nexport enum ComparisonOperator {\n EQUALS = \"==\",\n NOT_EQUALS = \"!=\",\n GREATER = \">\",\n LESS = \"<\",\n GREATER_EQUALS = \">=\",\n LESS_EQUALS = \"<=\",\n}\n\nexport enum BlendType {\n LINEAR = \"linear\",\n EASE_IN_OUT = \"ease_in_out\",\n}\n\nexport enum AnimationEvent {\n STATE_CHANGED = \"state_changed\",\n TRANSITION_START = \"transition_start\",\n TRANSITION_END = \"transition_end\",\n}\n\nexport interface Parameter {\n type: ParameterType\n value: any\n}\n\nexport interface TransitionCondition {\n parameter: string\n operator: ComparisonOperator\n value: any\n}\n\nexport interface TransitionConfig {\n from: string\n to: string\n conditions: TransitionCondition[]\n duration?: number\n priority?: number\n blend_type?: BlendType\n}\n\nexport interface ClipInfo {\n id: string\n is_playing: boolean\n weight: number\n loop: boolean\n}\n\nexport interface BlendTreeConfig {\n parameter: string\n children: { state_id: string; threshold: number }[]\n}\n\nexport interface ActiveTransition {\n from_state: string\n to_state: string\n progress: number\n}\n\ninterface StateInfo {\n name: string\n isTree: boolean\n duration: number\n}\n\ntype EventCallback = () => void\n\n/**\n * Lightweight animation state machine for visualization\n * No actual animation playback - SharedAnimationManager handles that\n */\nexport default class Animatrix {\n private states: Map<string, StateInfo> = new Map()\n private transitions: TransitionConfig[] = []\n private parameters: Map<string, Parameter> = new Map()\n private treeStates: Set<string> = new Set()\n private blendTreeConfigs: Map<string, BlendTreeConfig> = new Map()\n private currentState: string | null = null\n private activeTransition: ActiveTransition | null = null\n private listeners: Map<AnimationEvent, Set<EventCallback>> = new Map()\n\n constructor() {\n for (const event of Object.values(AnimationEvent)) {\n this.listeners.set(event, new Set())\n }\n }\n\n add_parameter(name: string, type: ParameterType, defaultValue: any): void {\n this.parameters.set(name, { type, value: defaultValue })\n }\n\n add_clip(name: string, clipInfo: { duration: number }): void {\n this.states.set(name, {\n name,\n isTree: false,\n duration: clipInfo.duration || 1,\n })\n }\n\n add_blend_tree_1d(\n id: string,\n parameter: string,\n children: { state_id: string; threshold: number }[]\n ): void {\n this.states.set(id, { name: id, isTree: true, duration: 1 })\n this.treeStates.add(id)\n this.blendTreeConfigs.set(id, { parameter, children })\n }\n\n add_transition(config: TransitionConfig): void {\n this.transitions.push(config)\n }\n\n set_state(name: string): void {\n if (this.currentState === name) return\n\n if (!this.states.has(name)) {\n console.warn(\n `[Animatrix] set_state: State '${name}' not registered! Available: ${[...this.states.keys()].join(\", \")}`\n )\n }\n\n this.currentState = name\n this.emit_event(AnimationEvent.STATE_CHANGED)\n }\n\n set_bool(name: string, value: boolean): void {\n const param = this.parameters.get(name)\n if (param) param.value = value\n }\n\n set_float(name: string, value: number): void {\n const param = this.parameters.get(name)\n if (param) param.value = value\n }\n\n set_int(name: string, value: number): void {\n const param = this.parameters.get(name)\n if (param) param.value = Math.floor(value)\n }\n\n get_float(name: string): number {\n const param = this.parameters.get(name)\n return param?.value ?? 0\n }\n\n get_bool(name: string): boolean {\n const param = this.parameters.get(name)\n return param?.value ?? false\n }\n\n get_int(name: string): number {\n const param = this.parameters.get(name)\n return Math.floor(param?.value ?? 0)\n }\n\n update(_deltaTime: number): void {\n // No-op - SharedAnimationManager handles actual playback\n }\n\n stop_all(): void {\n this.currentState = null\n }\n\n get_current_state(): string | null {\n return this.currentState\n }\n\n get_clips(): Map<string, ClipInfo> {\n const result = new Map<string, ClipInfo>()\n for (const [id] of this.states) {\n result.set(id, {\n id,\n is_playing: this.currentState === id,\n weight: this.currentState === id ? 1 : 0,\n loop: true,\n })\n }\n return result\n }\n\n get_transitions(): TransitionConfig[] {\n return this.transitions\n }\n\n get_active_transition(): ActiveTransition | null {\n return this.activeTransition\n }\n\n get_blend_tree_ids(): Set<string> {\n return this.treeStates\n }\n\n is_blend_tree_state(id: string): boolean {\n return this.treeStates.has(id)\n }\n\n get_blend_tree_config(id: string): BlendTreeConfig | null {\n return this.blendTreeConfigs.get(id) ?? null\n }\n\n get_clip_progress(_stateId: string): number {\n return 0\n }\n\n get_parameters_map(): Map<string, Parameter> {\n return this.parameters\n }\n\n add_listener(event: AnimationEvent, callback: EventCallback): void {\n this.listeners.get(event)?.add(callback)\n }\n\n remove_listener(event: AnimationEvent, callback: EventCallback): void {\n this.listeners.get(event)?.delete(callback)\n }\n\n private emit_event(event: AnimationEvent): void {\n this.listeners.get(event)?.forEach((cb) => cb())\n }\n}\n","import * as THREE from \"three\"\nimport { FBXLoader } from \"three/examples/jsm/loaders/FBXLoader.js\"\n\nexport class AnimationLibrary {\n private static clips: Map<string, THREE.AnimationClip> = new Map()\n private static loader: FBXLoader = new FBXLoader()\n private static debug: boolean = false\n\n // List of track name prefixes that are known to be non-bone objects\n // These are mesh/accessory names that shouldn't have animation tracks\n private static readonly ACCESSORY_PREFIXES = [\n \"hair_\",\n \"hat_\",\n \"face_accessory_\",\n \"fullBody_Toes\",\n \"fullBody_\", // Seems to be mesh names, not bones\n ]\n\n public static setDebug(enabled: boolean): void {\n AnimationLibrary.debug = enabled\n }\n\n public static async loadAnimation(id: string, path: string): Promise<THREE.AnimationClip> {\n let clip = AnimationLibrary.clips.get(id)\n if (clip) {\n console.warn(`[Animatrix] Loading an already loaded clip: ${id}`)\n return clip\n }\n\n const object = await AnimationLibrary.loader.loadAsync(path)\n if (object.animations && object.animations.length > 0) {\n clip = object.animations[0]\n\n // Pre-clean the animation by removing accessory/mesh tracks\n const originalTrackCount = clip.tracks.length\n const validTracks = clip.tracks.filter((track) => {\n const trackName = track.name.split(\".\")[0]\n // Remove tracks for known accessory/mesh prefixes\n return !AnimationLibrary.ACCESSORY_PREFIXES.some(\n (prefix) => trackName.startsWith(prefix) || trackName === prefix\n )\n })\n\n if (validTracks.length < originalTrackCount) {\n const removed = originalTrackCount - validTracks.length\n if (AnimationLibrary.debug) {\n console.log(\n `[AnimationLibrary] Pre-cleaned ${removed} accessory tracks from animation: ${id}`\n )\n }\n clip.tracks = validTracks\n }\n\n clip.optimize()\n clip.trim()\n clip.resetDuration()\n\n AnimationLibrary.clips.set(id, clip)\n\n if (AnimationLibrary.debug) {\n console.log(\n `[AnimationLibrary] Loaded animation: ${id} from ${path} (${clip.tracks.length} tracks)`\n )\n }\n\n return clip\n }\n\n throw new Error(\"Failed to load animation\")\n }\n\n public static async loadAnimations(paths: { [id: string]: string }): Promise<void> {\n const promises = Object.entries(paths).map(([id, path]) =>\n AnimationLibrary.loadAnimation(id, path)\n )\n await Promise.all(promises)\n }\n\n public static registerClip(id: string, clip: THREE.AnimationClip): void {\n if (AnimationLibrary.clips.has(id)) {\n console.warn(`[AnimationLibrary] Clip '${id}' already registered, skipping...`)\n return\n }\n\n AnimationLibrary.clips.set(id, clip)\n\n if (AnimationLibrary.debug) {\n console.log(\n `[AnimationLibrary] Registered animation clip: ${id} (${clip.tracks.length} tracks)`\n )\n }\n }\n\n public static getClip(id: string): THREE.AnimationClip | undefined {\n return AnimationLibrary.clips.get(id)\n }\n\n public static cloneClip(id: string): THREE.AnimationClip | undefined {\n const clip = AnimationLibrary.clips.get(id)\n return clip ? clip.clone() : undefined\n }\n\n public static getAllClips(): Map<string, THREE.AnimationClip> {\n return new Map(AnimationLibrary.clips)\n }\n\n public static hasClip(id: string): boolean {\n return AnimationLibrary.clips.has(id)\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Shared animation clip registry\n * Stores clips once, characters create their own mixers\n *\n * Note: We tried using AnimationObjectGroup for true sharing, but it had\n * issues with certain animations not applying to some character models.\n * Per-character mixers are slightly less efficient but much more reliable.\n */\nexport class SharedAnimationManager {\n private static instance: SharedAnimationManager | null = null\n\n // Cached clips (shared by all characters - this is the main memory savings)\n private clips: Map<string, THREE.AnimationClip> = new Map()\n\n private constructor() {}\n\n public static getInstance(): SharedAnimationManager {\n if (!SharedAnimationManager.instance) {\n SharedAnimationManager.instance = new SharedAnimationManager()\n }\n return SharedAnimationManager.instance\n }\n\n /**\n * Register an animation clip once\n */\n public registerClip(name: string, clip: THREE.AnimationClip): void {\n if (this.clips.has(name)) return\n this.clips.set(name, clip)\n }\n\n public getClip(name: string): THREE.AnimationClip | undefined {\n return this.clips.get(name)\n }\n\n public getRegisteredClipNames(): string[] {\n return [...this.clips.keys()]\n }\n\n /**\n * No-op for backward compatibility\n * Per-character mixers update themselves\n */\n public update(_deltaTime: number): void {\n // Each character's controller updates its own mixer\n }\n}\n\n/**\n * Per-character animation controller with its own mixer\n * Uses shared clips from SharedAnimationManager for memory efficiency\n */\nexport class CharacterAnimationController {\n private manager: SharedAnimationManager\n private mixer: THREE.AnimationMixer\n private actions: Map<string, THREE.AnimationAction> = new Map()\n private currentAnimation: string | null = null\n private crossfadeDuration: number = 0.2 // Default crossfade time in seconds\n private isPaused: boolean = false\n\n constructor(model: THREE.Object3D, manager: SharedAnimationManager) {\n this.manager = manager\n this.mixer = new THREE.AnimationMixer(model)\n }\n\n /**\n * Pause animation updates (for off-screen or distant characters)\n */\n public setPaused(paused: boolean): void {\n this.isPaused = paused\n }\n\n /**\n * Check if animation is paused\n */\n public getIsPaused(): boolean {\n return this.isPaused\n }\n\n /**\n * Set the crossfade duration for animation transitions\n */\n public setCrossfadeDuration(duration: number): void {\n this.crossfadeDuration = Math.max(0, duration)\n }\n\n /**\n * Play a single animation with crossfade transition\n */\n public playAnimation(name: string, startTime: number = 0): void {\n if (this.currentAnimation === name) return\n\n const clip = this.manager.getClip(name)\n if (!clip) {\n console.warn(`[CharacterAnimController] Animation '${name}' not registered!`)\n return\n }\n\n // Get or create action for the new animation\n let newAction = this.actions.get(name)\n if (!newAction) {\n newAction = this.mixer.clipAction(clip)\n this.actions.set(name, newAction)\n }\n\n // Get current action if exists\n const currentAction = this.currentAnimation ? this.actions.get(this.currentAnimation) : null\n\n if (currentAction && this.crossfadeDuration > 0) {\n // Crossfade from current to new animation\n newAction.reset()\n newAction.time = startTime\n newAction.setEffectiveTimeScale(1)\n newAction.setEffectiveWeight(1)\n newAction.play()\n currentAction.crossFadeTo(newAction, this.crossfadeDuration, true)\n } else {\n // No current animation or no crossfade - just play immediately\n if (currentAction) {\n currentAction.fadeOut(0.1)\n }\n newAction.reset()\n newAction.time = startTime\n newAction.setEffectiveTimeScale(1)\n newAction.setEffectiveWeight(1)\n newAction.fadeIn(0.1)\n newAction.play()\n }\n\n this.currentAnimation = name\n }\n\n /**\n * Update the mixer - MUST be called every frame\n * Returns early if paused (for performance optimization of off-screen characters)\n */\n public update(deltaTime: number): void {\n if (this.isPaused) return\n this.mixer.update(deltaTime)\n }\n\n /**\n * Stop all animations\n */\n public stopAll(): void {\n for (const action of this.actions.values()) {\n action.stop()\n }\n this.currentAnimation = null\n }\n\n /**\n * Cleanup\n */\n public dispose(): void {\n this.stopAll()\n this.mixer.stopAllAction()\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core/GameObject\"\nimport { AnimationLibrary } from \"./animation-library\"\nimport { SharedAnimationManager, CharacterAnimationController } from \"./SharedAnimationManager\"\nimport { AnimationCullingManager } from \"./AnimationCullingManager\"\nimport Animatrix, { ParameterType } from \"./animatrix\"\nimport AnimatrixVisualizer from \"./visualizer\"\n\nexport interface ParameterConfig {\n type: \"bool\" | \"float\" | \"int\"\n default: any\n}\n\nexport interface AnimationTreeChild {\n animation: string\n threshold: number\n}\n\nexport interface AnimationTree {\n parameter: string\n children: AnimationTreeChild[]\n}\n\nexport interface StateConfig {\n animation?: string\n tree?: AnimationTree\n randomizeStartTime?: boolean\n}\n\nexport interface TransitionConfig {\n from: string\n to: string\n when?: Record<string, any>\n /** Exit time as a normalized value (0-1). If true, defaults to 1.0 (end of animation) */\n exitTime?: number | boolean\n}\n\nexport interface AnimationGraphConfig {\n parameters?: Record<string, ParameterConfig>\n states: Record<string, StateConfig>\n transitions?: TransitionConfig[]\n initialState: string\n debug?: boolean\n}\n\nexport interface StoredTreeConfig {\n stateName: string\n tree: AnimationTree | null\n simpleAnimation: string | null\n}\n\nexport class AnimationGraphComponent extends Component {\n private static instances: Set<AnimationGraphComponent> = new Set()\n private static instancesByName: Map<string, AnimationGraphComponent> = new Map() // O(1) lookup\n private static sharedVisualizer: AnimatrixVisualizer | null = null\n private static debugViewEnabled: boolean = false\n private static treeConfigs: Map<string, Map<string, StoredTreeConfig>> = new Map()\n\n private config: AnimationGraphConfig\n private readonly model: THREE.Object3D\n private controller: CharacterAnimationController | null = null\n private sharedManager: SharedAnimationManager\n private animator: Animatrix | null = null\n private animatorName: string | null = null\n\n private parameters: Map<string, any> = new Map()\n private currentState: string | null = null\n private currentAnimation: string | null = null\n private stateElapsedTime: number = 0\n private currentStateDuration: number = 1\n\n // Pre-indexed transitions by source state for O(1) lookup\n private transitionsByState: Map<string, TransitionConfig[]> = new Map()\n // Cached state durations to avoid repeated clip lookups\n private stateDurations: Map<string, number> = new Map()\n\n // Frustum culling settings\n private useFrustumCulling: boolean = true\n private boundingRadius: number = 4 // Character bounding sphere radius in world units\n private cullingManager: AnimationCullingManager\n\n constructor(model: THREE.Object3D, config: AnimationGraphConfig) {\n super()\n this.model = model\n this.config = config\n this.sharedManager = SharedAnimationManager.getInstance()\n this.cullingManager = AnimationCullingManager.getInstance()\n\n if (config.parameters) {\n for (const [name, paramConfig] of Object.entries(config.parameters)) {\n this.parameters.set(name, paramConfig.default)\n }\n }\n }\n\n public static setDebugViewEnabled(enabled: boolean): void {\n AnimationGraphComponent.debugViewEnabled = enabled\n\n if (enabled) {\n if (!AnimationGraphComponent.sharedVisualizer) {\n AnimationGraphComponent.sharedVisualizer = new AnimatrixVisualizer()\n AnimationGraphComponent.sharedVisualizer.hide()\n }\n\n for (const instance of AnimationGraphComponent.instances) {\n if (instance.animator && instance.animatorName) {\n AnimationGraphComponent.sharedVisualizer.add_animator(\n instance.animatorName,\n instance.animator\n )\n }\n }\n\n AnimationGraphComponent.sharedVisualizer.show()\n } else {\n if (AnimationGraphComponent.sharedVisualizer) {\n AnimationGraphComponent.sharedVisualizer.hide()\n }\n }\n }\n\n public static isDebugViewEnabled(): boolean {\n return AnimationGraphComponent.debugViewEnabled\n }\n\n public static getTreeConfig(animatorName: string, stateName: string): StoredTreeConfig | null {\n const animatorConfigs = AnimationGraphComponent.treeConfigs.get(animatorName)\n if (!animatorConfigs) return null\n return animatorConfigs.get(stateName) || null\n }\n\n public static getStateConfigs(animatorName: string): Map<string, StoredTreeConfig> | null {\n return AnimationGraphComponent.treeConfigs.get(animatorName) || null\n }\n\n public static getParameterValue(animatorName: string, paramName: string): any {\n const instance = AnimationGraphComponent.instancesByName.get(animatorName)\n return instance?.parameters.get(paramName) ?? null\n }\n\n public static getCurrentAnimation(animatorName: string): string | null {\n const instance = AnimationGraphComponent.instancesByName.get(animatorName)\n return instance?.currentAnimation ?? null\n }\n\n public getAnimator(): Animatrix | null {\n return this.animator\n }\n\n protected onCreate(): void {\n AnimationGraphComponent.instances.add(this)\n this.setupAnimationGraph()\n }\n\n private setupAnimationGraph(): void {\n this.controller = new CharacterAnimationController(this.model, this.sharedManager)\n this.animator = new Animatrix()\n this.animatorName = this.gameObject?.name || `graph_${AnimationGraphComponent.instances.size}`\n\n // Register in name lookup map\n AnimationGraphComponent.instancesByName.set(this.animatorName, this)\n\n this.registerAnimationClips()\n this.setupAnimatrix()\n this.storeTreeConfigs()\n this.preIndexTransitions()\n this.cacheStateDurations()\n\n if (AnimationGraphComponent.debugViewEnabled && AnimationGraphComponent.sharedVisualizer) {\n AnimationGraphComponent.sharedVisualizer.add_animator(this.animatorName, this.animator)\n }\n\n this.setState(this.config.initialState)\n }\n\n /**\n * Pre-index transitions by source state for O(1) lookup during update\n */\n private preIndexTransitions(): void {\n this.transitionsByState.clear()\n if (!this.config.transitions) return\n\n for (const transition of this.config.transitions) {\n let stateTransitions = this.transitionsByState.get(transition.from)\n if (!stateTransitions) {\n stateTransitions = []\n this.transitionsByState.set(transition.from, stateTransitions)\n }\n stateTransitions.push(transition)\n }\n }\n\n /**\n * Cache state durations to avoid repeated AnimationLibrary lookups\n */\n private cacheStateDurations(): void {\n this.stateDurations.clear()\n for (const [stateName, stateConfig] of Object.entries(this.config.states)) {\n let duration = 1\n if (stateConfig.animation) {\n const clip = AnimationLibrary.getClip(stateConfig.animation)\n if (clip) duration = clip.duration\n } else if (stateConfig.tree && stateConfig.tree.children.length > 0) {\n const clip = AnimationLibrary.getClip(stateConfig.tree.children[0].animation)\n if (clip) duration = clip.duration\n }\n this.stateDurations.set(stateName, duration)\n }\n }\n\n private storeTreeConfigs(): void {\n if (!this.animatorName) return\n\n const stateConfigs = new Map<string, StoredTreeConfig>()\n\n for (const [stateName, stateConfig] of Object.entries(this.config.states)) {\n stateConfigs.set(stateName, {\n stateName,\n tree: stateConfig.tree || null,\n simpleAnimation: stateConfig.animation || null,\n })\n }\n\n AnimationGraphComponent.treeConfigs.set(this.animatorName, stateConfigs)\n }\n\n private registerAnimationClips(): void {\n const clipIds = new Set<string>()\n\n for (const stateConfig of Object.values(this.config.states)) {\n if (stateConfig.animation) {\n clipIds.add(stateConfig.animation)\n } else if (stateConfig.tree) {\n for (const child of stateConfig.tree.children) {\n clipIds.add(child.animation)\n }\n }\n }\n\n for (const clipId of clipIds) {\n const clip = AnimationLibrary.getClip(clipId)\n if (clip) {\n this.sharedManager.registerClip(clipId, clip)\n }\n }\n }\n\n private setupAnimatrix(): void {\n if (!this.animator) return\n\n if (this.config.parameters) {\n for (const [name, paramConfig] of Object.entries(this.config.parameters)) {\n let paramType: ParameterType\n switch (paramConfig.type) {\n case \"bool\":\n paramType = ParameterType.BOOL\n break\n case \"float\":\n paramType = ParameterType.FLOAT\n break\n case \"int\":\n paramType = ParameterType.INT\n break\n default:\n paramType = ParameterType.BOOL\n }\n this.animator.add_parameter(name, paramType, paramConfig.default)\n }\n }\n\n for (const [stateName, stateConfig] of Object.entries(this.config.states)) {\n let clipDuration = 1\n if (stateConfig.animation) {\n const clip = AnimationLibrary.getClip(stateConfig.animation)\n if (clip) clipDuration = clip.duration\n } else if (stateConfig.tree && stateConfig.tree.children.length > 0) {\n const clip = AnimationLibrary.getClip(stateConfig.tree.children[0].animation)\n if (clip) clipDuration = clip.duration\n }\n this.animator.add_clip(stateName, { duration: clipDuration })\n }\n\n if (this.config.transitions) {\n for (const transition of this.config.transitions) {\n this.animator.add_transition({\n from: transition.from,\n to: transition.to,\n conditions: transition.when\n ? Object.entries(transition.when).map(([param, value]) => ({\n parameter: param,\n operator: \"==\" as any,\n value: value,\n }))\n : [],\n })\n }\n }\n }\n\n public update(deltaTime: number): void {\n if (!this.controller || !this.gameObject.isEnabled()) return\n\n // Check frustum culling if enabled\n if (this.useFrustumCulling) {\n const cullResult = this.cullingManager.shouldUpdateAnimation(this.model, this.boundingRadius)\n if (!cullResult.shouldUpdate) {\n // Still advance state time even when culled (for proper transition timing)\n this.stateElapsedTime += deltaTime\n return\n }\n // LOD mode could reduce animation quality here if needed\n }\n\n this.animator?.update(deltaTime)\n this.controller.update(deltaTime)\n this.stateElapsedTime += deltaTime\n\n // Use pre-indexed transitions for O(1) lookup by current state\n if (this.currentState) {\n const stateTransitions = this.transitionsByState.get(this.currentState)\n if (stateTransitions) {\n for (const transition of stateTransitions) {\n // Check exit time condition if specified\n if (transition.exitTime !== undefined) {\n const exitThreshold =\n typeof transition.exitTime === \"boolean\" ? 1.0 : transition.exitTime\n const normalizedTime = this.stateElapsedTime / this.currentStateDuration\n if (normalizedTime < exitThreshold) continue\n }\n\n // Check parameter conditions if specified\n let allConditionsMet = true\n if (transition.when) {\n // Iterate object keys directly instead of Object.entries() to avoid allocation\n for (const param in transition.when) {\n if (this.parameters.get(param) !== transition.when[param]) {\n allConditionsMet = false\n break\n }\n }\n }\n\n if (allConditionsMet) {\n this.setState(transition.to)\n break\n }\n }\n }\n }\n\n this.updateAnimation()\n }\n\n private updateAnimation(): void {\n if (!this.currentState || !this.controller) return\n\n const stateConfig = this.config.states[this.currentState]\n if (!stateConfig) return\n\n let targetAnimation: string | null = null\n\n if (stateConfig.animation) {\n targetAnimation = stateConfig.animation\n } else if (stateConfig.tree) {\n const paramValue = this.parameters.get(stateConfig.tree.parameter) || 0\n\n for (let i = stateConfig.tree.children.length - 1; i >= 0; i--) {\n const child = stateConfig.tree.children[i]\n if (paramValue >= child.threshold) {\n targetAnimation = child.animation\n break\n }\n }\n\n if (!targetAnimation && stateConfig.tree.children.length > 0) {\n targetAnimation = stateConfig.tree.children[0].animation\n }\n }\n\n if (targetAnimation && targetAnimation !== this.currentAnimation) {\n if (this.config.debug) {\n console.log(\n `[AnimGraph] ${this.animatorName}: ${this.currentAnimation} -> ${targetAnimation} (model: ${this.model?.name || \"unnamed\"})`\n )\n }\n const startTime = this.getStateRandomizeTime(this.currentState)\n ? Math.random() * this.currentStateDuration\n : 0\n this.controller.playAnimation(targetAnimation, startTime)\n this.currentAnimation = targetAnimation\n }\n }\n\n public setParameter(name: string, value: any): void {\n this.parameters.set(name, value)\n\n if (this.animator) {\n if (typeof value === \"boolean\") {\n this.animator.set_bool(name, value)\n } else if (typeof value === \"number\") {\n if (Number.isInteger(value)) {\n this.animator.set_int(name, value)\n } else {\n this.animator.set_float(name, value)\n }\n }\n }\n }\n\n public getParameter(name: string): any {\n return this.parameters.get(name)\n }\n\n public setState(stateName: string): void {\n if (this.currentState === stateName) return\n\n if (this.config.debug) {\n console.log(`[AnimGraph] ${this.animatorName} setState: ${this.currentState} -> ${stateName}`)\n }\n\n this.currentState = stateName\n this.currentAnimation = null\n this.currentStateDuration = this.getStateDuration(stateName)\n\n if (this.getStateRandomizeTime(stateName)) {\n this.stateElapsedTime = Math.random() * this.currentStateDuration\n } else {\n this.stateElapsedTime = 0\n }\n\n this.animator?.set_state(stateName)\n this.updateAnimation()\n }\n\n public getCurrentState(): string | null {\n return this.currentState\n }\n\n /**\n * Pause/unpause animation updates.\n * Use for off-screen or distant characters to save CPU.\n * @param paused If true, animation mixer won't update (bones freeze)\n */\n public setPaused(paused: boolean): void {\n this.controller?.setPaused(paused)\n }\n\n /**\n * Check if animation is paused\n */\n public isPaused(): boolean {\n return this.controller?.getIsPaused() ?? false\n }\n\n /**\n * Enable/disable frustum culling for this animator.\n * When enabled, animation updates are skipped if the model is outside the camera frustum.\n * @param enabled Whether to use frustum culling (default: true)\n */\n public setFrustumCulling(enabled: boolean): void {\n this.useFrustumCulling = enabled\n }\n\n /**\n * Set the bounding radius used for frustum culling.\n * @param radius The sphere radius around the character (default: 2)\n */\n public setBoundingRadius(radius: number): void {\n this.boundingRadius = radius\n }\n\n /**\n * Get the AnimationCullingManager instance for global culling settings.\n * Use this to add cameras, configure distance culling, etc.\n */\n public static getCullingManager(): AnimationCullingManager {\n return AnimationCullingManager.getInstance()\n }\n\n private getStateDuration(stateName: string): number {\n // Use cached duration for O(1) lookup\n return this.stateDurations.get(stateName) ?? 1\n }\n\n private getStateRandomizeTime(stateName: string): boolean {\n const stateConfig = this.config.states[stateName]\n if (!stateConfig) return false\n return stateConfig.randomizeStartTime || false\n }\n\n public addEventListener(_event: string, _callback: (data?: any) => void): void {\n // Not implemented\n }\n\n protected onCleanup(): void {\n AnimationGraphComponent.instances.delete(this)\n\n if (this.animatorName) {\n AnimationGraphComponent.instancesByName.delete(this.animatorName)\n AnimationGraphComponent.treeConfigs.delete(this.animatorName)\n }\n\n if (AnimationGraphComponent.sharedVisualizer && this.animator && this.animatorName) {\n AnimationGraphComponent.sharedVisualizer.remove_animator(this.animatorName)\n }\n\n if (this.animator) {\n this.animator.stop_all()\n }\n\n if (this.controller) {\n this.controller.dispose()\n }\n }\n}\n","import Animatrix, { AnimationEvent, ParameterType } from \"./animatrix\"\nimport { AnimationGraphComponent, StoredTreeConfig, AnimationTree } from \"./AnimationGraphComponent\"\n\ninterface NodePosition {\n x: number\n y: number\n}\n\nexport default class AnimatrixVisualizer {\n private animator: Animatrix | null\n private animators: Map<string, Animatrix>\n private current_animator_name: string | null\n private canvas: HTMLCanvasElement\n private ctx: CanvasRenderingContext2D\n private node_positions: Map<string, NodePosition>\n private is_visible: boolean\n private container: HTMLDivElement\n private auto_layout_complete: boolean\n private animation_frame_id: number | null\n private event_listeners: Map<string, () => void>\n\n private readonly NODE_RADIUS = 35\n private readonly NODE_COLOR_IDLE = \"#444444\"\n private readonly NODE_COLOR_ACTIVE = \"#4CAF50\"\n private readonly NODE_COLOR_TRANSITIONING = \"#FFA726\"\n private readonly NODE_COLOR_BLENDTREE = \"#607D8B\"\n private readonly CONNECTION_COLOR = \"#888888\"\n private readonly CONNECTION_COLOR_ACTIVE = \"#2196F3\"\n private readonly TEXT_COLOR = \"#FFFFFF\"\n private readonly BG_COLOR = \"rgba(30, 30, 30, 0.95)\"\n\n // View transform (panning/zooming)\n private viewScale: number = 1\n private panX: number = 0\n private panY: number = 0\n private isPanningView: boolean = false\n private panStart: { x: number; y: number } = { x: 0, y: 0 }\n\n // Window drag/resize/minimize\n private isDraggingWindow: boolean = false\n private dragWindowOffset: { x: number; y: number } = { x: 0, y: 0 }\n private isResizingWindow: boolean = false\n private resizeStart: { x: number; y: number; w: number; h: number } = {\n x: 0,\n y: 0,\n w: 0,\n h: 0,\n }\n private isMinimized: boolean = false\n // Blend tree drawer states\n private nodeDrawerOpen: Set<string> = new Set()\n // Track hover state for chevron areas\n private hoveredChevron: string | null = null\n // Labels to draw in screen space (unscaled by zoom)\n private pendingLabels: Array<{\n text: string\n x: number\n y: number\n align: CanvasTextAlign\n baseline: CanvasTextBaseline\n font: string\n color: string\n }> = []\n\n // Drill-down view state\n private drillDownState: string | null = null\n private drillDownTreeConfig: StoredTreeConfig | null = null\n private lastClickTime: number = 0\n private lastClickNode: string | null = null\n\n private getLOD(): number {\n // 0 = full detail, 1 = medium, 2 = minimal, 3 = headers only\n const s = this.viewScale\n if (s >= 1.2) return 0\n if (s >= 0.8) return 1\n if (s >= 0.5) return 2\n return 3\n }\n\n constructor(animator?: Animatrix, name?: string) {\n this.animator = null\n this.animators = new Map()\n this.current_animator_name = null\n this.node_positions = new Map()\n this.is_visible = true\n this.auto_layout_complete = false\n this.animation_frame_id = null\n this.event_listeners = new Map()\n\n this.container = document.createElement(\"div\")\n this.container.style.position = \"absolute\"\n this.container.style.bottom = \"10px\"\n this.container.style.right = \"10px\"\n this.container.style.width = \"620px\"\n this.container.style.height = \"400px\"\n this.container.style.backgroundColor = this.BG_COLOR\n this.container.style.border = \"2px solid #333\"\n this.container.style.borderRadius = \"8px\"\n this.container.style.overflow = \"hidden\"\n this.container.style.fontFamily = \"monospace\"\n this.container.style.boxShadow = \"0 4px 6px rgba(0,0,0,0.3)\"\n this.container.style.zIndex = \"2147483647\"\n this.container.style.pointerEvents = \"auto\"\n\n const header = document.createElement(\"div\")\n header.style.backgroundColor = \"#222\"\n header.style.padding = \"8px\"\n header.style.color = \"#FFF\"\n header.style.fontSize = \"12px\"\n header.style.borderBottom = \"1px solid #444\"\n header.style.display = \"flex\"\n header.style.justifyContent = \"space-between\"\n header.style.alignItems = \"center\"\n header.style.cursor = \"move\"\n\n const title_span = document.createElement(\"span\")\n title_span.id = \"visualizer-title\"\n title_span.textContent = \"ANIMATION GRAPH\"\n header.appendChild(title_span)\n\n const controls_div = document.createElement(\"div\")\n controls_div.style.display = \"flex\"\n controls_div.style.gap = \"8px\"\n controls_div.style.alignItems = \"center\"\n\n const toggle_btn = document.createElement(\"button\")\n toggle_btn.textContent = \"−\"\n toggle_btn.style.background = \"none\"\n toggle_btn.style.border = \"1px solid #666\"\n toggle_btn.style.color = \"#FFF\"\n toggle_btn.style.cursor = \"pointer\"\n toggle_btn.style.padding = \"2px 8px\"\n toggle_btn.style.borderRadius = \"3px\"\n toggle_btn.onclick = () => this.toggle_minimize()\n controls_div.appendChild(toggle_btn)\n header.appendChild(controls_div)\n\n // Create main content area with flex layout\n const content_area = document.createElement(\"div\")\n content_area.style.display = \"flex\"\n content_area.style.height = \"calc(100% - 40px)\" // Account for header height\n content_area.style.backgroundColor = this.BG_COLOR\n\n const params_panel = document.createElement(\"div\")\n params_panel.id = \"params-panel\"\n params_panel.style.backgroundColor = \"#1a1a1a\"\n params_panel.style.padding = \"8px\"\n params_panel.style.fontSize = \"11px\"\n params_panel.style.color = \"#AAA\"\n params_panel.style.width = \"140px\"\n params_panel.style.minWidth = \"120px\"\n params_panel.style.overflowY = \"auto\"\n params_panel.style.borderRight = \"1px solid #333\"\n params_panel.style.flexShrink = \"0\"\n\n this.canvas = document.createElement(\"canvas\")\n this.canvas.style.flex = \"1\"\n this.canvas.style.minWidth = \"280px\"\n\n // Create animator list panel on the right\n const animator_list_panel = document.createElement(\"div\")\n animator_list_panel.id = \"animator-list-panel\"\n animator_list_panel.style.backgroundColor = \"#1a1a1a\"\n animator_list_panel.style.padding = \"8px\"\n animator_list_panel.style.fontSize = \"11px\"\n animator_list_panel.style.color = \"#AAA\"\n animator_list_panel.style.width = \"140px\"\n animator_list_panel.style.minWidth = \"120px\"\n animator_list_panel.style.overflowY = \"auto\"\n animator_list_panel.style.borderLeft = \"1px solid #333\"\n animator_list_panel.style.flexShrink = \"0\"\n\n const animator_list_header = document.createElement(\"div\")\n animator_list_header.style.color = \"#5B9AE8\"\n animator_list_header.style.fontWeight = \"bold\"\n animator_list_header.style.marginBottom = \"8px\"\n animator_list_header.style.fontSize = \"10px\"\n animator_list_header.style.textTransform = \"uppercase\"\n animator_list_header.textContent = \"Animators\"\n animator_list_panel.appendChild(animator_list_header)\n\n const animator_list_content = document.createElement(\"div\")\n animator_list_content.id = \"animator-list-content\"\n animator_list_panel.appendChild(animator_list_content)\n\n content_area.appendChild(params_panel)\n content_area.appendChild(this.canvas)\n content_area.appendChild(animator_list_panel)\n\n this.container.appendChild(header)\n this.container.appendChild(content_area)\n\n // Set initial visibility based on is_visible flag\n this.container.style.display = this.is_visible ? \"block\" : \"none\"\n\n document.body.appendChild(this.container)\n\n this.ctx = this.canvas.getContext(\"2d\")!\n\n const stopAll = (e: Event) => {\n e.stopPropagation()\n }\n // Prevent game input from consuming these events. Do NOT block move events so window listeners still receive them.\n ;[\"mousedown\", \"click\", \"dblclick\", \"contextmenu\", \"pointerdown\", \"wheel\"].forEach((type) => {\n this.container.addEventListener(type as any, stopAll)\n })\n // Ensure releasing inside the window stops drag/resize immediately\n this.container.addEventListener(\"mouseup\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.stop_window_drag()\n this.stop_window_resize()\n })\n this.container.addEventListener(\"pointerup\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.stop_window_drag()\n this.stop_window_resize()\n })\n\n this.canvas.addEventListener(\"mousedown\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.handle_mouse_down(e)\n })\n this.canvas.addEventListener(\"mousemove\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.handle_mouse_move(e)\n })\n this.canvas.addEventListener(\"mouseup\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.handle_mouse_up()\n })\n this.canvas.addEventListener(\n \"wheel\",\n (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.handle_wheel(e)\n },\n { passive: false }\n )\n\n // Enable window dragging via header (but not on buttons)\n header.addEventListener(\"mousedown\", (e) => {\n const target = e.target as HTMLElement\n if (target.tagName === \"BUTTON\") {\n return\n }\n e.preventDefault()\n e.stopPropagation()\n this.start_window_drag(e)\n })\n window.addEventListener(\"mousemove\", (e) => this.on_window_drag(e))\n window.addEventListener(\"mouseup\", () => {\n this.stop_window_drag()\n this.stop_window_resize()\n })\n window.addEventListener(\"pointerup\", () => {\n this.stop_window_drag()\n this.stop_window_resize()\n })\n\n // Resizer handle\n const resizer = document.createElement(\"div\")\n resizer.style.position = \"absolute\"\n resizer.style.width = \"14px\"\n resizer.style.height = \"14px\"\n resizer.style.right = \"2px\"\n resizer.style.bottom = \"2px\"\n resizer.style.cursor = \"se-resize\"\n resizer.style.background = \"linear-gradient(135deg, transparent 50%, #666 50%)\"\n this.container.appendChild(resizer)\n resizer.addEventListener(\"mousedown\", (e) => {\n e.preventDefault()\n e.stopPropagation()\n this.start_window_resize(e)\n })\n window.addEventListener(\"mousemove\", (e) => this.on_window_resize(e))\n window.addEventListener(\"mouseup\", () => this.stop_window_resize())\n\n // ESC key to exit drill-down view\n window.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\" && this.drillDownState) {\n this.exitDrillDown()\n }\n })\n\n if (animator) {\n this.add_animator(name || `animator_${this.animators.size + 1}`, animator)\n }\n\n this.update_canvas_size()\n this.start_animation_loop()\n }\n\n public add_animator(name: string, animator: Animatrix): void {\n this.animators.set(name, animator)\n\n if (!this.current_animator_name) {\n this.set_animator(name)\n } else {\n this.update_animator_select()\n }\n }\n\n public remove_animator(name: string): void {\n if (this.current_animator_name === name) {\n this.set_animator(null)\n }\n this.animators.delete(name)\n this.update_animator_select()\n }\n\n public set_animator(name: string | null): void {\n // Clean up old listeners\n this.cleanup_animator_listeners()\n\n if (name === null) {\n this.animator = null\n this.current_animator_name = null\n this.node_positions.clear()\n this.auto_layout_complete = false\n } else {\n const animator = this.animators.get(name)\n if (animator) {\n this.animator = animator\n this.current_animator_name = name\n this.setup_animator_listeners()\n this.node_positions.clear()\n this.auto_layout_complete = false\n // Ensure canvas size is updated before layout\n this.update_canvas_size()\n this.auto_layout_nodes()\n // Reset view so nodes appear centered by default\n this.viewScale = 1\n this.panX = 0\n this.panY = 0\n }\n }\n\n this.update_title()\n this.update_animator_select()\n this.render()\n }\n\n private setup_animator_listeners(): void {\n if (!this.animator) return\n\n const state_changed_listener = () => this.render()\n const transition_start_listener = () => this.render()\n const transition_end_listener = () => this.render()\n\n this.animator.add_listener(AnimationEvent.STATE_CHANGED, state_changed_listener)\n this.animator.add_listener(AnimationEvent.TRANSITION_START, transition_start_listener)\n this.animator.add_listener(AnimationEvent.TRANSITION_END, transition_end_listener)\n\n this.event_listeners.set(\"state_changed\", state_changed_listener)\n this.event_listeners.set(\"transition_start\", transition_start_listener)\n this.event_listeners.set(\"transition_end\", transition_end_listener)\n }\n\n private cleanup_animator_listeners(): void {\n if (!this.animator) return\n\n const state_changed_listener = this.event_listeners.get(\"state_changed\")\n const transition_start_listener = this.event_listeners.get(\"transition_start\")\n const transition_end_listener = this.event_listeners.get(\"transition_end\")\n\n if (state_changed_listener) {\n this.animator.remove_listener(AnimationEvent.STATE_CHANGED, state_changed_listener)\n }\n if (transition_start_listener) {\n this.animator.remove_listener(AnimationEvent.TRANSITION_START, transition_start_listener)\n }\n if (transition_end_listener) {\n this.animator.remove_listener(AnimationEvent.TRANSITION_END, transition_end_listener)\n }\n\n this.event_listeners.clear()\n }\n\n private update_animator_select(): void {\n const listContent = this.container.querySelector(\"#animator-list-content\") as HTMLElement\n if (!listContent) return\n\n listContent.innerHTML = \"\"\n\n if (this.animators.size === 0) {\n const emptyMsg = document.createElement(\"div\")\n emptyMsg.style.color = \"#666\"\n emptyMsg.style.fontStyle = \"italic\"\n emptyMsg.style.fontSize = \"10px\"\n emptyMsg.textContent = \"No animators\"\n listContent.appendChild(emptyMsg)\n return\n }\n\n this.animators.forEach((_, name) => {\n const item = document.createElement(\"div\")\n item.style.padding = \"6px 8px\"\n item.style.marginBottom = \"4px\"\n item.style.borderRadius = \"4px\"\n item.style.cursor = \"pointer\"\n item.style.fontSize = \"11px\"\n item.style.transition = \"background 0.15s\"\n item.style.whiteSpace = \"nowrap\"\n item.style.overflow = \"hidden\"\n item.style.textOverflow = \"ellipsis\"\n\n const isSelected = name === this.current_animator_name\n item.style.background = isSelected ? \"rgba(91, 154, 232, 0.3)\" : \"rgba(255, 255, 255, 0.05)\"\n item.style.color = isSelected ? \"#5B9AE8\" : \"#AAA\"\n item.style.fontWeight = isSelected ? \"bold\" : \"normal\"\n\n item.textContent = name\n item.title = name\n\n item.onmouseenter = () => {\n if (name !== this.current_animator_name) {\n item.style.background = \"rgba(255, 255, 255, 0.1)\"\n }\n }\n item.onmouseleave = () => {\n item.style.background =\n name === this.current_animator_name\n ? \"rgba(91, 154, 232, 0.3)\"\n : \"rgba(255, 255, 255, 0.05)\"\n }\n item.onclick = (e) => {\n e.stopPropagation()\n this.set_animator(name)\n }\n\n listContent.appendChild(item)\n })\n }\n\n private update_title(): void {\n const title = this.container.querySelector(\"#visualizer-title\") as HTMLElement\n if (!title) return\n\n if (this.drillDownState) {\n title.textContent = `DRILL-DOWN: ${this.drillDownState}`\n } else if (this.current_animator_name) {\n title.textContent = `ANIMATION GRAPH - ${this.current_animator_name}`\n } else {\n title.textContent = \"ANIMATION GRAPH - No Animator\"\n }\n }\n\n private start_animation_loop(): void {\n const animate = () => {\n this.render()\n this.animation_frame_id = requestAnimationFrame(animate)\n }\n animate()\n }\n\n private auto_layout_nodes(): void {\n if (!this.animator) return\n const clips = this.animator.get_clips()\n const blendNodes = this.animator.get_blend_tree_ids()\n const transitions = this.animator.get_transitions()\n\n // States referenced explicitly in transitions should always be visible\n const referencedStates = new Set<string>()\n transitions.forEach((t) => {\n if (t.from !== \"*\") referencedStates.add(t.from)\n referencedStates.add(t.to)\n })\n\n // Collect all child clip ids of any blend tree\n const childClipIds = new Set<string>()\n blendNodes.forEach((id) => {\n const cfg = this.animator!.get_blend_tree_config(id)\n if (cfg) {\n cfg.children.forEach((ch) => childClipIds.add(ch.state_id))\n }\n })\n\n // Clips that are not exclusively internal children (or are referenced in transitions)\n const baseClipIds = Array.from(clips.keys()).filter(\n (id) => !childClipIds.has(id) || referencedStates.has(id)\n )\n // Final node ids = base clips + blend tree ids\n const nodeIds: string[] = [...new Set<string>([...baseClipIds, ...blendNodes])]\n\n if (nodeIds.length === 0) return\n\n // Build graph structure\n const graph = this.buildGraph(nodeIds, transitions)\n\n // Check if graph has cycles (bidirectional edges)\n const hasCycles = this.detectCycles(nodeIds, graph)\n\n if (hasCycles) {\n // Use radial/force-directed layout for cyclic graphs\n this.radialLayout(nodeIds, graph)\n } else {\n // Use Sugiyama-style layered layout for DAGs\n const layers = this.assignLayers(nodeIds, graph)\n this.minimizeCrossings(layers, graph)\n this.assignCoordinates(layers, graph)\n }\n\n this.auto_layout_complete = true\n }\n\n private detectCycles(\n nodeIds: string[],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> }\n ): boolean {\n const { outgoing, incoming } = graph\n\n // Check for bidirectional edges (A->B and B->A)\n for (const [from, targets] of outgoing) {\n for (const to of targets) {\n if (outgoing.get(to)?.has(from)) {\n return true\n }\n }\n }\n\n // Also check if any node has both incoming and outgoing to suggest cycles\n for (const node of nodeIds) {\n const hasIn = (incoming.get(node)?.size || 0) > 0\n const hasOut = (outgoing.get(node)?.size || 0) > 0\n if (hasIn && hasOut) {\n // Could be part of a cycle - do DFS to confirm\n const visited = new Set<string>()\n const recStack = new Set<string>()\n\n const hasCycleDFS = (n: string): boolean => {\n visited.add(n)\n recStack.add(n)\n\n for (const neighbor of outgoing.get(n) || []) {\n if (!visited.has(neighbor)) {\n if (hasCycleDFS(neighbor)) return true\n } else if (recStack.has(neighbor)) {\n return true\n }\n }\n\n recStack.delete(n)\n return false\n }\n\n if (hasCycleDFS(node)) return true\n }\n }\n\n return false\n }\n\n private radialLayout(\n nodeIds: string[],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> }\n ): void {\n const { outgoing, incoming } = graph\n const canvasW = this.canvas.width\n const canvasH = this.canvas.height\n\n // Node dimensions for spacing\n const nodeW = 250\n const nodeH = 100\n\n // Find the hub node (most total connections)\n let hubNode = nodeIds[0]\n let maxConnections = 0\n\n for (const node of nodeIds) {\n const connections = (outgoing.get(node)?.size || 0) + (incoming.get(node)?.size || 0)\n if (connections > maxConnections) {\n maxConnections = connections\n hubNode = node\n }\n }\n\n // Get nodes directly connected to hub\n const hubConnected = new Set<string>()\n for (const n of outgoing.get(hubNode) || []) hubConnected.add(n)\n for (const n of incoming.get(hubNode) || []) hubConnected.add(n)\n\n // Separate into tiers: hub, directly connected, and others\n const directlyConnected = nodeIds.filter((n) => n !== hubNode && hubConnected.has(n))\n const others = nodeIds.filter((n) => n !== hubNode && !hubConnected.has(n))\n\n // Place hub in center\n const centerX = canvasW / 2\n const centerY = canvasH / 2\n this.node_positions.set(hubNode, { x: centerX, y: centerY })\n\n // Calculate radius for first ring - must fit all directly connected nodes\n const numDirectConnected = directlyConnected.length\n if (numDirectConnected > 0) {\n // Calculate minimum radius to avoid node overlap\n // Circumference needed = numNodes * (nodeWidth + gap)\n const nodeSpacing = nodeW + 60\n const circumference = numDirectConnected * nodeSpacing\n const minRadius = circumference / (2 * Math.PI)\n\n // Also ensure radius is enough to clear center node\n const clearanceRadius = Math.max(nodeW, nodeH) / 2 + nodeH / 2 + 80\n const radius = Math.max(minRadius, clearanceRadius, 200)\n\n // Sort connected nodes by their connections to each other (for better edge routing)\n const sortedConnected = this.sortNodesByConnectivity(directlyConnected, graph)\n\n // Place nodes in a circle\n for (let i = 0; i < sortedConnected.length; i++) {\n const angle = (2 * Math.PI * i) / sortedConnected.length - Math.PI / 2 // Start from top\n const x = centerX + radius * Math.cos(angle)\n const y = centerY + radius * Math.sin(angle)\n this.node_positions.set(sortedConnected[i], { x, y })\n }\n }\n\n // Place other nodes (not directly connected to hub) in outer ring\n if (others.length > 0) {\n const innerRadius =\n numDirectConnected > 0\n ? Math.max(\n ...directlyConnected.map((n) => {\n const pos = this.node_positions.get(n)!\n return Math.sqrt((pos.x - centerX) ** 2 + (pos.y - centerY) ** 2)\n })\n )\n : 200\n\n const outerRadius = innerRadius + nodeH + 100\n\n for (let i = 0; i < others.length; i++) {\n const angle = (2 * Math.PI * i) / others.length - Math.PI / 2\n const x = centerX + outerRadius * Math.cos(angle)\n const y = centerY + outerRadius * Math.sin(angle)\n this.node_positions.set(others[i], { x, y })\n }\n }\n\n // Fine-tune with force-directed adjustment\n this.forceDirectedRefinement(nodeIds, graph, 50)\n }\n\n private sortNodesByConnectivity(\n nodes: string[],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> }\n ): string[] {\n if (nodes.length <= 2) return nodes\n\n const { outgoing, incoming } = graph\n\n // Build adjacency between these nodes only\n const adj = new Map<string, Set<string>>()\n for (const n of nodes) {\n adj.set(n, new Set())\n }\n\n for (const n of nodes) {\n for (const target of outgoing.get(n) || []) {\n if (nodes.includes(target)) {\n adj.get(n)!.add(target)\n adj.get(target)!.add(n)\n }\n }\n }\n\n // Greedy ordering: start with first node, always pick the most connected neighbor\n const result: string[] = []\n const remaining = new Set(nodes)\n\n // Start with node that has most connections within the group\n let current = nodes.reduce((a, b) =>\n (adj.get(a)?.size || 0) >= (adj.get(b)?.size || 0) ? a : b\n )\n\n while (remaining.size > 0) {\n result.push(current)\n remaining.delete(current)\n\n if (remaining.size === 0) break\n\n // Find the remaining node most connected to current\n let bestNext: string | null = null\n let bestScore = -1\n\n for (const n of remaining) {\n const isConnected = adj.get(current)?.has(n) ? 1 : 0\n if (isConnected > bestScore || bestNext === null) {\n bestScore = isConnected\n bestNext = n\n }\n }\n\n current = bestNext!\n }\n\n return result\n }\n\n private forceDirectedRefinement(\n nodeIds: string[],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> },\n iterations: number\n ): void {\n const { outgoing } = graph\n const canvasW = this.canvas.width\n const canvasH = this.canvas.height\n const nodeW = 250\n const nodeH = 100\n const minDist = Math.max(nodeW, nodeH) + 40\n\n for (let iter = 0; iter < iterations; iter++) {\n const forces = new Map<string, { fx: number; fy: number }>()\n\n for (const id of nodeIds) {\n forces.set(id, { fx: 0, fy: 0 })\n }\n\n // Repulsion between all nodes\n for (let i = 0; i < nodeIds.length; i++) {\n for (let j = i + 1; j < nodeIds.length; j++) {\n const a = nodeIds[i]\n const b = nodeIds[j]\n const posA = this.node_positions.get(a)!\n const posB = this.node_positions.get(b)!\n\n const dx = posB.x - posA.x\n const dy = posB.y - posA.y\n const dist = Math.sqrt(dx * dx + dy * dy) || 1\n\n if (dist < minDist * 1.5) {\n const force = (minDist * 1.5 - dist) * 0.5\n const fx = (dx / dist) * force\n const fy = (dy / dist) * force\n\n forces.get(a)!.fx -= fx\n forces.get(a)!.fy -= fy\n forces.get(b)!.fx += fx\n forces.get(b)!.fy += fy\n }\n }\n }\n\n // Attraction along edges\n for (const [from, targets] of outgoing) {\n for (const to of targets) {\n const posFrom = this.node_positions.get(from)\n const posTo = this.node_positions.get(to)\n if (!posFrom || !posTo) continue\n\n const dx = posTo.x - posFrom.x\n const dy = posTo.y - posFrom.y\n const dist = Math.sqrt(dx * dx + dy * dy) || 1\n\n const idealDist = minDist * 1.2\n if (dist > idealDist) {\n const force = (dist - idealDist) * 0.02\n const fx = (dx / dist) * force\n const fy = (dy / dist) * force\n\n forces.get(from)!.fx += fx\n forces.get(from)!.fy += fy\n forces.get(to)!.fx -= fx\n forces.get(to)!.fy -= fy\n }\n }\n }\n\n // Apply forces\n const damping = 0.8 * (1 - iter / iterations) // Decrease over iterations\n const padding = nodeW / 2 + 20\n\n for (const id of nodeIds) {\n const pos = this.node_positions.get(id)!\n const f = forces.get(id)!\n\n pos.x += f.fx * damping\n pos.y += f.fy * damping\n\n // Keep within bounds\n pos.x = Math.max(padding, Math.min(canvasW - padding, pos.x))\n pos.y = Math.max(padding, Math.min(canvasH - padding, pos.y))\n }\n }\n }\n\n private buildGraph(\n nodeIds: string[],\n transitions: any[]\n ): {\n outgoing: Map<string, Set<string>>\n incoming: Map<string, Set<string>>\n edges: Array<{ from: string; to: string }>\n } {\n const outgoing = new Map<string, Set<string>>()\n const incoming = new Map<string, Set<string>>()\n const edges: Array<{ from: string; to: string }> = []\n\n for (const id of nodeIds) {\n outgoing.set(id, new Set())\n incoming.set(id, new Set())\n }\n\n for (const t of transitions) {\n if (t.from !== \"*\" && nodeIds.includes(t.from) && nodeIds.includes(t.to) && t.from !== t.to) {\n if (!outgoing.get(t.from)?.has(t.to)) {\n outgoing.get(t.from)?.add(t.to)\n incoming.get(t.to)?.add(t.from)\n edges.push({ from: t.from, to: t.to })\n }\n }\n }\n\n return { outgoing, incoming, edges }\n }\n\n private assignLayers(\n nodeIds: string[],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> }\n ): string[][] {\n const { outgoing, incoming } = graph\n const layers = new Map<string, number>()\n\n // Use longest path algorithm for layer assignment\n // First, find nodes with no incoming edges (roots)\n const roots = nodeIds.filter((id) => (incoming.get(id)?.size || 0) === 0)\n\n // If no roots (cyclic), pick node with minimum incoming edges\n const startNodes =\n roots.length > 0\n ? roots\n : [\n nodeIds.reduce((a, b) =>\n (incoming.get(a)?.size || 0) <= (incoming.get(b)?.size || 0) ? a : b\n ),\n ]\n\n // Compute longest path from any root to each node\n const computeLayer = (node: string, visited: Set<string>): number => {\n if (layers.has(node)) return layers.get(node)!\n if (visited.has(node)) return 0 // Cycle detected\n\n visited.add(node)\n const parents = incoming.get(node) || new Set()\n let maxParentLayer = -1\n\n for (const parent of parents) {\n const parentLayer = computeLayer(parent, visited)\n maxParentLayer = Math.max(maxParentLayer, parentLayer)\n }\n\n const layer = maxParentLayer + 1\n layers.set(node, layer)\n return layer\n }\n\n // Assign layers to all nodes\n for (const node of nodeIds) {\n if (!layers.has(node)) {\n computeLayer(node, new Set())\n }\n }\n\n // Handle disconnected nodes - place them based on their connections or at end\n const maxLayer = Math.max(...Array.from(layers.values()), 0)\n for (const node of nodeIds) {\n if (!layers.has(node)) {\n layers.set(node, maxLayer + 1)\n }\n }\n\n // Group into layer arrays\n const layerArrays: string[][] = []\n const layerCount = Math.max(...Array.from(layers.values())) + 1\n\n for (let i = 0; i < layerCount; i++) {\n layerArrays.push([])\n }\n\n for (const [node, layer] of layers) {\n layerArrays[layer].push(node)\n }\n\n // Remove empty layers\n return layerArrays.filter((l) => l.length > 0)\n }\n\n private minimizeCrossings(\n layers: string[][],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> }\n ): void {\n const { outgoing, incoming } = graph\n\n // Barycenter heuristic with multiple passes\n const numPasses = 4\n\n for (let pass = 0; pass < numPasses; pass++) {\n // Forward pass (top to bottom)\n for (let i = 1; i < layers.length; i++) {\n this.orderLayerByBarycenter(layers[i], layers[i - 1], incoming, true)\n }\n\n // Backward pass (bottom to top)\n for (let i = layers.length - 2; i >= 0; i--) {\n this.orderLayerByBarycenter(layers[i], layers[i + 1], outgoing, false)\n }\n }\n }\n\n private orderLayerByBarycenter(\n layer: string[],\n adjacentLayer: string[],\n connections: Map<string, Set<string>>,\n useIncoming: boolean\n ): void {\n // Create position map for adjacent layer\n const posMap = new Map<string, number>()\n adjacentLayer.forEach((node, idx) => posMap.set(node, idx))\n\n // Calculate barycenter for each node in current layer\n const barycenters: Array<{ node: string; bc: number }> = []\n\n for (const node of layer) {\n const connectedNodes = connections.get(node) || new Set()\n let sum = 0\n let count = 0\n\n for (const connected of connectedNodes) {\n const pos = posMap.get(connected)\n if (pos !== undefined) {\n sum += pos\n count++\n }\n }\n\n // If no connections, keep current relative position\n const bc = count > 0 ? sum / count : layer.indexOf(node)\n barycenters.push({ node, bc })\n }\n\n // Sort by barycenter\n barycenters.sort((a, b) => a.bc - b.bc)\n\n // Update layer order\n layer.length = 0\n barycenters.forEach(({ node }) => layer.push(node))\n }\n\n private assignCoordinates(\n layers: string[][],\n graph: {\n outgoing: Map<string, Set<string>>\n incoming: Map<string, Set<string>>\n edges: Array<{ from: string; to: string }>\n }\n ): void {\n const canvasW = this.canvas.width\n const canvasH = this.canvas.height\n\n // Get actual node dimensions (use max dimensions for spacing)\n const nodeW = 250 // Slightly more than the 240px node width\n const nodeH = 100 // Slightly more than the 80px node height\n\n // Layout constants - spacing includes node size + gap\n const paddingX = 60\n const paddingY = 60\n const gapX = 40 // Gap between nodes horizontally\n const gapY = 60 // Gap between layers vertically\n\n const nodeSpacingX = nodeW + gapX\n const nodeSpacingY = nodeH + gapY\n\n // Calculate required dimensions\n const maxNodesInLayer = Math.max(...layers.map((l) => l.length))\n const numLayers = layers.length\n\n // Calculate total graph size\n const totalWidth = maxNodesInLayer * nodeSpacingX - gapX\n const totalHeight = numLayers * nodeSpacingY - gapY\n\n // Center the graph in canvas\n const startX = Math.max(paddingX + nodeW / 2, (canvasW - totalWidth) / 2 + nodeW / 2)\n const startY = Math.max(paddingY + nodeH / 2, (canvasH - totalHeight) / 2 + nodeH / 2)\n\n // Position each layer\n for (let layerIdx = 0; layerIdx < layers.length; layerIdx++) {\n const layer = layers[layerIdx]\n const y = startY + layerIdx * nodeSpacingY\n\n // Center this layer horizontally\n const layerWidth = (layer.length - 1) * nodeSpacingX\n const layerStartX = (canvasW - layerWidth) / 2\n\n for (let nodeIdx = 0; nodeIdx < layer.length; nodeIdx++) {\n const node = layer[nodeIdx]\n const x = layer.length === 1 ? canvasW / 2 : layerStartX + nodeIdx * nodeSpacingX\n this.node_positions.set(node, { x, y })\n }\n }\n\n // Apply priority layout adjustment to reduce edge lengths\n this.priorityLayoutAdjustment(layers, graph, nodeSpacingX)\n }\n\n private priorityLayoutAdjustment(\n layers: string[][],\n graph: { outgoing: Map<string, Set<string>>; incoming: Map<string, Set<string>> },\n minSpacing: number\n ): void {\n const { incoming } = graph\n const nodeHalfWidth = 125 // Half of node width for bounds\n\n // Adjust each node to be closer to its parents' average position\n for (let layerIdx = 1; layerIdx < layers.length; layerIdx++) {\n const layer = layers[layerIdx]\n const positions: Array<{ node: string; idealX: number; currentX: number }> = []\n\n for (const node of layer) {\n const pos = this.node_positions.get(node)!\n const parents = incoming.get(node) || new Set()\n\n if (parents.size > 0) {\n // Calculate average parent X position\n let sumX = 0\n for (const parent of parents) {\n const parentPos = this.node_positions.get(parent)\n if (parentPos) sumX += parentPos.x\n }\n const idealX = sumX / parents.size\n positions.push({ node, idealX, currentX: pos.x })\n } else {\n positions.push({ node, idealX: pos.x, currentX: pos.x })\n }\n }\n\n // Sort by ideal position\n positions.sort((a, b) => a.idealX - b.idealX)\n\n // Assign new positions maintaining minimum spacing\n const canvasW = this.canvas.width\n const padding = nodeHalfWidth + 20\n\n for (let i = 0; i < positions.length; i++) {\n let newX = positions[i].idealX\n\n // Ensure minimum spacing from previous node\n if (i > 0) {\n const prevX = this.node_positions.get(positions[i - 1].node)!.x\n newX = Math.max(newX, prevX + minSpacing)\n }\n\n // Keep within bounds\n newX = Math.max(padding, Math.min(canvasW - padding, newX))\n\n this.node_positions.get(positions[i].node)!.x = newX\n }\n\n // Center the layer if it got pushed to one side\n const xs = layer.map((n) => this.node_positions.get(n)!.x)\n const minX = Math.min(...xs)\n const maxX = Math.max(...xs)\n const centerX = (minX + maxX) / 2\n const offset = canvasW / 2 - centerX\n\n // Only apply centering if it doesn't push nodes out of bounds\n if (minX + offset >= padding && maxX + offset <= canvasW - padding) {\n for (const node of layer) {\n this.node_positions.get(node)!.x += offset\n }\n }\n }\n }\n\n private dragging_node: string | null = null\n private drag_offset: NodePosition = { x: 0, y: 0 }\n\n private handle_mouse_down(event: MouseEvent): void {\n const rect = this.canvas.getBoundingClientRect()\n const sx = event.clientX - rect.left\n const sy = event.clientY - rect.top\n\n // Check for back button click in drill-down mode\n if (this.drillDownState) {\n if (sx >= 10 && sx <= 70 && sy >= 10 && sy <= 38) {\n this.exitDrillDown()\n return\n }\n // Double-click anywhere else exits drill-down\n const now = Date.now()\n if (now - this.lastClickTime < 300) {\n this.exitDrillDown()\n return\n }\n this.lastClickTime = now\n return\n }\n\n const x = (sx - this.panX) / this.viewScale\n const y = (sy - this.panY) / this.viewScale\n\n let hitNode: string | null = null\n let hitExpander: boolean = false\n this.node_positions.forEach((pos, state_id) => {\n const is_blend = this.animator?.is_blend_tree_state(state_id) || false\n const dims = this.get_node_dimensions(state_id, is_blend)\n const left = pos.x - dims.w / 2\n const top = pos.y - dims.h / 2\n const headerH = 24\n if (x >= left && x <= left + dims.w && y >= top && y <= top + dims.h) {\n hitNode = state_id\n // Only trigger expander if clicking specifically on the chevron area for blend nodes\n if (is_blend && y >= top && y <= top + headerH) {\n // Chevron is positioned at (left + 10, top + 6) and is about 12x12 pixels\n const chevronX = left + 10\n const chevronY = top + 6\n const chevronSize = 12\n if (\n x >= chevronX &&\n x <= chevronX + chevronSize &&\n y >= chevronY &&\n y <= chevronY + chevronSize\n ) {\n hitExpander = true\n }\n }\n }\n })\n\n if (hitNode) {\n if (hitExpander) {\n if (this.nodeDrawerOpen.has(hitNode)) this.nodeDrawerOpen.delete(hitNode)\n else this.nodeDrawerOpen.add(hitNode)\n this.render()\n return\n }\n\n // Check for double-click to enter drill-down view\n const now = Date.now()\n if (this.lastClickNode === hitNode && now - this.lastClickTime < 300) {\n this.enterDrillDown(hitNode)\n this.lastClickNode = null\n this.lastClickTime = 0\n return\n }\n this.lastClickNode = hitNode\n this.lastClickTime = now\n\n const pos = this.node_positions.get(hitNode)!\n this.dragging_node = hitNode\n this.drag_offset = { x: x - pos.x, y: y - pos.y }\n } else {\n this.isPanningView = true\n this.panStart = { x: sx - this.panX, y: sy - this.panY }\n }\n }\n\n private handle_mouse_move(event: MouseEvent): void {\n const rect = this.canvas.getBoundingClientRect()\n const sx = event.clientX - rect.left\n const sy = event.clientY - rect.top\n\n if (this.isPanningView) {\n this.panX = sx - this.panStart.x\n this.panY = sy - this.panStart.y\n this.render()\n return\n }\n\n if (this.dragging_node) {\n const x = (sx - this.panX) / this.viewScale\n const y = (sy - this.panY) / this.viewScale\n\n const pos = this.node_positions.get(this.dragging_node)\n if (pos) {\n pos.x = x - this.drag_offset.x\n pos.y = y - this.drag_offset.y\n this.render()\n }\n return\n }\n\n // Check for chevron hover states\n const x = (sx - this.panX) / this.viewScale\n const y = (sy - this.panY) / this.viewScale\n let newHoveredChevron: string | null = null\n\n this.node_positions.forEach((pos, state_id) => {\n const is_blend = this.animator?.is_blend_tree_state(state_id) || false\n if (!is_blend) return\n\n const dims = this.get_node_dimensions(state_id, is_blend)\n const left = pos.x - dims.w / 2\n const top = pos.y - dims.h / 2\n const headerH = 24\n\n if (y >= top && y <= top + headerH) {\n const chevronX = left + 10\n const chevronY = top + 6\n const chevronSize = 12\n if (\n x >= chevronX &&\n x <= chevronX + chevronSize &&\n y >= chevronY &&\n y <= chevronY + chevronSize\n ) {\n newHoveredChevron = state_id\n }\n }\n })\n\n if (newHoveredChevron !== this.hoveredChevron) {\n this.hoveredChevron = newHoveredChevron\n this.canvas.style.cursor = newHoveredChevron ? \"pointer\" : \"default\"\n this.render()\n }\n }\n\n private handle_mouse_up(): void {\n this.dragging_node = null\n this.isPanningView = false\n }\n\n private handle_wheel(event: WheelEvent): void {\n event.preventDefault()\n const delta = -event.deltaY\n const zoomFactor = delta > 0 ? 1.1 : 0.9\n const rect = this.canvas.getBoundingClientRect()\n const cx = event.clientX - rect.left\n const cy = event.clientY - rect.top\n\n const prevScale = this.viewScale\n let nextScale = this.viewScale * zoomFactor\n nextScale = Math.max(0.5, Math.min(2.5, nextScale))\n\n this.panX = cx - (cx - this.panX) * (nextScale / prevScale)\n this.panY = cy - (cy - this.panY) * (nextScale / prevScale)\n this.viewScale = nextScale\n this.render()\n }\n\n private start_window_drag(event: MouseEvent): void {\n const rect = this.container.getBoundingClientRect()\n this.isDraggingWindow = true\n this.dragWindowOffset = {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n }\n this.container.style.left = rect.left + \"px\"\n this.container.style.top = rect.top + \"px\"\n this.container.style.right = \"\"\n this.container.style.bottom = \"\"\n // Add a class cursor while dragging\n document.body.style.cursor = \"grabbing\"\n }\n\n private on_window_drag(event: MouseEvent): void {\n if (!this.isDraggingWindow) return\n const x = event.clientX - this.dragWindowOffset.x\n const y = event.clientY - this.dragWindowOffset.y\n this.container.style.left = x + \"px\"\n this.container.style.top = y + \"px\"\n }\n\n private stop_window_drag(): void {\n this.isDraggingWindow = false\n document.body.style.cursor = \"\"\n }\n\n private start_window_resize(event: MouseEvent): void {\n event.preventDefault()\n event.stopPropagation()\n const rect = this.container.getBoundingClientRect()\n this.isResizingWindow = true\n this.resizeStart = {\n x: event.clientX,\n y: event.clientY,\n w: rect.width,\n h: rect.height,\n }\n document.body.style.cursor = \"nwse-resize\"\n }\n\n private on_window_resize(event: MouseEvent): void {\n if (!this.isResizingWindow) return\n const dx = event.clientX - this.resizeStart.x\n const dy = event.clientY - this.resizeStart.y\n // Allow shrinking and growing with clamped min sizes\n const w = Math.max(360, this.resizeStart.w + dx)\n const h = Math.max(260, this.resizeStart.h + dy)\n this.container.style.width = w + \"px\"\n this.container.style.height = h + \"px\"\n this.update_canvas_size()\n this.render()\n }\n\n private stop_window_resize(): void {\n if (!this.isResizingWindow) return\n this.isResizingWindow = false\n document.body.style.cursor = \"\"\n }\n\n private toggle_minimize(): void {\n this.isMinimized = !this.isMinimized\n const content_area = this.container.children[1] as HTMLElement // content area is second child after header\n if (this.isMinimized) {\n content_area.style.display = \"none\"\n this.container.style.height = \"auto\"\n } else {\n content_area.style.display = \"flex\"\n this.update_canvas_size()\n }\n }\n\n private update_canvas_size(): void {\n const rect = this.container.getBoundingClientRect()\n const params = document.getElementById(\"params-panel\") as HTMLElement | null\n const headerHeight = 40\n const paramsWidth =\n params && params.style.display !== \"none\" ? params.getBoundingClientRect().width || 180 : 0\n const height = Math.max(120, rect.height - headerHeight)\n const width = Math.max(200, rect.width - paramsWidth)\n this.canvas.width = Math.floor(width)\n this.canvas.height = Math.floor(height)\n }\n\n private render(): void {\n if (!this.is_visible) return\n\n this.ctx.setTransform(1, 0, 0, 1, 0, 0)\n this.ctx.fillStyle = \"#1E1E1E\"\n this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height)\n\n // Render drill-down view if active\n if (this.drillDownState && this.drillDownTreeConfig) {\n this.render_drill_down_view()\n return\n }\n\n if (!this.auto_layout_complete) {\n this.auto_layout_nodes()\n }\n\n this.ctx.save()\n this.ctx.translate(this.panX, this.panY)\n this.ctx.scale(this.viewScale, this.viewScale)\n this.draw_connections()\n this.draw_nodes()\n this.ctx.restore()\n this.draw_labels_screen_space()\n this.update_parameters_panel()\n }\n\n private enterDrillDown(stateName: string): void {\n if (!this.current_animator_name) return\n\n const treeConfig = AnimationGraphComponent.getTreeConfig(this.current_animator_name, stateName)\n if (!treeConfig) return\n\n this.drillDownState = stateName\n this.drillDownTreeConfig = treeConfig\n this.render()\n this.update_title()\n }\n\n private exitDrillDown(): void {\n this.drillDownState = null\n this.drillDownTreeConfig = null\n this.render()\n this.update_title()\n }\n\n private render_drill_down_view(): void {\n if (!this.drillDownTreeConfig || !this.current_animator_name) return\n\n const ctx = this.ctx\n const w = this.canvas.width\n const h = this.canvas.height\n const padding = 20\n\n // Draw back button area\n ctx.fillStyle = \"#333\"\n ctx.fillRect(10, 10, 60, 28)\n ctx.strokeStyle = \"#555\"\n ctx.lineWidth = 1\n ctx.strokeRect(10, 10, 60, 28)\n ctx.fillStyle = \"#FFF\"\n ctx.font = \"12px monospace\"\n ctx.textAlign = \"center\"\n ctx.textBaseline = \"middle\"\n ctx.fillText(\"< Back\", 40, 24)\n\n // Draw state name header\n ctx.fillStyle = \"#5B9AE8\"\n ctx.font = \"bold 16px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(`State: ${this.drillDownState}`, w / 2, 24)\n\n if (this.drillDownTreeConfig.simpleAnimation) {\n // Simple animation - just show the animation name\n ctx.fillStyle = \"#AAA\"\n ctx.font = \"14px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(\"Simple Animation:\", w / 2, h / 2 - 20)\n ctx.fillStyle = \"#4CAF50\"\n ctx.font = \"bold 18px monospace\"\n ctx.fillText(this.drillDownTreeConfig.simpleAnimation, w / 2, h / 2 + 10)\n return\n }\n\n if (!this.drillDownTreeConfig.tree) return\n\n const tree = this.drillDownTreeConfig.tree\n const children = tree.children\n if (children.length === 0) return\n\n // Get current parameter value\n const paramValue =\n AnimationGraphComponent.getParameterValue(this.current_animator_name, tree.parameter) || 0\n const currentAnim = AnimationGraphComponent.getCurrentAnimation(this.current_animator_name)\n\n // Draw parameter name and value\n ctx.fillStyle = \"#AAA\"\n ctx.font = \"14px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(`Parameter: ${tree.parameter}`, w / 2, 60)\n ctx.fillStyle = \"#FFEE58\"\n ctx.font = \"bold 16px monospace\"\n ctx.fillText(\n `Value: ${typeof paramValue === \"number\" ? paramValue.toFixed(2) : paramValue}`,\n w / 2,\n 85\n )\n\n // Draw threshold slider\n const sliderY = 130\n const sliderWidth = w - padding * 4\n const sliderLeft = padding * 2\n const sliderRight = sliderLeft + sliderWidth\n\n // Get min/max thresholds\n const sortedChildren = [...children].sort((a, b) => a.threshold - b.threshold)\n const minT = sortedChildren[0].threshold\n const maxT = sortedChildren[sortedChildren.length - 1].threshold\n const range = Math.max(0.001, maxT - minT)\n\n // Draw slider background\n ctx.fillStyle = \"#333\"\n ctx.fillRect(sliderLeft, sliderY - 4, sliderWidth, 8)\n\n // Draw threshold markers\n for (const child of sortedChildren) {\n const x = sliderLeft + ((child.threshold - minT) / range) * sliderWidth\n ctx.strokeStyle = \"#666\"\n ctx.lineWidth = 2\n ctx.beginPath()\n ctx.moveTo(x, sliderY - 10)\n ctx.lineTo(x, sliderY + 10)\n ctx.stroke()\n\n ctx.fillStyle = \"#888\"\n ctx.font = \"10px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(child.threshold.toString(), x, sliderY + 22)\n }\n\n // Draw current value marker\n const clampedValue = Math.min(maxT, Math.max(minT, paramValue as number))\n const valueX = sliderLeft + ((clampedValue - minT) / range) * sliderWidth\n ctx.fillStyle = \"#FFEE58\"\n ctx.beginPath()\n ctx.arc(valueX, sliderY, 8, 0, Math.PI * 2)\n ctx.fill()\n\n // Draw animation children as cards\n const cardStartY = 170\n const cardHeight = 50\n const cardGap = 10\n const cardWidth = Math.min(\n 200,\n (w - padding * 2 - cardGap * (children.length - 1)) / children.length\n )\n\n const totalCardsWidth = cardWidth * children.length + cardGap * (children.length - 1)\n let cardX = (w - totalCardsWidth) / 2\n\n for (const child of sortedChildren) {\n const isActive = currentAnim === child.animation\n\n // Card background\n ctx.fillStyle = isActive ? \"rgba(76, 175, 80, 0.3)\" : \"rgba(255, 255, 255, 0.05)\"\n ctx.fillRect(cardX, cardStartY, cardWidth, cardHeight)\n\n // Card border\n ctx.strokeStyle = isActive ? \"#4CAF50\" : \"#444\"\n ctx.lineWidth = isActive ? 2 : 1\n ctx.strokeRect(cardX, cardStartY, cardWidth, cardHeight)\n\n // Animation name\n ctx.fillStyle = isActive ? \"#4CAF50\" : \"#AAA\"\n ctx.font = isActive ? \"bold 12px monospace\" : \"12px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(child.animation, cardX + cardWidth / 2, cardStartY + 20)\n\n // Threshold value\n ctx.fillStyle = \"#666\"\n ctx.font = \"10px monospace\"\n ctx.fillText(`>= ${child.threshold}`, cardX + cardWidth / 2, cardStartY + 38)\n\n // Active indicator\n if (isActive) {\n ctx.fillStyle = \"#4CAF50\"\n ctx.beginPath()\n ctx.arc(cardX + cardWidth / 2, cardStartY - 8, 4, 0, Math.PI * 2)\n ctx.fill()\n }\n\n cardX += cardWidth + cardGap\n }\n\n // Instructions\n ctx.fillStyle = \"#555\"\n ctx.font = \"11px monospace\"\n ctx.textAlign = \"center\"\n ctx.fillText(\"Double-click or press ESC to go back\", w / 2, h - 20)\n }\n\n private draw_connections(): void {\n if (!this.animator) return\n const transitions = this.animator.get_transitions()\n const active_transition = this.animator.get_active_transition()\n\n transitions.forEach((transition) => {\n const from_pos =\n transition.from === \"*\" ? { x: 40, y: 40 } : this.node_positions.get(transition.from)\n const to_pos = this.node_positions.get(transition.to)\n\n if (from_pos && to_pos) {\n const is_active =\n active_transition &&\n (active_transition.from_state === transition.from || transition.from === \"*\") &&\n active_transition.to_state === transition.to\n\n this.ctx.strokeStyle = is_active ? this.CONNECTION_COLOR_ACTIVE : this.CONNECTION_COLOR\n this.ctx.lineWidth = is_active ? 3 : 2\n this.ctx.setLineDash(transition.from === \"*\" ? [5, 5] : [])\n\n this.ctx.beginPath()\n\n if (transition.from === \"*\") {\n this.ctx.moveTo(from_pos.x, from_pos.y)\n this.ctx.lineTo(to_pos.x, to_pos.y)\n } else {\n // Get actual node dimensions for both nodes\n const fromIsBlend = this.animator?.is_blend_tree_state(transition.from) || false\n const toIsBlend = this.animator?.is_blend_tree_state(transition.to) || false\n const fromDims = this.get_node_dimensions(transition.from, fromIsBlend)\n const toDims = this.get_node_dimensions(transition.to, toIsBlend)\n\n // Calculate intersection points with rectangle edges\n const startPoint = this.getRectEdgePoint(from_pos, to_pos, fromDims.w / 2, fromDims.h / 2)\n const endPoint = this.getRectEdgePoint(to_pos, from_pos, toDims.w / 2, toDims.h / 2)\n\n this.ctx.moveTo(startPoint.x, startPoint.y)\n this.ctx.lineTo(endPoint.x, endPoint.y)\n\n // Draw arrow head at the end point\n const angle = Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x)\n const arrow_length = 12\n const arrow_angle = Math.PI / 6\n this.ctx.lineTo(\n endPoint.x - arrow_length * Math.cos(angle - arrow_angle),\n endPoint.y - arrow_length * Math.sin(angle - arrow_angle)\n )\n this.ctx.moveTo(endPoint.x, endPoint.y)\n this.ctx.lineTo(\n endPoint.x - arrow_length * Math.cos(angle + arrow_angle),\n endPoint.y - arrow_length * Math.sin(angle + arrow_angle)\n )\n }\n\n this.ctx.stroke()\n this.ctx.setLineDash([])\n\n if (is_active && active_transition) {\n const progress = active_transition.progress\n const mid_x = from_pos.x + (to_pos.x - from_pos.x) * progress\n const mid_y = from_pos.y + (to_pos.y - from_pos.y) * progress\n\n this.ctx.fillStyle = this.CONNECTION_COLOR_ACTIVE\n this.ctx.beginPath()\n this.ctx.arc(mid_x, mid_y, 5, 0, Math.PI * 2)\n this.ctx.fill()\n }\n }\n })\n\n // Simplify rendering: do not draw links to child clips; blend trees are summarized in their own node UI\n\n const any_state_pos = { x: 40, y: 40 }\n this.ctx.strokeStyle = \"#666\"\n this.ctx.strokeRect(any_state_pos.x - 15, any_state_pos.y - 10, 30, 20)\n\n this.ctx.fillStyle = \"#666\"\n this.ctx.font = \"10px monospace\"\n this.ctx.textAlign = \"center\"\n this.ctx.textBaseline = \"middle\"\n this.ctx.fillText(\"ANY\", any_state_pos.x, any_state_pos.y)\n }\n\n // Calculate the point where a line from center to target intersects a rectangle edge\n private getRectEdgePoint(\n center: { x: number; y: number },\n target: { x: number; y: number },\n halfWidth: number,\n halfHeight: number\n ): { x: number; y: number } {\n const dx = target.x - center.x\n const dy = target.y - center.y\n\n if (dx === 0 && dy === 0) {\n return { x: center.x, y: center.y }\n }\n\n // Calculate the scale factor to reach the rectangle edge\n const scaleX = halfWidth / Math.abs(dx || 0.001)\n const scaleY = halfHeight / Math.abs(dy || 0.001)\n const scale = Math.min(scaleX, scaleY)\n\n return {\n x: center.x + dx * scale,\n y: center.y + dy * scale,\n }\n }\n\n private draw_nodes(): void {\n if (!this.animator) return\n const current_state = this.animator.get_current_state()\n const active_transition = this.animator.get_active_transition()\n const clips = this.animator.get_clips()\n // const blendIds = this.animator.get_blend_tree_ids();\n\n this.node_positions.forEach((pos, state_id) => {\n const is_current = current_state === state_id\n const is_transitioning_from = active_transition?.from_state === state_id\n const is_transitioning_to = active_transition?.to_state === state_id\n const clip = clips.get(state_id)\n const is_blend = this.animator!.is_blend_tree_state(state_id)\n\n let fill_color = is_blend ? this.NODE_COLOR_BLENDTREE : this.NODE_COLOR_IDLE\n if (is_current && !active_transition) {\n fill_color = this.NODE_COLOR_ACTIVE\n } else if (is_transitioning_from || is_transitioning_to) {\n fill_color = this.NODE_COLOR_TRANSITIONING\n }\n\n // LOD and dimensions\n const lod = this.getLOD()\n const dims = this.get_node_dimensions(state_id, is_blend)\n const nodeW = dims.w\n const nodeH = dims.h\n const nx = pos.x - nodeW / 2\n const ny = pos.y - nodeH / 2\n\n // Node background and header\n const headerH = lod <= 1 ? 28 : 24\n this.draw_rounded_rect(\n nx,\n ny,\n nodeW,\n nodeH,\n 10,\n \"#20252a\",\n is_current ? \"#FFF\" : \"#666\",\n is_current ? 2 : 1\n )\n this.ctx.fillStyle = fill_color\n this.ctx.fillRect(nx + 1, ny + 1, nodeW - 2, headerH)\n\n // Expander chevron for blend trees\n if (is_blend) {\n const open = this.nodeDrawerOpen.has(state_id)\n const is_hovered = this.hoveredChevron === state_id\n this.draw_chevron(nx + 10, ny + 6, open, is_hovered)\n }\n\n // Title text in header (screen-space for readability)\n const headerFont =\n lod === 0\n ? \"bold 16px monospace\"\n : lod === 1\n ? \"bold 14px monospace\"\n : \"bold 12px monospace\"\n this.queue_label(\n state_id.toUpperCase(),\n pos.x,\n ny + headerH / 2,\n \"center\",\n \"middle\",\n headerFont,\n this.TEXT_COLOR\n )\n\n // If blend tree, draw its 1D line with thresholds and current value below the node\n if (is_blend) {\n const cfg = this.animator!.get_blend_tree_config(state_id)\n if (cfg) {\n if (lod <= 2) {\n const lineY = ny + headerH + (lod === 0 ? 28 : 20)\n const lineW = Math.min(160, nodeW - 20)\n const lineX = pos.x - lineW / 2\n this.ctx.strokeStyle = \"#90A4AE\"\n this.ctx.lineWidth = 2\n this.ctx.beginPath()\n this.ctx.moveTo(lineX, lineY)\n this.ctx.lineTo(lineX + lineW, lineY)\n this.ctx.stroke()\n\n // Draw thresholds as small ticks with compact labels\n const children = [...cfg.children].sort((a, b) => a.threshold - b.threshold)\n if (children.length > 0) {\n const minT = children[0].threshold\n const maxT = children[children.length - 1].threshold\n const range = Math.max(1e-5, maxT - minT)\n this.ctx.fillStyle = \"#CFD8DC\"\n this.ctx.strokeStyle = \"#90A4AE\"\n for (const ch of children) {\n const nx2 = lineX + ((ch.threshold - minT) / range) * lineW\n this.ctx.beginPath()\n this.ctx.moveTo(nx2, lineY - 4)\n this.ctx.lineTo(nx2, lineY + 4)\n this.ctx.stroke()\n if (lod <= 1) {\n const label = `${Number.isFinite(ch.threshold) ? ch.threshold : \"\"}`\n this.queue_label(\n label,\n nx2,\n lineY + 6,\n \"center\",\n \"top\",\n \"11px monospace\",\n \"#CFD8DC\"\n )\n }\n }\n\n // Current parameter marker\n const p = this.animator!.get_float(cfg.parameter)\n const px = lineX + ((Math.min(maxT, Math.max(minT, p)) - minT) / range) * lineW\n this.ctx.fillStyle = \"#FFEE58\"\n this.ctx.beginPath()\n this.ctx.arc(px, lineY, 3, 0, Math.PI * 2)\n this.ctx.fill()\n\n // Parameter name and value centered under the line\n if (lod <= 2) {\n const pf = lod === 0 ? \"12px monospace\" : \"11px monospace\"\n this.queue_label(\n `${cfg.parameter}: ${p.toFixed(2)}`,\n pos.x,\n lineY + 12,\n \"center\",\n \"top\",\n pf,\n \"#B0BEC5\"\n )\n }\n\n // Drawer with child clip names (if open)\n if (this.nodeDrawerOpen.has(state_id) && lod <= 1) {\n const listX = nx + 10\n let listY = lineY + 26\n\n // Get blend weights for each child to show which are active\n const paramValue = this.animator!.get_float(cfg.parameter)\n\n for (const ch of children) {\n // Calculate blend weight for this child based on parameter value\n let weight = 0\n const idx = children.indexOf(ch)\n if (children.length === 1) {\n weight = 1\n } else if (idx === 0) {\n // First child\n const nextThreshold = children[idx + 1]?.threshold ?? ch.threshold\n weight =\n paramValue <= ch.threshold\n ? 1\n : paramValue <= nextThreshold\n ? (nextThreshold - paramValue) / (nextThreshold - ch.threshold)\n : 0\n } else if (idx === children.length - 1) {\n // Last child\n const prevThreshold = children[idx - 1]?.threshold ?? ch.threshold\n weight =\n paramValue >= ch.threshold\n ? 1\n : paramValue >= prevThreshold\n ? (paramValue - prevThreshold) / (ch.threshold - prevThreshold)\n : 0\n } else {\n // Middle child - blend between neighbors\n const prevThreshold = children[idx - 1]?.threshold ?? ch.threshold\n const nextThreshold = children[idx + 1]?.threshold ?? ch.threshold\n if (paramValue >= prevThreshold && paramValue <= nextThreshold) {\n if (paramValue <= ch.threshold) {\n weight = (paramValue - prevThreshold) / (ch.threshold - prevThreshold)\n } else {\n weight = (nextThreshold - paramValue) / (nextThreshold - ch.threshold)\n }\n }\n }\n weight = Math.max(0, Math.min(1, weight))\n\n // Visual indicators based on weight\n let bullet = \"â€ĸ\"\n let color = \"#B0BEC5\"\n let bgColor = null\n\n if (weight > 0.8) {\n bullet = \"●\" // solid circle for primary\n color = \"#4CAF50\" // green for active\n bgColor = \"rgba(76, 175, 80, 0.1)\"\n } else if (weight > 0.3) {\n bullet = \"◐\" // half circle for blending\n color = \"#FFA726\" // orange for blending\n bgColor = \"rgba(255, 167, 38, 0.1)\"\n } else if (weight > 0.05) {\n bullet = \"○\" // hollow circle for minimal contribution\n color = \"#90A4AE\" // grey for minimal\n }\n\n // Draw background highlight for active clips\n if (bgColor) {\n this.ctx.fillStyle = bgColor\n this.ctx.fillRect(listX - 4, listY - 2, 200, 14)\n }\n\n const weightText = weight > 0.01 ? ` (${(weight * 100).toFixed(0)}%)` : \"\"\n this.queue_label(\n `${bullet} ${ch.state_id}${weightText} @ ${ch.threshold}`,\n listX,\n listY,\n \"left\",\n \"top\",\n \"12px monospace\",\n color\n )\n listY += 16\n }\n }\n }\n }\n }\n }\n\n if ((is_current || is_transitioning_from || is_transitioning_to) && this.animator) {\n const playback_progress = this.animator.get_clip_progress(state_id)\n const weight = is_transitioning_from\n ? 1 - active_transition!.progress\n : is_transitioning_to\n ? active_transition!.progress\n : is_current\n ? 1.0\n : 0\n if (lod <= 1) {\n const barY = ny + nodeH + 12\n this.draw_playback_indicator(pos.x, barY, playback_progress, weight, clip?.loop || false)\n }\n }\n })\n }\n\n private get_node_dimensions(state_id: string, is_blend: boolean): { w: number; h: number } {\n const lod = this.getLOD()\n const baseW = lod === 0 ? 240 : lod === 1 ? 220 : 200\n const baseH = is_blend ? (lod === 0 ? 130 : 110) : lod === 0 ? 80 : 70\n if (!is_blend) return { w: baseW, h: baseH }\n const open = this.nodeDrawerOpen.has(state_id)\n if (!open || lod > 1) return { w: baseW, h: baseH }\n // Add height to list all children lines\n const cfg = this.animator?.get_blend_tree_config(state_id)\n const extra = cfg ? cfg.children.length * 16 + 10 : 0\n return { w: baseW, h: baseH + extra }\n }\n\n private queue_label(\n text: string,\n x: number,\n y: number,\n align: CanvasTextAlign,\n baseline: CanvasTextBaseline,\n font: string,\n color: string\n ): void {\n // Transform world coords to screen space based on current pan/zoom\n const sx = x * this.viewScale + this.panX\n const sy = y * this.viewScale + this.panY\n this.pendingLabels.push({\n text,\n x: sx,\n y: sy,\n align,\n baseline,\n font,\n color,\n })\n }\n\n private draw_labels_screen_space(): void {\n if (this.pendingLabels.length === 0) return\n for (const lbl of this.pendingLabels) {\n this.ctx.setTransform(1, 0, 0, 1, 0, 0)\n this.ctx.fillStyle = lbl.color\n this.ctx.font = lbl.font\n this.ctx.textAlign = lbl.align\n this.ctx.textBaseline = lbl.baseline\n this.ctx.fillText(lbl.text, lbl.x, lbl.y)\n }\n this.pendingLabels.length = 0\n }\n\n private draw_chevron(x: number, y: number, open: boolean, hovered: boolean = false): void {\n const ctx = this.ctx\n\n // Draw hover background\n if (hovered) {\n ctx.fillStyle = \"rgba(255, 255, 255, 0.1)\"\n ctx.fillRect(x - 2, y - 2, 16, 16)\n ctx.strokeStyle = \"rgba(255, 255, 255, 0.3)\"\n ctx.lineWidth = 1\n ctx.strokeRect(x - 2, y - 2, 16, 16)\n }\n\n ctx.fillStyle = hovered ? \"#FFD700\" : \"#FFF\" // Gold when hovered, white otherwise\n ctx.beginPath()\n if (open) {\n // down arrow\n ctx.moveTo(x, y)\n ctx.lineTo(x + 12, y)\n ctx.lineTo(x + 6, y + 8)\n } else {\n // right arrow\n ctx.moveTo(x, y)\n ctx.lineTo(x + 8, y + 6)\n ctx.lineTo(x, y + 12)\n }\n ctx.closePath()\n ctx.fill()\n }\n\n private draw_rounded_rect(\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n fill: string,\n stroke: string,\n lineWidth: number\n ): void {\n const ctx = this.ctx\n ctx.fillStyle = fill\n ctx.strokeStyle = stroke\n ctx.lineWidth = lineWidth\n ctx.beginPath()\n ctx.moveTo(x + r, y)\n ctx.lineTo(x + w - r, y)\n ctx.quadraticCurveTo(x + w, y, x + w, y + r)\n ctx.lineTo(x + w, y + h - r)\n ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h)\n ctx.lineTo(x + r, y + h)\n ctx.quadraticCurveTo(x, y + h, x, y + h - r)\n ctx.lineTo(x, y + r)\n ctx.quadraticCurveTo(x, y, x + r, y)\n ctx.closePath()\n ctx.fill()\n ctx.stroke()\n }\n\n private draw_playback_indicator(\n x: number,\n y: number,\n progress: number,\n weight: number,\n is_looping: boolean\n ): void {\n const bar_width = 60\n const bar_height = 8\n const bar_x = x - bar_width / 2\n\n this.ctx.fillStyle = \"rgba(30, 30, 30, 0.8)\"\n this.ctx.fillRect(bar_x, y, bar_width, bar_height)\n\n const progress_color = is_looping ? \"#2196F3\" : \"#4CAF50\"\n this.ctx.fillStyle = progress_color\n this.ctx.fillRect(bar_x, y, bar_width * progress, bar_height)\n\n if (weight < 1.0) {\n this.ctx.fillStyle = `rgba(255, 255, 255, ${0.3 * (1 - weight)})`\n this.ctx.fillRect(bar_x, y, bar_width, bar_height)\n }\n\n this.ctx.strokeStyle = weight > 0 ? \"#AAA\" : \"#444\"\n this.ctx.lineWidth = 1\n this.ctx.strokeRect(bar_x, y, bar_width, bar_height)\n const playhead_x = bar_x + bar_width * progress\n this.ctx.strokeStyle = \"#FFF\"\n this.ctx.lineWidth = 2\n this.ctx.beginPath()\n this.ctx.moveTo(playhead_x, y - 2)\n this.ctx.lineTo(playhead_x, y + bar_height + 2)\n this.ctx.stroke()\n }\n\n private update_parameters_panel(): void {\n const panel = document.getElementById(\"params-panel\")\n if (!panel) return\n\n if (!this.animator) {\n panel.innerHTML =\n '<div style=\"color: #666; text-align: center; padding: 20px;\">No animator selected</div>'\n return\n }\n\n const params = this.animator.get_parameters_map()\n let html = '<div style=\"display: grid; grid-template-columns: 1fr 1fr; gap: 4px;\">'\n\n params.forEach((param, name) => {\n let value_display = param.value\n let color = \"#AAA\"\n\n if (param.type === ParameterType.BOOL) {\n value_display = param.value ? \"✓\" : \"✗\"\n color = param.value ? \"#4CAF50\" : \"#F44336\"\n } else if (param.type === ParameterType.TRIGGER) {\n value_display = param.value ? \"●\" : \"○\"\n color = param.value ? \"#FFA726\" : \"#666\"\n } else if (param.type === ParameterType.FLOAT) {\n value_display = param.value.toFixed(2)\n }\n\n html += `<div style=\"color: #888;\">${name}:</div>`\n html += `<div style=\"color: ${color}; font-weight: bold;\">${value_display}</div>`\n })\n\n html += \"</div>\"\n panel.innerHTML = html\n }\n\n public toggle_visibility(): void {\n this.is_visible = !this.is_visible\n this.container.style.display = this.is_visible ? \"block\" : \"none\"\n }\n\n public show(): void {\n this.is_visible = true\n this.container.style.display = \"block\"\n // Re-run layout now that container is visible and has proper dimensions\n this.update_canvas_size()\n if (this.animator) {\n this.node_positions.clear()\n this.auto_layout_complete = false\n this.auto_layout_nodes()\n }\n this.render()\n }\n\n public hide(): void {\n this.is_visible = false\n this.container.style.display = \"none\"\n }\n\n public destroy(): void {\n if (this.animation_frame_id !== null) {\n cancelAnimationFrame(this.animation_frame_id)\n }\n if (this.container.parentNode) {\n this.container.parentNode.removeChild(this.container)\n }\n }\n}\n","import { Component } from \"@engine/core/GameObject\"\nimport Animatrix, { ParameterType } from \"./animatrix\"\nimport AnimatrixVisualizer from \"./visualizer\"\n\n/**\n * Simplified component wrapper for Animatrix animation visualization\n * Note: For actual animation playback, use AnimationGraphComponent which uses SharedAnimationManager\n */\nexport class AnimationControllerComponent extends Component {\n private static instances: Set<AnimationControllerComponent> = new Set()\n private static sharedVisualizer: AnimatrixVisualizer | null = null\n private static debugViewEnabled: boolean = false\n\n private animator: Animatrix | null = null\n private debug: boolean = false\n\n constructor(debug: boolean = false) {\n super()\n this.debug = debug\n }\n\n public static setDebugViewEnabled(enabled: boolean): void {\n AnimationControllerComponent.debugViewEnabled = enabled\n\n if (enabled) {\n if (!AnimationControllerComponent.sharedVisualizer) {\n AnimationControllerComponent.sharedVisualizer = new AnimatrixVisualizer()\n AnimationControllerComponent.sharedVisualizer.hide()\n }\n\n for (const instance of AnimationControllerComponent.instances) {\n if (instance.animator) {\n const name =\n instance.gameObject?.name || `animator_${AnimationControllerComponent.instances.size}`\n AnimationControllerComponent.sharedVisualizer.add_animator(name, instance.animator)\n }\n }\n\n AnimationControllerComponent.sharedVisualizer.show()\n } else {\n if (AnimationControllerComponent.sharedVisualizer) {\n AnimationControllerComponent.sharedVisualizer.hide()\n }\n }\n }\n\n public static isDebugViewEnabled(): boolean {\n return AnimationControllerComponent.debugViewEnabled\n }\n\n public getAnimator(): Animatrix | null {\n return this.animator\n }\n\n public addParameter(name: string, type: ParameterType, initialValue?: any): void {\n this.animator?.add_parameter(name, type, initialValue)\n }\n\n public setBool(name: string, value: boolean): void {\n this.animator?.set_bool(name, value)\n }\n\n public setFloat(name: string, value: number): void {\n this.animator?.set_float(name, value)\n }\n\n public setInt(name: string, value: number): void {\n this.animator?.set_int(name, value)\n }\n\n public setState(stateId: string): boolean {\n this.animator?.set_state(stateId)\n return true\n }\n\n public getCurrentState(): string | null {\n return this.animator?.get_current_state() ?? null\n }\n\n public stopAll(): void {\n this.animator?.stop_all()\n }\n\n protected onCreate(): void {\n AnimationControllerComponent.instances.add(this)\n this.animator = new Animatrix()\n\n if (\n AnimationControllerComponent.debugViewEnabled &&\n AnimationControllerComponent.sharedVisualizer\n ) {\n const name =\n this.gameObject?.name || `animator_${AnimationControllerComponent.instances.size}`\n AnimationControllerComponent.sharedVisualizer.add_animator(name, this.animator)\n }\n }\n\n protected onCleanup(): void {\n AnimationControllerComponent.instances.delete(this)\n\n if (AnimationControllerComponent.sharedVisualizer && this.animator) {\n const name = this.gameObject?.name || \"unknown\"\n AnimationControllerComponent.sharedVisualizer.remove_animator(name)\n }\n\n if (this.animator) {\n this.animator.stop_all()\n }\n }\n\n public update(deltaTime: number): void {\n if (this.animator && this.gameObject.isEnabled()) {\n this.animator.update(deltaTime)\n }\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"@engine/core/GameObject\"\nimport { AnimationLibrary } from \"./animation-library\"\n\n/**\n * Component for managing animation library functionality\n * Provides centralized animation loading and caching as a component\n */\nexport class AnimationLibraryComponent extends Component {\n private loadedAnimations: Set<string> = new Set()\n private debug: boolean = false\n\n constructor(debug: boolean = false) {\n super()\n this.debug = debug\n }\n\n /**\n * Load a single animation and add it to the library\n */\n public async loadAnimation(id: string, path: string): Promise<THREE.AnimationClip> {\n try {\n const clip = await AnimationLibrary.loadAnimation(id, path)\n this.loadedAnimations.add(id)\n\n if (this.debug) {\n console.log(`[AnimationLibraryComponent] Loaded animation: ${id} from ${path}`)\n }\n\n return clip\n } catch (error) {\n console.error(\n `[AnimationLibraryComponent] Failed to load animation ${id} from ${path}:`,\n error\n )\n throw error\n }\n }\n\n /**\n * Load multiple animations in parallel\n */\n public async loadAnimations(paths: { [id: string]: string }): Promise<void> {\n try {\n await AnimationLibrary.loadAnimations(paths)\n\n // Track loaded animations\n Object.keys(paths).forEach((id) => this.loadedAnimations.add(id))\n\n if (this.debug) {\n console.log(\n `[AnimationLibraryComponent] Loaded ${Object.keys(paths).length} animations:`,\n Object.keys(paths)\n )\n }\n } catch (error) {\n console.error(`[AnimationLibraryComponent] Failed to load animations:`, error)\n throw error\n }\n }\n\n /**\n * Get an animation clip from the library\n */\n public getClip(id: string): THREE.AnimationClip | undefined {\n return AnimationLibrary.getClip(id)\n }\n\n /**\n * Get a cloned copy of an animation clip\n */\n public cloneClip(id: string): THREE.AnimationClip | undefined {\n return AnimationLibrary.cloneClip(id)\n }\n\n /**\n * Check if an animation is loaded in the library\n */\n public hasClip(id: string): boolean {\n return AnimationLibrary.hasClip(id)\n }\n\n /**\n * Get all loaded animations\n */\n public getAllClips(): Map<string, THREE.AnimationClip> {\n return AnimationLibrary.getAllClips()\n }\n\n /**\n * Get list of animations loaded by this component instance\n */\n public getLoadedAnimationIds(): string[] {\n return Array.from(this.loadedAnimations)\n }\n\n /**\n * Set debug mode for the animation library\n */\n public setDebug(enabled: boolean): void {\n this.debug = enabled\n AnimationLibrary.setDebug(enabled)\n }\n\n // ========== Component Lifecycle ==========\n\n protected onCreate(): void {\n if (this.debug) {\n console.log(`[AnimationLibraryComponent] Component created on ${this.gameObject.name}`)\n }\n }\n\n protected onCleanup(): void {\n // Note: We don't clear the global AnimationLibrary on cleanup since other objects might be using it\n // The global library persists across component instances\n\n if (this.debug) {\n console.log(\n `[AnimationLibraryComponent] Component cleaned up on ${this.gameObject.name}. Animations remain in global library.`\n )\n }\n }\n\n public onEnabled(): void {\n if (this.debug) {\n console.log(`[AnimationLibraryComponent] Component enabled on ${this.gameObject.name}`)\n }\n }\n\n public onDisabled(): void {\n if (this.debug) {\n console.log(`[AnimationLibraryComponent] Component disabled on ${this.gameObject.name}`)\n }\n }\n\n // ========== Utility Methods ==========\n\n /**\n * Preload a standard set of character animations\n * Useful for common character animation setups\n */\n public async preloadCharacterAnimations(basePath: string = \"assets/characters/\"): Promise<void> {\n const standardAnimations = {\n idle: `${basePath}anim_idle.fbx`,\n walk: `${basePath}anim_walk.fbx`,\n sitting_eating: `${basePath}anim_sitting_eating.fbx`,\n carry_idle: `${basePath}anim_carry_idle.fbx`,\n carry_walk: `${basePath}anim_carry_walking.fbx`,\n }\n\n await this.loadAnimations(standardAnimations)\n }\n\n /**\n * Check if all required animations are loaded\n */\n public hasAllAnimations(requiredIds: string[]): boolean {\n return requiredIds.every((id) => this.hasClip(id))\n }\n\n /**\n * Get missing animations from a required list\n */\n public getMissingAnimations(requiredIds: string[]): string[] {\n return requiredIds.filter((id) => !this.hasClip(id))\n }\n}\n","import { Component } from \"@engine/core/GameObject\"\nimport { AnimationControllerComponent } from \"./AnimationControllerComponent\"\nimport AnimatrixVisualizer from \"./visualizer\"\n\n/**\n * Component for visualizing animation state machines\n * Provides debug visualization functionality as a component\n */\nexport class AnimationVisualizerComponent extends Component {\n private visualizer: AnimatrixVisualizer | null = null\n private animationController: AnimationControllerComponent | null = null\n private name: string\n\n constructor(name?: string) {\n super()\n this.name = name || `visualizer_${Date.now()}`\n }\n\n /**\n * Set the animation controller to visualize\n */\n public setAnimationController(controller: AnimationControllerComponent): void {\n this.animationController = controller\n\n const animator = controller.getAnimator()\n if (animator) {\n if (this.visualizer) {\n // Update existing visualizer\n this.visualizer.add_animator(this.name, animator)\n this.visualizer.set_animator(this.name)\n } else {\n // Create new visualizer\n this.visualizer = new AnimatrixVisualizer(animator, this.name)\n // Hide by default - can be shown via debug panel\n this.visualizer.hide()\n }\n }\n }\n\n /**\n * Get the underlying visualizer instance\n */\n public getVisualizer(): AnimatrixVisualizer | null {\n return this.visualizer\n }\n\n /**\n * Show the visualizer UI\n */\n public show(): void {\n this.visualizer?.show()\n }\n\n /**\n * Hide the visualizer UI\n */\n public hide(): void {\n this.visualizer?.hide()\n }\n\n /**\n * Toggle visualizer visibility\n */\n public toggleVisibility(): void {\n this.visualizer?.toggle_visibility()\n }\n\n /**\n * Check if visualizer is currently visible\n */\n public isVisible(): boolean {\n // We can't directly check visibility from the current API, so we assume it's visible if it exists\n return this.visualizer !== null\n }\n\n /**\n * Destroy the visualizer UI\n */\n public destroyVisualizer(): void {\n if (this.visualizer) {\n this.visualizer.destroy()\n this.visualizer = null\n }\n }\n\n // ========== Component Lifecycle ==========\n\n protected onCreate(): void {\n // Try to automatically find an AnimationControllerComponent on the same GameObject\n const controller = this.getComponent(AnimationControllerComponent)\n if (controller) {\n this.setAnimationController(controller)\n console.log(\n `[AnimationVisualizerComponent] Auto-connected to AnimationController on ${this.gameObject.name}`\n )\n } else {\n console.log(\n `[AnimationVisualizerComponent] Component created on ${this.gameObject.name} - waiting for animation controller`\n )\n }\n }\n\n protected onCleanup(): void {\n this.destroyVisualizer()\n console.log(`[AnimationVisualizerComponent] Component cleaned up on ${this.gameObject.name}`)\n }\n\n public onEnabled(): void {\n // Don't automatically show visualizer when component is enabled\n // Let it be controlled manually via debug panel\n // this.show()\n }\n\n public onDisabled(): void {\n // Hide visualizer when component is disabled\n this.hide()\n }\n\n // ========== Utility Methods ==========\n\n /**\n * Auto-setup: find an AnimationControllerComponent on the same GameObject and connect to it\n */\n public autoConnectToController(): boolean {\n const controller = this.getComponent(AnimationControllerComponent)\n if (controller) {\n this.setAnimationController(controller)\n console.log(`[AnimationVisualizerComponent] Successfully connected to AnimationController`)\n return true\n }\n\n console.warn(\n `[AnimationVisualizerComponent] No AnimationControllerComponent found on ${this.gameObject.name}`\n )\n return false\n }\n\n /**\n * Connect to a specific animation controller component from another GameObject\n */\n public connectToController(controller: AnimationControllerComponent): void {\n this.setAnimationController(controller)\n console.log(`[AnimationVisualizerComponent] Connected to external AnimationController`)\n }\n}\n","/**\n * Console filter stub - kept for backwards compatibility\n * Filtering is no longer needed as animations are pre-cleaned\n */\nexport class AnimationConsoleFilter {\n private static isFilterActive = false\n\n /**\n * Enable filtering of PropertyBinding warnings for missing animation targets\n * NOTE: This is no longer needed as we're pre-cleaning animations\n */\n public static enable(): void {\n if (this.isFilterActive) return\n this.isFilterActive = true\n }\n\n /**\n * Disable the console filter\n */\n public static disable(): void {\n this.isFilterActive = false\n }\n\n /**\n * Check if the filter is currently active\n */\n public static isActive(): boolean {\n return this.isFilterActive\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Simple performance utilities for the animation system\n * Focuses on reducing skin influences and cleaning up animation tracks\n */\nexport class AnimationPerformance {\n /**\n * Reduce the number of bone influences per vertex for better mobile performance\n * @param skinnedMesh The skinned mesh to optimize\n * @param maxInfluences Maximum number of bone influences per vertex (default 2)\n */\n public static reduceSkinInfluences(\n skinnedMesh: THREE.SkinnedMesh,\n maxInfluences: number = 2\n ): void {\n const geometry = skinnedMesh.geometry\n\n // Check if this is a BufferGeometry with skinning attributes\n if (!geometry.attributes.skinIndex || !geometry.attributes.skinWeight) {\n return\n }\n\n const skinIndices = geometry.attributes.skinIndex.array as Float32Array\n const skinWeights = geometry.attributes.skinWeight.array as Float32Array\n\n // Process each vertex\n const vertexCount = skinIndices.length / 4 // 4 influences per vertex by default\n\n for (let i = 0; i < vertexCount; i++) {\n const offset = i * 4\n\n // Collect all influences for this vertex\n const influences: { index: number; weight: number }[] = []\n for (let j = 0; j < 4; j++) {\n if (skinWeights[offset + j] > 0) {\n influences.push({\n index: skinIndices[offset + j],\n weight: skinWeights[offset + j],\n })\n }\n }\n\n // Sort by weight (highest first)\n influences.sort((a, b) => b.weight - a.weight)\n\n // Keep only the top N influences and renormalize\n const kept = influences.slice(0, maxInfluences)\n const totalWeight = kept.reduce((sum, inf) => sum + inf.weight, 0)\n\n // Clear all influences first\n for (let j = 0; j < 4; j++) {\n skinIndices[offset + j] = 0\n skinWeights[offset + j] = 0\n }\n\n // Set the kept influences with normalized weights\n kept.forEach((inf, idx) => {\n skinIndices[offset + idx] = inf.index\n skinWeights[offset + idx] = totalWeight > 0 ? inf.weight / totalWeight : 0\n })\n }\n\n // Mark attributes as needing update\n geometry.attributes.skinIndex.needsUpdate = true\n geometry.attributes.skinWeight.needsUpdate = true\n }\n\n /**\n * Clean up animation clip by removing tracks for non-bone objects\n * This prevents PropertyBinding warnings and improves performance\n * Removes tracks for accessories, hair, hats, etc that are mesh names not bones\n *\n * IMPORTANT: Returns a NEW clip, does not modify the original\n */\n public static cleanAnimationClip(\n clip: THREE.AnimationClip,\n model: THREE.Object3D,\n silent: boolean = true\n ): THREE.AnimationClip {\n const validTracks: THREE.KeyframeTrack[] = []\n const removedTracks: string[] = []\n const originalTrackCount = clip.tracks.length\n\n // Find the skeleton/bones in the model\n let skeleton: THREE.Skeleton | null = null\n let bones: THREE.Bone[] = []\n model.traverse((child) => {\n if (child instanceof THREE.SkinnedMesh && child.skeleton) {\n skeleton = child.skeleton\n bones = skeleton.bones\n }\n })\n\n // Create a set of valid bone names for fast lookup\n const validBoneNames = new Set<string>()\n bones.forEach((bone) => validBoneNames.add(bone.name))\n\n // Also check for objects in the model hierarchy (for non-skeletal animations)\n const validObjectNames = new Set<string>()\n model.traverse((child) => {\n if (child.name) {\n validObjectNames.add(child.name)\n }\n })\n\n for (const track of clip.tracks) {\n // Extract the object name from the track name\n // Track names are like \"boneName.position\" or \"fullBody_Toes.quaternion\"\n const parts = track.name.split(\".\")\n if (parts.length < 2) {\n // Keep tracks without proper naming (shouldn't happen but be safe)\n validTracks.push(track.clone())\n continue\n }\n\n const objectName = parts[0]\n\n // Filter out known non-bone prefixes that are causing issues\n const isAccessory =\n objectName.includes(\"hair_\") ||\n objectName.includes(\"hat_\") ||\n objectName.includes(\"face_accessory_\") ||\n objectName === \"fullBody_Toes\" // This seems to be a mesh name, not a bone\n\n if (isAccessory) {\n removedTracks.push(track.name)\n continue\n }\n\n // Check if this is a valid bone or object in the model\n if (validBoneNames.has(objectName) || validObjectNames.has(objectName)) {\n validTracks.push(track.clone())\n } else {\n removedTracks.push(track.name)\n }\n }\n\n // Log what we're removing in development\n if (!silent && removedTracks.length > 0) {\n console.log(\n `[AnimationPerformance] Removed ${removedTracks.length}/${originalTrackCount} non-bone tracks from clip \"${clip.name || \"unnamed\"}\"`\n )\n if (process.env.NODE_ENV !== \"production\") {\n const uniqueObjects = [...new Set(removedTracks.map((t) => t.split(\".\")[0]))]\n console.log(\"[AnimationPerformance] Removed objects:\", uniqueObjects)\n }\n }\n\n // Create a NEW clip with the valid tracks - never modify the original\n const cleanedClip = new THREE.AnimationClip(\n clip.name,\n clip.duration,\n validTracks,\n clip.blendMode\n )\n\n return cleanedClip\n }\n\n /**\n * Process all skinned meshes in a model to reduce influences\n */\n public static optimizeModelForMobile(model: THREE.Object3D, maxInfluences: number = 2): void {\n model.traverse((child) => {\n if (child instanceof THREE.SkinnedMesh) {\n this.reduceSkinInfluences(child, maxInfluences)\n }\n })\n }\n\n /**\n * Clean all animation clips in a mixer to remove missing bone tracks\n */\n public static cleanMixerAnimations(mixer: THREE.AnimationMixer, model: THREE.Object3D): void {\n // Get all actions from the mixer\n const actions = (mixer as any)._actions as THREE.AnimationAction[]\n\n if (!actions) return\n\n for (const action of actions) {\n const originalClip = action.getClip()\n const cleanedClip = this.cleanAnimationClip(originalClip, model)\n\n // If the clip was modified, we need to recreate the action\n if (cleanedClip.tracks.length !== originalClip.tracks.length) {\n // Stop the current action\n action.stop()\n\n // Create a new action with the cleaned clip\n const newAction = mixer.clipAction(cleanedClip)\n\n // Copy settings from the original action\n newAction.loop = action.loop\n newAction.repetitions = action.repetitions\n newAction.clampWhenFinished = action.clampWhenFinished\n newAction.timeScale = action.timeScale\n\n // If the original was playing, start the new one\n if (action.isRunning()) {\n newAction.play()\n newAction.time = action.time\n }\n }\n }\n }\n\n /**\n * Check if running on a mobile device\n */\n public static isMobile(): boolean {\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(\n navigator.userAgent\n )\n }\n\n /**\n * Get recommended settings based on platform\n */\n public static getRecommendedSettings(): {\n maxSkinInfluences: number\n enableDebugLogs: boolean\n } {\n const isMobile = this.isMobile()\n\n return {\n maxSkinInfluences: isMobile ? 2 : 4,\n enableDebugLogs: !isMobile && process.env.NODE_ENV !== \"production\",\n }\n }\n}\n","import * as THREE from \"three\"\nimport { SplineDebugManager, SplineDebugConfig } from \"./SplineDebugManager\"\n\nexport interface SplinePointThree {\n position: THREE.Vector3\n index: number\n}\n\nexport interface SplineSegmentThree {\n startPoint: SplinePointThree\n endPoint: SplinePointThree\n length: number\n}\n\nexport enum SplineTypeThree {\n LINEAR = \"linear\",\n CATMULL_ROM = \"catmull_rom\",\n BEZIER = \"bezier\",\n}\n\nexport interface SplineConfigThree {\n type: SplineTypeThree\n resolution: number // Number of interpolated points per segment\n tension?: number // For Catmull-Rom splines (0-1)\n closed?: boolean // Whether the spline is a closed loop\n}\n\n/**\n * A flexible spline system for Three.js that can create smooth curves through waypoints\n */\nexport class SplineThree {\n private waypoints: THREE.Vector3[] = []\n private config: SplineConfigThree\n private interpolatedPoints: THREE.Vector3[] = []\n private segments: SplineSegmentThree[] = []\n private totalLength: number = 0\n private cumulativeDistances: number[] = [] // Distance from start to each interpolated point\n private debugEnabled: boolean = false\n private debugConfig: SplineDebugConfig | undefined\n\n constructor(\n config: SplineConfigThree = {\n type: SplineTypeThree.CATMULL_ROM,\n resolution: 10,\n tension: 0.5,\n closed: false,\n }\n ) {\n this.config = config\n\n // Auto-register with debug manager\n SplineDebugManager.getInstance().registerSpline(this)\n }\n\n /**\n * Set the waypoints for the spline\n */\n public setWaypoints(waypoints: THREE.Vector3[]): void {\n this.waypoints = waypoints.map((p) => p.clone())\n this.generateSpline()\n }\n\n /**\n * Get a point along the spline at parameter t (0-1)\n */\n public getPointAt(t: number): THREE.Vector3 {\n t = Math.max(0, Math.min(1, t))\n\n if (this.interpolatedPoints.length === 0) {\n return new THREE.Vector3()\n }\n\n if (t === 0) return this.interpolatedPoints[0].clone()\n if (t === 1) return this.interpolatedPoints[this.interpolatedPoints.length - 1].clone()\n\n const index = t * (this.interpolatedPoints.length - 1)\n const lowerIndex = Math.floor(index)\n const upperIndex = Math.ceil(index)\n const factor = index - lowerIndex\n\n if (lowerIndex === upperIndex) {\n return this.interpolatedPoints[lowerIndex].clone()\n }\n\n const p1 = this.interpolatedPoints[lowerIndex]\n const p2 = this.interpolatedPoints[upperIndex]\n\n return p1.clone().lerp(p2, factor)\n }\n\n /**\n * Get the direction (tangent) at parameter t (0-1)\n */\n public getDirectionAt(t: number): THREE.Vector3 {\n const epsilon = 0.001\n const t1 = Math.max(0, t - epsilon)\n const t2 = Math.min(1, t + epsilon)\n\n const p1 = this.getPointAt(t1)\n const p2 = this.getPointAt(t2)\n\n return p2.sub(p1).normalize()\n }\n\n /**\n * Convert a distance along the spline to a t parameter (0-1)\n * Uses the cumulative distance lookup table for accurate distance-based parameterization\n */\n private getTFromDistance(distance: number): number {\n if (this.totalLength === 0 || this.cumulativeDistances.length === 0) {\n return 0\n }\n\n // Clamp distance to valid range\n distance = Math.max(0, Math.min(this.totalLength, distance))\n\n // Handle edge cases\n if (distance === 0) return 0\n if (distance >= this.totalLength) return 1\n\n // Find the segment that contains this distance using binary search\n let left = 0\n let right = this.cumulativeDistances.length - 1\n\n while (left < right - 1) {\n const mid = Math.floor((left + right) / 2)\n if (this.cumulativeDistances[mid] <= distance) {\n left = mid\n } else {\n right = mid\n }\n }\n\n // Interpolate between the two points\n const startDistance = this.cumulativeDistances[left]\n const endDistance = this.cumulativeDistances[right]\n const segmentDistance = endDistance - startDistance\n\n if (segmentDistance === 0) {\n return left / (this.interpolatedPoints.length - 1)\n }\n\n const localT = (distance - startDistance) / segmentDistance\n const pointIndexT = (left + localT) / (this.interpolatedPoints.length - 1)\n\n return pointIndexT\n }\n\n /**\n * Get a point at a specific distance from the start\n * This now uses proper distance-based parameterization\n */\n public getPointAtDistance(distance: number): THREE.Vector3 {\n if (this.totalLength === 0) return new THREE.Vector3()\n\n const t = this.getTFromDistance(distance)\n return this.getPointAt(t)\n }\n\n /**\n * Get the direction (tangent) at a specific distance from the start\n * This now uses proper distance-based parameterization\n */\n public getDirectionAtDistance(distance: number): THREE.Vector3 {\n if (this.totalLength === 0) return new THREE.Vector3(0, 0, 1)\n\n const t = this.getTFromDistance(distance)\n return this.getDirectionAt(t)\n }\n\n /**\n * Find the closest point on the spline to a given position\n */\n public getClosestPoint(position: THREE.Vector3): {\n point: THREE.Vector3\n t: number\n distance: number\n } {\n let closestPoint = new THREE.Vector3()\n let closestT = 0\n let closestDistance = Infinity\n\n // Sample the spline at regular intervals\n const samples = 100\n for (let i = 0; i <= samples; i++) {\n const t = i / samples\n const point = this.getPointAt(t)\n const distance = position.distanceTo(point)\n\n if (distance < closestDistance) {\n closestDistance = distance\n closestPoint = point\n closestT = t\n }\n }\n\n return {\n point: closestPoint,\n t: closestT,\n distance: closestDistance,\n }\n }\n\n /**\n * Get the total length of the spline\n */\n public getTotalLength(): number {\n return this.totalLength\n }\n\n /**\n * Get all interpolated points\n */\n public getInterpolatedPoints(): THREE.Vector3[] {\n return this.interpolatedPoints.map((p) => p.clone())\n }\n\n /**\n * Get the original waypoints (not interpolated points)\n */\n public getWaypoints(): THREE.Vector3[] {\n return this.waypoints.map((p) => p.clone())\n }\n\n /**\n * Get the segments of the spline\n */\n public getSegments(): SplineSegmentThree[] {\n return this.segments\n }\n\n /**\n * Position a GameObject at parameter t along the spline with proper rotation\n */\n public setGameObjectAt(gameObject: any, t: number): void {\n const position = this.getPointAt(t)\n const direction = this.getDirectionAt(t)\n\n // Set position\n gameObject.position.copy(position)\n\n // Set rotation to face along the spline direction\n if (direction.length() > 0.001) {\n const angle = Math.atan2(direction.x, direction.z)\n gameObject.rotation.set(0, angle, 0)\n }\n }\n\n /**\n * Generate the spline interpolation\n */\n private generateSpline(): void {\n if (this.waypoints.length < 2) {\n this.interpolatedPoints = []\n this.segments = []\n this.totalLength = 0\n return\n }\n\n this.interpolatedPoints = []\n this.segments = []\n\n switch (this.config.type) {\n case SplineTypeThree.LINEAR:\n this.generateLinearSpline()\n break\n case SplineTypeThree.CATMULL_ROM:\n this.generateCatmullRomSpline()\n break\n case SplineTypeThree.BEZIER:\n this.generateBezierSpline()\n break\n }\n\n this.calculateSegments()\n this.calculateTotalLength()\n }\n\n /**\n * Generate linear interpolation between waypoints\n */\n private generateLinearSpline(): void {\n for (let i = 0; i < this.waypoints.length - 1; i++) {\n const start = this.waypoints[i]\n const end = this.waypoints[i + 1]\n\n for (let j = 0; j < this.config.resolution; j++) {\n const t = j / this.config.resolution\n const point = start.clone().lerp(end, t)\n this.interpolatedPoints.push(point)\n }\n }\n\n // Add final point\n this.interpolatedPoints.push(this.waypoints[this.waypoints.length - 1].clone())\n }\n\n /**\n * Generate Catmull-Rom spline interpolation\n */\n private generateCatmullRomSpline(): void {\n const tension = this.config.tension || 0.5\n\n for (let i = 0; i < this.waypoints.length - 1; i++) {\n const p0 = i > 0 ? this.waypoints[i - 1] : this.waypoints[i]\n const p1 = this.waypoints[i]\n const p2 = this.waypoints[i + 1]\n const p3 = i < this.waypoints.length - 2 ? this.waypoints[i + 2] : this.waypoints[i + 1]\n\n for (let j = 0; j < this.config.resolution; j++) {\n const t = j / this.config.resolution\n const point = this.catmullRomInterpolate(p0, p1, p2, p3, t, tension)\n this.interpolatedPoints.push(point)\n }\n }\n\n // Add final point\n this.interpolatedPoints.push(this.waypoints[this.waypoints.length - 1].clone())\n }\n\n /**\n * Catmull-Rom interpolation function\n */\n private catmullRomInterpolate(\n p0: THREE.Vector3,\n p1: THREE.Vector3,\n p2: THREE.Vector3,\n p3: THREE.Vector3,\n t: number,\n tension: number\n ): THREE.Vector3 {\n const t2 = t * t\n const t3 = t2 * t\n\n // Calculate tangent vectors (same as Babylon.js)\n const v0 = p2.clone().sub(p0).multiplyScalar(tension)\n const v1 = p3.clone().sub(p1).multiplyScalar(tension)\n\n // Use the same formula as Babylon.js for correct Catmull-Rom interpolation\n return p1\n .clone()\n .multiplyScalar(1 + 2 * t3 - 3 * t2)\n .add(p2.clone().multiplyScalar(3 * t2 - 2 * t3))\n .add(v0.clone().multiplyScalar(t3 - 2 * t2 + t))\n .add(v1.clone().multiplyScalar(t3 - t2))\n }\n\n /**\n * Generate Bezier spline (simplified - using quadratic Bezier)\n */\n private generateBezierSpline(): void {\n for (let i = 0; i < this.waypoints.length - 1; i++) {\n const start = this.waypoints[i]\n const end = this.waypoints[i + 1]\n const control = start.clone().lerp(end, 0.5)\n\n for (let j = 0; j < this.config.resolution; j++) {\n const t = j / this.config.resolution\n const point = this.quadraticBezier(start, control, end, t)\n this.interpolatedPoints.push(point)\n }\n }\n\n // Add final point\n this.interpolatedPoints.push(this.waypoints[this.waypoints.length - 1].clone())\n }\n\n /**\n * Quadratic Bezier interpolation\n */\n private quadraticBezier(\n p0: THREE.Vector3,\n p1: THREE.Vector3,\n p2: THREE.Vector3,\n t: number\n ): THREE.Vector3 {\n const oneMinusT = 1 - t\n\n return p0\n .clone()\n .multiplyScalar(oneMinusT * oneMinusT)\n .add(p1.clone().multiplyScalar(2 * oneMinusT * t))\n .add(p2.clone().multiplyScalar(t * t))\n }\n\n /**\n * Calculate segments between interpolated points\n */\n private calculateSegments(): void {\n this.segments = []\n\n for (let i = 0; i < this.interpolatedPoints.length - 1; i++) {\n const startPoint: SplinePointThree = {\n position: this.interpolatedPoints[i],\n index: i,\n }\n\n const endPoint: SplinePointThree = {\n position: this.interpolatedPoints[i + 1],\n index: i + 1,\n }\n\n const length = startPoint.position.distanceTo(endPoint.position)\n\n this.segments.push({\n startPoint,\n endPoint,\n length,\n })\n }\n }\n\n /**\n * Calculate total length of the spline and build cumulative distance lookup table\n */\n private calculateTotalLength(): void {\n this.cumulativeDistances = []\n this.totalLength = 0\n\n // First point is at distance 0\n if (this.interpolatedPoints.length > 0) {\n this.cumulativeDistances.push(0)\n }\n\n // Build cumulative distance array\n for (let i = 0; i < this.segments.length; i++) {\n this.totalLength += this.segments[i].length\n this.cumulativeDistances.push(this.totalLength)\n }\n }\n\n /**\n * Enable debug visualization for this spline\n */\n public enableDebug(config?: SplineDebugConfig): void {\n this.debugEnabled = true\n if (config) {\n this.debugConfig = config\n SplineDebugManager.getInstance().registerSpline(this, config)\n }\n }\n\n /**\n * Disable debug visualization for this spline\n */\n public disableDebug(): void {\n this.debugEnabled = false\n }\n\n /**\n * Check if debug is enabled for this spline\n */\n public isDebugEnabled(): boolean {\n return this.debugEnabled\n }\n\n /**\n * Get the debug configuration for this spline\n */\n public getDebugConfig(): SplineDebugConfig | undefined {\n return this.debugConfig\n }\n\n /**\n * Dispose of the spline and unregister from debug manager\n */\n public dispose(): void {\n SplineDebugManager.getInstance().unregisterSpline(this)\n }\n}\n"],"mappings":"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;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC5F;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAG;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC3F;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAG;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAC3F;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAG;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC5F;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC5F;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAC1F;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAG;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC3F;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAI;AAAA,IAAK;AAAA,EACxB;AACA,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,SAAK,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,EAAE,CAAC;AAC7B,cAAU,CAAC,IAAI,UAAU,IAAI,GAAG,IAAI,EAAE,CAAC,IAAI;AAAA,EAC7C;AACF,GAAG;AAGH,IAAM,QAAQ;AAAA,EACZ,CAAC,GAAG,GAAG,CAAC;AAAA,EACR,CAAC,IAAI,GAAG,CAAC;AAAA,EACT,CAAC,GAAG,IAAI,CAAC;AAAA,EACT,CAAC,IAAI,IAAI,CAAC;AAAA,EACV,CAAC,GAAG,GAAG,CAAC;AAAA,EACR,CAAC,IAAI,GAAG,CAAC;AAAA,EACT,CAAC,GAAG,GAAG,EAAE;AAAA,EACT,CAAC,IAAI,GAAG,EAAE;AAAA,EACV,CAAC,GAAG,GAAG,CAAC;AAAA,EACR,CAAC,GAAG,IAAI,CAAC;AAAA,EACT,CAAC,GAAG,GAAG,EAAE;AAAA,EACT,CAAC,GAAG,IAAI,EAAE;AACZ;AAGA,IAAM,KAAK,OAAO,KAAK,KAAK,CAAC,IAAI;AACjC,IAAM,MAAM,IAAI,KAAK,KAAK,CAAC,KAAK;AAChC,IAAM,KAAK,IAAI;AACf,IAAM,KAAK,IAAI;AAKf,SAAS,UAAU,GAAW,GAAmB;AAE/C,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,IAAI,KAAK,MAAM,IAAI,CAAC;AAC1B,QAAM,IAAI,KAAK,MAAM,IAAI,CAAC;AAG1B,QAAM,KAAK,IAAI,KAAK;AACpB,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AAGf,MAAI,IAAY;AAChB,MAAI,KAAK,IAAI;AACX,SAAK;AACL,SAAK;AAAA,EACP,OAAO;AACL,SAAK;AACL,SAAK;AAAA,EACP;AAEA,QAAM,KAAK,KAAK,KAAK;AACrB,QAAM,KAAK,KAAK,KAAK;AACrB,QAAM,KAAK,KAAK,IAAI,IAAI;AACxB,QAAM,KAAK,KAAK,IAAI,IAAI;AAGxB,QAAM,KAAK,IAAI;AACf,QAAM,KAAK,IAAI;AACf,QAAM,MAAM,UAAU,KAAK,KAAK,EAAE,CAAC;AACnC,QAAM,MAAM,UAAU,KAAK,KAAK,KAAK,KAAK,EAAE,CAAC;AAC7C,QAAM,MAAM,UAAU,KAAK,IAAI,KAAK,KAAK,CAAC,CAAC;AAG3C,MAAI,KAAK,GACP,KAAK,GACL,KAAK;AAEP,MAAI,KAAK,MAAM,KAAK,KAAK,KAAK;AAC9B,MAAI,MAAM,GAAG;AACX,UAAM;AACN,SAAK,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,MAAM,GAAG,EAAE,CAAC,IAAI;AAAA,EACvD;AAEA,MAAI,KAAK,MAAM,KAAK,KAAK,KAAK;AAC9B,MAAI,MAAM,GAAG;AACX,UAAM;AACN,SAAK,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,MAAM,GAAG,EAAE,CAAC,IAAI;AAAA,EACvD;AAEA,MAAI,KAAK,MAAM,KAAK,KAAK,KAAK;AAC9B,MAAI,MAAM,GAAG;AACX,UAAM;AACN,SAAK,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK,MAAM,GAAG,EAAE,CAAC,IAAI;AAAA,EACvD;AAGA,SAAO,MAAM,KAAK,KAAK;AACzB;AAiIA,SAAS,MAAM,GAAW,GAAW,SAAyB;AAC5D,MAAI,QAAQ;AACZ,MAAI,YAAY;AAChB,MAAI,YAAY;AAChB,MAAI,WAAW;AAEf,WAAS,IAAI,GAAG,IAAI,SAAS,KAAK;AAChC,aAAS,YAAY,UAAU,IAAI,WAAW,IAAI,SAAS;AAC3D,gBAAY;AACZ,iBAAa;AACb,iBAAa;AAAA,EACf;AAEA,SAAO,QAAQ;AACjB;AAkBO,IAAM,eAAe;AAAA,EAC1B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AACT;AAkIO,SAAS,sBACd,MAAqB,CAAC,GACtB,SAAwB,CAAC,GACT;AAChB,MAAI,YAAY,EAAE,GAAI,IAAI,aAAa,CAAC,EAAG;AAC3C,MAAI,YAAY,EAAE,GAAI,IAAI,aAAa,CAAC,EAAG;AAC3C,QAAM,gBAAgB,IAAI,gBAAgB;AAC1C,QAAM,oBAAoB;AAC1B,QAAM,YAAY;AAClB,QAAM,YAAY;AAClB,MAAI,sBAAsB,IAAI,WAAW,iBAAiB;AAE1D,QAAM,UAAU,OAAO,UACnB,OAAO,UACP,OAAO,aACL,IAAU,sBAAc,EAAE,KAAK,OAAO,UAAU,IAC/C,IAAY,aACX,IAAU,sBAAc,EAAE,KAAM,IAAY,UAAU,IACtD,IAAU,sBAAc,EAAE,KAAK,yBAAyB;AAChE,UAAQ,QAAQ;AAChB,UAAQ,QAAc;AACtB,UAAQ,QAAc;AACtB,UAAQ,YAAkB;AAC1B,UAAQ,YAAkB;AAC1B,UAAQ,kBAAkB;AAC1B,UAAQ,cAAc;AACtB,QAAM,WAAW,IAAU,0BAAkB;AAAA,IAC3C,UAAU;AAAA,MACR,KAAK,EAAE,OAAO,QAAQ;AAAA,MACtB,oBAAoB,EAAE,OAAO,IAAI,cAAc,IAAM,EAAI;AAAA,MACzD,YAAY;AAAA,QACV,OAAO,IAAU,gBAAQ,IAAI,aAAa,WAAW,GAAG,IAAI,aAAa,QAAQ,CAAC;AAAA,MACpF;AAAA,MACA,mBAAmB;AAAA,QACjB,OAAO,IAAI,cACN,IAAI,YAAY,eAChB,IAAI,YAAY,WAAW,MAAM,IAAI,YAAY,QAAQ,KAC1D;AAAA,MACN;AAAA,MACA,oBAAoB,EAAE,OAAO,EAAE;AAAA,MAC/B,mBAAmB,EAAE,OAAO,EAAI;AAAA,MAChC,WAAW,EAAE,OAAO,IAAU,gBAAQ,MAAO,IAAK,EAAE;AAAA,MACpD,sBAAsB;AAAA,QACpB,OAAQ,IAAI,qBAAqB,QAAS,IAAM;AAAA,MAClD;AAAA,IACF;AAAA,IACA,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAuBd,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IA+ChB,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU,IAAI,YAAkB;AAAA,IAChC,MAAY;AAAA,EACd,CAAC;AAEA,EAAC,SAAqC,qBAAqB,IAAI,sBAAsB;AAEtF,QAAM,WAAW,IAAU,sBAAc,GAAG,CAAC;AAC7C,QAAM,OAAO,IAAU,sBAAc,UAAU,UAAU,aAAa;AAEtE,QAAM,iBAAiB,IAAI,aAAa,gBAAgB,CAAC;AACzD,WAAS,IAAI,GAAG,IAAI,gBAAgB,GAAG,IAAK,gBAAe,CAAC,IAAI;AAChE,OAAK,gBAAgB,IAAU,iCAAyB,gBAAgB,CAAC;AAEzE,QAAM,kBAAkB,IAAI,aAAa,aAAa;AACtD,WAAS,aAAa,mBAAmB,IAAU,iCAAyB,iBAAiB,CAAC,CAAC;AAC/F,QAAM,gBAAgB,IAAI,aAAa,aAAa;AACpD,WAAS,aAAa,iBAAiB,IAAU,iCAAyB,eAAe,CAAC,CAAC;AAE3F,QAAM,YAAY,IAAI,aAAa,gBAAgB,CAAC;AACpD,QAAM,aAAa,IAAI,aAAa,gBAAgB,CAAC;AACrD,QAAM,OAAO,IAAI,aAAa,aAAa;AAC3C,QAAM,YAAY,IAAI,aAAa,aAAa;AAChD,QAAM,cAAc,IAAI,aAAa,aAAa;AAClD,QAAM,YAAY,IAAI,aAAa,aAAa;AAChD,QAAM,UAAU,IAAI,aAAa,aAAa;AAC9C,QAAM,YAAY,IAAI,aAAa,aAAa;AAChD,QAAM,eAAe,IAAI,aAAa,aAAa;AACnD,QAAM,cAAc,IAAI,aAAa,aAAa;AAClD,QAAM,SAAS,IAAI,aAAa,gBAAgB,CAAC;AACjD,QAAM,SAAS,IAAI,aAAa,gBAAgB,CAAC;AACjD,QAAM,SAAS,IAAI,aAAa,gBAAgB,CAAC;AACjD,QAAM,YAAY,IAAI,aAAa,gBAAgB,CAAC;AACpD,QAAM,YAAY,IAAI,WAAW,aAAa;AAG9C,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,MAAM,KAAK,CAAC,CAAC;AACvD,QAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,IAAI,MAAM,KAAK,CAAC,CAAC;AAGvD,QAAM,WAAW,IAAI,SAAS,CAAC;AAC/B,QAAM,eAAe,SAAS,WAAW;AACzC,QAAM,sBAAsB,SAAS,kBAAkB;AACvD,QAAM,sBAAsB,SAAS,kBAAkB;AACvD,QAAM,kBAAkB,SAAS,cAAc;AAC/C,QAAM,iBAAiB,SAAS,aAAa;AAC7C,QAAM,mBAAmB,SAAS,eAAe;AACjD,QAAM,eAAe,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,WAAW,CAAC,CAAC,CAAC;AAC/E,QAAM,iBAAiB,SAAS,aAAa;AAC7C,QAAM,iBAAiB,SAAS,aAAa;AAE7C,QAAM,UAAU,IAAI,UAAU,IAAI,QAAQ,MAAM,IAAI,IAAU,gBAAQ,GAAG,MAAM,CAAC;AAChF,QAAM,UAAU,IAAI,WAAW;AAG/B,QAAM,WAAW,IAAI,SAAS,KAAK;AACnC,QAAM,WAAW,IAAI,SAAS,KAAK;AACnC,QAAM,WAAW,IAAI,SAAS,KAAK;AACnC,QAAM,aAAa,aAAa,KAAK,aAAa,KAAK,aAAa;AAEpE,QAAM,gBAAgB,IAAI,UAAU;AAGpC,QAAM,WAAW,IAAI,YAAY,EAAE,MAAM,YAAqB,cAAc,GAAG;AAC/E,MAAI,mBAAmB,SAAS,SAAS,aAAc,SAAS,gBAAgB,KAAM;AAEtF,QAAM,QAAyB,IAAI,SAAS,aAAa;AACzD,QAAM,iBAAiB,IAAI,iBAAiB,IAAU,gBAAQ,GAAG,GAAG,CAAC,GAAG,MAAM,EAAE,UAAU;AAC1F,QAAM,iBAA2B,IAAI,aAAa,CAAC,KAAK,KAAK,IAAI,KAAK,KAAK,EAAE;AAC7E,QAAM,aAAuB,IAAI,SAAS,CAAC,GAAK,CAAG;AACnD,QAAM,YAAsB,IAAI,YAAY,CAAC,KAAK,CAAG;AACrD,QAAM,iBAA2B,IAAI,MAAM,SAAS,CAAC,KAAK,GAAG;AAC7D,QAAM,eAAyB,IAAI,MAAM,OAAO,CAAC,KAAK,GAAG;AAEzD,QAAM,gBAA0B,IAAI,WAAY,IAAI,SAAS,SAAS,CAAC,GAAG,KAAK,KAAK,CAAC,IAAK,CAAC,GAAG,CAAC;AAC/F,QAAM,cAAwB,IAAI,WAAY,IAAI,SAAS,YAAY,CAAC,IAAM,CAAG,IAAK,CAAC,GAAG,CAAC;AAC3F,QAAM,kBAA6B,IAAI,OAAO,SAAS,IAAU,gBAAQ,GAAG,KAAK,KAAK,CAAC;AACvF,QAAM,iBAA8C,IAAI,OAAO;AAC/D,QAAM,qBAA8B,IAAI,OAAO,iBAAiB;AAChE,QAAM,gBAAuC,IAAI,OAAO;AACxD,QAAM,gBAA2B,IAAI,OAAO,OAAO,IAAU,gBAAQ,KAAK,KAAK,MAAM,CAAC;AAEtF,QAAM,eAAe,IAAI,aAAa,CAAC;AACvC,QAAM,wBAAwB,aAAa,WAAW;AACtD,QAAM,SAAS,aAAa,UAAU;AACtC,QAAM,yBAAyB,aAAa,eAAe;AAC3D,QAAM,gBAAgB,aAAa,YAAY;AAC/C,QAAM,mBAAmB,aAAa,oBAAoB;AAE1D,MAAI,cAAc,IAAU,gBAAQ;AACpC,MAAI,mBAAmB;AAGvB,MAAI,iBAAiB,IAAI,eAAe;AACxC,MAAI,UAAU;AACd,MAAI,iBAAiB;AAGrB,QAAM,SAAS,SAAS,SAAS,UAAW,SAAS,UAAU,CAAC,IAAK,CAAC;AACtE,QAAM,kBAA4B,OAAO,IAAI,MAAM,CAAC;AACpD,QAAM,gBAA0B,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAExD,WAAS,qBAAqB;AAC5B,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,sBAAgB,CAAC,IAAI;AACrB,oBAAc,CAAC,IAAI,OAAO,CAAC,EAAE;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,uBAAuB;AAE3B,MAAI,iBAAiB;AACrB,MAAI,oBAAoB;AAExB,MAAI,aAAiC;AACrC,MAAI,mBAA8C;AAClD,MAAI,IAAI,SAAS,UAAU,aAAa,MAAM;AAa5C,QAASC,QAAT,SAAc,OAAe,OAAe;AAC1C,YAAM,IAAI,KAAK,IAAI,KAAK,IAAI;AAC5B,YAAM,MAAuB,CAAC;AAC9B,eAAS,IAAI,GAAG,KAAK,IAAI,KAAK;AAC5B,cAAM,IAAK,IAAI,KAAM,KAAK,KAAK;AAC/B,cAAM,IAAI,IAAU,gBAAQ,EACzB,KAAK,IAAI,EACT,eAAe,CAAC,EAChB,gBAAgB,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC,EAClC,gBAAgB,GAAG,KAAK,IAAI,CAAC,IAAI,CAAC;AACrC,YAAI,KAAK,CAAC;AAAA,MACZ;AACA,YAAM,OAAO,IAAU,uBAAe,EAAE,cAAc,GAAG;AACzD,YAAM,MAAM,IAAU,0BAAkB;AAAA,QACtC;AAAA,QACA,aAAa;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AACD,aAAO,IAAU,aAAK,MAAM,GAAG;AAAA,IACjC;AAnBS,eAAAA;AAZT,iBAAa,IAAU,cAAM;AAC7B,UAAM,IAAI;AACV,UAAM,OAAO,MAAM,QAAQ,cAAc,IAAI,eAAe,CAAC,IAAI;AACjE,UAAM,OAAO,MAAM,QAAQ,cAAc,IAAI,eAAe,CAAC,IAAI;AACjE,UAAM,OAAO;AACb,UAAM,IAAI,IAAU,gBAAQ;AAC5B,UAAM,IAAI,IAAU,gBAAQ;AAC5B,QAAI,KAAK,IAAI,KAAK,CAAC,IAAI,IAAK,GAAE,IAAI,GAAG,GAAG,CAAC;AAAA,QACpC,GAAE,IAAI,GAAG,GAAG,CAAC;AAClB,MAAE,MAAM,IAAI,EAAE,UAAU;AACxB,MAAE,KAAK,IAAI,EAAE,MAAM,CAAC,EAAE,UAAU;AAuBhC,UAAM,WAAW,IAAU,uBAAe,EAAE,cAAc;AAAA,MACxD,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAAA,MACzB,IAAU,gBAAQ,EAAE,KAAK,IAAI,EAAE,eAAe,CAAC;AAAA,IACjD,CAAC;AACD,eAAW,IAAI,IAAU,aAAK,UAAU,IAAU,0BAAkB,EAAE,OAAO,QAAS,CAAC,CAAC,CAAC;AACzF,eAAW,IAAIA,MAAK,MAAM,OAAQ,CAAC;AACnC,eAAW,IAAIA,MAAK,MAAM,QAAQ,CAAC;AAClC,IAAC,KAAwB,IAAI,UAAU;AAAA,EAC1C;AACA,MAAI,IAAI,iBAAiB;AACvB,UAAM,WAAW,KAAK,IAAI,IAAI,aAAa;AAC3C,UAAM,UAAU,IAAI,aAAa,WAAW,IAAI,CAAC;AACjD,UAAM,OAAO,IAAU,uBAAe;AACtC,SAAK,aAAa,YAAY,IAAU,wBAAgB,SAAS,CAAC,CAAC;AACnE,UAAM,MAAM,IAAU,0BAAkB;AAAA,MACtC,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AACD,uBAAmB,IAAU,qBAAa,MAAM,GAAG;AAClD,IAAC,KAAwB,IAAI,gBAAgB;AAAA,EAChD;AAEA,QAAM,KAAK,IAAU,gBAAQ;AAC7B,QAAM,iBAAiB,IAAU,gBAAQ;AACzC,QAAM,MAAM,IAAU,gBAAQ;AAC9B,QAAM,QAAQ,IAAU,gBAAQ;AAChC,QAAM,KAAK,IAAU,gBAAQ;AAC7B,QAAM,UAAU,IAAU,gBAAQ;AAClC,QAAM,WAAW,IAAU,gBAAQ;AACnC,QAAM,QAAQ,IAAU,gBAAQ;AAChC,QAAM,UAAU,IAAU,gBAAQ;AAClC,QAAM,UAAU,IAAU,gBAAQ;AAClC,QAAM,UAAU,IAAU,gBAAQ;AAClC,QAAM,UAAU,IAAU,gBAAQ;AAClC,QAAM,QAAQ,IAAU,gBAAQ;AAChC,QAAM,QAAQ,IAAU,gBAAQ;AAChC,QAAM,QAAQ,IAAU,gBAAQ;AAChC,QAAM,WAAW,IAAU,cAAM;AACjC,QAAM,WAAW,IAAU,gBAAQ;AACnC,QAAM,WAAW,IAAU,gBAAQ;AACnC,QAAM,WAAW,IAAU,gBAAQ;AACnC,QAAM,WAAW,IAAU,gBAAQ;AACnC,QAAM,WAAW,IAAU,gBAAQ;AAEnC,WAAS,gBAAgB,UAAyB,KAAmC;AACnF,YAAQ,OAAO;AAAA,MACb,KAAK,aAAa,MAAM;AACtB,iBAAS,KAAK,QAAQ,EAAE,IAAI,WAAW,EAAE,UAAU;AACnD,cAAM,QAAQ,UAAU,cAAc;AACtC,cAAM,OAAO,KAAK,IAAI,KAAK;AAC3B,cAAM,OAAO,KAAK,IAAI,KAAK;AAC3B,YAAI,KAAK,aAAa,EAAE,eAAe,IAAI,EAAE,gBAAgB,UAAU,IAAI,EAAE,UAAU;AACvF,eAAO;AAAA,MACT;AAAA,MACA,KAAK,aAAa;AAAA,MAClB,KAAK,aAAa,OAAO;AACvB,YAAI,IAAI,KAAK,OAAO,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,EAAE,UAAU;AACvF,eAAO;AAAA,MACT;AAAA,MACA;AACE,YAAI,IAAI,GAAG,GAAG,CAAC;AACf,eAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,iBAAiB,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAChD,QAAM,UAAU,IAAI,WAAW;AAE/B,WAAS,oBAAoB,QAAuB,KAAmC;AACrF,YAAQ,OAAO;AAAA,MACb,KAAK,aAAa;AAAA,MAClB,KAAK,aAAa,OAAO;AACvB,cAAM,IAAI,gBAAgB,KAAK,KAAK,KAAK,OAAO,CAAC;AACjD,cAAM,IAAI,KAAK,OAAO,IAAI,KAAK,KAAK;AACpC,cAAM,OAAO;AACb,YAAI,KAAK,IAAI,KAAK,CAAC,IAAI,IAAK,UAAS,IAAI,GAAG,GAAG,CAAC;AAAA,YAC3C,UAAS,IAAI,GAAG,GAAG,CAAC;AACzB,iBAAS,MAAM,IAAI,EAAE,UAAU;AAC/B,iBAAS,KAAK,IAAI,EAAE,MAAM,QAAQ,EAAE,UAAU;AAC9C,YACG,KAAK,MAAM,EACX,gBAAgB,UAAU,KAAK,IAAI,CAAC,IAAI,CAAC,EACzC,gBAAgB,UAAU,KAAK,IAAI,CAAC,IAAI,CAAC;AAC5C,eAAO;AAAA,MACT;AAAA,MACA,KAAK,aAAa,QAAQ;AACxB,iBACG,IAAI,KAAK,OAAO,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC,EACvE,UAAU;AACb,cAAM,KAAK,IAAI,gBAAgB,iBAAiB,KAAK,KAAK,KAAK,OAAO,CAAC;AACvE,YAAI,KAAK,MAAM,EAAE,gBAAgB,UAAU,CAAC;AAC5C,eAAO;AAAA,MACT;AAAA,MACA,KAAK,aAAa,KAAK;AACrB,YAAI;AAAA,UACF,OAAO,KAAK,KAAK,OAAO,IAAI,OAAO,QAAQ;AAAA,UAC3C,OAAO,KAAK,KAAK,OAAO,IAAI,OAAO,QAAQ;AAAA,UAC3C,OAAO,KAAK,KAAK,OAAO,IAAI,OAAO,QAAQ;AAAA,QAC7C;AACA,eAAO;AAAA,MACT;AAAA,MACA;AACE,YAAI,KAAK,MAAM;AACf,eAAO;AAAA,IACX;AAAA,EACF;AAGA,QAAM,oBAAoB,IAAI,cACzB,IAAI,YAAY,eAAe,IAAI,YAAY,WAAW,MAAM,IAAI,YAAY,QAAQ,KACzF;AACJ,QAAM,YAAY,IAAI,aAAa,OAAO;AAC1C,QAAM,aAAa,IAAI,aAAa,QAAQ;AAC5C,QAAM,iBAAiB,IAAI,aAAa,YAAY;AACpD,QAAM,yBAAyB,IAAI,aAAa,oBAAoB;AAEpE,WAAS,QAAQ,GAAW,SAAwB,aAAa;AAC/D,UAAM,MAAM,IAAI;AAChB,wBAAoB,QAAQ,QAAQ;AACpC,cAAU,MAAM,CAAC,IAAI,SAAS;AAC9B,cAAU,MAAM,CAAC,IAAI,SAAS;AAC9B,cAAU,MAAM,CAAC,IAAI,SAAS;AAE9B,oBAAgB,UAAU,QAAQ;AAClC,UAAM,QAAQ,UAAU,UAAU;AAClC,eAAW,MAAM,CAAC,IAAI,SAAS,IAAI;AACnC,eAAW,MAAM,CAAC,IAAI,SAAS,IAAI;AACnC,eAAW,MAAM,CAAC,IAAI,SAAS,IAAI;AAEnC,SAAK,CAAC,IAAI;AACV,cAAU,CAAC,IAAI,KAAK,IAAI,MAAQ,UAAU,SAAS,CAAC;AACpD,gBAAY,CAAC,IAAI;AAEjB,cAAU,CAAC,IAAI,UAAU,cAAc;AACvC,YAAQ,CAAC,IAAI,UAAU,YAAY;AACnC,cAAU,CAAC,IAAI,UAAU,aAAa;AACtC,iBAAa,CAAC,IAAI,UAAU,WAAW;AAGvC,gBAAY,CAAC,IAAI,yBAAyB,KAAK,OAAO,IAAI,oBAAoB;AAG9E,UAAM,WAAW,IAAI;AACrB,cAAU,WAAW,CAAC,IAAI,KAAK,OAAO,IAAI;AAC1C,cAAU,WAAW,CAAC,IAAI,KAAK,OAAO,IAAI;AAG1C,QAAI,OAAO;AACX,QAAI,QAAQ,KAAK,KAAK,OAAO,IAAI,MAAO,SAAQ;AAChD,QAAI,QAAQ,KAAK,KAAK,OAAO,IAAI,MAAO,SAAQ;AAChD,cAAU,CAAC,IAAI;AAGf,UAAM,OAAO,IAAI;AAEjB,QAAI,kBAAkB,eAAe,SAAS,GAAG;AAC/C,YAAM,SAAS,eAAe,KAAK,MAAM,KAAK,OAAO,IAAI,eAAe,MAAM,CAAC;AAC/E,YAAM,KAAK,MAAM;AAAA,IACnB,OAAO;AACL,eAAS,iBAAiB,KAAK;AAAA,IACjC;AACA,WAAO,OAAO,CAAC,IAAI,MAAM;AACzB,WAAO,OAAO,CAAC,IAAI,MAAM;AACzB,WAAO,OAAO,CAAC,IAAI,MAAM;AACzB,WAAO,OAAO,CAAC,IAAI,MAAM;AAEzB,QAAI,eAAe;AACjB,eAAS,eAAe,KAAK;AAC7B,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AAAA,IAC3B,OAAO;AACL,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AAAA,IAC3B;AAIA,QAAI,oBAAoB;AACtB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AAAA,IAC3B,OAAO;AACL,eAAS,eAAe,KAAK;AAC7B,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AACzB,aAAO,OAAO,CAAC,IAAI,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,WAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,SAAK,CAAC,IAAI;AACV,cAAU,CAAC,IAAI;AAAA,EACjB;AAGA,WAAS,mBAA4B;AACnC,aAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,UAAI,KAAK,CAAC,IAAI,UAAU,CAAC,EAAG,QAAO;AAAA,IACrC;AACA,WAAO;AAAA,EACT;AAGA,WAAS,aAAmB;AAC1B,aAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AACtC,WAAK,CAAC,IAAI,UAAU,CAAC,IAAI;AAAA,IAC3B;AACA,SAAK,QAAQ;AAAA,EACf;AAGA,QAAM,aAAa,IAAI,cAAc;AAGrC,QAAM,eAAe,IAAU,gBAAQ;AACvC,QAAM,YAAY,IAAU,gBAAQ;AACpC,QAAM,iBAAiB,IAAU,gBAAQ;AAEzC,QAAM,SAAS,CAAC,IAAY,QAAsB,uBAAuC;AACvF,QAAI,WAAY,YAAW,SAAS,KAAK,WAAW;AACpD,QAAI,kBAAkB;AACpB,YAAM,OAAO,iBAAiB,SAAS,aAAa,UAAU;AAC9D,YAAM,MAAM,KAAK;AACjB,UAAI,IAAI;AACR,YAAM,QAAQ;AACd,YAAM,WAAW,IAAI,SAAS;AAC9B,eAAS,IAAI,GAAG,IAAI,iBAAiB,IAAI,IAAI,UAAU,KAAK;AAC1D,YAAI,KAAK,CAAC,KAAK,UAAU,CAAC,EAAG;AAC7B,cAAM,MAAM,IAAI;AAChB,cAAM,IAAI,UAAU,MAAM,CAAC;AAC3B,cAAM,IAAI,UAAU,MAAM,CAAC;AAC3B,cAAM,IAAI,UAAU,MAAM,CAAC;AAC3B,cAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,cAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,cAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,YAAI,GAAG,IAAI;AACX,YAAI,GAAG,IAAI;AACX,YAAI,GAAG,IAAI;AACX,YAAI,GAAG,IAAI,IAAI,KAAK;AACpB,YAAI,GAAG,IAAI,IAAI,KAAK;AACpB,YAAI,GAAG,IAAI,IAAI,KAAK;AAAA,MACtB;AACA,aAAO,IAAI,IAAI,QAAQ,IAAK,KAAI,CAAC,IAAI;AACrC,WAAK,cAAc;AAAA,IACrB;AAGA,UAAM,WAAW,IAAI,YAAY;AACjC,UAAM,iBAAiB,YAAY,KAAK,UAAU;AAElD,QAAI,kBAAkB,CAAC,gBAAgB;AACrC,iBAAW;AAGX,UAAI,SAAS,SAAS,cAAc,gBAAgB;AAElD,YAAI,mBAAmB,GAAG;AACxB,8BAAoB,mBAAmB;AACvC,gBAAM,UAAU,KAAK,MAAM,gBAAgB;AAC3C,cAAI,UAAU,GAAG;AACf,gCAAoB;AACpB,gBAAI,UAAU;AACd,qBAAS,IAAI,GAAG,IAAI,iBAAiB,UAAU,SAAS,KAAK;AAC3D,kBAAI,KAAK,CAAC,KAAK,UAAU,CAAC,GAAG;AAC3B,wBAAQ,GAAG,WAAW;AACtB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,WAAW,SAAS,SAAS,WAAW,gBAAgB;AAEtD,iBAAS,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM;AACzC,gBAAM,IAAI,OAAO,EAAE;AACnB,gBAAM,kBAAkB,gBAAgB,EAAE;AAC1C,gBAAM,YAAY,EAAE,UAAU;AAE9B,cAAI,mBAAmB,UAAW;AAElC,cAAI,WAAW,cAAc,EAAE,GAAG;AAEhC,kBAAM,aAAa,EAAE,KAAK;AAG1B,4BAAgB,EAAE;AAClB,gBAAI,gBAAgB,EAAE,IAAI,WAAW;AACnC,4BAAc,EAAE,IAAI,WAAW,EAAE,YAAY;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,WAAW,KAAK,WAAW,UAAU;AACvC,YAAI,IAAI,SAAS;AAEf,oBAAU;AACV,6BAAmB;AAAA,QACrB,WAAW,CAAC,gBAAgB;AAG1B,cAAI,iBAAiB,GAAG;AACtB,6BAAiB;AACjB,6BAAiB;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,UAAM,oBAAoB,OAAO,aAAa,CAAC,EAAE,UAAU;AAC3D,OAAG,oBAAoB,OAAO,aAAa,CAAC,EAAE,UAAU;AACxD,YAAQ,oBAAoB,OAAO,aAAa,CAAC,EAAE,UAAU;AAC7D,YAAQ,KAAK,OAAO,EAAE,OAAO;AAI7B,QAAI,oBAAoB;AACtB,qBAAe,KAAK,kBAAkB,EAAE,OAAO;AAC/C,YAAM,mBAAmB,cAAc;AACvC,SAAG,mBAAmB,cAAc;AACpC,cAAQ,mBAAmB,cAAc;AACzC,cAAQ,mBAAmB,cAAc;AAAA,IAC3C;AAIA,UAAM,aAAa,eAAe;AAClC,QAAI,YAAY;AAEd,mBAAa,IAAI,GAAG,GAAG,CAAC;AACxB,gBAAU,IAAI,GAAG,GAAG,CAAC;AACrB,qBAAe,IAAI,GAAG,GAAG,CAAC;AAAA,IAC5B;AAGA,UAAM,WAAW,IAAI,WAAW,2BAA2B;AAC3D,UAAM,oBAAoB,IAAI,WAAW,yBAAyB;AAClE,UAAM,iBAAiB,IAAI,WAAW,iBAAiB;AAGvD,QAAI,WAAW;AAEf,aAAS,IAAI,GAAG,IAAI,eAAe,KAAK;AAEtC,UAAI,KAAK,CAAC,KAAK,UAAU,CAAC,EAAG;AAE7B,YAAM,MAAM,IAAI;AAGhB,YAAM,eAAe,KAAK,CAAC,IAAI,UAAU,CAAC;AAG1C,YAAM,uBAAuB,uBAAuB,IAAI,mBAAmB,cAAc,CAAC;AAC1F,YAAM,0BAA0B;AAAA,QAC9B,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAGA,iBAAW,MAAM,CAAC,KAAK,QAAQ,IAAI;AACnC,iBAAW,MAAM,CAAC,KAAK,QAAQ,IAAI;AACnC,iBAAW,MAAM,CAAC,KAAK,QAAQ,IAAI;AAGnC,UAAI,UAAU,GAAG;AACf,cAAM,aAAa,IAAI,UAAU;AACjC,cAAM,cAAc,KAAK,IAAI,GAAG,UAAU;AAC1C,mBAAW,MAAM,CAAC,KAAK;AACvB,mBAAW,MAAM,CAAC,KAAK;AACvB,mBAAW,MAAM,CAAC,KAAK;AAAA,MACzB;AAKA,UAAI,YAAY;AAEd,YAAI,aAAa,GAAG;AAClB,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AACnC,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AAEnC,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,oBAAU,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACtC,oBAAU,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AAEtC,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,qBAAW,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACvC,qBAAW,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AAAA,QACzC;AAGA,YAAI,aAAa,GAAG;AAClB,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AACnC,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AAEnC,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,oBAAU,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACtC,oBAAU,MAAM,CAAC,IAAI,CAAC,KAAK,OAAO,KAAK;AAEvC,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,qBAAW,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACvC,qBAAW,MAAM,CAAC,IAAI,CAAC,KAAK,OAAO,KAAK;AAAA,QAC1C;AAGA,YAAI,aAAa,GAAG;AAClB,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AACnC,gBAAM,OAAO,KAAK,IAAI,WAAW,EAAE;AAEnC,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,oBAAU,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACtC,oBAAU,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AAEtC,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,gBAAM,KAAK,WAAW,MAAM,CAAC;AAC7B,qBAAW,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AACvC,qBAAW,MAAM,CAAC,IAAI,KAAK,OAAO,KAAK;AAAA,QACzC;AAAA,MACF;AAGA,YAAM,qBAAqB;AAC3B,gBAAU,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,IAAI,KAAK;AACjD,gBAAU,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,IAAI,KAAK;AACjD,gBAAU,MAAM,CAAC,KAAK,WAAW,MAAM,CAAC,IAAI,KAAK;AACjD,WAAK,CAAC,KAAK;AAGX,gBAAU,CAAC,KAAK,aAAa,CAAC,IAAI,KAAK;AAGvC,UAAI,yBAAyB,UAAU,MAAM,CAAC,KAAK,UAAU,WAAW,MAAM,CAAC,IAAI,GAAG;AACpF,kBAAU,MAAM,CAAC,IAAI;AACrB,mBAAW,MAAM,CAAC,IAAI,CAAC,WAAW,MAAM,CAAC,IAAI;AAC7C,mBAAW,MAAM,CAAC,KAAK;AACvB,mBAAW,MAAM,CAAC,KAAK;AACvB,oBAAY,CAAC;AACb,YAAI,YAAY,CAAC,KAAK,kBAAkB;AACtC,oBAAU,CAAC,IAAI,KAAK,CAAC;AACrB;AAAA,QACF;AAAA,MACF;AAGA,UAAI,KAAK,CAAC,KAAK,UAAU,CAAC,EAAG;AAE7B,UAAI,IAAI,UAAU,MAAM,CAAC,GAAG,UAAU,MAAM,CAAC,GAAG,UAAU,MAAM,CAAC,CAAC;AAGlE,UAAI,iBAAiB;AACrB,UAAI,sBAAsB;AAC1B,UAAI,cAAc;AAChB,cAAM,WAAW,IAAI;AACrB,cAAM,QAAQ,UAAU,WAAW,CAAC;AACpC,cAAM,QAAQ,UAAU,WAAW,CAAC;AACpC,cAAM,aAAa,KAAK,CAAC,IAAI;AAG7B,cAAM,SACJ,eAAe,IACX,OAAO,QAAQ,cAAc,gBAAgB,QAAQ,gBAAgB,YAAY,IACjF,WAAW,QAAQ,cAAc,gBAAgB,QAAQ,cAAc;AAC7E,cAAM,SACJ,eAAe,IACX;AAAA,WACG,QAAQ,MAAM,cAAc;AAAA,WAC5B,QAAQ,OAAO;AAAA,UAChB;AAAA,QACF,IACA,WAAW,QAAQ,MAAM,cAAc,iBAAiB,QAAQ,OAAO,cAAc;AAC3F,cAAM,SACJ,eAAe,IACX;AAAA,WACG,QAAQ,MAAM,cAAc;AAAA,WAC5B,QAAQ,OAAO;AAAA,UAChB;AAAA,QACF,IACA,WAAW,QAAQ,MAAM,cAAc,iBAAiB,QAAQ,OAAO,cAAc;AAG3F,YAAI,sBAAsB,GAAG;AAC3B,cAAI,KAAK,SAAS,sBAAsB;AACxC,cAAI,KAAK,SAAS,sBAAsB;AACxC,cAAI,KAAK,SAAS,sBAAsB;AAAA,QAC1C;AAGA,YAAI,sBAAsB,GAAG;AAC3B,gBAAM,WACJ,eAAe,IACX;AAAA,aACG,QAAQ,MAAM,cAAc;AAAA,aAC5B,QAAQ,OAAO;AAAA,YAChB;AAAA,UACF,IACA;AAAA,aACG,QAAQ,MAAM,cAAc;AAAA,aAC5B,QAAQ,OAAO;AAAA,UAClB;AACN,2BAAiB,WAAW;AAAA,QAC9B;AAGA,YAAI,kBAAkB,GAAG;AACvB,gBAAM,UACJ,eAAe,IACX;AAAA,aACG,QAAQ,MAAM,cAAc;AAAA,aAC5B,QAAQ,OAAO;AAAA,YAChB;AAAA,UACF,IACA;AAAA,aACG,QAAQ,MAAM,cAAc;AAAA,aAC5B,QAAQ,OAAO;AAAA,UAClB;AAEN,gCAAsB,IAAI,UAAU;AAAA,QACtC;AAAA,MACF;AAEA,UAAI,QAAQ;AACZ,UAAI,YAAY,CAAC,YAAY;AAG3B,YAAI,UAAU,WAAW,MAAM,CAAC;AAChC,YAAI,UAAU,WAAW,MAAM,CAAC;AAChC,YAAI,UAAU,WAAW,MAAM,CAAC;AAMhC,YAAI,YAAY;AACd,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,gBAAM,KAAK,UAAU,MAAM,CAAC;AAC5B,cAAI,aAAa,GAAG;AAClB,uBAAW,CAAC,WAAW;AACvB,uBAAW,WAAW;AAAA,UACxB;AACA,cAAI,aAAa,GAAG;AAClB,uBAAW,WAAW;AACtB,uBAAW,CAAC,WAAW;AAAA,UACzB;AACA,cAAI,aAAa,GAAG;AAClB,uBAAW,CAAC,WAAW;AACvB,uBAAW,WAAW;AAAA,UACxB;AAAA,QACF;AAEA,gBAAQ;AAAA,UACN,UAAU,MAAM,CAAC,IAAI,UAAU;AAAA,UAC/B,UAAU,MAAM,CAAC,IAAI,UAAU;AAAA,UAC/B,UAAU,MAAM,CAAC,IAAI,UAAU;AAAA,QACjC;AACA,gBAAQ,KAAK,OAAO,EAAE,QAAQ,MAAM;AACpC,gBAAQ,KAAK,GAAG,EAAE,QAAQ,MAAM;AAChC,cAAM,KAAK,QAAQ,IAAI,QAAQ;AAC/B,cAAM,KAAK,QAAQ,IAAI,QAAQ;AAC/B,gBAAQ,KAAK,MAAM,IAAI,EAAE,IAAI,KAAK,KAAK;AAAA,MACzC;AACA,eAAS,UAAU,CAAC,IAAI;AACxB,YAAM,OAAO,KAAK,IAAI,KAAK;AAC3B,YAAM,OAAO,KAAK,IAAI,KAAK;AAE3B,UAAI,YAAY;AAEd,iBAAS;AAAA,UACP,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,UACtC,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,UACtC,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,QACxC;AACA,cAAM;AAAA,UACJ,CAAC,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,UACvC,CAAC,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,UACvC,CAAC,aAAa,IAAI,OAAO,UAAU,IAAI;AAAA,QACzC;AAAA,MACF,OAAO;AAEL,iBAAS;AAAA,UACP,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,UACxB,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,UACxB,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,QAC1B;AACA,cAAM;AAAA,UACJ,CAAC,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,UACzB,CAAC,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,UACzB,CAAC,MAAM,IAAI,OAAO,GAAG,IAAI;AAAA,QAC3B;AAAA,MACF;AAEA,6BAAuB,oBAAoB,iBAAiB;AAC5D,YAAM,OAAO,KAAK,MAAM,WAAW,MAAM,CAAC,GAAG,WAAW,MAAM,CAAC,GAAG,WAAW,MAAM,CAAC,CAAC;AACrF,YAAM,UAAU,IAAI,OAAO;AAG3B,YAAM,YAAY,KAAK,CAAC,IAAI,UAAU,CAAC;AAGvC,YAAM,sBAAsB,uBAAuB,IAAI,kBAAkB,WAAW,CAAC;AACrF,YAAM,oBACJ,IAAI,wBAAwB,SACxB,uBAAuB,IAAI,qBAAqB,WAAW,CAAC,IAC5D;AAEN,YAAM,IACJ,KAAK,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,SAAS,IAAI,sBAAsB;AACpE,UAAI,KAAK,YAAY;AACrB,UAAI,KAAK,YAAY,IAAI;AAGzB,YAAM,OAAO,UAAU,CAAC;AACxB,UAAI,OAAO,EAAG,MAAK,CAAC;AACpB,UAAI,OAAO,EAAG,MAAK,CAAC;AAGpB,YAAM,YAAY,IAAI;AACtB,YAAM;AAAA,QACJ,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,MACtB;AACA,YAAM;AAAA,QACJ,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,QACpB,OAAO,YAAY,CAAC;AAAA,MACtB;AACA,UAAI,eAAe;AACjB,cAAM;AAAA,UACJ,OAAO,YAAY,CAAC;AAAA,UACpB,OAAO,YAAY,CAAC;AAAA,UACpB,OAAO,YAAY,CAAC;AAAA,UACpB,OAAO,YAAY,CAAC;AAAA,QACtB;AACA,YAAI,YAAY,KAAK;AACnB,mBAAS,OAAO,OAAO,YAAY,GAAG,KAAK;AAAA,QAC7C,OAAO;AACL,mBAAS,OAAO,QAAQ,YAAY,OAAO,GAAG,KAAK;AAAA,QACrD;AAAA,MACF,OAAO;AACL,iBAAS,OAAO,OAAO,WAAW,KAAK;AAAA,MACzC;AAGA,eAAS,OAAO,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACzC,WAAK,WAAW,UAAU,QAAQ;AAElC,sBAAgB,QAAQ,IAAI,sBAAsB,OAAO,oBAAoB,MAAM;AAGnF,YAAM,SAAS,aAAa,iBAAiB;AAC7C,SAAG;AAAA,QACD,SAAS,IAAI;AAAA,QACb,MAAM,IAAI;AAAA,QACV,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,SAAS,IAAI;AAAA,QACb,MAAM,IAAI;AAAA,QACV,OAAO;AAAA,QACP,IAAI;AAAA,QACJ,SAAS,IAAI;AAAA,QACb,MAAM,IAAI;AAAA,QACV,OAAO;AAAA,QACP,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,WAAK,YAAY,UAAU,EAAE;AAG7B,UAAI,IAAI,aAAa;AACnB,YAAI;AACJ,YAAI,mBAAmB,iBAAiB;AAGtC,gBAAM,UAAU,MAAM,QAAQ,SAAS,IAAI,UAAU,CAAC,IAAK;AAC3D,gBAAM,UAAU,MAAM,QAAQ,SAAS,IAAI,UAAU,CAAC,IAAK;AAC3D,gBAAM,iBACJ,UAAU,WAAW,UAAU,CAAC,IAAI,YAAY,UAAU,WAAW;AAGvE,mBAAS,iBAAiB;AAAA,QAC5B,OAAO;AAEL,mBAAS,KAAK,CAAC,IAAI,YAAY,YAAY,CAAC;AAC5C,cAAI,YAAY;AACd,qBAAS,SAAS;AAAA,UACpB,OAAO;AACL,qBAAS,KAAK,IAAI,QAAQ,oBAAoB,IAAI;AAAA,UACpD;AAAA,QACF;AACA,sBAAc,QAAQ,IAAI;AAAA,MAC5B;AAEA;AAAA,IACF;AAGA,SAAK,QAAQ;AACZ,IAAC,KAAK,eAA6D,cAAc;AAClF,QAAI,KAAK,cAAe,MAAK,cAAc,cAAc;AACzD,UAAM,KAAK,SAAS,aAAa,iBAAiB;AAClD,QAAI,GAAI,IAAG,cAAc;AACzB,UAAM,MAAM,SAAS,aAAa,eAAe;AACjD,QAAI,IAAK,KAAI,cAAc;AAE3B,UAAM,YAAY,IAAI;AACtB,UAAM,YAAY;AAClB,QAAI,aAAa,WAAW;AAC1B,YAAM,QAAQ,UAAU;AACxB,YAAM,QAAQ,UAAU;AACxB,YAAM,QAAQ,UAAU,cAAc,QAAQ;AAC9C,gBAAU,SAAS,mBAAmB,QAAQ;AAC7C,MAAC,UAAU,SAAS,WAAW,MAAwB,IAAI,OAAO,KAAK;AACxE,gBAAU,SAAS,kBAAkB,QAAQ;AAC7C,gBAAU,SAAS,mBAAmB,QAAQ;AAC9C,gBAAU,SAAS,kBAAkB,QAAQ;AAAA,IAC/C,WAAW,WAAW;AACpB,gBAAU,SAAS,mBAAmB,QAAQ;AAAA,IAChD;AAAA,EACF;AAEA,QAAM,QAAQ,CAAC,QAAuB,QAAgB,OAAO;AAC3D,gBAAY,KAAK,MAAM;AAEvB,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAI,iBAAiB,UAAU,OAAO,KAAK;AACzD,UAAI,KAAK,CAAC,KAAK,UAAU,CAAC,GAAG;AAC3B,gBAAQ,GAAG,MAAM;AACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,CAAC,QAAuB;AACzC,UAAM,IAAI;AACV,QAAI,EAAE,SAAS,IAAK,GAAE,SAAS,IAAI,QAAQ;AAC3C,QAAI,cAAc;AAClB,MAAE,cAAc;AAAA,EAClB;AAEA,QAAM,eAAe,CAAC,SAAiB;AACrC,uBAAmB,KAAK,IAAI,GAAG,QAAQ,CAAC;AAAA,EAC1C;AAEA,QAAM,YAAY,CAAC,WAA0B;AAC3C,gBAAY,KAAK,MAAM;AAAA,EACzB;AAGA,QAAM,eAAe,MAAM;AACzB,qBAAiB;AACjB,qBAAiB;AAAA,EACnB;AAEA,QAAM,eAAe,MAAM;AACzB,qBAAiB;AACjB,cAAU;AACV,qBAAiB;AACjB,uBAAmB;AACnB,uBAAmB;AACnB,eAAW;AAAA,EACb;AAEA,QAAM,kBAAkB,MAAM;AAC5B,iBAAa;AACb,iBAAa;AAAA,EACf;AAGA,QAAM,oBAAoB,CAAC,WAAwC;AAEjE,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ;AAGb,WAAO,SAAS,CAAC,UAAU;AAEzB,UAAI,UAAU,KAAM;AAEpB,YAAM,eAAe,MAAM,SAAS;AACpC,UAAI,cAAc;AAEhB,YAAI,WAAW,OAAQ,cAAa,eAAe;AAAA,iBAC1C,WAAW,OAAQ,cAAa,eAAe;AAAA,iBAC/C,WAAW,UAAW,cAAa,kBAAkB;AAAA,MAChE;AAAA,IACF,CAAC;AAAA,EACH;AAGA,QAAM,OAAO,MAAM;AACjB,iBAAa;AACb,sBAAkB,MAAM;AAAA,EAC1B;AAEA,QAAM,OAAO,MAAM;AACjB,iBAAa;AACb,sBAAkB,MAAM;AAAA,EAC1B;AAEA,QAAM,UAAU,MAAM;AACpB,oBAAgB;AAChB,sBAAkB,SAAS;AAAA,EAC7B;AAEA,QAAM,YAAY,MAAM;AAExB,QAAM,aAAa,MAAM;AAEzB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AIrlDO,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,UAAO;AACP,EAAAA,eAAA,WAAQ;AACR,EAAAA,eAAA,SAAM;AACN,EAAAA,eAAA,aAAU;AAJA,SAAAA;AAAA,GAAA;AAOL,IAAK,qBAAL,kBAAKC,wBAAL;AACL,EAAAA,oBAAA,YAAS;AACT,EAAAA,oBAAA,gBAAa;AACb,EAAAA,oBAAA,aAAU;AACV,EAAAA,oBAAA,UAAO;AACP,EAAAA,oBAAA,oBAAiB;AACjB,EAAAA,oBAAA,iBAAc;AANJ,SAAAA;AAAA,GAAA;AASL,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,YAAS;AACT,EAAAA,WAAA,iBAAc;AAFJ,SAAAA;AAAA,GAAA;AAKL,IAAK,iBAAL,kBAAKC,oBAAL;AACL,EAAAA,gBAAA,mBAAgB;AAChB,EAAAA,gBAAA,sBAAmB;AACnB,EAAAA,gBAAA,oBAAiB;AAHP,SAAAA;AAAA,GAAA;AAwDZ,IAAqB,YAArB,MAA+B;AAAA,EACrB,SAAiC,oBAAI,IAAI;AAAA,EACzC,cAAkC,CAAC;AAAA,EACnC,aAAqC,oBAAI,IAAI;AAAA,EAC7C,aAA0B,oBAAI,IAAI;AAAA,EAClC,mBAAiD,oBAAI,IAAI;AAAA,EACzD,eAA8B;AAAA,EAC9B,mBAA4C;AAAA,EAC5C,YAAqD,oBAAI,IAAI;AAAA,EAErE,cAAc;AACZ,eAAW,SAAS,OAAO,OAAO,cAAc,GAAG;AACjD,WAAK,UAAU,IAAI,OAAO,oBAAI,IAAI,CAAC;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,cAAc,MAAc,MAAqB,cAAyB;AACxE,SAAK,WAAW,IAAI,MAAM,EAAE,MAAM,OAAO,aAAa,CAAC;AAAA,EACzD;AAAA,EAEA,SAAS,MAAc,UAAsC;AAC3D,SAAK,OAAO,IAAI,MAAM;AAAA,MACpB;AAAA,MACA,QAAQ;AAAA,MACR,UAAU,SAAS,YAAY;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,kBACE,IACA,WACA,UACM;AACN,SAAK,OAAO,IAAI,IAAI,EAAE,MAAM,IAAI,QAAQ,MAAM,UAAU,EAAE,CAAC;AAC3D,SAAK,WAAW,IAAI,EAAE;AACtB,SAAK,iBAAiB,IAAI,IAAI,EAAE,WAAW,SAAS,CAAC;AAAA,EACvD;AAAA,EAEA,eAAe,QAAgC;AAC7C,SAAK,YAAY,KAAK,MAAM;AAAA,EAC9B;AAAA,EAEA,UAAU,MAAoB;AAC5B,QAAI,KAAK,iBAAiB,KAAM;AAEhC,QAAI,CAAC,KAAK,OAAO,IAAI,IAAI,GAAG;AAC1B,cAAQ;AAAA,QACN,iCAAiC,IAAI,gCAAgC,CAAC,GAAG,KAAK,OAAO,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,MACzG;AAAA,IACF;AAEA,SAAK,eAAe;AACpB,SAAK,WAAW,mCAA4B;AAAA,EAC9C;AAAA,EAEA,SAAS,MAAc,OAAsB;AAC3C,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,QAAI,MAAO,OAAM,QAAQ;AAAA,EAC3B;AAAA,EAEA,UAAU,MAAc,OAAqB;AAC3C,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,QAAI,MAAO,OAAM,QAAQ;AAAA,EAC3B;AAAA,EAEA,QAAQ,MAAc,OAAqB;AACzC,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,QAAI,MAAO,OAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,EAC3C;AAAA,EAEA,UAAU,MAAsB;AAC9B,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EAEA,SAAS,MAAuB;AAC9B,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EAEA,QAAQ,MAAsB;AAC5B,UAAM,QAAQ,KAAK,WAAW,IAAI,IAAI;AACtC,WAAO,KAAK,MAAM,OAAO,SAAS,CAAC;AAAA,EACrC;AAAA,EAEA,OAAO,YAA0B;AAAA,EAEjC;AAAA,EAEA,WAAiB;AACf,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,oBAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,YAAmC;AACjC,UAAM,SAAS,oBAAI,IAAsB;AACzC,eAAW,CAAC,EAAE,KAAK,KAAK,QAAQ;AAC9B,aAAO,IAAI,IAAI;AAAA,QACb;AAAA,QACA,YAAY,KAAK,iBAAiB;AAAA,QAClC,QAAQ,KAAK,iBAAiB,KAAK,IAAI;AAAA,QACvC,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEA,kBAAsC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,wBAAiD;AAC/C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAAkC;AAChC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,oBAAoB,IAAqB;AACvC,WAAO,KAAK,WAAW,IAAI,EAAE;AAAA,EAC/B;AAAA,EAEA,sBAAsB,IAAoC;AACxD,WAAO,KAAK,iBAAiB,IAAI,EAAE,KAAK;AAAA,EAC1C;AAAA,EAEA,kBAAkB,UAA0B;AAC1C,WAAO;AAAA,EACT;AAAA,EAEA,qBAA6C;AAC3C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAa,OAAuB,UAA+B;AACjE,SAAK,UAAU,IAAI,KAAK,GAAG,IAAI,QAAQ;AAAA,EACzC;AAAA,EAEA,gBAAgB,OAAuB,UAA+B;AACpE,SAAK,UAAU,IAAI,KAAK,GAAG,OAAO,QAAQ;AAAA,EAC5C;AAAA,EAEQ,WAAW,OAA6B;AAC9C,SAAK,UAAU,IAAI,KAAK,GAAG,QAAQ,CAAC,OAAO,GAAG,CAAC;AAAA,EACjD;AACF;;;ACjOA,SAAS,iBAAiB;AAEnB,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EAC5B,OAAe,QAA0C,oBAAI,IAAI;AAAA,EACjE,OAAe,SAAoB,IAAI,UAAU;AAAA,EACjD,OAAe,QAAiB;AAAA;AAAA;AAAA,EAIhC,OAAwB,qBAAqB;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EACF;AAAA,EAEA,OAAc,SAAS,SAAwB;AAC7C,sBAAiB,QAAQ;AAAA,EAC3B;AAAA,EAEA,aAAoB,cAAc,IAAY,MAA4C;AACxF,QAAI,OAAO,kBAAiB,MAAM,IAAI,EAAE;AACxC,QAAI,MAAM;AACR,cAAQ,KAAK,+CAA+C,EAAE,EAAE;AAChE,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,MAAM,kBAAiB,OAAO,UAAU,IAAI;AAC3D,QAAI,OAAO,cAAc,OAAO,WAAW,SAAS,GAAG;AACrD,aAAO,OAAO,WAAW,CAAC;AAG1B,YAAM,qBAAqB,KAAK,OAAO;AACvC,YAAM,cAAc,KAAK,OAAO,OAAO,CAAC,UAAU;AAChD,cAAM,YAAY,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC;AAEzC,eAAO,CAAC,kBAAiB,mBAAmB;AAAA,UAC1C,CAAC,WAAW,UAAU,WAAW,MAAM,KAAK,cAAc;AAAA,QAC5D;AAAA,MACF,CAAC;AAED,UAAI,YAAY,SAAS,oBAAoB;AAC3C,cAAM,UAAU,qBAAqB,YAAY;AACjD,YAAI,kBAAiB,OAAO;AAC1B,kBAAQ;AAAA,YACN,kCAAkC,OAAO,qCAAqC,EAAE;AAAA,UAClF;AAAA,QACF;AACA,aAAK,SAAS;AAAA,MAChB;AAEA,WAAK,SAAS;AACd,WAAK,KAAK;AACV,WAAK,cAAc;AAEnB,wBAAiB,MAAM,IAAI,IAAI,IAAI;AAEnC,UAAI,kBAAiB,OAAO;AAC1B,gBAAQ;AAAA,UACN,wCAAwC,EAAE,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM;AAAA,QAChF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAEA,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAAA,EAEA,aAAoB,eAAe,OAAgD;AACjF,UAAM,WAAW,OAAO,QAAQ,KAAK,EAAE;AAAA,MAAI,CAAC,CAAC,IAAI,IAAI,MACnD,kBAAiB,cAAc,IAAI,IAAI;AAAA,IACzC;AACA,UAAM,QAAQ,IAAI,QAAQ;AAAA,EAC5B;AAAA,EAEA,OAAc,aAAa,IAAY,MAAiC;AACtE,QAAI,kBAAiB,MAAM,IAAI,EAAE,GAAG;AAClC,cAAQ,KAAK,4BAA4B,EAAE,mCAAmC;AAC9E;AAAA,IACF;AAEA,sBAAiB,MAAM,IAAI,IAAI,IAAI;AAEnC,QAAI,kBAAiB,OAAO;AAC1B,cAAQ;AAAA,QACN,iDAAiD,EAAE,KAAK,KAAK,OAAO,MAAM;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAc,QAAQ,IAA6C;AACjE,WAAO,kBAAiB,MAAM,IAAI,EAAE;AAAA,EACtC;AAAA,EAEA,OAAc,UAAU,IAA6C;AACnE,UAAM,OAAO,kBAAiB,MAAM,IAAI,EAAE;AAC1C,WAAO,OAAO,KAAK,MAAM,IAAI;AAAA,EAC/B;AAAA,EAEA,OAAc,cAAgD;AAC5D,WAAO,IAAI,IAAI,kBAAiB,KAAK;AAAA,EACvC;AAAA,EAEA,OAAc,QAAQ,IAAqB;AACzC,WAAO,kBAAiB,MAAM,IAAI,EAAE;AAAA,EACtC;AACF;;;AC7GA,YAAYC,aAAW;AAUhB,IAAM,yBAAN,MAAM,wBAAuB;AAAA,EAClC,OAAe,WAA0C;AAAA;AAAA,EAGjD,QAA0C,oBAAI,IAAI;AAAA,EAElD,cAAc;AAAA,EAAC;AAAA,EAEvB,OAAc,cAAsC;AAClD,QAAI,CAAC,wBAAuB,UAAU;AACpC,8BAAuB,WAAW,IAAI,wBAAuB;AAAA,IAC/D;AACA,WAAO,wBAAuB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,MAAc,MAAiC;AACjE,QAAI,KAAK,MAAM,IAAI,IAAI,EAAG;AAC1B,SAAK,MAAM,IAAI,MAAM,IAAI;AAAA,EAC3B;AAAA,EAEO,QAAQ,MAA+C;AAC5D,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEO,yBAAmC;AACxC,WAAO,CAAC,GAAG,KAAK,MAAM,KAAK,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,YAA0B;AAAA,EAExC;AACF;AAMO,IAAM,+BAAN,MAAmC;AAAA,EAChC;AAAA,EACA;AAAA,EACA,UAA8C,oBAAI,IAAI;AAAA,EACtD,mBAAkC;AAAA,EAClC,oBAA4B;AAAA;AAAA,EAC5B,WAAoB;AAAA,EAE5B,YAAY,OAAuB,SAAiC;AAClE,SAAK,UAAU;AACf,SAAK,QAAQ,IAAU,uBAAe,KAAK;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,QAAuB;AACtC,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKO,cAAuB;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,qBAAqB,UAAwB;AAClD,SAAK,oBAAoB,KAAK,IAAI,GAAG,QAAQ;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKO,cAAc,MAAc,YAAoB,GAAS;AAC9D,QAAI,KAAK,qBAAqB,KAAM;AAEpC,UAAM,OAAO,KAAK,QAAQ,QAAQ,IAAI;AACtC,QAAI,CAAC,MAAM;AACT,cAAQ,KAAK,wCAAwC,IAAI,mBAAmB;AAC5E;AAAA,IACF;AAGA,QAAI,YAAY,KAAK,QAAQ,IAAI,IAAI;AACrC,QAAI,CAAC,WAAW;AACd,kBAAY,KAAK,MAAM,WAAW,IAAI;AACtC,WAAK,QAAQ,IAAI,MAAM,SAAS;AAAA,IAClC;AAGA,UAAM,gBAAgB,KAAK,mBAAmB,KAAK,QAAQ,IAAI,KAAK,gBAAgB,IAAI;AAExF,QAAI,iBAAiB,KAAK,oBAAoB,GAAG;AAE/C,gBAAU,MAAM;AAChB,gBAAU,OAAO;AACjB,gBAAU,sBAAsB,CAAC;AACjC,gBAAU,mBAAmB,CAAC;AAC9B,gBAAU,KAAK;AACf,oBAAc,YAAY,WAAW,KAAK,mBAAmB,IAAI;AAAA,IACnE,OAAO;AAEL,UAAI,eAAe;AACjB,sBAAc,QAAQ,GAAG;AAAA,MAC3B;AACA,gBAAU,MAAM;AAChB,gBAAU,OAAO;AACjB,gBAAU,sBAAsB,CAAC;AACjC,gBAAU,mBAAmB,CAAC;AAC9B,gBAAU,OAAO,GAAG;AACpB,gBAAU,KAAK;AAAA,IACjB;AAEA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,OAAO,WAAyB;AACrC,QAAI,KAAK,SAAU;AACnB,SAAK,MAAM,OAAO,SAAS;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,aAAO,KAAK;AAAA,IACd;AACA,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,SAAK,QAAQ;AACb,SAAK,MAAM,cAAc;AAAA,EAC3B;AACF;;;AC7GO,IAAM,0BAAN,MAAM,iCAAgC,UAAU;AAAA,EACrD,OAAe,YAA0C,oBAAI,IAAI;AAAA,EACjE,OAAe,kBAAwD,oBAAI,IAAI;AAAA;AAAA,EAC/E,OAAe,mBAA+C;AAAA,EAC9D,OAAe,mBAA4B;AAAA,EAC3C,OAAe,cAA0D,oBAAI,IAAI;AAAA,EAEzE;AAAA,EACS;AAAA,EACT,aAAkD;AAAA,EAClD;AAAA,EACA,WAA6B;AAAA,EAC7B,eAA8B;AAAA,EAE9B,aAA+B,oBAAI,IAAI;AAAA,EACvC,eAA8B;AAAA,EAC9B,mBAAkC;AAAA,EAClC,mBAA2B;AAAA,EAC3B,uBAA+B;AAAA;AAAA,EAG/B,qBAAsD,oBAAI,IAAI;AAAA;AAAA,EAE9D,iBAAsC,oBAAI,IAAI;AAAA;AAAA,EAG9C,oBAA6B;AAAA,EAC7B,iBAAyB;AAAA;AAAA,EACzB;AAAA,EAER,YAAY,OAAuB,QAA8B;AAC/D,UAAM;AACN,SAAK,QAAQ;AACb,SAAK,SAAS;AACd,SAAK,gBAAgB,uBAAuB,YAAY;AACxD,SAAK,iBAAiB,wBAAwB,YAAY;AAE1D,QAAI,OAAO,YAAY;AACrB,iBAAW,CAAC,MAAM,WAAW,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACnE,aAAK,WAAW,IAAI,MAAM,YAAY,OAAO;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAc,oBAAoB,SAAwB;AACxD,6BAAwB,mBAAmB;AAE3C,QAAI,SAAS;AACX,UAAI,CAAC,yBAAwB,kBAAkB;AAC7C,iCAAwB,mBAAmB,IAAI,oBAAoB;AACnE,iCAAwB,iBAAiB,KAAK;AAAA,MAChD;AAEA,iBAAW,YAAY,yBAAwB,WAAW;AACxD,YAAI,SAAS,YAAY,SAAS,cAAc;AAC9C,mCAAwB,iBAAiB;AAAA,YACvC,SAAS;AAAA,YACT,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAEA,+BAAwB,iBAAiB,KAAK;AAAA,IAChD,OAAO;AACL,UAAI,yBAAwB,kBAAkB;AAC5C,iCAAwB,iBAAiB,KAAK;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAc,qBAA8B;AAC1C,WAAO,yBAAwB;AAAA,EACjC;AAAA,EAEA,OAAc,cAAc,cAAsB,WAA4C;AAC5F,UAAM,kBAAkB,yBAAwB,YAAY,IAAI,YAAY;AAC5E,QAAI,CAAC,gBAAiB,QAAO;AAC7B,WAAO,gBAAgB,IAAI,SAAS,KAAK;AAAA,EAC3C;AAAA,EAEA,OAAc,gBAAgB,cAA4D;AACxF,WAAO,yBAAwB,YAAY,IAAI,YAAY,KAAK;AAAA,EAClE;AAAA,EAEA,OAAc,kBAAkB,cAAsB,WAAwB;AAC5E,UAAM,WAAW,yBAAwB,gBAAgB,IAAI,YAAY;AACzE,WAAO,UAAU,WAAW,IAAI,SAAS,KAAK;AAAA,EAChD;AAAA,EAEA,OAAc,oBAAoB,cAAqC;AACrE,UAAM,WAAW,yBAAwB,gBAAgB,IAAI,YAAY;AACzE,WAAO,UAAU,oBAAoB;AAAA,EACvC;AAAA,EAEO,cAAgC;AACrC,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,WAAiB;AACzB,6BAAwB,UAAU,IAAI,IAAI;AAC1C,SAAK,oBAAoB;AAAA,EAC3B;AAAA,EAEQ,sBAA4B;AAClC,SAAK,aAAa,IAAI,6BAA6B,KAAK,OAAO,KAAK,aAAa;AACjF,SAAK,WAAW,IAAI,UAAU;AAC9B,SAAK,eAAe,KAAK,YAAY,QAAQ,SAAS,yBAAwB,UAAU,IAAI;AAG5F,6BAAwB,gBAAgB,IAAI,KAAK,cAAc,IAAI;AAEnE,SAAK,uBAAuB;AAC5B,SAAK,eAAe;AACpB,SAAK,iBAAiB;AACtB,SAAK,oBAAoB;AACzB,SAAK,oBAAoB;AAEzB,QAAI,yBAAwB,oBAAoB,yBAAwB,kBAAkB;AACxF,+BAAwB,iBAAiB,aAAa,KAAK,cAAc,KAAK,QAAQ;AAAA,IACxF;AAEA,SAAK,SAAS,KAAK,OAAO,YAAY;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAClC,SAAK,mBAAmB,MAAM;AAC9B,QAAI,CAAC,KAAK,OAAO,YAAa;AAE9B,eAAW,cAAc,KAAK,OAAO,aAAa;AAChD,UAAI,mBAAmB,KAAK,mBAAmB,IAAI,WAAW,IAAI;AAClE,UAAI,CAAC,kBAAkB;AACrB,2BAAmB,CAAC;AACpB,aAAK,mBAAmB,IAAI,WAAW,MAAM,gBAAgB;AAAA,MAC/D;AACA,uBAAiB,KAAK,UAAU;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAClC,SAAK,eAAe,MAAM;AAC1B,eAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM,GAAG;AACzE,UAAI,WAAW;AACf,UAAI,YAAY,WAAW;AACzB,cAAM,OAAO,iBAAiB,QAAQ,YAAY,SAAS;AAC3D,YAAI,KAAM,YAAW,KAAK;AAAA,MAC5B,WAAW,YAAY,QAAQ,YAAY,KAAK,SAAS,SAAS,GAAG;AACnE,cAAM,OAAO,iBAAiB,QAAQ,YAAY,KAAK,SAAS,CAAC,EAAE,SAAS;AAC5E,YAAI,KAAM,YAAW,KAAK;AAAA,MAC5B;AACA,WAAK,eAAe,IAAI,WAAW,QAAQ;AAAA,IAC7C;AAAA,EACF;AAAA,EAEQ,mBAAyB;AAC/B,QAAI,CAAC,KAAK,aAAc;AAExB,UAAM,eAAe,oBAAI,IAA8B;AAEvD,eAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM,GAAG;AACzE,mBAAa,IAAI,WAAW;AAAA,QAC1B;AAAA,QACA,MAAM,YAAY,QAAQ;AAAA,QAC1B,iBAAiB,YAAY,aAAa;AAAA,MAC5C,CAAC;AAAA,IACH;AAEA,6BAAwB,YAAY,IAAI,KAAK,cAAc,YAAY;AAAA,EACzE;AAAA,EAEQ,yBAA+B;AACrC,UAAM,UAAU,oBAAI,IAAY;AAEhC,eAAW,eAAe,OAAO,OAAO,KAAK,OAAO,MAAM,GAAG;AAC3D,UAAI,YAAY,WAAW;AACzB,gBAAQ,IAAI,YAAY,SAAS;AAAA,MACnC,WAAW,YAAY,MAAM;AAC3B,mBAAW,SAAS,YAAY,KAAK,UAAU;AAC7C,kBAAQ,IAAI,MAAM,SAAS;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAEA,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,iBAAiB,QAAQ,MAAM;AAC5C,UAAI,MAAM;AACR,aAAK,cAAc,aAAa,QAAQ,IAAI;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,SAAU;AAEpB,QAAI,KAAK,OAAO,YAAY;AAC1B,iBAAW,CAAC,MAAM,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,UAAU,GAAG;AACxE,YAAI;AACJ,gBAAQ,YAAY,MAAM;AAAA,UACxB,KAAK;AACH;AACA;AAAA,UACF,KAAK;AACH;AACA;AAAA,UACF,KAAK;AACH;AACA;AAAA,UACF;AACE;AAAA,QACJ;AACA,aAAK,SAAS,cAAc,MAAM,WAAW,YAAY,OAAO;AAAA,MAClE;AAAA,IACF;AAEA,eAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,KAAK,OAAO,MAAM,GAAG;AACzE,UAAI,eAAe;AACnB,UAAI,YAAY,WAAW;AACzB,cAAM,OAAO,iBAAiB,QAAQ,YAAY,SAAS;AAC3D,YAAI,KAAM,gBAAe,KAAK;AAAA,MAChC,WAAW,YAAY,QAAQ,YAAY,KAAK,SAAS,SAAS,GAAG;AACnE,cAAM,OAAO,iBAAiB,QAAQ,YAAY,KAAK,SAAS,CAAC,EAAE,SAAS;AAC5E,YAAI,KAAM,gBAAe,KAAK;AAAA,MAChC;AACA,WAAK,SAAS,SAAS,WAAW,EAAE,UAAU,aAAa,CAAC;AAAA,IAC9D;AAEA,QAAI,KAAK,OAAO,aAAa;AAC3B,iBAAW,cAAc,KAAK,OAAO,aAAa;AAChD,aAAK,SAAS,eAAe;AAAA,UAC3B,MAAM,WAAW;AAAA,UACjB,IAAI,WAAW;AAAA,UACf,YAAY,WAAW,OACnB,OAAO,QAAQ,WAAW,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,KAAK,OAAO;AAAA,YACvD,WAAW;AAAA,YACX,UAAU;AAAA,YACV;AAAA,UACF,EAAE,IACF,CAAC;AAAA,QACP,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEO,OAAO,WAAyB;AACrC,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,WAAW,UAAU,EAAG;AAGtD,QAAI,KAAK,mBAAmB;AAC1B,YAAM,aAAa,KAAK,eAAe,sBAAsB,KAAK,OAAO,KAAK,cAAc;AAC5F,UAAI,CAAC,WAAW,cAAc;AAE5B,aAAK,oBAAoB;AACzB;AAAA,MACF;AAAA,IAEF;AAEA,SAAK,UAAU,OAAO,SAAS;AAC/B,SAAK,WAAW,OAAO,SAAS;AAChC,SAAK,oBAAoB;AAGzB,QAAI,KAAK,cAAc;AACrB,YAAM,mBAAmB,KAAK,mBAAmB,IAAI,KAAK,YAAY;AACtE,UAAI,kBAAkB;AACpB,mBAAW,cAAc,kBAAkB;AAEzC,cAAI,WAAW,aAAa,QAAW;AACrC,kBAAM,gBACJ,OAAO,WAAW,aAAa,YAAY,IAAM,WAAW;AAC9D,kBAAM,iBAAiB,KAAK,mBAAmB,KAAK;AACpD,gBAAI,iBAAiB,cAAe;AAAA,UACtC;AAGA,cAAI,mBAAmB;AACvB,cAAI,WAAW,MAAM;AAEnB,uBAAW,SAAS,WAAW,MAAM;AACnC,kBAAI,KAAK,WAAW,IAAI,KAAK,MAAM,WAAW,KAAK,KAAK,GAAG;AACzD,mCAAmB;AACnB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,cAAI,kBAAkB;AACpB,iBAAK,SAAS,WAAW,EAAE;AAC3B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,kBAAwB;AAC9B,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,WAAY;AAE5C,UAAM,cAAc,KAAK,OAAO,OAAO,KAAK,YAAY;AACxD,QAAI,CAAC,YAAa;AAElB,QAAI,kBAAiC;AAErC,QAAI,YAAY,WAAW;AACzB,wBAAkB,YAAY;AAAA,IAChC,WAAW,YAAY,MAAM;AAC3B,YAAM,aAAa,KAAK,WAAW,IAAI,YAAY,KAAK,SAAS,KAAK;AAEtE,eAAS,IAAI,YAAY,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC9D,cAAM,QAAQ,YAAY,KAAK,SAAS,CAAC;AACzC,YAAI,cAAc,MAAM,WAAW;AACjC,4BAAkB,MAAM;AACxB;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,mBAAmB,YAAY,KAAK,SAAS,SAAS,GAAG;AAC5D,0BAAkB,YAAY,KAAK,SAAS,CAAC,EAAE;AAAA,MACjD;AAAA,IACF;AAEA,QAAI,mBAAmB,oBAAoB,KAAK,kBAAkB;AAChE,UAAI,KAAK,OAAO,OAAO;AACrB,gBAAQ;AAAA,UACN,eAAe,KAAK,YAAY,KAAK,KAAK,gBAAgB,OAAO,eAAe,YAAY,KAAK,OAAO,QAAQ,SAAS;AAAA,QAC3H;AAAA,MACF;AACA,YAAM,YAAY,KAAK,sBAAsB,KAAK,YAAY,IAC1D,KAAK,OAAO,IAAI,KAAK,uBACrB;AACJ,WAAK,WAAW,cAAc,iBAAiB,SAAS;AACxD,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEO,aAAa,MAAc,OAAkB;AAClD,SAAK,WAAW,IAAI,MAAM,KAAK;AAE/B,QAAI,KAAK,UAAU;AACjB,UAAI,OAAO,UAAU,WAAW;AAC9B,aAAK,SAAS,SAAS,MAAM,KAAK;AAAA,MACpC,WAAW,OAAO,UAAU,UAAU;AACpC,YAAI,OAAO,UAAU,KAAK,GAAG;AAC3B,eAAK,SAAS,QAAQ,MAAM,KAAK;AAAA,QACnC,OAAO;AACL,eAAK,SAAS,UAAU,MAAM,KAAK;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEO,aAAa,MAAmB;AACrC,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA,EAEO,SAAS,WAAyB;AACvC,QAAI,KAAK,iBAAiB,UAAW;AAErC,QAAI,KAAK,OAAO,OAAO;AACrB,cAAQ,IAAI,eAAe,KAAK,YAAY,cAAc,KAAK,YAAY,OAAO,SAAS,EAAE;AAAA,IAC/F;AAEA,SAAK,eAAe;AACpB,SAAK,mBAAmB;AACxB,SAAK,uBAAuB,KAAK,iBAAiB,SAAS;AAE3D,QAAI,KAAK,sBAAsB,SAAS,GAAG;AACzC,WAAK,mBAAmB,KAAK,OAAO,IAAI,KAAK;AAAA,IAC/C,OAAO;AACL,WAAK,mBAAmB;AAAA,IAC1B;AAEA,SAAK,UAAU,UAAU,SAAS;AAClC,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEO,kBAAiC;AACtC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,UAAU,QAAuB;AACtC,SAAK,YAAY,UAAU,MAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKO,WAAoB;AACzB,WAAO,KAAK,YAAY,YAAY,KAAK;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,kBAAkB,SAAwB;AAC/C,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,kBAAkB,QAAsB;AAC7C,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,oBAA6C;AACzD,WAAO,wBAAwB,YAAY;AAAA,EAC7C;AAAA,EAEQ,iBAAiB,WAA2B;AAElD,WAAO,KAAK,eAAe,IAAI,SAAS,KAAK;AAAA,EAC/C;AAAA,EAEQ,sBAAsB,WAA4B;AACxD,UAAM,cAAc,KAAK,OAAO,OAAO,SAAS;AAChD,QAAI,CAAC,YAAa,QAAO;AACzB,WAAO,YAAY,sBAAsB;AAAA,EAC3C;AAAA,EAEO,iBAAiB,QAAgB,WAAuC;AAAA,EAE/E;AAAA,EAEU,YAAkB;AAC1B,6BAAwB,UAAU,OAAO,IAAI;AAE7C,QAAI,KAAK,cAAc;AACrB,+BAAwB,gBAAgB,OAAO,KAAK,YAAY;AAChE,+BAAwB,YAAY,OAAO,KAAK,YAAY;AAAA,IAC9D;AAEA,QAAI,yBAAwB,oBAAoB,KAAK,YAAY,KAAK,cAAc;AAClF,+BAAwB,iBAAiB,gBAAgB,KAAK,YAAY;AAAA,IAC5E;AAEA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,SAAS;AAAA,IACzB;AAEA,QAAI,KAAK,YAAY;AACnB,WAAK,WAAW,QAAQ;AAAA,IAC1B;AAAA,EACF;AACF;;;AC1fA,IAAqB,sBAArB,MAAyC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAES,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,mBAAmB;AAAA,EACnB,0BAA0B;AAAA,EAC1B,aAAa;AAAA,EACb,WAAW;AAAA;AAAA,EAGpB,YAAoB;AAAA,EACpB,OAAe;AAAA,EACf,OAAe;AAAA,EACf,gBAAyB;AAAA,EACzB,WAAqC,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA;AAAA,EAGlD,mBAA4B;AAAA,EAC5B,mBAA6C,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC1D,mBAA4B;AAAA,EAC5B,cAA8D;AAAA,IACpE,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAAA,EACQ,cAAuB;AAAA;AAAA,EAEvB,iBAA8B,oBAAI,IAAI;AAAA;AAAA,EAEtC,iBAAgC;AAAA;AAAA,EAEhC,gBAQH,CAAC;AAAA;AAAA,EAGE,iBAAgC;AAAA,EAChC,sBAA+C;AAAA,EAC/C,gBAAwB;AAAA,EACxB,gBAA+B;AAAA,EAE/B,SAAiB;AAEvB,UAAM,IAAI,KAAK;AACf,QAAI,KAAK,IAAK,QAAO;AACrB,QAAI,KAAK,IAAK,QAAO;AACrB,QAAI,KAAK,IAAK,QAAO;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,UAAsB,MAAe;AAC/C,SAAK,WAAW;AAChB,SAAK,YAAY,oBAAI,IAAI;AACzB,SAAK,wBAAwB;AAC7B,SAAK,iBAAiB,oBAAI,IAAI;AAC9B,SAAK,aAAa;AAClB,SAAK,uBAAuB;AAC5B,SAAK,qBAAqB;AAC1B,SAAK,kBAAkB,oBAAI,IAAI;AAE/B,SAAK,YAAY,SAAS,cAAc,KAAK;AAC7C,SAAK,UAAU,MAAM,WAAW;AAChC,SAAK,UAAU,MAAM,SAAS;AAC9B,SAAK,UAAU,MAAM,QAAQ;AAC7B,SAAK,UAAU,MAAM,QAAQ;AAC7B,SAAK,UAAU,MAAM,SAAS;AAC9B,SAAK,UAAU,MAAM,kBAAkB,KAAK;AAC5C,SAAK,UAAU,MAAM,SAAS;AAC9B,SAAK,UAAU,MAAM,eAAe;AACpC,SAAK,UAAU,MAAM,WAAW;AAChC,SAAK,UAAU,MAAM,aAAa;AAClC,SAAK,UAAU,MAAM,YAAY;AACjC,SAAK,UAAU,MAAM,SAAS;AAC9B,SAAK,UAAU,MAAM,gBAAgB;AAErC,UAAM,SAAS,SAAS,cAAc,KAAK;AAC3C,WAAO,MAAM,kBAAkB;AAC/B,WAAO,MAAM,UAAU;AACvB,WAAO,MAAM,QAAQ;AACrB,WAAO,MAAM,WAAW;AACxB,WAAO,MAAM,eAAe;AAC5B,WAAO,MAAM,UAAU;AACvB,WAAO,MAAM,iBAAiB;AAC9B,WAAO,MAAM,aAAa;AAC1B,WAAO,MAAM,SAAS;AAEtB,UAAM,aAAa,SAAS,cAAc,MAAM;AAChD,eAAW,KAAK;AAChB,eAAW,cAAc;AACzB,WAAO,YAAY,UAAU;AAE7B,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,MAAM,UAAU;AAC7B,iBAAa,MAAM,MAAM;AACzB,iBAAa,MAAM,aAAa;AAEhC,UAAM,aAAa,SAAS,cAAc,QAAQ;AAClD,eAAW,cAAc;AACzB,eAAW,MAAM,aAAa;AAC9B,eAAW,MAAM,SAAS;AAC1B,eAAW,MAAM,QAAQ;AACzB,eAAW,MAAM,SAAS;AAC1B,eAAW,MAAM,UAAU;AAC3B,eAAW,MAAM,eAAe;AAChC,eAAW,UAAU,MAAM,KAAK,gBAAgB;AAChD,iBAAa,YAAY,UAAU;AACnC,WAAO,YAAY,YAAY;AAG/B,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,MAAM,UAAU;AAC7B,iBAAa,MAAM,SAAS;AAC5B,iBAAa,MAAM,kBAAkB,KAAK;AAE1C,UAAM,eAAe,SAAS,cAAc,KAAK;AACjD,iBAAa,KAAK;AAClB,iBAAa,MAAM,kBAAkB;AACrC,iBAAa,MAAM,UAAU;AAC7B,iBAAa,MAAM,WAAW;AAC9B,iBAAa,MAAM,QAAQ;AAC3B,iBAAa,MAAM,QAAQ;AAC3B,iBAAa,MAAM,WAAW;AAC9B,iBAAa,MAAM,YAAY;AAC/B,iBAAa,MAAM,cAAc;AACjC,iBAAa,MAAM,aAAa;AAEhC,SAAK,SAAS,SAAS,cAAc,QAAQ;AAC7C,SAAK,OAAO,MAAM,OAAO;AACzB,SAAK,OAAO,MAAM,WAAW;AAG7B,UAAM,sBAAsB,SAAS,cAAc,KAAK;AACxD,wBAAoB,KAAK;AACzB,wBAAoB,MAAM,kBAAkB;AAC5C,wBAAoB,MAAM,UAAU;AACpC,wBAAoB,MAAM,WAAW;AACrC,wBAAoB,MAAM,QAAQ;AAClC,wBAAoB,MAAM,QAAQ;AAClC,wBAAoB,MAAM,WAAW;AACrC,wBAAoB,MAAM,YAAY;AACtC,wBAAoB,MAAM,aAAa;AACvC,wBAAoB,MAAM,aAAa;AAEvC,UAAM,uBAAuB,SAAS,cAAc,KAAK;AACzD,yBAAqB,MAAM,QAAQ;AACnC,yBAAqB,MAAM,aAAa;AACxC,yBAAqB,MAAM,eAAe;AAC1C,yBAAqB,MAAM,WAAW;AACtC,yBAAqB,MAAM,gBAAgB;AAC3C,yBAAqB,cAAc;AACnC,wBAAoB,YAAY,oBAAoB;AAEpD,UAAM,wBAAwB,SAAS,cAAc,KAAK;AAC1D,0BAAsB,KAAK;AAC3B,wBAAoB,YAAY,qBAAqB;AAErD,iBAAa,YAAY,YAAY;AACrC,iBAAa,YAAY,KAAK,MAAM;AACpC,iBAAa,YAAY,mBAAmB;AAE5C,SAAK,UAAU,YAAY,MAAM;AACjC,SAAK,UAAU,YAAY,YAAY;AAGvC,SAAK,UAAU,MAAM,UAAU,KAAK,aAAa,UAAU;AAE3D,aAAS,KAAK,YAAY,KAAK,SAAS;AAExC,SAAK,MAAM,KAAK,OAAO,WAAW,IAAI;AAEtC,UAAM,UAAU,CAAC,MAAa;AAC5B,QAAE,gBAAgB;AAAA,IACpB;AAEC,KAAC,aAAa,SAAS,YAAY,eAAe,eAAe,OAAO,EAAE,QAAQ,CAAC,SAAS;AAC3F,WAAK,UAAU,iBAAiB,MAAa,OAAO;AAAA,IACtD,CAAC;AAED,SAAK,UAAU,iBAAiB,WAAW,CAAC,MAAM;AAChD,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AACD,SAAK,UAAU,iBAAiB,aAAa,CAAC,MAAM;AAClD,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AAED,SAAK,OAAO,iBAAiB,aAAa,CAAC,MAAM;AAC/C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,kBAAkB,CAAC;AAAA,IAC1B,CAAC;AACD,SAAK,OAAO,iBAAiB,aAAa,CAAC,MAAM;AAC/C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,kBAAkB,CAAC;AAAA,IAC1B,CAAC;AACD,SAAK,OAAO,iBAAiB,WAAW,CAAC,MAAM;AAC7C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AACD,SAAK,OAAO;AAAA,MACV;AAAA,MACA,CAAC,MAAM;AACL,UAAE,eAAe;AACjB,UAAE,gBAAgB;AAClB,aAAK,aAAa,CAAC;AAAA,MACrB;AAAA,MACA,EAAE,SAAS,MAAM;AAAA,IACnB;AAGA,WAAO,iBAAiB,aAAa,CAAC,MAAM;AAC1C,YAAM,SAAS,EAAE;AACjB,UAAI,OAAO,YAAY,UAAU;AAC/B;AAAA,MACF;AACA,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,kBAAkB,CAAC;AAAA,IAC1B,CAAC;AACD,WAAO,iBAAiB,aAAa,CAAC,MAAM,KAAK,eAAe,CAAC,CAAC;AAClE,WAAO,iBAAiB,WAAW,MAAM;AACvC,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AACD,WAAO,iBAAiB,aAAa,MAAM;AACzC,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IAC1B,CAAC;AAGD,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,MAAM,WAAW;AACzB,YAAQ,MAAM,QAAQ;AACtB,YAAQ,MAAM,SAAS;AACvB,YAAQ,MAAM,QAAQ;AACtB,YAAQ,MAAM,SAAS;AACvB,YAAQ,MAAM,SAAS;AACvB,YAAQ,MAAM,aAAa;AAC3B,SAAK,UAAU,YAAY,OAAO;AAClC,YAAQ,iBAAiB,aAAa,CAAC,MAAM;AAC3C,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAClB,WAAK,oBAAoB,CAAC;AAAA,IAC5B,CAAC;AACD,WAAO,iBAAiB,aAAa,CAAC,MAAM,KAAK,iBAAiB,CAAC,CAAC;AACpE,WAAO,iBAAiB,WAAW,MAAM,KAAK,mBAAmB,CAAC;AAGlE,WAAO,iBAAiB,WAAW,CAAC,MAAM;AACxC,UAAI,EAAE,QAAQ,YAAY,KAAK,gBAAgB;AAC7C,aAAK,cAAc;AAAA,MACrB;AAAA,IACF,CAAC;AAED,QAAI,UAAU;AACZ,WAAK,aAAa,QAAQ,YAAY,KAAK,UAAU,OAAO,CAAC,IAAI,QAAQ;AAAA,IAC3E;AAEA,SAAK,mBAAmB;AACxB,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEO,aAAa,MAAc,UAA2B;AAC3D,SAAK,UAAU,IAAI,MAAM,QAAQ;AAEjC,QAAI,CAAC,KAAK,uBAAuB;AAC/B,WAAK,aAAa,IAAI;AAAA,IACxB,OAAO;AACL,WAAK,uBAAuB;AAAA,IAC9B;AAAA,EACF;AAAA,EAEO,gBAAgB,MAAoB;AACzC,QAAI,KAAK,0BAA0B,MAAM;AACvC,WAAK,aAAa,IAAI;AAAA,IACxB;AACA,SAAK,UAAU,OAAO,IAAI;AAC1B,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEO,aAAa,MAA2B;AAE7C,SAAK,2BAA2B;AAEhC,QAAI,SAAS,MAAM;AACjB,WAAK,WAAW;AAChB,WAAK,wBAAwB;AAC7B,WAAK,eAAe,MAAM;AAC1B,WAAK,uBAAuB;AAAA,IAC9B,OAAO;AACL,YAAM,WAAW,KAAK,UAAU,IAAI,IAAI;AACxC,UAAI,UAAU;AACZ,aAAK,WAAW;AAChB,aAAK,wBAAwB;AAC7B,aAAK,yBAAyB;AAC9B,aAAK,eAAe,MAAM;AAC1B,aAAK,uBAAuB;AAE5B,aAAK,mBAAmB;AACxB,aAAK,kBAAkB;AAEvB,aAAK,YAAY;AACjB,aAAK,OAAO;AACZ,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAEA,SAAK,aAAa;AAClB,SAAK,uBAAuB;AAC5B,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,2BAAiC;AACvC,QAAI,CAAC,KAAK,SAAU;AAEpB,UAAM,yBAAyB,MAAM,KAAK,OAAO;AACjD,UAAM,4BAA4B,MAAM,KAAK,OAAO;AACpD,UAAM,0BAA0B,MAAM,KAAK,OAAO;AAElD,SAAK,SAAS,kDAA2C,sBAAsB;AAC/E,SAAK,SAAS,wDAA8C,yBAAyB;AACrF,SAAK,SAAS,oDAA4C,uBAAuB;AAEjF,SAAK,gBAAgB,IAAI,iBAAiB,sBAAsB;AAChE,SAAK,gBAAgB,IAAI,oBAAoB,yBAAyB;AACtE,SAAK,gBAAgB,IAAI,kBAAkB,uBAAuB;AAAA,EACpE;AAAA,EAEQ,6BAAmC;AACzC,QAAI,CAAC,KAAK,SAAU;AAEpB,UAAM,yBAAyB,KAAK,gBAAgB,IAAI,eAAe;AACvE,UAAM,4BAA4B,KAAK,gBAAgB,IAAI,kBAAkB;AAC7E,UAAM,0BAA0B,KAAK,gBAAgB,IAAI,gBAAgB;AAEzE,QAAI,wBAAwB;AAC1B,WAAK,SAAS,qDAA8C,sBAAsB;AAAA,IACpF;AACA,QAAI,2BAA2B;AAC7B,WAAK,SAAS,2DAAiD,yBAAyB;AAAA,IAC1F;AACA,QAAI,yBAAyB;AAC3B,WAAK,SAAS,uDAA+C,uBAAuB;AAAA,IACtF;AAEA,SAAK,gBAAgB,MAAM;AAAA,EAC7B;AAAA,EAEQ,yBAA+B;AACrC,UAAM,cAAc,KAAK,UAAU,cAAc,wBAAwB;AACzE,QAAI,CAAC,YAAa;AAElB,gBAAY,YAAY;AAExB,QAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,YAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,eAAS,MAAM,QAAQ;AACvB,eAAS,MAAM,YAAY;AAC3B,eAAS,MAAM,WAAW;AAC1B,eAAS,cAAc;AACvB,kBAAY,YAAY,QAAQ;AAChC;AAAA,IACF;AAEA,SAAK,UAAU,QAAQ,CAAC,GAAG,SAAS;AAClC,YAAM,OAAO,SAAS,cAAc,KAAK;AACzC,WAAK,MAAM,UAAU;AACrB,WAAK,MAAM,eAAe;AAC1B,WAAK,MAAM,eAAe;AAC1B,WAAK,MAAM,SAAS;AACpB,WAAK,MAAM,WAAW;AACtB,WAAK,MAAM,aAAa;AACxB,WAAK,MAAM,aAAa;AACxB,WAAK,MAAM,WAAW;AACtB,WAAK,MAAM,eAAe;AAE1B,YAAM,aAAa,SAAS,KAAK;AACjC,WAAK,MAAM,aAAa,aAAa,4BAA4B;AACjE,WAAK,MAAM,QAAQ,aAAa,YAAY;AAC5C,WAAK,MAAM,aAAa,aAAa,SAAS;AAE9C,WAAK,cAAc;AACnB,WAAK,QAAQ;AAEb,WAAK,eAAe,MAAM;AACxB,YAAI,SAAS,KAAK,uBAAuB;AACvC,eAAK,MAAM,aAAa;AAAA,QAC1B;AAAA,MACF;AACA,WAAK,eAAe,MAAM;AACxB,aAAK,MAAM,aACT,SAAS,KAAK,wBACV,4BACA;AAAA,MACR;AACA,WAAK,UAAU,CAAC,MAAM;AACpB,UAAE,gBAAgB;AAClB,aAAK,aAAa,IAAI;AAAA,MACxB;AAEA,kBAAY,YAAY,IAAI;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA,EAEQ,eAAqB;AAC3B,UAAM,QAAQ,KAAK,UAAU,cAAc,mBAAmB;AAC9D,QAAI,CAAC,MAAO;AAEZ,QAAI,KAAK,gBAAgB;AACvB,YAAM,cAAc,eAAe,KAAK,cAAc;AAAA,IACxD,WAAW,KAAK,uBAAuB;AACrC,YAAM,cAAc,qBAAqB,KAAK,qBAAqB;AAAA,IACrE,OAAO;AACL,YAAM,cAAc;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,uBAA6B;AACnC,UAAM,UAAU,MAAM;AACpB,WAAK,OAAO;AACZ,WAAK,qBAAqB,sBAAsB,OAAO;AAAA,IACzD;AACA,YAAQ;AAAA,EACV;AAAA,EAEQ,oBAA0B;AAChC,QAAI,CAAC,KAAK,SAAU;AACpB,UAAM,QAAQ,KAAK,SAAS,UAAU;AACtC,UAAM,aAAa,KAAK,SAAS,mBAAmB;AACpD,UAAM,cAAc,KAAK,SAAS,gBAAgB;AAGlD,UAAM,mBAAmB,oBAAI,IAAY;AACzC,gBAAY,QAAQ,CAAC,MAAM;AACzB,UAAI,EAAE,SAAS,IAAK,kBAAiB,IAAI,EAAE,IAAI;AAC/C,uBAAiB,IAAI,EAAE,EAAE;AAAA,IAC3B,CAAC;AAGD,UAAM,eAAe,oBAAI,IAAY;AACrC,eAAW,QAAQ,CAAC,OAAO;AACzB,YAAM,MAAM,KAAK,SAAU,sBAAsB,EAAE;AACnD,UAAI,KAAK;AACP,YAAI,SAAS,QAAQ,CAAC,OAAO,aAAa,IAAI,GAAG,QAAQ,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAGD,UAAM,cAAc,MAAM,KAAK,MAAM,KAAK,CAAC,EAAE;AAAA,MAC3C,CAAC,OAAO,CAAC,aAAa,IAAI,EAAE,KAAK,iBAAiB,IAAI,EAAE;AAAA,IAC1D;AAEA,UAAM,UAAoB,CAAC,GAAG,oBAAI,IAAY,CAAC,GAAG,aAAa,GAAG,UAAU,CAAC,CAAC;AAE9E,QAAI,QAAQ,WAAW,EAAG;AAG1B,UAAM,QAAQ,KAAK,WAAW,SAAS,WAAW;AAGlD,UAAM,YAAY,KAAK,aAAa,SAAS,KAAK;AAElD,QAAI,WAAW;AAEb,WAAK,aAAa,SAAS,KAAK;AAAA,IAClC,OAAO;AAEL,YAAM,SAAS,KAAK,aAAa,SAAS,KAAK;AAC/C,WAAK,kBAAkB,QAAQ,KAAK;AACpC,WAAK,kBAAkB,QAAQ,KAAK;AAAA,IACtC;AAEA,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEQ,aACN,SACA,OACS;AACT,UAAM,EAAE,UAAU,SAAS,IAAI;AAG/B,eAAW,CAAC,MAAM,OAAO,KAAK,UAAU;AACtC,iBAAW,MAAM,SAAS;AACxB,YAAI,SAAS,IAAI,EAAE,GAAG,IAAI,IAAI,GAAG;AAC/B,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAGA,eAAW,QAAQ,SAAS;AAC1B,YAAM,SAAS,SAAS,IAAI,IAAI,GAAG,QAAQ,KAAK;AAChD,YAAM,UAAU,SAAS,IAAI,IAAI,GAAG,QAAQ,KAAK;AACjD,UAAI,SAAS,QAAQ;AAEnB,cAAM,UAAU,oBAAI,IAAY;AAChC,cAAM,WAAW,oBAAI,IAAY;AAEjC,cAAM,cAAc,CAAC,MAAuB;AAC1C,kBAAQ,IAAI,CAAC;AACb,mBAAS,IAAI,CAAC;AAEd,qBAAW,YAAY,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;AAC5C,gBAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG;AAC1B,kBAAI,YAAY,QAAQ,EAAG,QAAO;AAAA,YACpC,WAAW,SAAS,IAAI,QAAQ,GAAG;AACjC,qBAAO;AAAA,YACT;AAAA,UACF;AAEA,mBAAS,OAAO,CAAC;AACjB,iBAAO;AAAA,QACT;AAEA,YAAI,YAAY,IAAI,EAAG,QAAO;AAAA,MAChC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,aACN,SACA,OACM;AACN,UAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,UAAU,KAAK,OAAO;AAG5B,UAAM,QAAQ;AACd,UAAM,QAAQ;AAGd,QAAI,UAAU,QAAQ,CAAC;AACvB,QAAI,iBAAiB;AAErB,eAAW,QAAQ,SAAS;AAC1B,YAAM,eAAe,SAAS,IAAI,IAAI,GAAG,QAAQ,MAAM,SAAS,IAAI,IAAI,GAAG,QAAQ;AACnF,UAAI,cAAc,gBAAgB;AAChC,yBAAiB;AACjB,kBAAU;AAAA,MACZ;AAAA,IACF;AAGA,UAAM,eAAe,oBAAI,IAAY;AACrC,eAAW,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,EAAG,cAAa,IAAI,CAAC;AAC/D,eAAW,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,EAAG,cAAa,IAAI,CAAC;AAG/D,UAAM,oBAAoB,QAAQ,OAAO,CAAC,MAAM,MAAM,WAAW,aAAa,IAAI,CAAC,CAAC;AACpF,UAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,MAAM,WAAW,CAAC,aAAa,IAAI,CAAC,CAAC;AAG1E,UAAM,UAAU,UAAU;AAC1B,UAAM,UAAU,UAAU;AAC1B,SAAK,eAAe,IAAI,SAAS,EAAE,GAAG,SAAS,GAAG,QAAQ,CAAC;AAG3D,UAAM,qBAAqB,kBAAkB;AAC7C,QAAI,qBAAqB,GAAG;AAG1B,YAAM,cAAc,QAAQ;AAC5B,YAAM,gBAAgB,qBAAqB;AAC3C,YAAM,YAAY,iBAAiB,IAAI,KAAK;AAG5C,YAAM,kBAAkB,KAAK,IAAI,OAAO,KAAK,IAAI,IAAI,QAAQ,IAAI;AACjE,YAAM,SAAS,KAAK,IAAI,WAAW,iBAAiB,GAAG;AAGvD,YAAM,kBAAkB,KAAK,wBAAwB,mBAAmB,KAAK;AAG7E,eAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,cAAM,QAAS,IAAI,KAAK,KAAK,IAAK,gBAAgB,SAAS,KAAK,KAAK;AACrE,cAAM,IAAI,UAAU,SAAS,KAAK,IAAI,KAAK;AAC3C,cAAM,IAAI,UAAU,SAAS,KAAK,IAAI,KAAK;AAC3C,aAAK,eAAe,IAAI,gBAAgB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;AAAA,MACtD;AAAA,IACF;AAGA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,cACJ,qBAAqB,IACjB,KAAK;AAAA,QACH,GAAG,kBAAkB,IAAI,CAAC,MAAM;AAC9B,gBAAM,MAAM,KAAK,eAAe,IAAI,CAAC;AACrC,iBAAO,KAAK,MAAM,IAAI,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,CAAC;AAAA,QAClE,CAAC;AAAA,MACH,IACA;AAEN,YAAM,cAAc,cAAc,QAAQ;AAE1C,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,cAAM,QAAS,IAAI,KAAK,KAAK,IAAK,OAAO,SAAS,KAAK,KAAK;AAC5D,cAAM,IAAI,UAAU,cAAc,KAAK,IAAI,KAAK;AAChD,cAAM,IAAI,UAAU,cAAc,KAAK,IAAI,KAAK;AAChD,aAAK,eAAe,IAAI,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;AAAA,MAC7C;AAAA,IACF;AAGA,SAAK,wBAAwB,SAAS,OAAO,EAAE;AAAA,EACjD;AAAA,EAEQ,wBACN,OACA,OACU;AACV,QAAI,MAAM,UAAU,EAAG,QAAO;AAE9B,UAAM,EAAE,UAAU,SAAS,IAAI;AAG/B,UAAM,MAAM,oBAAI,IAAyB;AACzC,eAAW,KAAK,OAAO;AACrB,UAAI,IAAI,GAAG,oBAAI,IAAI,CAAC;AAAA,IACtB;AAEA,eAAW,KAAK,OAAO;AACrB,iBAAW,UAAU,SAAS,IAAI,CAAC,KAAK,CAAC,GAAG;AAC1C,YAAI,MAAM,SAAS,MAAM,GAAG;AAC1B,cAAI,IAAI,CAAC,EAAG,IAAI,MAAM;AACtB,cAAI,IAAI,MAAM,EAAG,IAAI,CAAC;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAmB,CAAC;AAC1B,UAAM,YAAY,IAAI,IAAI,KAAK;AAG/B,QAAI,UAAU,MAAM;AAAA,MAAO,CAAC,GAAG,OAC5B,IAAI,IAAI,CAAC,GAAG,QAAQ,OAAO,IAAI,IAAI,CAAC,GAAG,QAAQ,KAAK,IAAI;AAAA,IAC3D;AAEA,WAAO,UAAU,OAAO,GAAG;AACzB,aAAO,KAAK,OAAO;AACnB,gBAAU,OAAO,OAAO;AAExB,UAAI,UAAU,SAAS,EAAG;AAG1B,UAAI,WAA0B;AAC9B,UAAI,YAAY;AAEhB,iBAAW,KAAK,WAAW;AACzB,cAAM,cAAc,IAAI,IAAI,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI;AACnD,YAAI,cAAc,aAAa,aAAa,MAAM;AAChD,sBAAY;AACZ,qBAAW;AAAA,QACb;AAAA,MACF;AAEA,gBAAU;AAAA,IACZ;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,wBACN,SACA,OACA,YACM;AACN,UAAM,EAAE,SAAS,IAAI;AACrB,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,QAAQ;AACd,UAAM,QAAQ;AACd,UAAM,UAAU,KAAK,IAAI,OAAO,KAAK,IAAI;AAEzC,aAAS,OAAO,GAAG,OAAO,YAAY,QAAQ;AAC5C,YAAM,SAAS,oBAAI,IAAwC;AAE3D,iBAAW,MAAM,SAAS;AACxB,eAAO,IAAI,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;AAAA,MACjC;AAGA,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,iBAAS,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AAC3C,gBAAM,IAAI,QAAQ,CAAC;AACnB,gBAAM,IAAI,QAAQ,CAAC;AACnB,gBAAM,OAAO,KAAK,eAAe,IAAI,CAAC;AACtC,gBAAM,OAAO,KAAK,eAAe,IAAI,CAAC;AAEtC,gBAAM,KAAK,KAAK,IAAI,KAAK;AACzB,gBAAM,KAAK,KAAK,IAAI,KAAK;AACzB,gBAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,KAAK;AAE7C,cAAI,OAAO,UAAU,KAAK;AACxB,kBAAM,SAAS,UAAU,MAAM,QAAQ;AACvC,kBAAM,KAAM,KAAK,OAAQ;AACzB,kBAAM,KAAM,KAAK,OAAQ;AAEzB,mBAAO,IAAI,CAAC,EAAG,MAAM;AACrB,mBAAO,IAAI,CAAC,EAAG,MAAM;AACrB,mBAAO,IAAI,CAAC,EAAG,MAAM;AACrB,mBAAO,IAAI,CAAC,EAAG,MAAM;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAGA,iBAAW,CAAC,MAAM,OAAO,KAAK,UAAU;AACtC,mBAAW,MAAM,SAAS;AACxB,gBAAM,UAAU,KAAK,eAAe,IAAI,IAAI;AAC5C,gBAAM,QAAQ,KAAK,eAAe,IAAI,EAAE;AACxC,cAAI,CAAC,WAAW,CAAC,MAAO;AAExB,gBAAM,KAAK,MAAM,IAAI,QAAQ;AAC7B,gBAAM,KAAK,MAAM,IAAI,QAAQ;AAC7B,gBAAM,OAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,KAAK;AAE7C,gBAAM,YAAY,UAAU;AAC5B,cAAI,OAAO,WAAW;AACpB,kBAAM,SAAS,OAAO,aAAa;AACnC,kBAAM,KAAM,KAAK,OAAQ;AACzB,kBAAM,KAAM,KAAK,OAAQ;AAEzB,mBAAO,IAAI,IAAI,EAAG,MAAM;AACxB,mBAAO,IAAI,IAAI,EAAG,MAAM;AACxB,mBAAO,IAAI,EAAE,EAAG,MAAM;AACtB,mBAAO,IAAI,EAAE,EAAG,MAAM;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AAGA,YAAM,UAAU,OAAO,IAAI,OAAO;AAClC,YAAM,UAAU,QAAQ,IAAI;AAE5B,iBAAW,MAAM,SAAS;AACxB,cAAM,MAAM,KAAK,eAAe,IAAI,EAAE;AACtC,cAAM,IAAI,OAAO,IAAI,EAAE;AAEvB,YAAI,KAAK,EAAE,KAAK;AAChB,YAAI,KAAK,EAAE,KAAK;AAGhB,YAAI,IAAI,KAAK,IAAI,SAAS,KAAK,IAAI,UAAU,SAAS,IAAI,CAAC,CAAC;AAC5D,YAAI,IAAI,KAAK,IAAI,SAAS,KAAK,IAAI,UAAU,SAAS,IAAI,CAAC,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WACN,SACA,aAKA;AACA,UAAM,WAAW,oBAAI,IAAyB;AAC9C,UAAM,WAAW,oBAAI,IAAyB;AAC9C,UAAM,QAA6C,CAAC;AAEpD,eAAW,MAAM,SAAS;AACxB,eAAS,IAAI,IAAI,oBAAI,IAAI,CAAC;AAC1B,eAAS,IAAI,IAAI,oBAAI,IAAI,CAAC;AAAA,IAC5B;AAEA,eAAW,KAAK,aAAa;AAC3B,UAAI,EAAE,SAAS,OAAO,QAAQ,SAAS,EAAE,IAAI,KAAK,QAAQ,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI;AAC3F,YAAI,CAAC,SAAS,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,EAAE,GAAG;AACpC,mBAAS,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,EAAE;AAC9B,mBAAS,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI;AAC9B,gBAAM,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,EAAE,GAAG,CAAC;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,UAAU,MAAM;AAAA,EACrC;AAAA,EAEQ,aACN,SACA,OACY;AACZ,UAAM,EAAE,UAAU,SAAS,IAAI;AAC/B,UAAM,SAAS,oBAAI,IAAoB;AAIvC,UAAM,QAAQ,QAAQ,OAAO,CAAC,QAAQ,SAAS,IAAI,EAAE,GAAG,QAAQ,OAAO,CAAC;AAGxE,UAAM,aACJ,MAAM,SAAS,IACX,QACA;AAAA,MACE,QAAQ;AAAA,QAAO,CAAC,GAAG,OAChB,SAAS,IAAI,CAAC,GAAG,QAAQ,OAAO,SAAS,IAAI,CAAC,GAAG,QAAQ,KAAK,IAAI;AAAA,MACrE;AAAA,IACF;AAGN,UAAM,eAAe,CAAC,MAAc,YAAiC;AACnE,UAAI,OAAO,IAAI,IAAI,EAAG,QAAO,OAAO,IAAI,IAAI;AAC5C,UAAI,QAAQ,IAAI,IAAI,EAAG,QAAO;AAE9B,cAAQ,IAAI,IAAI;AAChB,YAAM,UAAU,SAAS,IAAI,IAAI,KAAK,oBAAI,IAAI;AAC9C,UAAI,iBAAiB;AAErB,iBAAW,UAAU,SAAS;AAC5B,cAAM,cAAc,aAAa,QAAQ,OAAO;AAChD,yBAAiB,KAAK,IAAI,gBAAgB,WAAW;AAAA,MACvD;AAEA,YAAM,QAAQ,iBAAiB;AAC/B,aAAO,IAAI,MAAM,KAAK;AACtB,aAAO;AAAA,IACT;AAGA,eAAW,QAAQ,SAAS;AAC1B,UAAI,CAAC,OAAO,IAAI,IAAI,GAAG;AACrB,qBAAa,MAAM,oBAAI,IAAI,CAAC;AAAA,MAC9B;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,IAAI,GAAG,MAAM,KAAK,OAAO,OAAO,CAAC,GAAG,CAAC;AAC3D,eAAW,QAAQ,SAAS;AAC1B,UAAI,CAAC,OAAO,IAAI,IAAI,GAAG;AACrB,eAAO,IAAI,MAAM,WAAW,CAAC;AAAA,MAC/B;AAAA,IACF;AAGA,UAAM,cAA0B,CAAC;AACjC,UAAM,aAAa,KAAK,IAAI,GAAG,MAAM,KAAK,OAAO,OAAO,CAAC,CAAC,IAAI;AAE9D,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,kBAAY,KAAK,CAAC,CAAC;AAAA,IACrB;AAEA,eAAW,CAAC,MAAM,KAAK,KAAK,QAAQ;AAClC,kBAAY,KAAK,EAAE,KAAK,IAAI;AAAA,IAC9B;AAGA,WAAO,YAAY,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EAC/C;AAAA,EAEQ,kBACN,QACA,OACM;AACN,UAAM,EAAE,UAAU,SAAS,IAAI;AAG/B,UAAM,YAAY;AAElB,aAAS,OAAO,GAAG,OAAO,WAAW,QAAQ;AAE3C,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,aAAK,uBAAuB,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,UAAU,IAAI;AAAA,MACtE;AAGA,eAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,aAAK,uBAAuB,OAAO,CAAC,GAAG,OAAO,IAAI,CAAC,GAAG,UAAU,KAAK;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,uBACN,OACA,eACA,aACA,aACM;AAEN,UAAM,SAAS,oBAAI,IAAoB;AACvC,kBAAc,QAAQ,CAAC,MAAM,QAAQ,OAAO,IAAI,MAAM,GAAG,CAAC;AAG1D,UAAM,cAAmD,CAAC;AAE1D,eAAW,QAAQ,OAAO;AACxB,YAAM,iBAAiB,YAAY,IAAI,IAAI,KAAK,oBAAI,IAAI;AACxD,UAAI,MAAM;AACV,UAAI,QAAQ;AAEZ,iBAAW,aAAa,gBAAgB;AACtC,cAAM,MAAM,OAAO,IAAI,SAAS;AAChC,YAAI,QAAQ,QAAW;AACrB,iBAAO;AACP;AAAA,QACF;AAAA,MACF;AAGA,YAAM,KAAK,QAAQ,IAAI,MAAM,QAAQ,MAAM,QAAQ,IAAI;AACvD,kBAAY,KAAK,EAAE,MAAM,GAAG,CAAC;AAAA,IAC/B;AAGA,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;AAGtC,UAAM,SAAS;AACf,gBAAY,QAAQ,CAAC,EAAE,KAAK,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,EACpD;AAAA,EAEQ,kBACN,QACA,OAKM;AACN,UAAM,UAAU,KAAK,OAAO;AAC5B,UAAM,UAAU,KAAK,OAAO;AAG5B,UAAM,QAAQ;AACd,UAAM,QAAQ;AAGd,UAAM,WAAW;AACjB,UAAM,WAAW;AACjB,UAAM,OAAO;AACb,UAAM,OAAO;AAEb,UAAM,eAAe,QAAQ;AAC7B,UAAM,eAAe,QAAQ;AAG7B,UAAM,kBAAkB,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAC/D,UAAM,YAAY,OAAO;AAGzB,UAAM,aAAa,kBAAkB,eAAe;AACpD,UAAM,cAAc,YAAY,eAAe;AAG/C,UAAM,SAAS,KAAK,IAAI,WAAW,QAAQ,IAAI,UAAU,cAAc,IAAI,QAAQ,CAAC;AACpF,UAAM,SAAS,KAAK,IAAI,WAAW,QAAQ,IAAI,UAAU,eAAe,IAAI,QAAQ,CAAC;AAGrF,aAAS,WAAW,GAAG,WAAW,OAAO,QAAQ,YAAY;AAC3D,YAAM,QAAQ,OAAO,QAAQ;AAC7B,YAAM,IAAI,SAAS,WAAW;AAG9B,YAAM,cAAc,MAAM,SAAS,KAAK;AACxC,YAAM,eAAe,UAAU,cAAc;AAE7C,eAAS,UAAU,GAAG,UAAU,MAAM,QAAQ,WAAW;AACvD,cAAM,OAAO,MAAM,OAAO;AAC1B,cAAM,IAAI,MAAM,WAAW,IAAI,UAAU,IAAI,cAAc,UAAU;AACrE,aAAK,eAAe,IAAI,MAAM,EAAE,GAAG,EAAE,CAAC;AAAA,MACxC;AAAA,IACF;AAGA,SAAK,yBAAyB,QAAQ,OAAO,YAAY;AAAA,EAC3D;AAAA,EAEQ,yBACN,QACA,OACA,YACM;AACN,UAAM,EAAE,SAAS,IAAI;AACrB,UAAM,gBAAgB;AAGtB,aAAS,WAAW,GAAG,WAAW,OAAO,QAAQ,YAAY;AAC3D,YAAM,QAAQ,OAAO,QAAQ;AAC7B,YAAM,YAAuE,CAAC;AAE9E,iBAAW,QAAQ,OAAO;AACxB,cAAM,MAAM,KAAK,eAAe,IAAI,IAAI;AACxC,cAAM,UAAU,SAAS,IAAI,IAAI,KAAK,oBAAI,IAAI;AAE9C,YAAI,QAAQ,OAAO,GAAG;AAEpB,cAAI,OAAO;AACX,qBAAW,UAAU,SAAS;AAC5B,kBAAM,YAAY,KAAK,eAAe,IAAI,MAAM;AAChD,gBAAI,UAAW,SAAQ,UAAU;AAAA,UACnC;AACA,gBAAM,SAAS,OAAO,QAAQ;AAC9B,oBAAU,KAAK,EAAE,MAAM,QAAQ,UAAU,IAAI,EAAE,CAAC;AAAA,QAClD,OAAO;AACL,oBAAU,KAAK,EAAE,MAAM,QAAQ,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;AAAA,QACzD;AAAA,MACF;AAGA,gBAAU,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAG5C,YAAM,UAAU,KAAK,OAAO;AAC5B,YAAM,UAAU,gBAAgB;AAEhC,eAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,YAAI,OAAO,UAAU,CAAC,EAAE;AAGxB,YAAI,IAAI,GAAG;AACT,gBAAM,QAAQ,KAAK,eAAe,IAAI,UAAU,IAAI,CAAC,EAAE,IAAI,EAAG;AAC9D,iBAAO,KAAK,IAAI,MAAM,QAAQ,UAAU;AAAA,QAC1C;AAGA,eAAO,KAAK,IAAI,SAAS,KAAK,IAAI,UAAU,SAAS,IAAI,CAAC;AAE1D,aAAK,eAAe,IAAI,UAAU,CAAC,EAAE,IAAI,EAAG,IAAI;AAAA,MAClD;AAGA,YAAM,KAAK,MAAM,IAAI,CAAC,MAAM,KAAK,eAAe,IAAI,CAAC,EAAG,CAAC;AACzD,YAAM,OAAO,KAAK,IAAI,GAAG,EAAE;AAC3B,YAAM,OAAO,KAAK,IAAI,GAAG,EAAE;AAC3B,YAAM,WAAW,OAAO,QAAQ;AAChC,YAAM,SAAS,UAAU,IAAI;AAG7B,UAAI,OAAO,UAAU,WAAW,OAAO,UAAU,UAAU,SAAS;AAClE,mBAAW,QAAQ,OAAO;AACxB,eAAK,eAAe,IAAI,IAAI,EAAG,KAAK;AAAA,QACtC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAA+B;AAAA,EAC/B,cAA4B,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAEzC,kBAAkB,OAAyB;AACjD,UAAM,OAAO,KAAK,OAAO,sBAAsB;AAC/C,UAAM,KAAK,MAAM,UAAU,KAAK;AAChC,UAAM,KAAK,MAAM,UAAU,KAAK;AAGhC,QAAI,KAAK,gBAAgB;AACvB,UAAI,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,IAAI;AAChD,aAAK,cAAc;AACnB;AAAA,MACF;AAEA,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,MAAM,KAAK,gBAAgB,KAAK;AAClC,aAAK,cAAc;AACnB;AAAA,MACF;AACA,WAAK,gBAAgB;AACrB;AAAA,IACF;AAEA,UAAM,KAAK,KAAK,KAAK,QAAQ,KAAK;AAClC,UAAM,KAAK,KAAK,KAAK,QAAQ,KAAK;AAElC,QAAI,UAAyB;AAC7B,QAAI,cAAuB;AAC3B,SAAK,eAAe,QAAQ,CAAC,KAAK,aAAa;AAC7C,YAAM,WAAW,KAAK,UAAU,oBAAoB,QAAQ,KAAK;AACjE,YAAM,OAAO,KAAK,oBAAoB,UAAU,QAAQ;AACxD,YAAM,OAAO,IAAI,IAAI,KAAK,IAAI;AAC9B,YAAM,MAAM,IAAI,IAAI,KAAK,IAAI;AAC7B,YAAM,UAAU;AAChB,UAAI,KAAK,QAAQ,KAAK,OAAO,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,KAAK,GAAG;AACpE,kBAAU;AAEV,YAAI,YAAY,KAAK,OAAO,KAAK,MAAM,SAAS;AAE9C,gBAAM,WAAW,OAAO;AACxB,gBAAM,WAAW,MAAM;AACvB,gBAAM,cAAc;AACpB,cACE,KAAK,YACL,KAAK,WAAW,eAChB,KAAK,YACL,KAAK,WAAW,aAChB;AACA,0BAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,SAAS;AACX,UAAI,aAAa;AACf,YAAI,KAAK,eAAe,IAAI,OAAO,EAAG,MAAK,eAAe,OAAO,OAAO;AAAA,YACnE,MAAK,eAAe,IAAI,OAAO;AACpC,aAAK,OAAO;AACZ;AAAA,MACF;AAGA,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,KAAK,kBAAkB,WAAW,MAAM,KAAK,gBAAgB,KAAK;AACpE,aAAK,eAAe,OAAO;AAC3B,aAAK,gBAAgB;AACrB,aAAK,gBAAgB;AACrB;AAAA,MACF;AACA,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAErB,YAAM,MAAM,KAAK,eAAe,IAAI,OAAO;AAC3C,WAAK,gBAAgB;AACrB,WAAK,cAAc,EAAE,GAAG,IAAI,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE;AAAA,IAClD,OAAO;AACL,WAAK,gBAAgB;AACrB,WAAK,WAAW,EAAE,GAAG,KAAK,KAAK,MAAM,GAAG,KAAK,KAAK,KAAK;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAAyB;AACjD,UAAM,OAAO,KAAK,OAAO,sBAAsB;AAC/C,UAAM,KAAK,MAAM,UAAU,KAAK;AAChC,UAAM,KAAK,MAAM,UAAU,KAAK;AAEhC,QAAI,KAAK,eAAe;AACtB,WAAK,OAAO,KAAK,KAAK,SAAS;AAC/B,WAAK,OAAO,KAAK,KAAK,SAAS;AAC/B,WAAK,OAAO;AACZ;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,YAAMC,MAAK,KAAK,KAAK,QAAQ,KAAK;AAClC,YAAMC,MAAK,KAAK,KAAK,QAAQ,KAAK;AAElC,YAAM,MAAM,KAAK,eAAe,IAAI,KAAK,aAAa;AACtD,UAAI,KAAK;AACP,YAAI,IAAID,KAAI,KAAK,YAAY;AAC7B,YAAI,IAAIC,KAAI,KAAK,YAAY;AAC7B,aAAK,OAAO;AAAA,MACd;AACA;AAAA,IACF;AAGA,UAAM,KAAK,KAAK,KAAK,QAAQ,KAAK;AAClC,UAAM,KAAK,KAAK,KAAK,QAAQ,KAAK;AAClC,QAAI,oBAAmC;AAEvC,SAAK,eAAe,QAAQ,CAAC,KAAK,aAAa;AAC7C,YAAM,WAAW,KAAK,UAAU,oBAAoB,QAAQ,KAAK;AACjE,UAAI,CAAC,SAAU;AAEf,YAAM,OAAO,KAAK,oBAAoB,UAAU,QAAQ;AACxD,YAAM,OAAO,IAAI,IAAI,KAAK,IAAI;AAC9B,YAAM,MAAM,IAAI,IAAI,KAAK,IAAI;AAC7B,YAAM,UAAU;AAEhB,UAAI,KAAK,OAAO,KAAK,MAAM,SAAS;AAClC,cAAM,WAAW,OAAO;AACxB,cAAM,WAAW,MAAM;AACvB,cAAM,cAAc;AACpB,YACE,KAAK,YACL,KAAK,WAAW,eAChB,KAAK,YACL,KAAK,WAAW,aAChB;AACA,8BAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,sBAAsB,KAAK,gBAAgB;AAC7C,WAAK,iBAAiB;AACtB,WAAK,OAAO,MAAM,SAAS,oBAAoB,YAAY;AAC3D,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEQ,aAAa,OAAyB;AAC5C,UAAM,eAAe;AACrB,UAAM,QAAQ,CAAC,MAAM;AACrB,UAAM,aAAa,QAAQ,IAAI,MAAM;AACrC,UAAM,OAAO,KAAK,OAAO,sBAAsB;AAC/C,UAAM,KAAK,MAAM,UAAU,KAAK;AAChC,UAAM,KAAK,MAAM,UAAU,KAAK;AAEhC,UAAM,YAAY,KAAK;AACvB,QAAI,YAAY,KAAK,YAAY;AACjC,gBAAY,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,SAAS,CAAC;AAElD,SAAK,OAAO,MAAM,KAAK,KAAK,SAAS,YAAY;AACjD,SAAK,OAAO,MAAM,KAAK,KAAK,SAAS,YAAY;AACjD,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,kBAAkB,OAAyB;AACjD,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,SAAK,mBAAmB;AACxB,SAAK,mBAAmB;AAAA,MACtB,GAAG,MAAM,UAAU,KAAK;AAAA,MACxB,GAAG,MAAM,UAAU,KAAK;AAAA,IAC1B;AACA,SAAK,UAAU,MAAM,OAAO,KAAK,OAAO;AACxC,SAAK,UAAU,MAAM,MAAM,KAAK,MAAM;AACtC,SAAK,UAAU,MAAM,QAAQ;AAC7B,SAAK,UAAU,MAAM,SAAS;AAE9B,aAAS,KAAK,MAAM,SAAS;AAAA,EAC/B;AAAA,EAEQ,eAAe,OAAyB;AAC9C,QAAI,CAAC,KAAK,iBAAkB;AAC5B,UAAM,IAAI,MAAM,UAAU,KAAK,iBAAiB;AAChD,UAAM,IAAI,MAAM,UAAU,KAAK,iBAAiB;AAChD,SAAK,UAAU,MAAM,OAAO,IAAI;AAChC,SAAK,UAAU,MAAM,MAAM,IAAI;AAAA,EACjC;AAAA,EAEQ,mBAAyB;AAC/B,SAAK,mBAAmB;AACxB,aAAS,KAAK,MAAM,SAAS;AAAA,EAC/B;AAAA,EAEQ,oBAAoB,OAAyB;AACnD,UAAM,eAAe;AACrB,UAAM,gBAAgB;AACtB,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,SAAK,mBAAmB;AACxB,SAAK,cAAc;AAAA,MACjB,GAAG,MAAM;AAAA,MACT,GAAG,MAAM;AAAA,MACT,GAAG,KAAK;AAAA,MACR,GAAG,KAAK;AAAA,IACV;AACA,aAAS,KAAK,MAAM,SAAS;AAAA,EAC/B;AAAA,EAEQ,iBAAiB,OAAyB;AAChD,QAAI,CAAC,KAAK,iBAAkB;AAC5B,UAAM,KAAK,MAAM,UAAU,KAAK,YAAY;AAC5C,UAAM,KAAK,MAAM,UAAU,KAAK,YAAY;AAE5C,UAAM,IAAI,KAAK,IAAI,KAAK,KAAK,YAAY,IAAI,EAAE;AAC/C,UAAM,IAAI,KAAK,IAAI,KAAK,KAAK,YAAY,IAAI,EAAE;AAC/C,SAAK,UAAU,MAAM,QAAQ,IAAI;AACjC,SAAK,UAAU,MAAM,SAAS,IAAI;AAClC,SAAK,mBAAmB;AACxB,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,iBAAkB;AAC5B,SAAK,mBAAmB;AACxB,aAAS,KAAK,MAAM,SAAS;AAAA,EAC/B;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,cAAc,CAAC,KAAK;AACzB,UAAM,eAAe,KAAK,UAAU,SAAS,CAAC;AAC9C,QAAI,KAAK,aAAa;AACpB,mBAAa,MAAM,UAAU;AAC7B,WAAK,UAAU,MAAM,SAAS;AAAA,IAChC,OAAO;AACL,mBAAa,MAAM,UAAU;AAC7B,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEQ,qBAA2B;AACjC,UAAM,OAAO,KAAK,UAAU,sBAAsB;AAClD,UAAM,SAAS,SAAS,eAAe,cAAc;AACrD,UAAM,eAAe;AACrB,UAAM,cACJ,UAAU,OAAO,MAAM,YAAY,SAAS,OAAO,sBAAsB,EAAE,SAAS,MAAM;AAC5F,UAAM,SAAS,KAAK,IAAI,KAAK,KAAK,SAAS,YAAY;AACvD,UAAM,QAAQ,KAAK,IAAI,KAAK,KAAK,QAAQ,WAAW;AACpD,SAAK,OAAO,QAAQ,KAAK,MAAM,KAAK;AACpC,SAAK,OAAO,SAAS,KAAK,MAAM,MAAM;AAAA,EACxC;AAAA,EAEQ,SAAe;AACrB,QAAI,CAAC,KAAK,WAAY;AAEtB,SAAK,IAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACtC,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,SAAS,GAAG,GAAG,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM;AAG7D,QAAI,KAAK,kBAAkB,KAAK,qBAAqB;AACnD,WAAK,uBAAuB;AAC5B;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,sBAAsB;AAC9B,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK,IAAI,KAAK;AACd,SAAK,IAAI,UAAU,KAAK,MAAM,KAAK,IAAI;AACvC,SAAK,IAAI,MAAM,KAAK,WAAW,KAAK,SAAS;AAC7C,SAAK,iBAAiB;AACtB,SAAK,WAAW;AAChB,SAAK,IAAI,QAAQ;AACjB,SAAK,yBAAyB;AAC9B,SAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEQ,eAAe,WAAyB;AAC9C,QAAI,CAAC,KAAK,sBAAuB;AAEjC,UAAM,aAAa,wBAAwB,cAAc,KAAK,uBAAuB,SAAS;AAC9F,QAAI,CAAC,WAAY;AAEjB,SAAK,iBAAiB;AACtB,SAAK,sBAAsB;AAC3B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,gBAAsB;AAC5B,SAAK,iBAAiB;AACtB,SAAK,sBAAsB;AAC3B,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEQ,yBAA+B;AACrC,QAAI,CAAC,KAAK,uBAAuB,CAAC,KAAK,sBAAuB;AAE9D,UAAM,MAAM,KAAK;AACjB,UAAM,IAAI,KAAK,OAAO;AACtB,UAAM,IAAI,KAAK,OAAO;AACtB,UAAM,UAAU;AAGhB,QAAI,YAAY;AAChB,QAAI,SAAS,IAAI,IAAI,IAAI,EAAE;AAC3B,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,WAAW,IAAI,IAAI,IAAI,EAAE;AAC7B,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI,YAAY;AAChB,QAAI,eAAe;AACnB,QAAI,SAAS,UAAU,IAAI,EAAE;AAG7B,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI,YAAY;AAChB,QAAI,SAAS,UAAU,KAAK,cAAc,IAAI,IAAI,GAAG,EAAE;AAEvD,QAAI,KAAK,oBAAoB,iBAAiB;AAE5C,UAAI,YAAY;AAChB,UAAI,OAAO;AACX,UAAI,YAAY;AAChB,UAAI,SAAS,qBAAqB,IAAI,GAAG,IAAI,IAAI,EAAE;AACnD,UAAI,YAAY;AAChB,UAAI,OAAO;AACX,UAAI,SAAS,KAAK,oBAAoB,iBAAiB,IAAI,GAAG,IAAI,IAAI,EAAE;AACxE;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,oBAAoB,KAAM;AAEpC,UAAM,OAAO,KAAK,oBAAoB;AACtC,UAAM,WAAW,KAAK;AACtB,QAAI,SAAS,WAAW,EAAG;AAG3B,UAAM,aACJ,wBAAwB,kBAAkB,KAAK,uBAAuB,KAAK,SAAS,KAAK;AAC3F,UAAM,cAAc,wBAAwB,oBAAoB,KAAK,qBAAqB;AAG1F,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI,YAAY;AAChB,QAAI,SAAS,cAAc,KAAK,SAAS,IAAI,IAAI,GAAG,EAAE;AACtD,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI;AAAA,MACF,UAAU,OAAO,eAAe,WAAW,WAAW,QAAQ,CAAC,IAAI,UAAU;AAAA,MAC7E,IAAI;AAAA,MACJ;AAAA,IACF;AAGA,UAAM,UAAU;AAChB,UAAM,cAAc,IAAI,UAAU;AAClC,UAAM,aAAa,UAAU;AAC7B,UAAM,cAAc,aAAa;AAGjC,UAAM,iBAAiB,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAC7E,UAAM,OAAO,eAAe,CAAC,EAAE;AAC/B,UAAM,OAAO,eAAe,eAAe,SAAS,CAAC,EAAE;AACvD,UAAMC,SAAQ,KAAK,IAAI,MAAO,OAAO,IAAI;AAGzC,QAAI,YAAY;AAChB,QAAI,SAAS,YAAY,UAAU,GAAG,aAAa,CAAC;AAGpD,eAAW,SAAS,gBAAgB;AAClC,YAAM,IAAI,cAAe,MAAM,YAAY,QAAQA,SAAS;AAC5D,UAAI,cAAc;AAClB,UAAI,YAAY;AAChB,UAAI,UAAU;AACd,UAAI,OAAO,GAAG,UAAU,EAAE;AAC1B,UAAI,OAAO,GAAG,UAAU,EAAE;AAC1B,UAAI,OAAO;AAEX,UAAI,YAAY;AAChB,UAAI,OAAO;AACX,UAAI,YAAY;AAChB,UAAI,SAAS,MAAM,UAAU,SAAS,GAAG,GAAG,UAAU,EAAE;AAAA,IAC1D;AAGA,UAAM,eAAe,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,UAAoB,CAAC;AACxE,UAAM,SAAS,cAAe,eAAe,QAAQA,SAAS;AAC9D,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI,IAAI,QAAQ,SAAS,GAAG,GAAG,KAAK,KAAK,CAAC;AAC1C,QAAI,KAAK;AAGT,UAAM,aAAa;AACnB,UAAM,aAAa;AACnB,UAAM,UAAU;AAChB,UAAM,YAAY,KAAK;AAAA,MACrB;AAAA,OACC,IAAI,UAAU,IAAI,WAAW,SAAS,SAAS,MAAM,SAAS;AAAA,IACjE;AAEA,UAAM,kBAAkB,YAAY,SAAS,SAAS,WAAW,SAAS,SAAS;AACnF,QAAI,SAAS,IAAI,mBAAmB;AAEpC,eAAW,SAAS,gBAAgB;AAClC,YAAM,WAAW,gBAAgB,MAAM;AAGvC,UAAI,YAAY,WAAW,2BAA2B;AACtD,UAAI,SAAS,OAAO,YAAY,WAAW,UAAU;AAGrD,UAAI,cAAc,WAAW,YAAY;AACzC,UAAI,YAAY,WAAW,IAAI;AAC/B,UAAI,WAAW,OAAO,YAAY,WAAW,UAAU;AAGvD,UAAI,YAAY,WAAW,YAAY;AACvC,UAAI,OAAO,WAAW,wBAAwB;AAC9C,UAAI,YAAY;AAChB,UAAI,SAAS,MAAM,WAAW,QAAQ,YAAY,GAAG,aAAa,EAAE;AAGpE,UAAI,YAAY;AAChB,UAAI,OAAO;AACX,UAAI,SAAS,MAAM,MAAM,SAAS,IAAI,QAAQ,YAAY,GAAG,aAAa,EAAE;AAG5E,UAAI,UAAU;AACZ,YAAI,YAAY;AAChB,YAAI,UAAU;AACd,YAAI,IAAI,QAAQ,YAAY,GAAG,aAAa,GAAG,GAAG,GAAG,KAAK,KAAK,CAAC;AAChE,YAAI,KAAK;AAAA,MACX;AAEA,eAAS,YAAY;AAAA,IACvB;AAGA,QAAI,YAAY;AAChB,QAAI,OAAO;AACX,QAAI,YAAY;AAChB,QAAI,SAAS,wCAAwC,IAAI,GAAG,IAAI,EAAE;AAAA,EACpE;AAAA,EAEQ,mBAAyB;AAC/B,QAAI,CAAC,KAAK,SAAU;AACpB,UAAM,cAAc,KAAK,SAAS,gBAAgB;AAClD,UAAM,oBAAoB,KAAK,SAAS,sBAAsB;AAE9D,gBAAY,QAAQ,CAAC,eAAe;AAClC,YAAM,WACJ,WAAW,SAAS,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,IAAI,KAAK,eAAe,IAAI,WAAW,IAAI;AACtF,YAAM,SAAS,KAAK,eAAe,IAAI,WAAW,EAAE;AAEpD,UAAI,YAAY,QAAQ;AACtB,cAAM,YACJ,sBACC,kBAAkB,eAAe,WAAW,QAAQ,WAAW,SAAS,QACzE,kBAAkB,aAAa,WAAW;AAE5C,aAAK,IAAI,cAAc,YAAY,KAAK,0BAA0B,KAAK;AACvE,aAAK,IAAI,YAAY,YAAY,IAAI;AACrC,aAAK,IAAI,YAAY,WAAW,SAAS,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAE1D,aAAK,IAAI,UAAU;AAEnB,YAAI,WAAW,SAAS,KAAK;AAC3B,eAAK,IAAI,OAAO,SAAS,GAAG,SAAS,CAAC;AACtC,eAAK,IAAI,OAAO,OAAO,GAAG,OAAO,CAAC;AAAA,QACpC,OAAO;AAEL,gBAAM,cAAc,KAAK,UAAU,oBAAoB,WAAW,IAAI,KAAK;AAC3E,gBAAM,YAAY,KAAK,UAAU,oBAAoB,WAAW,EAAE,KAAK;AACvE,gBAAM,WAAW,KAAK,oBAAoB,WAAW,MAAM,WAAW;AACtE,gBAAM,SAAS,KAAK,oBAAoB,WAAW,IAAI,SAAS;AAGhE,gBAAM,aAAa,KAAK,iBAAiB,UAAU,QAAQ,SAAS,IAAI,GAAG,SAAS,IAAI,CAAC;AACzF,gBAAM,WAAW,KAAK,iBAAiB,QAAQ,UAAU,OAAO,IAAI,GAAG,OAAO,IAAI,CAAC;AAEnF,eAAK,IAAI,OAAO,WAAW,GAAG,WAAW,CAAC;AAC1C,eAAK,IAAI,OAAO,SAAS,GAAG,SAAS,CAAC;AAGtC,gBAAM,QAAQ,KAAK,MAAM,SAAS,IAAI,WAAW,GAAG,SAAS,IAAI,WAAW,CAAC;AAC7E,gBAAM,eAAe;AACrB,gBAAM,cAAc,KAAK,KAAK;AAC9B,eAAK,IAAI;AAAA,YACP,SAAS,IAAI,eAAe,KAAK,IAAI,QAAQ,WAAW;AAAA,YACxD,SAAS,IAAI,eAAe,KAAK,IAAI,QAAQ,WAAW;AAAA,UAC1D;AACA,eAAK,IAAI,OAAO,SAAS,GAAG,SAAS,CAAC;AACtC,eAAK,IAAI;AAAA,YACP,SAAS,IAAI,eAAe,KAAK,IAAI,QAAQ,WAAW;AAAA,YACxD,SAAS,IAAI,eAAe,KAAK,IAAI,QAAQ,WAAW;AAAA,UAC1D;AAAA,QACF;AAEA,aAAK,IAAI,OAAO;AAChB,aAAK,IAAI,YAAY,CAAC,CAAC;AAEvB,YAAI,aAAa,mBAAmB;AAClC,gBAAM,WAAW,kBAAkB;AACnC,gBAAM,QAAQ,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK;AACrD,gBAAM,QAAQ,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK;AAErD,eAAK,IAAI,YAAY,KAAK;AAC1B,eAAK,IAAI,UAAU;AACnB,eAAK,IAAI,IAAI,OAAO,OAAO,GAAG,GAAG,KAAK,KAAK,CAAC;AAC5C,eAAK,IAAI,KAAK;AAAA,QAChB;AAAA,MACF;AAAA,IACF,CAAC;AAID,UAAM,gBAAgB,EAAE,GAAG,IAAI,GAAG,GAAG;AACrC,SAAK,IAAI,cAAc;AACvB,SAAK,IAAI,WAAW,cAAc,IAAI,IAAI,cAAc,IAAI,IAAI,IAAI,EAAE;AAEtE,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,OAAO;AAChB,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,eAAe;AACxB,SAAK,IAAI,SAAS,OAAO,cAAc,GAAG,cAAc,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGQ,iBACN,QACA,QACA,WACA,YAC0B;AAC1B,UAAM,KAAK,OAAO,IAAI,OAAO;AAC7B,UAAM,KAAK,OAAO,IAAI,OAAO;AAE7B,QAAI,OAAO,KAAK,OAAO,GAAG;AACxB,aAAO,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,EAAE;AAAA,IACpC;AAGA,UAAM,SAAS,YAAY,KAAK,IAAI,MAAM,IAAK;AAC/C,UAAM,SAAS,aAAa,KAAK,IAAI,MAAM,IAAK;AAChD,UAAM,QAAQ,KAAK,IAAI,QAAQ,MAAM;AAErC,WAAO;AAAA,MACL,GAAG,OAAO,IAAI,KAAK;AAAA,MACnB,GAAG,OAAO,IAAI,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EAEQ,aAAmB;AACzB,QAAI,CAAC,KAAK,SAAU;AACpB,UAAM,gBAAgB,KAAK,SAAS,kBAAkB;AACtD,UAAM,oBAAoB,KAAK,SAAS,sBAAsB;AAC9D,UAAM,QAAQ,KAAK,SAAS,UAAU;AAGtC,SAAK,eAAe,QAAQ,CAAC,KAAK,aAAa;AAC7C,YAAM,aAAa,kBAAkB;AACrC,YAAM,wBAAwB,mBAAmB,eAAe;AAChE,YAAM,sBAAsB,mBAAmB,aAAa;AAC5D,YAAM,OAAO,MAAM,IAAI,QAAQ;AAC/B,YAAM,WAAW,KAAK,SAAU,oBAAoB,QAAQ;AAE5D,UAAI,aAAa,WAAW,KAAK,uBAAuB,KAAK;AAC7D,UAAI,cAAc,CAAC,mBAAmB;AACpC,qBAAa,KAAK;AAAA,MACpB,WAAW,yBAAyB,qBAAqB;AACvD,qBAAa,KAAK;AAAA,MACpB;AAGA,YAAM,MAAM,KAAK,OAAO;AACxB,YAAM,OAAO,KAAK,oBAAoB,UAAU,QAAQ;AACxD,YAAM,QAAQ,KAAK;AACnB,YAAM,QAAQ,KAAK;AACnB,YAAM,KAAK,IAAI,IAAI,QAAQ;AAC3B,YAAM,KAAK,IAAI,IAAI,QAAQ;AAG3B,YAAM,UAAU,OAAO,IAAI,KAAK;AAChC,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,SAAS;AAAA,QACtB,aAAa,IAAI;AAAA,MACnB;AACA,WAAK,IAAI,YAAY;AACrB,WAAK,IAAI,SAAS,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO;AAGpD,UAAI,UAAU;AACZ,cAAM,OAAO,KAAK,eAAe,IAAI,QAAQ;AAC7C,cAAM,aAAa,KAAK,mBAAmB;AAC3C,aAAK,aAAa,KAAK,IAAI,KAAK,GAAG,MAAM,UAAU;AAAA,MACrD;AAGA,YAAM,aACJ,QAAQ,IACJ,wBACA,QAAQ,IACN,wBACA;AACR,WAAK;AAAA,QACH,SAAS,YAAY;AAAA,QACrB,IAAI;AAAA,QACJ,KAAK,UAAU;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AAGA,UAAI,UAAU;AACZ,cAAM,MAAM,KAAK,SAAU,sBAAsB,QAAQ;AACzD,YAAI,KAAK;AACP,cAAI,OAAO,GAAG;AACZ,kBAAM,QAAQ,KAAK,WAAW,QAAQ,IAAI,KAAK;AAC/C,kBAAM,QAAQ,KAAK,IAAI,KAAK,QAAQ,EAAE;AACtC,kBAAM,QAAQ,IAAI,IAAI,QAAQ;AAC9B,iBAAK,IAAI,cAAc;AACvB,iBAAK,IAAI,YAAY;AACrB,iBAAK,IAAI,UAAU;AACnB,iBAAK,IAAI,OAAO,OAAO,KAAK;AAC5B,iBAAK,IAAI,OAAO,QAAQ,OAAO,KAAK;AACpC,iBAAK,IAAI,OAAO;AAGhB,kBAAM,WAAW,CAAC,GAAG,IAAI,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAC3E,gBAAI,SAAS,SAAS,GAAG;AACvB,oBAAM,OAAO,SAAS,CAAC,EAAE;AACzB,oBAAM,OAAO,SAAS,SAAS,SAAS,CAAC,EAAE;AAC3C,oBAAMA,SAAQ,KAAK,IAAI,MAAM,OAAO,IAAI;AACxC,mBAAK,IAAI,YAAY;AACrB,mBAAK,IAAI,cAAc;AACvB,yBAAW,MAAM,UAAU;AACzB,sBAAM,MAAM,SAAU,GAAG,YAAY,QAAQA,SAAS;AACtD,qBAAK,IAAI,UAAU;AACnB,qBAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AAC9B,qBAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AAC9B,qBAAK,IAAI,OAAO;AAChB,oBAAI,OAAO,GAAG;AACZ,wBAAM,QAAQ,GAAG,OAAO,SAAS,GAAG,SAAS,IAAI,GAAG,YAAY,EAAE;AAClE,uBAAK;AAAA,oBACH;AAAA,oBACA;AAAA,oBACA,QAAQ;AAAA,oBACR;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAGA,oBAAM,IAAI,KAAK,SAAU,UAAU,IAAI,SAAS;AAChD,oBAAM,KAAK,SAAU,KAAK,IAAI,MAAM,KAAK,IAAI,MAAM,CAAC,CAAC,IAAI,QAAQA,SAAS;AAC1E,mBAAK,IAAI,YAAY;AACrB,mBAAK,IAAI,UAAU;AACnB,mBAAK,IAAI,IAAI,IAAI,OAAO,GAAG,GAAG,KAAK,KAAK,CAAC;AACzC,mBAAK,IAAI,KAAK;AAGd,kBAAI,OAAO,GAAG;AACZ,sBAAM,KAAK,QAAQ,IAAI,mBAAmB;AAC1C,qBAAK;AAAA,kBACH,GAAG,IAAI,SAAS,KAAK,EAAE,QAAQ,CAAC,CAAC;AAAA,kBACjC,IAAI;AAAA,kBACJ,QAAQ;AAAA,kBACR;AAAA,kBACA;AAAA,kBACA;AAAA,kBACA;AAAA,gBACF;AAAA,cACF;AAGA,kBAAI,KAAK,eAAe,IAAI,QAAQ,KAAK,OAAO,GAAG;AACjD,sBAAM,QAAQ,KAAK;AACnB,oBAAI,QAAQ,QAAQ;AAGpB,sBAAM,aAAa,KAAK,SAAU,UAAU,IAAI,SAAS;AAEzD,2BAAW,MAAM,UAAU;AAEzB,sBAAI,SAAS;AACb,wBAAM,MAAM,SAAS,QAAQ,EAAE;AAC/B,sBAAI,SAAS,WAAW,GAAG;AACzB,6BAAS;AAAA,kBACX,WAAW,QAAQ,GAAG;AAEpB,0BAAM,gBAAgB,SAAS,MAAM,CAAC,GAAG,aAAa,GAAG;AACzD,6BACE,cAAc,GAAG,YACb,IACA,cAAc,iBACX,gBAAgB,eAAe,gBAAgB,GAAG,aACnD;AAAA,kBACV,WAAW,QAAQ,SAAS,SAAS,GAAG;AAEtC,0BAAM,gBAAgB,SAAS,MAAM,CAAC,GAAG,aAAa,GAAG;AACzD,6BACE,cAAc,GAAG,YACb,IACA,cAAc,iBACX,aAAa,kBAAkB,GAAG,YAAY,iBAC/C;AAAA,kBACV,OAAO;AAEL,0BAAM,gBAAgB,SAAS,MAAM,CAAC,GAAG,aAAa,GAAG;AACzD,0BAAM,gBAAgB,SAAS,MAAM,CAAC,GAAG,aAAa,GAAG;AACzD,wBAAI,cAAc,iBAAiB,cAAc,eAAe;AAC9D,0BAAI,cAAc,GAAG,WAAW;AAC9B,kCAAU,aAAa,kBAAkB,GAAG,YAAY;AAAA,sBAC1D,OAAO;AACL,kCAAU,gBAAgB,eAAe,gBAAgB,GAAG;AAAA,sBAC9D;AAAA,oBACF;AAAA,kBACF;AACA,2BAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AAGxC,sBAAI,SAAS;AACb,sBAAI,QAAQ;AACZ,sBAAI,UAAU;AAEd,sBAAI,SAAS,KAAK;AAChB,6BAAS;AACT,4BAAQ;AACR,8BAAU;AAAA,kBACZ,WAAW,SAAS,KAAK;AACvB,6BAAS;AACT,4BAAQ;AACR,8BAAU;AAAA,kBACZ,WAAW,SAAS,MAAM;AACxB,6BAAS;AACT,4BAAQ;AAAA,kBACV;AAGA,sBAAI,SAAS;AACX,yBAAK,IAAI,YAAY;AACrB,yBAAK,IAAI,SAAS,QAAQ,GAAG,QAAQ,GAAG,KAAK,EAAE;AAAA,kBACjD;AAEA,wBAAM,aAAa,SAAS,OAAO,MAAM,SAAS,KAAK,QAAQ,CAAC,CAAC,OAAO;AACxE,uBAAK;AAAA,oBACH,GAAG,MAAM,IAAI,GAAG,QAAQ,GAAG,UAAU,OAAO,GAAG,SAAS;AAAA,oBACxD;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,oBACA;AAAA,kBACF;AACA,2BAAS;AAAA,gBACX;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,WAAK,cAAc,yBAAyB,wBAAwB,KAAK,UAAU;AACjF,cAAM,oBAAoB,KAAK,SAAS,kBAAkB,QAAQ;AAClE,cAAM,SAAS,wBACX,IAAI,kBAAmB,WACvB,sBACE,kBAAmB,WACnB,aACE,IACA;AACR,YAAI,OAAO,GAAG;AACZ,gBAAM,OAAO,KAAK,QAAQ;AAC1B,eAAK,wBAAwB,IAAI,GAAG,MAAM,mBAAmB,QAAQ,MAAM,QAAQ,KAAK;AAAA,QAC1F;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB,UAAkB,UAA6C;AACzF,UAAM,MAAM,KAAK,OAAO;AACxB,UAAM,QAAQ,QAAQ,IAAI,MAAM,QAAQ,IAAI,MAAM;AAClD,UAAM,QAAQ,WAAY,QAAQ,IAAI,MAAM,MAAO,QAAQ,IAAI,KAAK;AACpE,QAAI,CAAC,SAAU,QAAO,EAAE,GAAG,OAAO,GAAG,MAAM;AAC3C,UAAM,OAAO,KAAK,eAAe,IAAI,QAAQ;AAC7C,QAAI,CAAC,QAAQ,MAAM,EAAG,QAAO,EAAE,GAAG,OAAO,GAAG,MAAM;AAElD,UAAM,MAAM,KAAK,UAAU,sBAAsB,QAAQ;AACzD,UAAM,QAAQ,MAAM,IAAI,SAAS,SAAS,KAAK,KAAK;AACpD,WAAO,EAAE,GAAG,OAAO,GAAG,QAAQ,MAAM;AAAA,EACtC;AAAA,EAEQ,YACN,MACA,GACA,GACA,OACA,UACA,MACA,OACM;AAEN,UAAM,KAAK,IAAI,KAAK,YAAY,KAAK;AACrC,UAAM,KAAK,IAAI,KAAK,YAAY,KAAK;AACrC,SAAK,cAAc,KAAK;AAAA,MACtB;AAAA,MACA,GAAG;AAAA,MACH,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,2BAAiC;AACvC,QAAI,KAAK,cAAc,WAAW,EAAG;AACrC,eAAW,OAAO,KAAK,eAAe;AACpC,WAAK,IAAI,aAAa,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AACtC,WAAK,IAAI,YAAY,IAAI;AACzB,WAAK,IAAI,OAAO,IAAI;AACpB,WAAK,IAAI,YAAY,IAAI;AACzB,WAAK,IAAI,eAAe,IAAI;AAC5B,WAAK,IAAI,SAAS,IAAI,MAAM,IAAI,GAAG,IAAI,CAAC;AAAA,IAC1C;AACA,SAAK,cAAc,SAAS;AAAA,EAC9B;AAAA,EAEQ,aAAa,GAAW,GAAW,MAAe,UAAmB,OAAa;AACxF,UAAM,MAAM,KAAK;AAGjB,QAAI,SAAS;AACX,UAAI,YAAY;AAChB,UAAI,SAAS,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AACjC,UAAI,cAAc;AAClB,UAAI,YAAY;AAChB,UAAI,WAAW,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AAAA,IACrC;AAEA,QAAI,YAAY,UAAU,YAAY;AACtC,QAAI,UAAU;AACd,QAAI,MAAM;AAER,UAAI,OAAO,GAAG,CAAC;AACf,UAAI,OAAO,IAAI,IAAI,CAAC;AACpB,UAAI,OAAO,IAAI,GAAG,IAAI,CAAC;AAAA,IACzB,OAAO;AAEL,UAAI,OAAO,GAAG,CAAC;AACf,UAAI,OAAO,IAAI,GAAG,IAAI,CAAC;AACvB,UAAI,OAAO,GAAG,IAAI,EAAE;AAAA,IACtB;AACA,QAAI,UAAU;AACd,QAAI,KAAK;AAAA,EACX;AAAA,EAEQ,kBACN,GACA,GACA,GACA,GACA,GACA,MACA,QACA,WACM;AACN,UAAM,MAAM,KAAK;AACjB,QAAI,YAAY;AAChB,QAAI,cAAc;AAClB,QAAI,YAAY;AAChB,QAAI,UAAU;AACd,QAAI,OAAO,IAAI,GAAG,CAAC;AACnB,QAAI,OAAO,IAAI,IAAI,GAAG,CAAC;AACvB,QAAI,iBAAiB,IAAI,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAC3C,QAAI,OAAO,IAAI,GAAG,IAAI,IAAI,CAAC;AAC3B,QAAI,iBAAiB,IAAI,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG,IAAI,CAAC;AACnD,QAAI,OAAO,IAAI,GAAG,IAAI,CAAC;AACvB,QAAI,iBAAiB,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,CAAC;AAC3C,QAAI,OAAO,GAAG,IAAI,CAAC;AACnB,QAAI,iBAAiB,GAAG,GAAG,IAAI,GAAG,CAAC;AACnC,QAAI,UAAU;AACd,QAAI,KAAK;AACT,QAAI,OAAO;AAAA,EACb;AAAA,EAEQ,wBACN,GACA,GACA,UACA,QACA,YACM;AACN,UAAM,YAAY;AAClB,UAAM,aAAa;AACnB,UAAM,QAAQ,IAAI,YAAY;AAE9B,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,SAAS,OAAO,GAAG,WAAW,UAAU;AAEjD,UAAM,iBAAiB,aAAa,YAAY;AAChD,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,SAAS,OAAO,GAAG,YAAY,UAAU,UAAU;AAE5D,QAAI,SAAS,GAAK;AAChB,WAAK,IAAI,YAAY,uBAAuB,OAAO,IAAI,OAAO;AAC9D,WAAK,IAAI,SAAS,OAAO,GAAG,WAAW,UAAU;AAAA,IACnD;AAEA,SAAK,IAAI,cAAc,SAAS,IAAI,SAAS;AAC7C,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,WAAW,OAAO,GAAG,WAAW,UAAU;AACnD,UAAM,aAAa,QAAQ,YAAY;AACvC,SAAK,IAAI,cAAc;AACvB,SAAK,IAAI,YAAY;AACrB,SAAK,IAAI,UAAU;AACnB,SAAK,IAAI,OAAO,YAAY,IAAI,CAAC;AACjC,SAAK,IAAI,OAAO,YAAY,IAAI,aAAa,CAAC;AAC9C,SAAK,IAAI,OAAO;AAAA,EAClB;AAAA,EAEQ,0BAAgC;AACtC,UAAM,QAAQ,SAAS,eAAe,cAAc;AACpD,QAAI,CAAC,MAAO;AAEZ,QAAI,CAAC,KAAK,UAAU;AAClB,YAAM,YACJ;AACF;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,SAAS,mBAAmB;AAChD,QAAI,OAAO;AAEX,WAAO,QAAQ,CAAC,OAAO,SAAS;AAC9B,UAAI,gBAAgB,MAAM;AAC1B,UAAI,QAAQ;AAEZ,UAAI,MAAM,4BAA6B;AACrC,wBAAgB,MAAM,QAAQ,WAAM;AACpC,gBAAQ,MAAM,QAAQ,YAAY;AAAA,MACpC,WAAW,MAAM,kCAAgC;AAC/C,wBAAgB,MAAM,QAAQ,WAAM;AACpC,gBAAQ,MAAM,QAAQ,YAAY;AAAA,MACpC,WAAW,MAAM,8BAA8B;AAC7C,wBAAgB,MAAM,MAAM,QAAQ,CAAC;AAAA,MACvC;AAEA,cAAQ,6BAA6B,IAAI;AACzC,cAAQ,sBAAsB,KAAK,yBAAyB,aAAa;AAAA,IAC3E,CAAC;AAED,YAAQ;AACR,UAAM,YAAY;AAAA,EACpB;AAAA,EAEO,oBAA0B;AAC/B,SAAK,aAAa,CAAC,KAAK;AACxB,SAAK,UAAU,MAAM,UAAU,KAAK,aAAa,UAAU;AAAA,EAC7D;AAAA,EAEO,OAAa;AAClB,SAAK,aAAa;AAClB,SAAK,UAAU,MAAM,UAAU;AAE/B,SAAK,mBAAmB;AACxB,QAAI,KAAK,UAAU;AACjB,WAAK,eAAe,MAAM;AAC1B,WAAK,uBAAuB;AAC5B,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,OAAO;AAAA,EACd;AAAA,EAEO,OAAa;AAClB,SAAK,aAAa;AAClB,SAAK,UAAU,MAAM,UAAU;AAAA,EACjC;AAAA,EAEO,UAAgB;AACrB,QAAI,KAAK,uBAAuB,MAAM;AACpC,2BAAqB,KAAK,kBAAkB;AAAA,IAC9C;AACA,QAAI,KAAK,UAAU,YAAY;AAC7B,WAAK,UAAU,WAAW,YAAY,KAAK,SAAS;AAAA,IACtD;AAAA,EACF;AACF;;;AC5hEO,IAAM,+BAAN,MAAM,sCAAqC,UAAU;AAAA,EAC1D,OAAe,YAA+C,oBAAI,IAAI;AAAA,EACtE,OAAe,mBAA+C;AAAA,EAC9D,OAAe,mBAA4B;AAAA,EAEnC,WAA6B;AAAA,EAC7B,QAAiB;AAAA,EAEzB,YAAY,QAAiB,OAAO;AAClC,UAAM;AACN,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,OAAc,oBAAoB,SAAwB;AACxD,kCAA6B,mBAAmB;AAEhD,QAAI,SAAS;AACX,UAAI,CAAC,8BAA6B,kBAAkB;AAClD,sCAA6B,mBAAmB,IAAI,oBAAoB;AACxE,sCAA6B,iBAAiB,KAAK;AAAA,MACrD;AAEA,iBAAW,YAAY,8BAA6B,WAAW;AAC7D,YAAI,SAAS,UAAU;AACrB,gBAAM,OACJ,SAAS,YAAY,QAAQ,YAAY,8BAA6B,UAAU,IAAI;AACtF,wCAA6B,iBAAiB,aAAa,MAAM,SAAS,QAAQ;AAAA,QACpF;AAAA,MACF;AAEA,oCAA6B,iBAAiB,KAAK;AAAA,IACrD,OAAO;AACL,UAAI,8BAA6B,kBAAkB;AACjD,sCAA6B,iBAAiB,KAAK;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAc,qBAA8B;AAC1C,WAAO,8BAA6B;AAAA,EACtC;AAAA,EAEO,cAAgC;AACrC,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,aAAa,MAAc,MAAqB,cAA0B;AAC/E,SAAK,UAAU,cAAc,MAAM,MAAM,YAAY;AAAA,EACvD;AAAA,EAEO,QAAQ,MAAc,OAAsB;AACjD,SAAK,UAAU,SAAS,MAAM,KAAK;AAAA,EACrC;AAAA,EAEO,SAAS,MAAc,OAAqB;AACjD,SAAK,UAAU,UAAU,MAAM,KAAK;AAAA,EACtC;AAAA,EAEO,OAAO,MAAc,OAAqB;AAC/C,SAAK,UAAU,QAAQ,MAAM,KAAK;AAAA,EACpC;AAAA,EAEO,SAAS,SAA0B;AACxC,SAAK,UAAU,UAAU,OAAO;AAChC,WAAO;AAAA,EACT;AAAA,EAEO,kBAAiC;AACtC,WAAO,KAAK,UAAU,kBAAkB,KAAK;AAAA,EAC/C;AAAA,EAEO,UAAgB;AACrB,SAAK,UAAU,SAAS;AAAA,EAC1B;AAAA,EAEU,WAAiB;AACzB,kCAA6B,UAAU,IAAI,IAAI;AAC/C,SAAK,WAAW,IAAI,UAAU;AAE9B,QACE,8BAA6B,oBAC7B,8BAA6B,kBAC7B;AACA,YAAM,OACJ,KAAK,YAAY,QAAQ,YAAY,8BAA6B,UAAU,IAAI;AAClF,oCAA6B,iBAAiB,aAAa,MAAM,KAAK,QAAQ;AAAA,IAChF;AAAA,EACF;AAAA,EAEU,YAAkB;AAC1B,kCAA6B,UAAU,OAAO,IAAI;AAElD,QAAI,8BAA6B,oBAAoB,KAAK,UAAU;AAClE,YAAM,OAAO,KAAK,YAAY,QAAQ;AACtC,oCAA6B,iBAAiB,gBAAgB,IAAI;AAAA,IACpE;AAEA,QAAI,KAAK,UAAU;AACjB,WAAK,SAAS,SAAS;AAAA,IACzB;AAAA,EACF;AAAA,EAEO,OAAO,WAAyB;AACrC,QAAI,KAAK,YAAY,KAAK,WAAW,UAAU,GAAG;AAChD,WAAK,SAAS,OAAO,SAAS;AAAA,IAChC;AAAA,EACF;AACF;;;AC3GO,IAAM,4BAAN,cAAwC,UAAU;AAAA,EAC/C,mBAAgC,oBAAI,IAAI;AAAA,EACxC,QAAiB;AAAA,EAEzB,YAAY,QAAiB,OAAO;AAClC,UAAM;AACN,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,cAAc,IAAY,MAA4C;AACjF,QAAI;AACF,YAAM,OAAO,MAAM,iBAAiB,cAAc,IAAI,IAAI;AAC1D,WAAK,iBAAiB,IAAI,EAAE;AAE5B,UAAI,KAAK,OAAO;AACd,gBAAQ,IAAI,iDAAiD,EAAE,SAAS,IAAI,EAAE;AAAA,MAChF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,wDAAwD,EAAE,SAAS,IAAI;AAAA,QACvE;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,eAAe,OAAgD;AAC1E,QAAI;AACF,YAAM,iBAAiB,eAAe,KAAK;AAG3C,aAAO,KAAK,KAAK,EAAE,QAAQ,CAAC,OAAO,KAAK,iBAAiB,IAAI,EAAE,CAAC;AAEhE,UAAI,KAAK,OAAO;AACd,gBAAQ;AAAA,UACN,sCAAsC,OAAO,KAAK,KAAK,EAAE,MAAM;AAAA,UAC/D,OAAO,KAAK,KAAK;AAAA,QACnB;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,0DAA0D,KAAK;AAC7E,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,IAA6C;AAC1D,WAAO,iBAAiB,QAAQ,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,IAA6C;AAC5D,WAAO,iBAAiB,UAAU,EAAE;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKO,QAAQ,IAAqB;AAClC,WAAO,iBAAiB,QAAQ,EAAE;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKO,cAAgD;AACrD,WAAO,iBAAiB,YAAY;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKO,wBAAkC;AACvC,WAAO,MAAM,KAAK,KAAK,gBAAgB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,SAAwB;AACtC,SAAK,QAAQ;AACb,qBAAiB,SAAS,OAAO;AAAA,EACnC;AAAA;AAAA,EAIU,WAAiB;AACzB,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,oDAAoD,KAAK,WAAW,IAAI,EAAE;AAAA,IACxF;AAAA,EACF;AAAA,EAEU,YAAkB;AAI1B,QAAI,KAAK,OAAO;AACd,cAAQ;AAAA,QACN,uDAAuD,KAAK,WAAW,IAAI;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAAA,EAEO,YAAkB;AACvB,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,oDAAoD,KAAK,WAAW,IAAI,EAAE;AAAA,IACxF;AAAA,EACF;AAAA,EAEO,aAAmB;AACxB,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,qDAAqD,KAAK,WAAW,IAAI,EAAE;AAAA,IACzF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,2BAA2B,WAAmB,sBAAqC;AAC9F,UAAM,qBAAqB;AAAA,MACzB,MAAM,GAAG,QAAQ;AAAA,MACjB,MAAM,GAAG,QAAQ;AAAA,MACjB,gBAAgB,GAAG,QAAQ;AAAA,MAC3B,YAAY,GAAG,QAAQ;AAAA,MACvB,YAAY,GAAG,QAAQ;AAAA,IACzB;AAEA,UAAM,KAAK,eAAe,kBAAkB;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,aAAgC;AACtD,WAAO,YAAY,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKO,qBAAqB,aAAiC;AAC3D,WAAO,YAAY,OAAO,CAAC,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;AAAA,EACrD;AACF;;;AC9JO,IAAM,+BAAN,cAA2C,UAAU;AAAA,EAClD,aAAyC;AAAA,EACzC,sBAA2D;AAAA,EAC3D;AAAA,EAER,YAAY,MAAe;AACzB,UAAM;AACN,SAAK,OAAO,QAAQ,cAAc,KAAK,IAAI,CAAC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKO,uBAAuB,YAAgD;AAC5E,SAAK,sBAAsB;AAE3B,UAAM,WAAW,WAAW,YAAY;AACxC,QAAI,UAAU;AACZ,UAAI,KAAK,YAAY;AAEnB,aAAK,WAAW,aAAa,KAAK,MAAM,QAAQ;AAChD,aAAK,WAAW,aAAa,KAAK,IAAI;AAAA,MACxC,OAAO;AAEL,aAAK,aAAa,IAAI,oBAAoB,UAAU,KAAK,IAAI;AAE7D,aAAK,WAAW,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,gBAA4C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,OAAa;AAClB,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKO,OAAa;AAClB,SAAK,YAAY,KAAK;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAyB;AAC9B,SAAK,YAAY,kBAAkB;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKO,YAAqB;AAE1B,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKO,oBAA0B;AAC/B,QAAI,KAAK,YAAY;AACnB,WAAK,WAAW,QAAQ;AACxB,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA,EAIU,WAAiB;AAEzB,UAAM,aAAa,KAAK,aAAa,4BAA4B;AACjE,QAAI,YAAY;AACd,WAAK,uBAAuB,UAAU;AACtC,cAAQ;AAAA,QACN,2EAA2E,KAAK,WAAW,IAAI;AAAA,MACjG;AAAA,IACF,OAAO;AACL,cAAQ;AAAA,QACN,uDAAuD,KAAK,WAAW,IAAI;AAAA,MAC7E;AAAA,IACF;AAAA,EACF;AAAA,EAEU,YAAkB;AAC1B,SAAK,kBAAkB;AACvB,YAAQ,IAAI,0DAA0D,KAAK,WAAW,IAAI,EAAE;AAAA,EAC9F;AAAA,EAEO,YAAkB;AAAA,EAIzB;AAAA,EAEO,aAAmB;AAExB,SAAK,KAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,0BAAmC;AACxC,UAAM,aAAa,KAAK,aAAa,4BAA4B;AACjE,QAAI,YAAY;AACd,WAAK,uBAAuB,UAAU;AACtC,cAAQ,IAAI,8EAA8E;AAC1F,aAAO;AAAA,IACT;AAEA,YAAQ;AAAA,MACN,2EAA2E,KAAK,WAAW,IAAI;AAAA,IACjG;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,oBAAoB,YAAgD;AACzE,SAAK,uBAAuB,UAAU;AACtC,YAAQ,IAAI,0EAA0E;AAAA,EACxF;AACF;;;AC5IO,IAAM,yBAAN,MAA6B;AAAA,EAClC,OAAe,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,OAAc,SAAe;AAC3B,QAAI,KAAK,eAAgB;AACzB,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,UAAgB;AAC5B,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,WAAoB;AAChC,WAAO,KAAK;AAAA,EACd;AACF;;;AC7BA,YAAYC,aAAW;AAMhB,IAAM,uBAAN,MAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,OAAc,qBACZ,aACA,gBAAwB,GAClB;AACN,UAAM,WAAW,YAAY;AAG7B,QAAI,CAAC,SAAS,WAAW,aAAa,CAAC,SAAS,WAAW,YAAY;AACrE;AAAA,IACF;AAEA,UAAM,cAAc,SAAS,WAAW,UAAU;AAClD,UAAM,cAAc,SAAS,WAAW,WAAW;AAGnD,UAAM,cAAc,YAAY,SAAS;AAEzC,aAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,YAAM,SAAS,IAAI;AAGnB,YAAM,aAAkD,CAAC;AACzD,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAI,YAAY,SAAS,CAAC,IAAI,GAAG;AAC/B,qBAAW,KAAK;AAAA,YACd,OAAO,YAAY,SAAS,CAAC;AAAA,YAC7B,QAAQ,YAAY,SAAS,CAAC;AAAA,UAChC,CAAC;AAAA,QACH;AAAA,MACF;AAGA,iBAAW,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAG7C,YAAM,OAAO,WAAW,MAAM,GAAG,aAAa;AAC9C,YAAM,cAAc,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAGjE,eAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,oBAAY,SAAS,CAAC,IAAI;AAC1B,oBAAY,SAAS,CAAC,IAAI;AAAA,MAC5B;AAGA,WAAK,QAAQ,CAAC,KAAK,QAAQ;AACzB,oBAAY,SAAS,GAAG,IAAI,IAAI;AAChC,oBAAY,SAAS,GAAG,IAAI,cAAc,IAAI,IAAI,SAAS,cAAc;AAAA,MAC3E,CAAC;AAAA,IACH;AAGA,aAAS,WAAW,UAAU,cAAc;AAC5C,aAAS,WAAW,WAAW,cAAc;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAc,mBACZ,MACA,OACA,SAAkB,MACG;AACrB,UAAM,cAAqC,CAAC;AAC5C,UAAM,gBAA0B,CAAC;AACjC,UAAM,qBAAqB,KAAK,OAAO;AAGvC,QAAI,WAAkC;AACtC,QAAI,QAAsB,CAAC;AAC3B,UAAM,SAAS,CAAC,UAAU;AACxB,UAAI,iBAAuB,uBAAe,MAAM,UAAU;AACxD,mBAAW,MAAM;AACjB,gBAAQ,SAAS;AAAA,MACnB;AAAA,IACF,CAAC;AAGD,UAAM,iBAAiB,oBAAI,IAAY;AACvC,UAAM,QAAQ,CAAC,SAAS,eAAe,IAAI,KAAK,IAAI,CAAC;AAGrD,UAAM,mBAAmB,oBAAI,IAAY;AACzC,UAAM,SAAS,CAAC,UAAU;AACxB,UAAI,MAAM,MAAM;AACd,yBAAiB,IAAI,MAAM,IAAI;AAAA,MACjC;AAAA,IACF,CAAC;AAED,eAAW,SAAS,KAAK,QAAQ;AAG/B,YAAM,QAAQ,MAAM,KAAK,MAAM,GAAG;AAClC,UAAI,MAAM,SAAS,GAAG;AAEpB,oBAAY,KAAK,MAAM,MAAM,CAAC;AAC9B;AAAA,MACF;AAEA,YAAM,aAAa,MAAM,CAAC;AAG1B,YAAM,cACJ,WAAW,SAAS,OAAO,KAC3B,WAAW,SAAS,MAAM,KAC1B,WAAW,SAAS,iBAAiB,KACrC,eAAe;AAEjB,UAAI,aAAa;AACf,sBAAc,KAAK,MAAM,IAAI;AAC7B;AAAA,MACF;AAGA,UAAI,eAAe,IAAI,UAAU,KAAK,iBAAiB,IAAI,UAAU,GAAG;AACtE,oBAAY,KAAK,MAAM,MAAM,CAAC;AAAA,MAChC,OAAO;AACL,sBAAc,KAAK,MAAM,IAAI;AAAA,MAC/B;AAAA,IACF;AAGA,QAAI,CAAC,UAAU,cAAc,SAAS,GAAG;AACvC,cAAQ;AAAA,QACN,kCAAkC,cAAc,MAAM,IAAI,kBAAkB,+BAA+B,KAAK,QAAQ,SAAS;AAAA,MACnI;AACA,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAM,gBAAgB,CAAC,GAAG,IAAI,IAAI,cAAc,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,gBAAQ,IAAI,2CAA2C,aAAa;AAAA,MACtE;AAAA,IACF;AAGA,UAAM,cAAc,IAAU;AAAA,MAC5B,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,IACP;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,uBAAuB,OAAuB,gBAAwB,GAAS;AAC3F,UAAM,SAAS,CAAC,UAAU;AACxB,UAAI,iBAAuB,qBAAa;AACtC,aAAK,qBAAqB,OAAO,aAAa;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,qBAAqB,OAA6B,OAA6B;AAE3F,UAAM,UAAW,MAAc;AAE/B,QAAI,CAAC,QAAS;AAEd,eAAW,UAAU,SAAS;AAC5B,YAAM,eAAe,OAAO,QAAQ;AACpC,YAAM,cAAc,KAAK,mBAAmB,cAAc,KAAK;AAG/D,UAAI,YAAY,OAAO,WAAW,aAAa,OAAO,QAAQ;AAE5D,eAAO,KAAK;AAGZ,cAAM,YAAY,MAAM,WAAW,WAAW;AAG9C,kBAAU,OAAO,OAAO;AACxB,kBAAU,cAAc,OAAO;AAC/B,kBAAU,oBAAoB,OAAO;AACrC,kBAAU,YAAY,OAAO;AAG7B,YAAI,OAAO,UAAU,GAAG;AACtB,oBAAU,KAAK;AACf,oBAAU,OAAO,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,WAAoB;AAChC,WAAO,iEAAiE;AAAA,MACtE,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,yBAGZ;AACA,UAAM,WAAW,KAAK,SAAS;AAE/B,WAAO;AAAA,MACL,mBAAmB,WAAW,IAAI;AAAA,MAClC,iBAAiB,CAAC,YAAY,QAAQ,IAAI,aAAa;AAAA,IACzD;AAAA,EACF;AACF;;;ACtOA,YAAYC,aAAW;AAchB,IAAK,kBAAL,kBAAKC,qBAAL;AACL,EAAAA,iBAAA,YAAS;AACT,EAAAA,iBAAA,iBAAc;AACd,EAAAA,iBAAA,YAAS;AAHC,SAAAA;AAAA,GAAA;AAgBL,IAAM,cAAN,MAAkB;AAAA,EACf,YAA6B,CAAC;AAAA,EAC9B;AAAA,EACA,qBAAsC,CAAC;AAAA,EACvC,WAAiC,CAAC;AAAA,EAClC,cAAsB;AAAA,EACtB,sBAAgC,CAAC;AAAA;AAAA,EACjC,eAAwB;AAAA,EACxB;AAAA,EAER,YACE,SAA4B;AAAA,IAC1B,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,QAAQ;AAAA,EACV,GACA;AACA,SAAK,SAAS;AAGd,uBAAmB,YAAY,EAAE,eAAe,IAAI;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,WAAkC;AACpD,SAAK,YAAY,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAC/C,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKO,WAAW,GAA0B;AAC1C,QAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAE9B,QAAI,KAAK,mBAAmB,WAAW,GAAG;AACxC,aAAO,IAAU,gBAAQ;AAAA,IAC3B;AAEA,QAAI,MAAM,EAAG,QAAO,KAAK,mBAAmB,CAAC,EAAE,MAAM;AACrD,QAAI,MAAM,EAAG,QAAO,KAAK,mBAAmB,KAAK,mBAAmB,SAAS,CAAC,EAAE,MAAM;AAEtF,UAAM,QAAQ,KAAK,KAAK,mBAAmB,SAAS;AACpD,UAAM,aAAa,KAAK,MAAM,KAAK;AACnC,UAAM,aAAa,KAAK,KAAK,KAAK;AAClC,UAAM,SAAS,QAAQ;AAEvB,QAAI,eAAe,YAAY;AAC7B,aAAO,KAAK,mBAAmB,UAAU,EAAE,MAAM;AAAA,IACnD;AAEA,UAAM,KAAK,KAAK,mBAAmB,UAAU;AAC7C,UAAM,KAAK,KAAK,mBAAmB,UAAU;AAE7C,WAAO,GAAG,MAAM,EAAE,KAAK,IAAI,MAAM;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKO,eAAe,GAA0B;AAC9C,UAAM,UAAU;AAChB,UAAM,KAAK,KAAK,IAAI,GAAG,IAAI,OAAO;AAClC,UAAM,KAAK,KAAK,IAAI,GAAG,IAAI,OAAO;AAElC,UAAM,KAAK,KAAK,WAAW,EAAE;AAC7B,UAAM,KAAK,KAAK,WAAW,EAAE;AAE7B,WAAO,GAAG,IAAI,EAAE,EAAE,UAAU;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,UAA0B;AACjD,QAAI,KAAK,gBAAgB,KAAK,KAAK,oBAAoB,WAAW,GAAG;AACnE,aAAO;AAAA,IACT;AAGA,eAAW,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,aAAa,QAAQ,CAAC;AAG3D,QAAI,aAAa,EAAG,QAAO;AAC3B,QAAI,YAAY,KAAK,YAAa,QAAO;AAGzC,QAAI,OAAO;AACX,QAAI,QAAQ,KAAK,oBAAoB,SAAS;AAE9C,WAAO,OAAO,QAAQ,GAAG;AACvB,YAAM,MAAM,KAAK,OAAO,OAAO,SAAS,CAAC;AACzC,UAAI,KAAK,oBAAoB,GAAG,KAAK,UAAU;AAC7C,eAAO;AAAA,MACT,OAAO;AACL,gBAAQ;AAAA,MACV;AAAA,IACF;AAGA,UAAM,gBAAgB,KAAK,oBAAoB,IAAI;AACnD,UAAM,cAAc,KAAK,oBAAoB,KAAK;AAClD,UAAM,kBAAkB,cAAc;AAEtC,QAAI,oBAAoB,GAAG;AACzB,aAAO,QAAQ,KAAK,mBAAmB,SAAS;AAAA,IAClD;AAEA,UAAM,UAAU,WAAW,iBAAiB;AAC5C,UAAM,eAAe,OAAO,WAAW,KAAK,mBAAmB,SAAS;AAExE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBAAmB,UAAiC;AACzD,QAAI,KAAK,gBAAgB,EAAG,QAAO,IAAU,gBAAQ;AAErD,UAAM,IAAI,KAAK,iBAAiB,QAAQ;AACxC,WAAO,KAAK,WAAW,CAAC;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,uBAAuB,UAAiC;AAC7D,QAAI,KAAK,gBAAgB,EAAG,QAAO,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAE5D,UAAM,IAAI,KAAK,iBAAiB,QAAQ;AACxC,WAAO,KAAK,eAAe,CAAC;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,UAIrB;AACA,QAAI,eAAe,IAAU,gBAAQ;AACrC,QAAI,WAAW;AACf,QAAI,kBAAkB;AAGtB,UAAM,UAAU;AAChB,aAAS,IAAI,GAAG,KAAK,SAAS,KAAK;AACjC,YAAM,IAAI,IAAI;AACd,YAAM,QAAQ,KAAK,WAAW,CAAC;AAC/B,YAAM,WAAW,SAAS,WAAW,KAAK;AAE1C,UAAI,WAAW,iBAAiB;AAC9B,0BAAkB;AAClB,uBAAe;AACf,mBAAW;AAAA,MACb;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,GAAG;AAAA,MACH,UAAU;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAyB;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,wBAAyC;AAC9C,WAAO,KAAK,mBAAmB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKO,eAAgC;AACrC,WAAO,KAAK,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKO,cAAoC;AACzC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,YAAiB,GAAiB;AACvD,UAAM,WAAW,KAAK,WAAW,CAAC;AAClC,UAAM,YAAY,KAAK,eAAe,CAAC;AAGvC,eAAW,SAAS,KAAK,QAAQ;AAGjC,QAAI,UAAU,OAAO,IAAI,MAAO;AAC9B,YAAM,QAAQ,KAAK,MAAM,UAAU,GAAG,UAAU,CAAC;AACjD,iBAAW,SAAS,IAAI,GAAG,OAAO,CAAC;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,QAAI,KAAK,UAAU,SAAS,GAAG;AAC7B,WAAK,qBAAqB,CAAC;AAC3B,WAAK,WAAW,CAAC;AACjB,WAAK,cAAc;AACnB;AAAA,IACF;AAEA,SAAK,qBAAqB,CAAC;AAC3B,SAAK,WAAW,CAAC;AAEjB,YAAQ,KAAK,OAAO,MAAM;AAAA,MACxB,KAAK;AACH,aAAK,qBAAqB;AAC1B;AAAA,MACF,KAAK;AACH,aAAK,yBAAyB;AAC9B;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB;AAC1B;AAAA,IACJ;AAEA,SAAK,kBAAkB;AACvB,SAAK,qBAAqB;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,SAAS,GAAG,KAAK;AAClD,YAAM,QAAQ,KAAK,UAAU,CAAC;AAC9B,YAAM,MAAM,KAAK,UAAU,IAAI,CAAC;AAEhC,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,YAAY,KAAK;AAC/C,cAAM,IAAI,IAAI,KAAK,OAAO;AAC1B,cAAM,QAAQ,MAAM,MAAM,EAAE,KAAK,KAAK,CAAC;AACvC,aAAK,mBAAmB,KAAK,KAAK;AAAA,MACpC;AAAA,IACF;AAGA,SAAK,mBAAmB,KAAK,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,EAAE,MAAM,CAAC;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKQ,2BAAiC;AACvC,UAAM,UAAU,KAAK,OAAO,WAAW;AAEvC,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,SAAS,GAAG,KAAK;AAClD,YAAM,KAAK,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAC3D,YAAM,KAAK,KAAK,UAAU,CAAC;AAC3B,YAAM,KAAK,KAAK,UAAU,IAAI,CAAC;AAC/B,YAAM,KAAK,IAAI,KAAK,UAAU,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC;AAEvF,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,YAAY,KAAK;AAC/C,cAAM,IAAI,IAAI,KAAK,OAAO;AAC1B,cAAM,QAAQ,KAAK,sBAAsB,IAAI,IAAI,IAAI,IAAI,GAAG,OAAO;AACnE,aAAK,mBAAmB,KAAK,KAAK;AAAA,MACpC;AAAA,IACF;AAGA,SAAK,mBAAmB,KAAK,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,EAAE,MAAM,CAAC;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBACN,IACA,IACA,IACA,IACA,GACA,SACe;AACf,UAAM,KAAK,IAAI;AACf,UAAM,KAAK,KAAK;AAGhB,UAAM,KAAK,GAAG,MAAM,EAAE,IAAI,EAAE,EAAE,eAAe,OAAO;AACpD,UAAM,KAAK,GAAG,MAAM,EAAE,IAAI,EAAE,EAAE,eAAe,OAAO;AAGpD,WAAO,GACJ,MAAM,EACN,eAAe,IAAI,IAAI,KAAK,IAAI,EAAE,EAClC,IAAI,GAAG,MAAM,EAAE,eAAe,IAAI,KAAK,IAAI,EAAE,CAAC,EAC9C,IAAI,GAAG,MAAM,EAAE,eAAe,KAAK,IAAI,KAAK,CAAC,CAAC,EAC9C,IAAI,GAAG,MAAM,EAAE,eAAe,KAAK,EAAE,CAAC;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,aAAS,IAAI,GAAG,IAAI,KAAK,UAAU,SAAS,GAAG,KAAK;AAClD,YAAM,QAAQ,KAAK,UAAU,CAAC;AAC9B,YAAM,MAAM,KAAK,UAAU,IAAI,CAAC;AAChC,YAAM,UAAU,MAAM,MAAM,EAAE,KAAK,KAAK,GAAG;AAE3C,eAAS,IAAI,GAAG,IAAI,KAAK,OAAO,YAAY,KAAK;AAC/C,cAAM,IAAI,IAAI,KAAK,OAAO;AAC1B,cAAM,QAAQ,KAAK,gBAAgB,OAAO,SAAS,KAAK,CAAC;AACzD,aAAK,mBAAmB,KAAK,KAAK;AAAA,MACpC;AAAA,IACF;AAGA,SAAK,mBAAmB,KAAK,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,EAAE,MAAM,CAAC;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,IACA,IACA,IACA,GACe;AACf,UAAM,YAAY,IAAI;AAEtB,WAAO,GACJ,MAAM,EACN,eAAe,YAAY,SAAS,EACpC,IAAI,GAAG,MAAM,EAAE,eAAe,IAAI,YAAY,CAAC,CAAC,EAChD,IAAI,GAAG,MAAM,EAAE,eAAe,IAAI,CAAC,CAAC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AAChC,SAAK,WAAW,CAAC;AAEjB,aAAS,IAAI,GAAG,IAAI,KAAK,mBAAmB,SAAS,GAAG,KAAK;AAC3D,YAAM,aAA+B;AAAA,QACnC,UAAU,KAAK,mBAAmB,CAAC;AAAA,QACnC,OAAO;AAAA,MACT;AAEA,YAAM,WAA6B;AAAA,QACjC,UAAU,KAAK,mBAAmB,IAAI,CAAC;AAAA,QACvC,OAAO,IAAI;AAAA,MACb;AAEA,YAAM,SAAS,WAAW,SAAS,WAAW,SAAS,QAAQ;AAE/D,WAAK,SAAS,KAAK;AAAA,QACjB;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AACnC,SAAK,sBAAsB,CAAC;AAC5B,SAAK,cAAc;AAGnB,QAAI,KAAK,mBAAmB,SAAS,GAAG;AACtC,WAAK,oBAAoB,KAAK,CAAC;AAAA,IACjC;AAGA,aAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,WAAK,eAAe,KAAK,SAAS,CAAC,EAAE;AACrC,WAAK,oBAAoB,KAAK,KAAK,WAAW;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,QAAkC;AACnD,SAAK,eAAe;AACpB,QAAI,QAAQ;AACV,WAAK,cAAc;AACnB,yBAAmB,YAAY,EAAE,eAAe,MAAM,MAAM;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,eAAqB;AAC1B,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKO,iBAA0B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAgD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,uBAAmB,YAAY,EAAE,iBAAiB,IAAI;AAAA,EACxD;AACF;","names":["THREE","THREE","THREE","THREE","THREE","THREE","THREE","THREE","THREE","THREE","THREE","THREE","camera","THREE","THREE","THREE","ring","ParameterType","ComparisonOperator","BlendType","AnimationEvent","THREE","x","y","range","THREE","THREE","SplineTypeThree"]}