@series-inc/rundot-3d-engine 0.6.2 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/systems/physics/PhysicsSystem.ts","../src/engine/core/ComponentUpdater.ts","../src/systems/input/InputManager.ts","../src/systems/math/MathUtil.ts","../src/systems/math/TweenSystem.ts","../src/systems/math/SecondOrderDynamics.ts","../src/platform/CapacitorPlatform.ts","../src/platform/index.ts","../src/systems/audio/AudioSystem.ts","../src/engine/core/GameObject.ts","../src/engine/core/VenusGame.ts","../src/systems/audio/MusicSystem.ts","../src/engine/render/InstancedMeshManager.ts","../src/systems/animatrix/AnimationCullingManager.ts","../src/systems/audio/Audio2D.ts","../src/engine/assets/SkeletonCache.ts","../src/engine/assets/AssetManager.ts","../src/systems/physics/RigidBodyComponentThree.ts","../src/systems/prefabs/ComponentRegistry.ts","../src/systems/prefabs/PrefabComponent.ts","../src/systems/prefabs/types.ts","../src/systems/prefabs/PrefabNode.ts","../src/systems/prefabs/Prefab.ts","../src/systems/prefabs/PrefabCollection.ts","../src/systems/prefabs/PrefabInstance.ts","../src/systems/prefabs/PrefabLoader.ts","../src/systems/stowkit/StowKitSystem.ts"],"sourcesContent":["import * as THREE from \"three\"\nimport { ConvexGeometry } from \"three/examples/jsm/geometries/ConvexGeometry.js\"\nimport {\n World,\n RigidBody,\n Collider,\n RigidBodyDesc,\n ColliderDesc,\n EventQueue,\n ActiveEvents,\n} from \"@dimforge/rapier3d\"\n\n/**\n * Three.js physics system using Rapier\n * Much simpler than Babylon.js Havok integration\n */\nexport class PhysicsSystem {\n private static world: World | null = null\n private static isInitialized: boolean = false\n private static rigidBodies: Map<string, RigidBody> = new Map()\n private static colliders: Map<string, Collider> = new Map()\n\n // Fixed-step integration\n private static fixedTimeStep: number = 1 / 120 // 120 Hz physics for smoother motion\n private static maxSubSteps: number = 8 // Prevent spiral of death\n private static accumulator: number = 0\n private static alpha: number = 0 // Interpolation alpha (0..1)\n\n /**\n * Configure physics stepping parameters at runtime\n */\n public static configure(params: { fixedTimeStep?: number; maxSubSteps?: number } = {}): void {\n if (typeof params.fixedTimeStep === \"number\" && params.fixedTimeStep > 0) {\n PhysicsSystem.fixedTimeStep = params.fixedTimeStep\n }\n if (typeof params.maxSubSteps === \"number\" && params.maxSubSteps >= 1) {\n PhysicsSystem.maxSubSteps = params.maxSubSteps\n }\n }\n\n /**\n * Get interpolation alpha for rendering (accumulator / fixedTimeStep)\n */\n public static getInterpolationAlpha(): number {\n return PhysicsSystem.alpha\n }\n\n // Proper Rapier collision event system\n private static eventQueue: EventQueue | null = null\n private static colliderHandleToComponent: Map<number, any> = new Map() // Maps collider handle to component\n private static colliderHandleToId: Map<number, string> = new Map() // Maps collider handle to ID\n private static colliderIdToGameObject: Map<string, any> = new Map() // Maps collider ID to GameObject (for all colliders)\n\n // Debug visualization\n private static debugEnabled: boolean = false\n private static debugScene: THREE.Scene | null = null\n private static debugMeshes: Map<string, THREE.Mesh> = new Map()\n private static debugMaterial: THREE.Material | null = null\n\n /**\n * Initialize Rapier physics world\n */\n public static async initialize(): Promise<void> {\n if (PhysicsSystem.isInitialized) {\n return\n }\n\n try {\n // Import Rapier\n const RAPIER = await import(\"@dimforge/rapier3d\")\n\n // Create physics world with gravity\n const gravity = new RAPIER.Vector3(0.0, -9.81, 0.0)\n PhysicsSystem.world = new RAPIER.World(gravity)\n\n // Create event queue for collision events\n PhysicsSystem.eventQueue = new RAPIER.EventQueue(true)\n\n PhysicsSystem.isInitialized = true\n } catch (error) {\n console.error(\"❌ Failed to initialize PhysicsSystem:\", error)\n }\n }\n\n /**\n * Get the physics world\n */\n public static getWorld(): World | null {\n return PhysicsSystem.world\n }\n\n /**\n * Check if physics is initialized\n */\n public static isReady(): boolean {\n return PhysicsSystem.isInitialized && PhysicsSystem.world !== null\n }\n\n /**\n * Step the physics simulation\n */\n public static step(deltaTime: number): void {\n if (!PhysicsSystem.world) {\n return\n }\n\n // Accumulate time and step in fixed increments\n PhysicsSystem.accumulator += deltaTime\n const h = PhysicsSystem.fixedTimeStep\n const maxTime = PhysicsSystem.maxSubSteps * h\n if (PhysicsSystem.accumulator > maxTime) {\n // Clamp to avoid excessive catch-up work on long frames\n PhysicsSystem.accumulator = maxTime\n }\n\n let numSteps = 0\n while (PhysicsSystem.accumulator >= h) {\n // Use fixed timestep for deterministic simulation\n ;(PhysicsSystem.world as any).timestep = h\n if (PhysicsSystem.eventQueue) {\n PhysicsSystem.world.step(PhysicsSystem.eventQueue)\n PhysicsSystem.processCollisionEvents()\n } else {\n PhysicsSystem.world.step()\n }\n\n PhysicsSystem.accumulator -= h\n numSteps++\n }\n\n // Store interpolation alpha for optional render smoothing\n PhysicsSystem.alpha = PhysicsSystem.accumulator / h\n\n // Update debug mesh positions\n PhysicsSystem.updateDebugMeshes()\n }\n\n /**\n * Create a rigid body\n */\n public static createRigidBody(\n id: string,\n rigidBodyDesc: RigidBodyDesc,\n colliderDesc?: ColliderDesc\n ): { rigidBody: RigidBody; collider?: Collider } | null {\n if (!PhysicsSystem.world) return null\n\n // Create rigid body\n const rigidBody = PhysicsSystem.world.createRigidBody(rigidBodyDesc)\n PhysicsSystem.rigidBodies.set(id, rigidBody)\n\n let collider: Collider | undefined\n if (colliderDesc) {\n collider = PhysicsSystem.world.createCollider(colliderDesc, rigidBody)\n PhysicsSystem.colliders.set(id, collider)\n\n // Create debug mesh for this collider\n PhysicsSystem.addDebugMesh(id)\n }\n\n return { rigidBody, collider }\n }\n\n /**\n * Register a GameObject with its collider ID (called by RigidBodyComponentThree for all colliders)\n */\n public static registerGameObject(colliderId: string, gameObject: any): void {\n PhysicsSystem.colliderIdToGameObject.set(colliderId, gameObject)\n\n // Enable collision events for all colliders so they can participate in sensor collisions\n const collider = PhysicsSystem.colliders.get(colliderId)\n if (collider) {\n const handle = collider.handle\n // Map handle to ID for collision event processing\n PhysicsSystem.colliderHandleToId.set(handle, colliderId)\n // Enable collision events so this collider can collide with sensors\n collider.setActiveEvents(ActiveEvents.COLLISION_EVENTS)\n }\n }\n\n /**\n * Unregister a GameObject from collider mapping\n */\n public static unregisterGameObject(colliderId: string): void {\n PhysicsSystem.colliderIdToGameObject.delete(colliderId)\n\n // Also remove handle mapping if it exists\n const collider = PhysicsSystem.colliders.get(colliderId)\n if (collider) {\n const handle = collider.handle\n PhysicsSystem.colliderHandleToId.delete(handle)\n }\n }\n\n /**\n * Register a component for trigger events\n */\n public static registerTriggerComponent(colliderId: string, component: any): void {\n // Find the collider by ID and get its handle\n const collider = PhysicsSystem.colliders.get(colliderId)\n if (collider) {\n const handle = collider.handle\n // Register the component to receive trigger callbacks\n PhysicsSystem.colliderHandleToComponent.set(handle, component)\n // Handle-to-ID mapping should already be set by registerGameObject\n } else {\n console.error(`🔥 PhysicsSystem: Could not find collider with ID ${colliderId}`)\n console.log(\n `🔍 Available collider IDs: ${Array.from(PhysicsSystem.colliders.keys()).join(\", \")}`\n )\n }\n }\n\n /**\n * Unregister a component from trigger events\n */\n public static unregisterTriggerComponent(colliderId: string): void {\n const collider = PhysicsSystem.colliders.get(colliderId)\n if (collider) {\n const handle = collider.handle\n // Only remove the component mapping - handle-to-ID mapping stays for GameObject lookup\n PhysicsSystem.colliderHandleToComponent.delete(handle)\n }\n }\n\n /**\n * Process collision events from the event queue\n */\n private static processCollisionEvents(): void {\n if (!PhysicsSystem.eventQueue) return\n\n let eventCount = 0\n\n // Drain collision events from the event queue\n PhysicsSystem.eventQueue.drainCollisionEvents((handle1, handle2, started) => {\n eventCount++\n\n // Get components for both colliders\n const component1 = PhysicsSystem.colliderHandleToComponent.get(handle1)\n const component2 = PhysicsSystem.colliderHandleToComponent.get(handle2)\n const id1 = PhysicsSystem.colliderHandleToId.get(handle1)\n const id2 = PhysicsSystem.colliderHandleToId.get(handle2)\n\n // Debug: log all collision events to see what's happening\n const gameObject1 = PhysicsSystem.colliderIdToGameObject.get(id1 || \"\")\n const gameObject2 = PhysicsSystem.colliderIdToGameObject.get(id2 || \"\")\n // Collision detected: ${gameObject1?.name || id1} <-> ${gameObject2?.name || id2}\n\n // Components identified\n\n // Get colliders to check which is sensor\n const collider1 = PhysicsSystem.colliders.get(id1 || \"\")\n const collider2 = PhysicsSystem.colliders.get(id2 || \"\")\n\n if (!collider1 || !collider2) {\n return // Missing colliders\n }\n\n const collider1IsSensor = collider1.isSensor()\n const collider2IsSensor = collider2.isSensor()\n\n // Sensor types determined\n\n // If collider1 is sensor, notify its component about collider2\n if (collider1IsSensor && component1) {\n const otherGameObject =\n component2?.gameObject || PhysicsSystem.colliderIdToGameObject.get(id2 || \"\")\n if (otherGameObject) {\n if (started && component1.onTriggerEnter) {\n component1.onTriggerEnter(otherGameObject)\n } else if (!started && component1.onTriggerExit) {\n component1.onTriggerExit(otherGameObject)\n }\n }\n }\n\n // If collider2 is sensor, notify its component about collider1\n if (collider2IsSensor && component2) {\n const otherGameObject =\n component1?.gameObject || PhysicsSystem.colliderIdToGameObject.get(id1 || \"\")\n if (otherGameObject) {\n if (started && component2.onTriggerEnter) {\n component2.onTriggerEnter(otherGameObject)\n } else if (!started && component2.onTriggerExit) {\n component2.onTriggerExit(otherGameObject)\n }\n }\n }\n })\n\n // Events processed silently\n }\n\n /**\n * Remove a rigid body\n */\n public static removeRigidBody(id: string): void {\n if (!PhysicsSystem.world) return\n\n // Remove debug mesh first\n PhysicsSystem.removeDebugMesh(id)\n\n const rigidBody = PhysicsSystem.rigidBodies.get(id)\n if (rigidBody) {\n PhysicsSystem.world.removeRigidBody(rigidBody)\n PhysicsSystem.rigidBodies.delete(id)\n }\n\n const collider = PhysicsSystem.colliders.get(id)\n if (collider) {\n PhysicsSystem.world.removeCollider(collider, true)\n PhysicsSystem.colliders.delete(id)\n }\n }\n\n /**\n * Get rigid body by ID\n */\n public static getRigidBody(id: string): RigidBody | null {\n return PhysicsSystem.rigidBodies.get(id) || null\n }\n\n /**\n * Get collider by ID\n */\n public static getCollider(id: string): Collider | null {\n return PhysicsSystem.colliders.get(id) || null\n }\n\n /**\n * Sync Three.js object position with physics body\n */\n public static syncObjectToPhysics(object: THREE.Object3D, rigidBody: RigidBody, collider?: Collider): void {\n const translation = rigidBody.translation()\n const rotation = rigidBody.rotation()\n\n // Update Three.js object position\n object.position.set(translation.x, translation.y, translation.z)\n object.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w)\n\n // Apply collider world position (accounts for collider-local offset from body)\n if (collider) {\n const ct = collider.translation()\n object.position.set(ct.x, ct.y, ct.z)\n }\n }\n\n /**\n * Sync physics body position to Three.js object\n */\n public static syncPhysicsToObject(rigidBody: RigidBody, object: THREE.Object3D): void {\n const position = object.position\n const quaternion = object.quaternion\n\n // Update physics body position\n rigidBody.setTranslation({ x: position.x, y: position.y, z: position.z }, true)\n rigidBody.setRotation(\n {\n x: quaternion.x,\n y: quaternion.y,\n z: quaternion.z,\n w: quaternion.w,\n },\n true\n )\n }\n\n /**\n * Create a ground plane\n */\n public static createGround(\n size: number = 50\n ): { rigidBody: RigidBody; collider: Collider } | null {\n if (!PhysicsSystem.world) return null\n\n // Create ground rigid body descriptor\n const groundBodyDesc = RigidBodyDesc.fixed().setTranslation(0, 0, 0)\n\n // Create ground collider descriptor\n const groundColliderDesc = ColliderDesc.cuboid(size / 2, 0.1, size / 2)\n\n const result = PhysicsSystem.createRigidBody(\"ground\", groundBodyDesc, groundColliderDesc)\n return result ? { rigidBody: result.rigidBody, collider: result.collider! } : null\n }\n\n /**\n * Create a box collider\n */\n public static createBox(\n id: string,\n position: THREE.Vector3,\n size: THREE.Vector3,\n isDynamic: boolean = true\n ): { rigidBody: RigidBody; collider: Collider } | null {\n if (!PhysicsSystem.world) return null\n\n // Create rigid body descriptor\n const bodyDesc = isDynamic ? RigidBodyDesc.dynamic() : RigidBodyDesc.fixed()\n\n bodyDesc.setTranslation(position.x, position.y, position.z)\n\n // Create collider descriptor\n const colliderDesc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2)\n\n const result = PhysicsSystem.createRigidBody(id, bodyDesc, colliderDesc)\n return result ? { rigidBody: result.rigidBody, collider: result.collider! } : null\n }\n\n /**\n * Create a sphere collider\n */\n public static createSphere(\n id: string,\n position: THREE.Vector3,\n radius: number,\n isDynamic: boolean = true\n ): { rigidBody: RigidBody; collider: Collider } | null {\n if (!PhysicsSystem.world) return null\n\n // Create rigid body descriptor\n const bodyDesc = isDynamic ? RigidBodyDesc.dynamic() : RigidBodyDesc.fixed()\n\n bodyDesc.setTranslation(position.x, position.y, position.z)\n\n // Create collider descriptor\n const colliderDesc = ColliderDesc.ball(radius)\n\n const result = PhysicsSystem.createRigidBody(id, bodyDesc, colliderDesc)\n return result ? { rigidBody: result.rigidBody, collider: result.collider! } : null\n }\n\n /**\n * Initialize debug visualization\n */\n public static initializeDebug(scene: THREE.Scene): void {\n PhysicsSystem.debugScene = scene\n\n // Create debug material - semi-transparent wireframe that ignores depth\n PhysicsSystem.debugMaterial = new THREE.MeshBasicMaterial({\n color: 0x00ff00,\n wireframe: true,\n transparent: true,\n opacity: 0.3,\n depthTest: false, // Always render on top, ignores depth\n depthWrite: false, // Don't write to depth buffer\n })\n }\n\n /**\n * Toggle physics debug visualization\n */\n public static setDebugEnabled(enabled: boolean): void {\n PhysicsSystem.debugEnabled = enabled\n\n if (enabled) {\n PhysicsSystem.showAllDebugMeshes()\n } else {\n PhysicsSystem.hideAllDebugMeshes()\n }\n }\n\n /**\n * Get debug enabled state\n */\n public static isDebugEnabled(): boolean {\n return PhysicsSystem.debugEnabled\n }\n\n /**\n * Create debug mesh for a collider\n */\n private static createDebugMesh(id: string, collider: Collider): THREE.Mesh | null {\n if (!PhysicsSystem.debugMaterial || !PhysicsSystem.debugScene) return null\n\n const shape = collider.shape\n let geometry: THREE.BufferGeometry | null = null\n\n // Create geometry based on collider shape type\n switch (shape.type) {\n case 0: // Ball/Sphere\n const radius = (shape as any).radius\n geometry = new THREE.SphereGeometry(radius, 16, 12)\n break\n\n case 1: // Cuboid/Box\n const halfExtents = (shape as any).halfExtents\n geometry = new THREE.BoxGeometry(halfExtents.x * 2, halfExtents.y * 2, halfExtents.z * 2)\n break\n\n case 2: // Capsule\n const capsuleRadius = (shape as any).radius\n const capsuleHalfHeight = (shape as any).halfHeight\n const capsuleGeometry = new THREE.CapsuleGeometry(\n capsuleRadius,\n capsuleHalfHeight * 2,\n 8,\n 16\n )\n geometry = capsuleGeometry\n break\n\n case 9: { // ConvexPolyhedron\n const convex = shape as any\n const vertices = convex.vertices as Float32Array\n if (vertices && vertices.length >= 9) {\n const points: THREE.Vector3[] = []\n for (let i = 0; i < vertices.length; i += 3) {\n points.push(new THREE.Vector3(vertices[i], vertices[i + 1], vertices[i + 2]))\n }\n geometry = new ConvexGeometry(points)\n }\n break\n }\n\n default:\n // For other shapes, create a simple box as fallback\n geometry = new THREE.BoxGeometry(1, 1, 1)\n console.warn(`Unsupported collider shape type: ${shape.type}, using box fallback`)\n break\n }\n\n if (!geometry) return null\n\n // Create debug mesh\n const debugMesh = new THREE.Mesh(geometry, PhysicsSystem.debugMaterial)\n debugMesh.name = `debug_${id}`\n\n // Position the debug mesh at the collider's world position\n const rigidBody = PhysicsSystem.rigidBodies.get(id)\n if (rigidBody) {\n PhysicsSystem.syncObjectToPhysics(debugMesh, rigidBody, collider)\n }\n\n return debugMesh\n }\n\n /**\n * Add debug mesh for a physics body\n */\n private static addDebugMesh(id: string): void {\n if (!PhysicsSystem.debugScene || PhysicsSystem.debugMeshes.has(id)) return\n\n const collider = PhysicsSystem.colliders.get(id)\n if (!collider) return\n\n const debugMesh = PhysicsSystem.createDebugMesh(id, collider)\n if (debugMesh) {\n PhysicsSystem.debugMeshes.set(id, debugMesh)\n\n if (PhysicsSystem.debugEnabled) {\n PhysicsSystem.debugScene.add(debugMesh)\n }\n }\n }\n\n /**\n * Remove debug mesh for a physics body\n */\n private static removeDebugMesh(id: string): void {\n const debugMesh = PhysicsSystem.debugMeshes.get(id)\n if (debugMesh) {\n if (PhysicsSystem.debugScene) {\n PhysicsSystem.debugScene.remove(debugMesh)\n }\n debugMesh.geometry.dispose()\n PhysicsSystem.debugMeshes.delete(id)\n }\n }\n\n /**\n * Show all debug meshes\n */\n private static showAllDebugMeshes(): void {\n if (!PhysicsSystem.debugScene) return\n\n PhysicsSystem.debugMeshes.forEach((mesh) => {\n PhysicsSystem.debugScene!.add(mesh)\n })\n }\n\n /**\n * Hide all debug meshes\n */\n private static hideAllDebugMeshes(): void {\n if (!PhysicsSystem.debugScene) return\n\n PhysicsSystem.debugMeshes.forEach((mesh) => {\n PhysicsSystem.debugScene!.remove(mesh)\n })\n }\n\n /**\n * Update debug mesh positions to match physics bodies\n */\n public static updateDebugMeshes(): void {\n if (!PhysicsSystem.debugEnabled || !PhysicsSystem.debugScene) return\n\n PhysicsSystem.debugMeshes.forEach((mesh, id) => {\n const rigidBody = PhysicsSystem.rigidBodies.get(id)\n if (rigidBody) {\n // Check if rigid body is enabled and show/hide debug mesh accordingly\n const isEnabled = rigidBody.isEnabled()\n\n if (isEnabled) {\n // Update position and show mesh if not already in scene\n const collider = PhysicsSystem.colliders.get(id)\n PhysicsSystem.syncObjectToPhysics(mesh, rigidBody, collider ?? undefined)\n if (!PhysicsSystem.debugScene!.children.includes(mesh)) {\n PhysicsSystem.debugScene!.add(mesh)\n }\n } else {\n // Hide mesh if rigid body is disabled\n if (PhysicsSystem.debugScene!.children.includes(mesh)) {\n PhysicsSystem.debugScene!.remove(mesh)\n }\n }\n }\n })\n }\n\n /**\n * Dispose of physics system\n */\n public static dispose(): void {\n // Clean up debug meshes\n PhysicsSystem.debugMeshes.forEach((mesh) => {\n if (PhysicsSystem.debugScene) {\n PhysicsSystem.debugScene.remove(mesh)\n }\n mesh.geometry.dispose()\n })\n PhysicsSystem.debugMeshes.clear()\n\n if (PhysicsSystem.debugMaterial) {\n PhysicsSystem.debugMaterial.dispose()\n PhysicsSystem.debugMaterial = null\n }\n\n PhysicsSystem.debugScene = null\n PhysicsSystem.debugEnabled = false\n\n if (PhysicsSystem.world) {\n PhysicsSystem.world.free()\n PhysicsSystem.world = null\n }\n\n if (PhysicsSystem.eventQueue) {\n PhysicsSystem.eventQueue.free()\n PhysicsSystem.eventQueue = null\n }\n\n PhysicsSystem.rigidBodies.clear()\n PhysicsSystem.colliders.clear()\n PhysicsSystem.colliderHandleToComponent.clear()\n PhysicsSystem.colliderHandleToId.clear()\n PhysicsSystem.isInitialized = false\n\n console.log(\"🎯 PhysicsSystem disposed\")\n }\n}\n","import * as THREE from \"three\"\nimport { Component } from \"./GameObject\"\n\n/**\n * Component updater for Three.js components\n * Handles the update loop for all registered components\n */\nexport class ComponentUpdater {\n private static updateableComponents = new Set<Component>()\n private static lateUpdateableComponents = new Set<Component>()\n private static updateCount = 0 // Debug counter\n\n /**\n * Register a component for updates\n * @internal Only called by Component class\n */\n static registerComponent(component: Component): void {\n ComponentUpdater.updateableComponents.add(component)\n // Removed excessive logging: console.log(`📝 ComponentUpdater: Registered ${component.constructor.name} for updates. Total: ${ComponentUpdater.updateableComponents.size}`);\n }\n\n /**\n * Unregister a component from updates\n * @internal Only called by Component class\n */\n static unregisterComponent(component: Component): void {\n ComponentUpdater.updateableComponents.delete(component)\n // Component unregistered from updates\n }\n\n /**\n * Register a component for late updates\n * @internal Only called by Component class\n */\n static registerLateUpdateComponent(component: Component): void {\n ComponentUpdater.lateUpdateableComponents.add(component)\n console.log(\n `📝 ComponentUpdater: Registered ${component.constructor.name} for late updates. Total: ${ComponentUpdater.lateUpdateableComponents.size}`\n )\n }\n\n /**\n * Unregister a component from late updates\n * @internal Only called by Component class\n */\n static unregisterLateUpdateComponent(component: Component): void {\n ComponentUpdater.lateUpdateableComponents.delete(component)\n // Component unregistered from late updates\n }\n\n /**\n * Initialize the component updater\n */\n static initialize(scene: THREE.Scene): void {\n // ComponentUpdater initialized\n }\n\n /**\n * Update all registered components\n */\n static update(deltaTime: number): void {\n this.updateCount++\n for (const component of ComponentUpdater.updateableComponents) {\n if (component.getGameObject().visible) {\n try {\n component.update?.(deltaTime)\n } catch (error) {\n console.error(`❌ Error updating component ${component.constructor.name}:`, error)\n }\n }\n }\n }\n\n /**\n * Late update all registered components\n */\n static lateUpdate(deltaTime: number): void {\n for (const component of ComponentUpdater.lateUpdateableComponents) {\n if (component.getGameObject().visible) {\n try {\n component.lateUpdate?.(deltaTime)\n } catch (error) {\n console.error(`❌ Error late updating component ${component.constructor.name}:`, error)\n }\n }\n }\n }\n\n /**\n * Dispose all components\n */\n static dispose(): void {\n ComponentUpdater.updateableComponents.clear()\n ComponentUpdater.lateUpdateableComponents.clear()\n console.log(\"🔄 ComponentUpdater disposed\")\n }\n}\n","/**\n * Simple centralized input management system\n * Just tracks key state - gameplay logic stays in components\n */\n\nexport enum InputAction {\n MOVE_FORWARD = \"move_forward\",\n MOVE_BACKWARD = \"move_backward\",\n MOVE_LEFT = \"move_left\",\n MOVE_RIGHT = \"move_right\",\n RUN = \"run\",\n}\n\n/**\n * Default key bindings - can be customized later\n */\nexport const DEFAULT_KEY_BINDINGS: Record<InputAction, string> = {\n [InputAction.MOVE_FORWARD]: \"KeyW\",\n [InputAction.MOVE_BACKWARD]: \"KeyS\",\n [InputAction.MOVE_LEFT]: \"KeyA\",\n [InputAction.MOVE_RIGHT]: \"KeyD\",\n [InputAction.RUN]: \"ShiftLeft\",\n}\n\n/**\n * Centralized Input Manager - Singleton\n * Simple API for checking if keys/actions are currently pressed\n */\nexport class InputManager {\n private static instance: InputManager\n\n // Input state\n private activeKeys = new Set<string>()\n private keyBindings: Record<InputAction, string> = {\n ...DEFAULT_KEY_BINDINGS,\n }\n private isEnabled = true\n\n // Bound event listeners for proper cleanup\n private boundKeyDown = this.onKeyDown.bind(this)\n private boundKeyUp = this.onKeyUp.bind(this)\n private boundWindowBlur = this.onWindowBlur.bind(this)\n\n private constructor() {\n this.setupEventListeners()\n }\n\n /**\n * Get singleton instance\n */\n public static getInstance(): InputManager {\n if (!InputManager.instance) {\n InputManager.instance = new InputManager()\n }\n return InputManager.instance\n }\n\n /**\n * Initialize the input system (call this in VenusGame)\n */\n public static initialize(): void {\n InputManager.getInstance()\n // InputManager initialized\n }\n\n /**\n * Setup DOM event listeners\n */\n private setupEventListeners(): void {\n document.addEventListener(\"keydown\", this.boundKeyDown)\n document.addEventListener(\"keyup\", this.boundKeyUp)\n window.addEventListener(\"blur\", this.boundWindowBlur)\n }\n\n /**\n * Handle key down events\n */\n private onKeyDown(event: KeyboardEvent): void {\n if (!this.isEnabled) return\n\n // Prevent default for game keys to avoid browser shortcuts\n if (this.isGameKey(event.code)) {\n event.preventDefault()\n }\n\n this.activeKeys.add(event.code)\n }\n\n /**\n * Handle key up events\n */\n private onKeyUp(event: KeyboardEvent): void {\n this.activeKeys.delete(event.code)\n }\n\n /**\n * Handle window blur to prevent stuck keys\n */\n private onWindowBlur(): void {\n this.activeKeys.clear()\n }\n\n /**\n * Check if a specific action is currently pressed\n */\n public isActionPressed(action: InputAction): boolean {\n if (!this.isEnabled) return false\n\n const keyCode = this.keyBindings[action]\n return this.activeKeys.has(keyCode)\n }\n\n /**\n * Check if a specific key code is currently pressed\n */\n public isKeyPressed(keyCode: string): boolean {\n return this.isEnabled && this.activeKeys.has(keyCode)\n }\n\n /**\n * Enable/disable input processing\n */\n public setEnabled(enabled: boolean): void {\n this.isEnabled = enabled\n if (!enabled) {\n this.activeKeys.clear()\n }\n }\n\n /**\n * Update key binding for an action\n */\n public setKeyBinding(action: InputAction, keyCode: string): void {\n this.keyBindings[action] = keyCode\n }\n\n /**\n * Check if a key code is used by the game (for preventDefault)\n */\n private isGameKey(keyCode: string): boolean {\n return Object.values(this.keyBindings).includes(keyCode)\n }\n\n /**\n * Get all currently active keys (for debugging)\n */\n public getActiveKeys(): string[] {\n return Array.from(this.activeKeys)\n }\n\n /**\n * Cleanup - remove event listeners\n */\n public dispose(): void {\n document.removeEventListener(\"keydown\", this.boundKeyDown)\n document.removeEventListener(\"keyup\", this.boundKeyUp)\n window.removeEventListener(\"blur\", this.boundWindowBlur)\n this.activeKeys.clear()\n }\n}\n\n// Export simple convenience functions - just key state checking\nexport const Input = {\n isPressed: (action: InputAction) => InputManager.getInstance().isActionPressed(action),\n isKeyPressed: (keyCode: string) => InputManager.getInstance().isKeyPressed(keyCode),\n setEnabled: (enabled: boolean) => InputManager.getInstance().setEnabled(enabled),\n}\n","/**\n * Math utilities for game development\n */\nexport class MathUtil {\n /**\n * Linear interpolation - exponential approach, never quite reaches target\n * @param current Current value\n * @param target Target value\n * @param factor Interpolation factor (0-1)\n * @returns Interpolated value\n */\n static lerp(current: number, target: number, factor: number): number {\n return current + (target - current) * factor\n }\n\n /**\n * Move towards - linear approach with max speed, reaches target exactly\n * @param current Current value\n * @param target Target value\n * @param maxDelta Maximum change per call\n * @returns New value moved towards target\n */\n static moveTowards(current: number, target: number, maxDelta: number): number {\n const diff = target - current\n if (Math.abs(diff) <= maxDelta) {\n return target\n }\n return current + Math.sign(diff) * maxDelta\n }\n\n /**\n * Clamp a value between min and max\n * @param value Value to clamp\n * @param min Minimum value\n * @param max Maximum value\n * @returns Clamped value\n */\n static clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n }\n\n /**\n * Check if two values are approximately equal\n * @param a First value\n * @param b Second value\n * @param epsilon Tolerance (default: 0.001)\n * @returns True if values are approximately equal\n */\n static approximately(a: number, b: number, epsilon: number = 0.001): boolean {\n return Math.abs(a - b) < epsilon\n }\n}\n","/**\n * Easing functions for smooth animations\n */\nexport class Easing {\n static linear(t: number): number {\n return t\n }\n\n static easeInQuad(t: number): number {\n return t * t\n }\n\n static easeOutQuad(t: number): number {\n return t * (2 - t)\n }\n\n static easeInOutQuad(t: number): number {\n return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t\n }\n\n static easeInCubic(t: number): number {\n return t * t * t\n }\n\n static easeOutCubic(t: number): number {\n return --t * t * t + 1\n }\n\n static easeInOutCubic(t: number): number {\n return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1\n }\n\n // Spring physics-based easing\n static spring(t: number, damping: number = 0.8, stiffness: number = 0.15): number {\n return 1 - Math.exp(-damping * t) * Math.cos(stiffness * t * Math.PI * 2)\n }\n\n // Elastic easing - perfect for bounce/spring effects\n static easeOutElastic(t: number): number {\n const c4 = (2 * Math.PI) / 3\n return t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1\n }\n\n // Back easings and anticipate/overshoot combo\n static easeInBack(t: number, s: number = 1.70158): number {\n return t * t * ((s + 1) * t - s)\n }\n\n static easeOutBack(t: number, s: number = 1.70158): number {\n t = t - 1\n return 1 + t * t * ((s + 1) * t + s)\n }\n\n // Anticipate (goes slightly negative) then overshoot (>1) in a single curve\n static anticipateOvershoot(t: number, s: number = 2.2): number {\n if (t < 0.5) {\n return 0.5 * Easing.easeInBack(t * 2, s)\n }\n return 0.5 * Easing.easeOutBack(t * 2 - 1, s) + 0.5\n }\n}\n\n/**\n * Individual tween instance\n */\nexport class Tween {\n private target: any\n private property: string\n private startValue: number\n private endValue: number\n private duration: number\n private elapsed: number = 0\n private easingFunction: (t: number) => number\n private onComplete?: () => void\n private onUpdate?: (value: number) => void\n private active: boolean = true\n\n constructor(\n target: any,\n property: string,\n endValue: number,\n duration: number,\n easingFunction: (t: number) => number = Easing.linear\n ) {\n this.target = target\n this.property = property\n this.startValue = target[property]\n this.endValue = endValue\n this.duration = duration\n this.easingFunction = easingFunction\n\n if (TweenSystem.debugLogging) {\n console.log(\n `[Tween] Created: property=${property}, start=${this.startValue}, end=${endValue}, duration=${duration}`\n )\n }\n }\n\n /**\n * Set completion callback\n */\n public onCompleted(callback: () => void): Tween {\n this.onComplete = callback\n return this\n }\n\n /**\n * Set update callback\n */\n public onUpdated(callback: (value: number) => void): Tween {\n this.onUpdate = callback\n return this\n }\n\n /**\n * Update the tween (optimized for performance)\n */\n public update(deltaTime: number): boolean {\n // Fast path for inactive tweens\n if (!this.active) return false\n\n this.elapsed += deltaTime\n\n // Fast path for incomplete tweens\n if (this.elapsed < this.duration) {\n const t = this.elapsed / this.duration\n const easedT = this.easingFunction(t)\n const currentValue = this.startValue + (this.endValue - this.startValue) * easedT\n this.target[this.property] = currentValue\n\n // Only call update callback if it exists\n if (this.onUpdate) {\n this.onUpdate(currentValue)\n }\n\n // Debug logging with reduced frequency\n if (TweenSystem.debugLogging && Math.random() < 0.02) {\n console.log(\n `[Tween] Progress: ${this.property}=${currentValue.toFixed(2)} (${(t * 100).toFixed(0)}%)`\n )\n }\n\n return true\n }\n\n // Tween completed\n this.target[this.property] = this.endValue\n this.active = false\n\n if (TweenSystem.debugLogging) {\n console.log(`[Tween] Completed: ${this.property}=${this.endValue}`)\n }\n\n // Call completion callback if it exists\n if (this.onComplete) {\n this.onComplete()\n }\n\n return false\n }\n\n /**\n * Stop the tween\n */\n public stop(): void {\n this.active = false\n }\n\n /**\n * Check if tween is active\n */\n public isActive(): boolean {\n return this.active\n }\n}\n\n/**\n * Global tween manager with performance optimizations\n */\nexport class TweenSystem {\n private static tweens: Tween[] = []\n private static pendingTweens: Tween[] = [] // Tweens created during update\n public static debugLogging: boolean = false // Disabled by default\n private static lastActiveFrame: number = 0\n private static frameCount: number = 0\n\n /**\n * Create and register a new tween\n */\n static tween(\n target: any,\n property: string,\n endValue: number,\n duration: number,\n easingFunction?: (t: number) => number\n ): Tween {\n const tween = new Tween(target, property, endValue, duration, easingFunction)\n\n // If we're currently updating, add to pending list to avoid modification during iteration\n if (this.pendingTweens.length > 0 || this.frameCount - this.lastActiveFrame < 2) {\n this.pendingTweens.push(tween)\n } else {\n this.tweens.push(tween)\n }\n\n return tween\n }\n\n /**\n * Update all active tweens (optimized to skip when empty)\n */\n static update(deltaTime: number): void {\n this.frameCount++\n\n // Early exit if no tweens to process\n if (this.tweens.length === 0 && this.pendingTweens.length === 0) {\n // System is sleeping - no tweens active\n return\n }\n\n this.lastActiveFrame = this.frameCount\n\n // Debug: log deltaTime occasionally\n if (this.debugLogging && Math.random() < 0.01 && this.tweens.length > 0) {\n console.log(`[TweenSystem] Updating ${this.tweens.length} tweens with deltaTime=${deltaTime}`)\n }\n\n // Process existing tweens\n const activeTweens: Tween[] = []\n for (const tween of this.tweens) {\n const isActive = tween.update(deltaTime)\n if (isActive) {\n activeTweens.push(tween)\n }\n }\n\n // Add any pending tweens that were created during update\n if (this.pendingTweens.length > 0) {\n activeTweens.push(...this.pendingTweens)\n this.pendingTweens = []\n }\n\n this.tweens = activeTweens\n }\n\n /**\n * Stop all tweens\n */\n static stopAll(): void {\n this.tweens.forEach((tween) => tween.stop())\n this.tweens = []\n this.pendingTweens = []\n }\n\n /**\n * Get number of active tweens\n */\n static getActiveCount(): number {\n return this.tweens.length + this.pendingTweens.length\n }\n\n /**\n * Check if the tween system is currently active\n */\n static isActive(): boolean {\n return this.tweens.length > 0 || this.pendingTweens.length > 0\n }\n\n /**\n * Get performance stats for debugging\n */\n static getStats(): {\n active: number\n pending: number\n lastActiveFrame: number\n currentFrame: number\n } {\n return {\n active: this.tweens.length,\n pending: this.pendingTweens.length,\n lastActiveFrame: this.lastActiveFrame,\n currentFrame: this.frameCount,\n }\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Second-order dynamics system for smooth, physics-based animation\n * Based on the critically damped harmonic oscillator\n * Perfect for springy, responsive animations that react to input changes\n */\nexport class SecondOrderDynamics {\n private k1: number\n private k2: number\n private k3: number\n private xp: THREE.Vector3 // Previous input\n private y: THREE.Vector3 // Current output position\n private yd: THREE.Vector3 // Current output velocity\n\n /**\n * Create a second-order dynamics system\n * @param f - Frequency (speed of response) - higher = faster response\n * @param z - Damping coefficient - 0 = no damping (oscillates forever), 1 = critically damped, >1 = overdamped\n * @param r - Initial response factor - affects initial \"kick\" of the animation\n * @param initialValue - Starting position\n */\n constructor(f: number, z: number, r: number, initialValue: THREE.Vector3 = new THREE.Vector3()) {\n // Compute constants\n const pi = Math.PI\n const w = 2 * pi * f // Angular frequency\n const d = w * Math.sqrt(Math.abs(z * z - 1)) // Damped frequency\n\n this.k1 = z / (pi * f)\n this.k2 = 1 / (w * w)\n this.k3 = (r * z) / w\n\n // Initialize state\n this.xp = initialValue.clone()\n this.y = initialValue.clone()\n this.yd = new THREE.Vector3()\n }\n\n /**\n * Update the system with a new target position\n * @param x - Target position\n * @param deltaTime - Time step\n * @returns Current smoothed position\n */\n update(x: THREE.Vector3, deltaTime: number): THREE.Vector3 {\n if (deltaTime === 0) {\n return this.y.clone()\n }\n\n // Estimate velocity from position change\n const xd = new THREE.Vector3().subVectors(x, this.xp).divideScalar(deltaTime)\n\n this.xp.copy(x)\n\n // Clamp deltaTime to prevent instability\n const T = Math.min(deltaTime, 0.05) // Max 50ms timestep\n\n // Integrate position by velocity\n this.y.addScaledVector(this.yd, T)\n\n // Integrate velocity by acceleration\n const acceleration = new THREE.Vector3()\n .addScaledVector(x, 1)\n .addScaledVector(xd, this.k3)\n .addScaledVector(this.y, -1)\n .addScaledVector(this.yd, -this.k1)\n .divideScalar(this.k2)\n\n this.yd.addScaledVector(acceleration, T)\n\n return this.y.clone()\n }\n\n /**\n * Get current position without updating\n */\n getCurrentPosition(): THREE.Vector3 {\n return this.y.clone()\n }\n\n /**\n * Get current velocity\n */\n getCurrentVelocity(): THREE.Vector3 {\n return this.yd.clone()\n }\n\n /**\n * Reset the system to a new position\n */\n reset(position: THREE.Vector3): void {\n this.xp.copy(position)\n this.y.copy(position)\n this.yd.set(0, 0, 0)\n }\n}\n\n/**\n * Simplified 1D version for scalar values\n */\nexport class SecondOrderDynamics1D {\n private k1: number\n private k2: number\n private k3: number\n private xp: number // Previous input\n private y: number // Current output position\n private yd: number // Current output velocity\n\n constructor(f: number, z: number, r: number, initialValue: number = 0) {\n const pi = Math.PI\n const w = 2 * pi * f\n\n this.k1 = z / (pi * f)\n this.k2 = 1 / (w * w)\n this.k3 = (r * z) / w\n\n this.xp = initialValue\n this.y = initialValue\n this.yd = 0\n }\n\n update(x: number, deltaTime: number): number {\n if (deltaTime === 0) return this.y\n\n const xd = (x - this.xp) / deltaTime\n this.xp = x\n\n const T = Math.min(deltaTime, 0.05)\n\n this.y += this.yd * T\n\n const acceleration = (x + this.k3 * xd - this.y - this.k1 * this.yd) / this.k2\n this.yd += acceleration * T\n\n return this.y\n }\n\n getCurrentValue(): number {\n return this.y\n }\n\n getCurrentVelocity(): number {\n return this.yd\n }\n\n reset(value: number): void {\n this.xp = value\n this.y = value\n this.yd = 0\n }\n}\n","/**\n * Capacitor Platform Implementation\n *\n * Implements the PlatformService interface using Capacitor plugins.\n * Used for standalone APK/iOS builds.\n * Includes AppsFlyer for retention/analytics on native (Android/iOS).\n */\n\nimport { Capacitor } from \"@capacitor/core\"\nimport { Preferences } from \"@capacitor/preferences\"\nimport { LocalNotifications } from \"@capacitor/local-notifications\"\nimport { App } from \"@capacitor/app\"\nimport { SplashScreen } from \"@capacitor/splash-screen\"\n\nimport type {\n PlatformService,\n PlatformContext,\n PlatformStorage,\n PlatformCache,\n PlatformAnalytics,\n PlatformAds,\n PlatformIAP,\n PlatformCDN,\n PlatformNotifications,\n PlatformLifecycles,\n PlatformPreloader,\n} from \"./PlatformService\"\n\n// Logging prefix for all Capacitor platform calls\nconst LOG_PREFIX = \"[Capacitor]\"\n\n// Helper to generate numeric notification IDs from string IDs\nfunction stringToNotificationId(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = ((hash << 5) - hash) + char\n hash = hash & hash // Convert to 32bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * CapacitorPlatform - Implementation using real Capacitor plugins\n */\nexport class CapacitorPlatform implements PlatformService {\n readonly platformId = \"capacitor\" as const\n\n // Storage implementation using @capacitor/preferences\n readonly storage: PlatformStorage = {\n getItem: async (key: string): Promise<string | null> => {\n console.log(`${LOG_PREFIX} storage.getItem(\"${key}\")`)\n const { value } = await Preferences.get({ key })\n console.log(`${LOG_PREFIX} storage.getItem(\"${key}\") =>`, value ? `\"${value.substring(0, 50)}${value.length > 50 ? '...' : ''}\"` : 'null')\n return value\n },\n setItem: async (key: string, value: string): Promise<void> => {\n console.log(`${LOG_PREFIX} storage.setItem(\"${key}\", \"${value.substring(0, 50)}${value.length > 50 ? '...' : ''}\")`)\n await Preferences.set({ key, value })\n },\n removeItem: async (key: string): Promise<void> => {\n console.log(`${LOG_PREFIX} storage.removeItem(\"${key}\")`)\n await Preferences.remove({ key })\n },\n length: async (): Promise<number> => {\n // Preferences doesn't have a length method, so we get all keys\n const { keys } = await Preferences.keys()\n console.log(`${LOG_PREFIX} storage.length() => ${keys.length}`)\n return keys.length\n },\n key: async (index: number): Promise<string | null> => {\n const { keys } = await Preferences.keys()\n const key = keys[index] ?? null\n console.log(`${LOG_PREFIX} storage.key(${index}) => \"${key}\"`)\n return key\n },\n }\n\n // Cache implementation (same as storage for Capacitor, but with prefix)\n readonly cache: PlatformCache = {\n getItem: async (key: string): Promise<string | null> => {\n console.log(`${LOG_PREFIX} cache.getItem(\"${key}\")`)\n const { value } = await Preferences.get({ key: `cache_${key}` })\n console.log(`${LOG_PREFIX} cache.getItem(\"${key}\") =>`, value ? `\"${value.substring(0, 50)}...\"` : 'null')\n return value\n },\n setItem: async (key: string, value: string): Promise<void> => {\n console.log(`${LOG_PREFIX} cache.setItem(\"${key}\", \"${value.substring(0, 50)}...\")`)\n await Preferences.set({ key: `cache_${key}`, value })\n },\n removeItem: async (key: string): Promise<void> => {\n console.log(`${LOG_PREFIX} cache.removeItem(\"${key}\")`)\n await Preferences.remove({ key: `cache_${key}` })\n },\n }\n\n // AppsFlyer module (lazy-loaded, only on native)\n private appsFlyerModule: { AppsFlyer: { initSDK: (config: any) => Promise<unknown>; logEvent: (event: { eventName: string; eventValue?: Record<string, unknown> }) => Promise<unknown> } } | null = null\n\n // Analytics implementation - AppsFlyer on native, console fallback otherwise\n readonly analytics: PlatformAnalytics = {\n trackFunnelStep: (step: number, name: string) => {\n console.log(`${LOG_PREFIX} analytics.trackFunnelStep(${step}, \"${name}\")`)\n this.sendAppsFlyerEvent(`funnel_step_${step}`, { af_content: name })\n },\n recordCustomEvent: (eventName: string, params?: Record<string, unknown>) => {\n console.log(`${LOG_PREFIX} analytics.recordCustomEvent(\"${eventName}\")`, params)\n this.sendAppsFlyerEvent(eventName, params ?? {})\n },\n }\n\n private sendAppsFlyerEvent(eventName: string, eventValue: Record<string, unknown>): void {\n if (!this.appsFlyerModule) return\n this.appsFlyerModule.AppsFlyer.logEvent({ eventName, eventValue }).catch(() => {})\n }\n\n // Ads implementation\n // TODO: Add @capacitor-community/admob when ready for monetization\n readonly ads: PlatformAds = {\n showRewardedAdAsync: async (): Promise<boolean> => {\n console.log(`${LOG_PREFIX} ads.showRewardedAdAsync() - returning true (no ads configured)`)\n // Return true for testing so the game flow continues\n return true\n },\n showInterstitialAd: async (): Promise<boolean> => {\n console.log(`${LOG_PREFIX} ads.showInterstitialAd() - returning true (no ads configured)`)\n return true\n },\n }\n\n // IAP implementation using Preferences for local currency storage\n // TODO: Add real IAP plugin when ready for monetization\n readonly iap: PlatformIAP = {\n getHardCurrencyBalance: async (): Promise<number> => {\n const { value } = await Preferences.get({ key: \"premium_currency\" })\n const balance = value ? parseInt(value, 10) : 0\n console.log(`${LOG_PREFIX} iap.getHardCurrencyBalance() => ${balance}`)\n return balance\n },\n spendCurrency: async (productId: string, amount: number): Promise<void> => {\n console.log(`${LOG_PREFIX} iap.spendCurrency(\"${productId}\", ${amount})`)\n const current = await this.iap.getHardCurrencyBalance()\n if (current < amount) {\n throw new Error(\"Insufficient currency\")\n }\n await Preferences.set({ key: \"premium_currency\", value: (current - amount).toString() })\n },\n openStore: async (): Promise<void> => {\n console.log(`${LOG_PREFIX} iap.openStore() - not implemented yet`)\n // TODO: Show custom store UI or integrate with native purchase flow\n },\n }\n\n // CDN implementation - for standalone, assets are bundled with the app\n // Assets like .stow files are in public/cdn-assets/ folder\n readonly cdn: PlatformCDN = {\n fetchAsset: async (path: string): Promise<Blob> => {\n // For standalone builds, assets should be in the app bundle\n let fetchPath = path\n \n // Handle different path formats:\n // 1. Already absolute URL (http/https) - use as-is\n // 2. Absolute path from root (/) - use as-is\n // 3. Already relative (./) - use as-is\n // 4. Already prefixed with cdn-assets/ - just add ./\n // 5. Other relative paths - prepend ./cdn-assets/\n if (path.startsWith('http://') || path.startsWith('https://')) {\n fetchPath = path\n } else if (path.startsWith('/')) {\n fetchPath = path\n } else if (path.startsWith('./')) {\n fetchPath = path\n } else if (path.startsWith('cdn-assets/')) {\n fetchPath = `./${path}`\n } else {\n // Relative path (like \"Core.stow\" or \"shared3d/VFX/VFX_Core.stow\")\n // All CDN assets are stored in public/cdn-assets/\n fetchPath = `./cdn-assets/${path}`\n }\n \n console.log(`${LOG_PREFIX} cdn.fetchAsset(\"${path}\") => fetching from \"${fetchPath}\"`)\n \n try {\n const response = await fetch(fetchPath)\n if (!response.ok) {\n console.error(`${LOG_PREFIX} cdn.fetchAsset(\"${path}\") => HTTP ${response.status} ${response.statusText}`)\n throw new Error(`Failed to fetch asset: ${path} (HTTP ${response.status})`)\n }\n const blob = await response.blob()\n console.log(`${LOG_PREFIX} cdn.fetchAsset(\"${path}\") => success (${blob.size} bytes, type: ${blob.type})`)\n return blob\n } catch (error) {\n console.error(`${LOG_PREFIX} cdn.fetchAsset(\"${path}\") => error:`, error)\n throw error\n }\n },\n fetchBlob: async (path: string): Promise<Blob> => {\n return this.cdn.fetchAsset(path)\n },\n }\n\n // Notification channel for Android 8+\n private notificationChannelCreated = false\n\n private async ensureNotificationChannel(): Promise<void> {\n if (this.notificationChannelCreated) return\n \n try {\n // Create notification channel for Android 8+ (API 26+)\n await LocalNotifications.createChannel({\n id: 'game_notifications',\n name: 'Game Notifications',\n description: 'Notifications from Burger Shop Rush',\n importance: 4, // High importance\n visibility: 1, // Public\n sound: 'default',\n vibration: true,\n })\n this.notificationChannelCreated = true\n console.log(`${LOG_PREFIX} notifications: channel created`)\n } catch (error) {\n // Channel creation might fail on iOS or older Android, that's OK\n console.log(`${LOG_PREFIX} notifications: channel creation skipped (not needed on this platform)`)\n this.notificationChannelCreated = true\n }\n }\n\n // Notifications implementation using @capacitor/local-notifications\n readonly notifications: PlatformNotifications = {\n scheduleAsync: async (\n title: string,\n body: string,\n delaySeconds: number,\n notificationId?: string\n ): Promise<void> => {\n const id = notificationId ? stringToNotificationId(notificationId) : Date.now()\n console.log(`${LOG_PREFIX} notifications.scheduleAsync(\"${title}\", \"${body}\", ${delaySeconds}s, id=${id})`)\n \n try {\n // Request permission first\n const permission = await LocalNotifications.requestPermissions()\n console.log(`${LOG_PREFIX} notifications: permission status =`, permission.display)\n \n if (permission.display !== 'granted') {\n console.warn(`${LOG_PREFIX} notifications: permission not granted (${permission.display})`)\n return\n }\n\n // Ensure notification channel exists (Android 8+)\n await this.ensureNotificationChannel()\n\n const scheduledTime = new Date(Date.now() + delaySeconds * 1000)\n console.log(`${LOG_PREFIX} notifications: scheduling for ${scheduledTime.toISOString()}`)\n\n await LocalNotifications.schedule({\n notifications: [\n {\n id,\n title,\n body,\n schedule: { at: scheduledTime },\n channelId: 'game_notifications', // Required for Android 8+\n smallIcon: 'ic_launcher_background', // Must exist in res/drawable (avoids Invalid resource ID)\n largeIcon: 'ic_launcher',\n },\n ],\n })\n \n // Verify it was scheduled\n const pending = await LocalNotifications.getPending()\n console.log(`${LOG_PREFIX} notifications.scheduleAsync() => scheduled successfully, pending count: ${pending.notifications.length}`)\n } catch (error) {\n console.error(`${LOG_PREFIX} notifications.scheduleAsync() => error:`, error)\n }\n },\n cancelNotification: async (notificationId: string): Promise<void> => {\n const id = stringToNotificationId(notificationId)\n console.log(`${LOG_PREFIX} notifications.cancelNotification(\"${notificationId}\") => id=${id}`)\n \n try {\n await LocalNotifications.cancel({\n notifications: [{ id }],\n })\n console.log(`${LOG_PREFIX} notifications.cancelNotification() => cancelled successfully`)\n } catch (error) {\n console.error(`${LOG_PREFIX} notifications.cancelNotification() => error:`, error)\n }\n },\n }\n\n // Lifecycles implementation using @capacitor/app\n private resumeCallbacks: (() => void)[] = []\n private pauseCallbacks: (() => void)[] = []\n private appListenerSetup = false\n\n readonly lifecycles: PlatformLifecycles = {\n onResume: (callback: () => void) => {\n console.log(`${LOG_PREFIX} lifecycles.onResume() - registered callback`)\n this.resumeCallbacks.push(callback)\n },\n onPause: (callback: () => void) => {\n console.log(`${LOG_PREFIX} lifecycles.onPause() - registered callback`)\n this.pauseCallbacks.push(callback)\n },\n }\n\n private async initAppsFlyerAsync(): Promise<void> {\n console.log(`${LOG_PREFIX} AppsFlyer: initAppsFlyerAsync() called (native platform)`)\n\n const devKey = (import.meta as any).env?.VITE_APPSFLYER_DEV_KEY as string | undefined\n if (!devKey || devKey === \"your_dev_key_here\") {\n console.warn(`${LOG_PREFIX} AppsFlyer: VITE_APPSFLYER_DEV_KEY not set or placeholder, skipping init`)\n return\n }\n console.log(`${LOG_PREFIX} AppsFlyer: dev key present (length ${devKey.length})`)\n\n try {\n const { AppsFlyer } = await import(\"appsflyer-capacitor-plugin\")\n this.appsFlyerModule = { AppsFlyer }\n console.log(`${LOG_PREFIX} AppsFlyer: plugin loaded`)\n\n const appID = (import.meta as any).env?.VITE_APPSFLYER_APP_ID as string | undefined\n const isDebug = (import.meta as any).env?.VITE_APPSFLYER_DEBUG === \"true\" || (import.meta as any).env?.DEV === true\n\n await AppsFlyer.initSDK({\n devKey,\n appID: appID || \"\",\n isDebug,\n waitForATTUserAuthorization: 10,\n registerConversionListener: true,\n registerOnDeepLink: true,\n })\n console.log(`${LOG_PREFIX} AppsFlyer: initSDK() completed`)\n\n // Send login event to verify AppsFlyer is working (visible in In-app events)\n await AppsFlyer.logEvent({ eventName: \"af_login\", eventValue: { af_timestamp: Date.now().toString() } })\n console.log(`${LOG_PREFIX} AppsFlyer: af_login event sent`)\n } catch (err) {\n console.error(`${LOG_PREFIX} AppsFlyer init failed:`, err)\n }\n }\n\n // Preloader implementation using @capacitor/splash-screen\n readonly preloader: PlatformPreloader = {\n hideLoadScreen: async (): Promise<void> => {\n console.log(`${LOG_PREFIX} preloader.hideLoadScreen()`)\n try {\n await SplashScreen.hide()\n console.log(`${LOG_PREFIX} preloader.hideLoadScreen() => splash screen hidden`)\n } catch (error) {\n console.log(`${LOG_PREFIX} preloader.hideLoadScreen() => no splash screen to hide (web mode)`)\n }\n \n // Also hide any custom loading element\n const loader = document.getElementById(\"loading-screen\")\n if (loader) {\n loader.style.display = \"none\"\n console.log(`${LOG_PREFIX} preloader.hideLoadScreen() - hid #loading-screen element`)\n }\n },\n }\n\n // Initialize\n async initializeAsync(options?: { usePreloader?: boolean }): Promise<PlatformContext> {\n console.log(`${LOG_PREFIX} initializeAsync()`, options)\n\n // Init AppsFlyer on native only (Android/iOS) - enables retention, installs, sessions\n if (Capacitor.isNativePlatform()) {\n await this.initAppsFlyerAsync()\n }\n\n // Set up lifecycle listeners using Capacitor App plugin\n if (!this.appListenerSetup) {\n this.appListenerSetup = true\n \n try {\n App.addListener(\"appStateChange\", ({ isActive }) => {\n if (isActive) {\n console.log(`${LOG_PREFIX} app state: active - calling ${this.resumeCallbacks.length} resume callbacks`)\n this.resumeCallbacks.forEach(cb => cb())\n } else {\n console.log(`${LOG_PREFIX} app state: inactive - calling ${this.pauseCallbacks.length} pause callbacks`)\n this.pauseCallbacks.forEach(cb => cb())\n }\n })\n console.log(`${LOG_PREFIX} App lifecycle listener registered`)\n } catch (error) {\n console.log(`${LOG_PREFIX} App plugin not available (web mode), using visibility API fallback`)\n // Fallback using visibility API for web testing\n document.addEventListener(\"visibilitychange\", () => {\n if (document.hidden) {\n console.log(`${LOG_PREFIX} visibility: hidden - calling pause callbacks`)\n this.pauseCallbacks.forEach(cb => cb())\n } else {\n console.log(`${LOG_PREFIX} visibility: visible - calling resume callbacks`)\n this.resumeCallbacks.forEach(cb => cb())\n }\n })\n }\n }\n\n console.log(`${LOG_PREFIX} ✅ Platform initialized successfully`)\n \n return {\n initialized: true,\n data: { platform: \"capacitor\" },\n }\n }\n\n // Logging\n log(message: string, ...args: unknown[]): void {\n console.log(`${LOG_PREFIX} log:`, message, ...args)\n }\n}\n","/**\n * Platform Abstraction Layer\n * \n * Provides a unified API for platform-specific features.\n * Automatically selects the appropriate platform implementation\n * based on build configuration or runtime detection.\n * \n * Usage:\n * import { Platform } from \"@series-ai/venus-three/platform\"\n * \n * // Initialize (call once at startup)\n * await Platform.initializeAsync()\n * \n * // Use platform APIs\n * await Platform.storage.setItem(\"key\", \"value\")\n * Platform.analytics.trackFunnelStep(1, \"Started\")\n */\n\nexport type { \n PlatformService,\n PlatformContext,\n PlatformStorage,\n PlatformCache,\n PlatformAnalytics,\n PlatformAds,\n PlatformIAP,\n PlatformCDN,\n PlatformNotifications,\n PlatformLifecycles,\n PlatformPreloader,\n} from \"./PlatformService\"\n\n// Note: We don't export RundotPlatform directly to avoid loading RundotGameAPI\n// in Capacitor builds. Use dynamic import if you need RundotPlatform explicitly.\nexport { CapacitorPlatform } from \"./CapacitorPlatform\"\n\nimport type { PlatformService } from \"./PlatformService\"\nimport { CapacitorPlatform } from \"./CapacitorPlatform\"\n\n/**\n * Platform type for build configuration\n */\nexport type PlatformType = \"rundot\" | \"capacitor\" | \"auto\"\n\n/**\n * Singleton platform instance\n */\nlet platformInstance: PlatformService | null = null\n\n/**\n * Detect which platform to use based on environment\n */\nfunction detectPlatform(): PlatformType {\n // When running on Run dot (e.g. getreel.com), we must use RundotPlatform so\n // cdn.fetchAsset() goes through RundotGameAPI.cdn (correct CDN URLs). If we\n // used Capacitor here, fetch would hit relative ./cdn-assets/ and 404.\n if (typeof window !== \"undefined\" && typeof window.location?.hostname === \"string\") {\n const host = window.location.hostname.toLowerCase()\n if (host.includes(\"getreel.com\") || host.includes(\"h5-apps.getreel.com\")) {\n return \"rundot\"\n }\n }\n\n // Check for Capacitor\n if (typeof window !== \"undefined\" && (window as any).Capacitor) {\n return \"capacitor\"\n }\n \n // Check for build-time environment variable\n // Set VITE_PLATFORM=capacitor in your .env for Capacitor builds\n if (typeof import.meta !== \"undefined\" && (import.meta as any).env?.VITE_PLATFORM === \"capacitor\") {\n return \"capacitor\"\n }\n \n // Default to Rundot\n return \"rundot\"\n}\n\n/**\n * Create a platform instance based on type\n * Uses dynamic import for RundotPlatform to avoid loading RundotGameAPI in Capacitor builds\n */\nasync function createPlatformAsync(type: PlatformType): Promise<PlatformService> {\n let resolvedType = type === \"auto\" ? detectPlatform() : type\n\n // In Capacitor builds, RundotPlatform is not bundled (external). Never try to load it.\n const buildIsCapacitor =\n typeof (import.meta as any).env !== \"undefined\" &&\n (import.meta as any).env?.VITE_PLATFORM === \"capacitor\"\n if (buildIsCapacitor && resolvedType === \"rundot\") {\n console.log(\"[Platform] Capacitor build: forcing CapacitorPlatform (Rundot not bundled)\")\n resolvedType = \"capacitor\"\n }\n\n switch (resolvedType) {\n case \"capacitor\":\n console.log(\"[Platform] Using CapacitorPlatform\")\n return new CapacitorPlatform()\n case \"rundot\":\n default:\n console.log(\"[Platform] Using RundotPlatform (dynamic import)\")\n const { RundotPlatform } = await import(\"./RundotPlatform\")\n return new RundotPlatform()\n }\n}\n\n/**\n * Create a platform instance synchronously (for backwards compatibility)\n * Only works for Capacitor - Rundot requires async initialization\n */\nfunction createPlatformSync(type: PlatformType): PlatformService {\n const resolvedType = type === \"auto\" ? detectPlatform() : type\n \n if (resolvedType === \"capacitor\") {\n console.log(\"[Platform] Using CapacitorPlatform\")\n return new CapacitorPlatform()\n }\n \n // For Rundot, we need async loading - throw helpful error\n throw new Error(\n \"[Platform] RundotPlatform requires async initialization. \" +\n \"Use initializePlatformAsync() instead, or set VITE_PLATFORM=capacitor for Capacitor builds.\"\n )\n}\n\n/**\n * Initialize and get the platform instance (async)\n * \n * @param type - Platform type to use (\"rundot\", \"capacitor\", or \"auto\")\n * @returns The platform service instance\n */\nexport async function initializePlatformAsync(type: PlatformType = \"auto\"): Promise<PlatformService> {\n if (platformInstance) {\n console.warn(\"[Platform] Already initialized, returning existing instance\")\n return platformInstance\n }\n \n platformInstance = await createPlatformAsync(type)\n return platformInstance\n}\n\n/**\n * Initialize and get the platform instance (sync - Capacitor only)\n * For backwards compatibility. Use initializePlatformAsync() for Rundot.\n * \n * @param type - Platform type to use (\"rundot\", \"capacitor\", or \"auto\")\n * @returns The platform service instance\n */\nexport function initializePlatform(type: PlatformType = \"auto\"): PlatformService {\n if (platformInstance) {\n console.warn(\"[Platform] Already initialized, returning existing instance\")\n return platformInstance\n }\n \n // For Capacitor, we can initialize synchronously\n const resolvedType = type === \"auto\" ? detectPlatform() : type\n if (resolvedType === \"capacitor\") {\n platformInstance = new CapacitorPlatform()\n return platformInstance\n }\n \n // For Rundot, warn and throw - must use async\n throw new Error(\n \"[Platform] RundotPlatform requires async initialization in this build. \" +\n \"The RundotGameAPI is loaded dynamically to prevent it from loading in Capacitor builds. \" +\n \"Use initializePlatformAsync() for Rundot platform, or set VITE_PLATFORM=capacitor.\"\n )\n}\n\n/**\n * Get the current platform instance\n * Throws if platform has not been initialized\n */\nexport function getPlatform(): PlatformService {\n if (!platformInstance) {\n throw new Error(\n \"[Platform] Platform not initialized. Call initializePlatform() first, \" +\n \"or use Platform singleton which auto-initializes.\"\n )\n }\n return platformInstance\n}\n\n/**\n * Check if platform has been initialized\n */\nexport function isPlatformInitialized(): boolean {\n return platformInstance !== null\n}\n\n/**\n * Reset the platform instance (mainly for testing)\n */\nexport function resetPlatform(): void {\n platformInstance = null\n}\n\n/**\n * Platform singleton with lazy initialization\n * \n * This is the primary way to access platform APIs throughout the codebase.\n * It auto-initializes on first access using auto-detection.\n * \n * For Capacitor builds: Works synchronously, auto-initializes on first access.\n * For Rundot builds: Requires calling initializePlatformAsync() before first access.\n * \n * Usage:\n * import { Platform } from \"@series-ai/venus-three/platform\"\n * await Platform.storage.setItem(\"key\", \"value\")\n */\nexport const Platform: PlatformService = new Proxy({} as PlatformService, {\n get(_target, prop: keyof PlatformService) {\n if (!platformInstance) {\n // Auto-initialize on first access - only works for Capacitor\n const detectedType = detectPlatform()\n if (detectedType === \"capacitor\") {\n console.log(\"[Platform] Auto-initializing CapacitorPlatform on first access\")\n platformInstance = new CapacitorPlatform()\n } else {\n throw new Error(\n \"[Platform] Platform not initialized. For Rundot builds, call initializePlatformAsync() before accessing Platform. \" +\n \"For Capacitor builds, set VITE_PLATFORM=capacitor in your .env file.\"\n )\n }\n }\n return platformInstance[prop]\n },\n})\n","import * as THREE from \"three\"\n\nexport const AudioSystem: AudioSystemInstance = {\n mainListener: null,\n\n /**\n * Initialize the audio system with proper browser autoplay handling\n * Call this after setting up mainListener to ensure all audio works correctly\n */\n initialize(): void {\n let audioUnlocked = false\n\n const unlockAudioOnInteraction = async () => {\n if (audioUnlocked) return\n\n try {\n // Resume main AudioSystem context (used by Audio2D components)\n const mainContext = (AudioSystem.mainListener as any)?.context\n if (mainContext && mainContext.state === \"suspended\") {\n await mainContext.resume()\n console.log(\"🔊 Audio context resumed\")\n }\n\n audioUnlocked = true\n\n // Remove event listeners after first successful interaction\n document.removeEventListener(\"click\", unlockAudioOnInteraction)\n document.removeEventListener(\"keydown\", unlockAudioOnInteraction)\n document.removeEventListener(\"touchstart\", unlockAudioOnInteraction)\n\n console.log(\"🎵 Audio system initialized\")\n } catch (error) {\n console.warn(\"Failed to initialize audio:\", error)\n }\n }\n\n // Add event listeners for user interaction to unlock audio\n document.addEventListener(\"click\", unlockAudioOnInteraction)\n document.addEventListener(\"keydown\", unlockAudioOnInteraction)\n document.addEventListener(\"touchstart\", unlockAudioOnInteraction)\n\n console.log(\"🎵 Audio system ready - waiting for user interaction\")\n },\n}\n\nexport const Main2DAudioBank: AudioBank2D = {}\nexport const Main3DAudioBank: AudioBank3D = {}\n\nexport type AudioSystemInstance = {\n mainListener: THREE.AudioListener | null\n initialize(): void\n}\n\n// Internal master volume state for mute/unmute\nlet __masterVolume: number = 1.0\nlet __masterMuted: boolean = false\n\nexport type AudioBank2D = {\n [key: string]: THREE.Audio\n}\n\nexport type AudioBank3D = {\n [key: string]: THREE.PositionalAudio\n}\n\n// New config type for loading 2D/3D audio with properties (volume first)\nexport type AudioClip2DConfig = {\n path: string\n volume?: number\n}\nexport type AudioClip3DConfig = {\n path: string\n volume?: number\n}\n\nexport async function PopulateAudioBank2D(\n systemInstance: AudioSystemInstance,\n audioBank: AudioBank2D,\n clips: AudioClip2DConfig[]\n): Promise<void> {\n const loadPromises = clips.map((cfg) => {\n return new Promise<void>((resolve, reject) => {\n if (systemInstance.mainListener) {\n audioBank[cfg.path] = new THREE.Audio(systemInstance.mainListener)\n } else {\n console.error(\"Main listener is not set in AudioSystemInstance\")\n reject(new Error(`Main listener is not set for ${cfg.path}`))\n return\n }\n const audioLoader = new THREE.AudioLoader()\n audioLoader.load(\n cfg.path,\n function (buffer) {\n audioBank[cfg.path].setBuffer(buffer)\n audioBank[cfg.path].setLoop(false)\n const clipVolume = typeof cfg.volume === \"number\" ? cfg.volume : 1.0\n audioBank[cfg.path].setVolume(clipVolume)\n resolve()\n },\n undefined, // progress callback\n function (error) {\n console.error(`Failed to load audio file: ${cfg.path}`, error)\n reject(error)\n }\n )\n })\n })\n\n await Promise.all(loadPromises)\n}\n\nexport async function PopulateAudioBank3D(\n systemInstance: AudioSystemInstance,\n audioBank: AudioBank3D,\n clips: AudioClip3DConfig[]\n): Promise<void> {\n const loadPromises = clips.map((cfg) => {\n return new Promise<void>((resolve, reject) => {\n if (systemInstance.mainListener) {\n audioBank[cfg.path] = new THREE.PositionalAudio(systemInstance.mainListener)\n } else {\n console.error(\"Main listener is not set in AudioSystemInstance\")\n reject(new Error(`Main listener is not set for ${cfg.path}`))\n return\n }\n const audioLoader = new THREE.AudioLoader()\n audioLoader.load(\n cfg.path,\n function (buffer) {\n audioBank[cfg.path].setBuffer(buffer)\n audioBank[cfg.path].setRefDistance(20)\n audioBank[cfg.path].setLoop(false)\n const clipVolume = typeof cfg.volume === \"number\" ? cfg.volume : 1.0\n audioBank[cfg.path].setVolume(clipVolume)\n resolve()\n },\n undefined, // progress callback\n function (error) {\n console.error(`Failed to load audio file: ${cfg.path}`, error)\n reject(error)\n }\n )\n })\n })\n\n await Promise.all(loadPromises)\n}\n\nexport function PlayAudioOneShot2D(audioBank: AudioBank2D, audioClip: string) {\n if (!audioBank[audioClip]) {\n throw new Error(`Audio clip not found in bank: ${audioClip}`)\n }\n\n if (!audioBank[audioClip].buffer) {\n throw new Error(`Audio clip not loaded yet: ${audioClip}`)\n }\n\n audioBank[audioClip].play()\n}\n\n/**\n * Play a random 2D audio clip from the provided list.\n * Only clips that exist and are loaded in the provided bank will be considered.\n * Returns the clip name that was played.\n */\nexport function PlayAudioRandom2D(audioBank: AudioBank2D, clipNames: string[]): string {\n if (!Array.isArray(clipNames) || clipNames.length === 0) {\n throw new Error(\"No audio clip names provided to PlayAudioRandom2D\")\n }\n\n // Filter to clips that exist in the bank and are loaded\n const candidates = clipNames.filter((name) => {\n const audio = audioBank[name]\n return !!(audio && audio.buffer)\n })\n\n if (candidates.length === 0) {\n throw new Error(\"None of the provided audio clips are loaded in the audio bank\")\n }\n\n const index = Math.floor(Math.random() * candidates.length)\n const chosen = candidates[index]\n PlayAudioOneShot2D(audioBank, chosen)\n return chosen\n}\n\nexport function PlayAudioOneShot3D(\n audioBank: AudioBank3D,\n audioClip: string,\n parentObject: THREE.Object3D\n) {\n if (!audioBank[audioClip]) {\n throw new Error(`Audio clip not found in bank: ${audioClip}`)\n }\n\n if (!audioBank[audioClip].buffer) {\n throw new Error(`Audio clip not loaded yet: ${audioClip}`)\n }\n\n parentObject.add(audioBank[audioClip])\n audioBank[audioClip].play()\n}\n\n/** Set global master volume using Three.js AudioListener */\nexport function SetMasterVolume(volume: number): void {\n const v = Math.max(0, Math.min(1, volume))\n __masterVolume = v\n\n if (AudioSystem.mainListener) {\n AudioSystem.mainListener.setMasterVolume(__masterMuted ? 0 : v)\n }\n}\n\n/** Get the last set (intended) master volume [0..1]. */\nexport function GetMasterVolume(): number {\n return __masterVolume\n}\n\n/** Toggle global mute using Three.js AudioListener */\nexport function SetAudioMuted(muted: boolean): void {\n __masterMuted = !!muted\n\n if (AudioSystem.mainListener) {\n AudioSystem.mainListener.setMasterVolume(__masterMuted ? 0 : __masterVolume)\n }\n}\n\n/** Check if audio is currently muted globally. */\nexport function IsAudioMuted(): boolean {\n return __masterMuted\n}\n","import * as THREE from \"three\"\nimport { VenusGame } from \"./VenusGame.ts\"\nimport { ComponentUpdater } from \"./ComponentUpdater\"\n\n/**\n * Three.js version of GameObject\n * Clean implementation without Babylon.js dependencies\n */\nexport class GameObject extends THREE.Object3D {\n private components = new Map<new (...args: any[]) => Component, Component>()\n private isDestroyed: boolean = false\n private static idCounter: number = 0\n\n /**\n * Create a new Three.js GameObject\n * @param name Optional name for the GameObject. If not provided, an auto-generated name will be used.\n */\n constructor(name?: string) {\n super()\n\n // Generate a name if none provided\n this.name = name || `GameObject_${GameObject.idCounter++}`\n\n // Add to the scene\n VenusGame.scene.add(this)\n }\n\n /**\n * Adds a component instance to the GameObject\n * @returns The component instance\n * @throws If component of same type already exists\n */\n addComponent<T extends Component>(component: T): T {\n if (this.isDestroyed) {\n throw new Error(\"Cannot add component to destroyed GameObject\")\n }\n\n const componentType = component.constructor as new (...args: any[]) => T\n\n if (this.components.has(componentType)) {\n throw new Error(`Component ${componentType.name} already exists on GameObject ${this.name}`)\n }\n\n try {\n // Attach the component\n component.attach(this)\n this.components.set(componentType, component)\n\n return component\n } catch (error) {\n // Provide better context for component initialization errors\n console.error(\n `❌ Failed to add component ${componentType.name} to GameObject \"${this.name}\":`,\n error\n )\n throw error // Re-throw to stop initialization\n }\n }\n\n /**\n * Gets a component of the specified type\n * @returns The component if found, undefined otherwise\n */\n getComponent<T extends Component>(componentType: new (...args: any[]) => T): T | undefined {\n return this.components.get(componentType) as T | undefined\n }\n\n /**\n * Checks if the GameObject has a component of the specified type\n */\n hasComponent<T extends Component>(componentType: new (...args: any[]) => T): boolean {\n return this.components.has(componentType)\n }\n\n /**\n * Walks up the parent hierarchy looking for a component of the given type.\n * Checks this GameObject first, then each ancestor.\n * @returns The first matching component, or undefined\n */\n getComponentInParent<T extends Component>(componentType: new (...args: any[]) => T): T | undefined {\n let current: THREE.Object3D | null = this as THREE.Object3D\n while (current) {\n if (current instanceof GameObject) {\n const comp = current.getComponent(componentType)\n if (comp) return comp\n }\n current = current.parent\n }\n return undefined\n }\n\n /**\n * Searches this GameObject and all descendants for a component of the given type.\n * Uses depth-first traversal, returns the first match.\n * @returns The first matching component, or undefined\n */\n getComponentInChildren<T extends Component>(componentType: new (...args: any[]) => T): T | undefined {\n const comp = this.getComponent(componentType)\n if (comp) return comp\n\n for (const child of this.children) {\n if (child instanceof GameObject) {\n const found = child.getComponentInChildren(componentType)\n if (found) return found\n }\n }\n return undefined\n }\n\n /**\n * Searches this GameObject and all descendants for all components of the given type.\n * @returns Array of all matching components\n */\n getComponentsInChildren<T extends Component>(componentType: new (...args: any[]) => T): T[] {\n const results: T[] = []\n const comp = this.getComponent(componentType)\n if (comp) results.push(comp)\n\n for (const child of this.children) {\n if (child instanceof GameObject) {\n results.push(...child.getComponentsInChildren(componentType))\n }\n }\n return results\n }\n\n /**\n * Removes a component of the specified type\n * @returns true if component was found and removed\n */\n removeComponent<T extends Component>(componentType: new (...args: any[]) => T): boolean {\n const component = this.components.get(componentType)\n if (!component) return false\n\n // Cleanup and remove the component\n component.cleanup()\n this.components.delete(componentType)\n return true\n }\n\n /**\n * Disposes of the GameObject and all its components\n */\n dispose(): void {\n if (this.isDestroyed) return\n this.isDestroyed = true\n\n // First, recursively dispose all child GameObjects (and their components)\n // Collect children first to avoid modification during iteration\n const childGameObjects: GameObject[] = []\n for (const child of this.children) {\n if (child instanceof GameObject) {\n childGameObjects.push(child)\n }\n }\n\n // Dispose each child GameObject (this will recursively dispose their children too)\n for (const child of childGameObjects) {\n child.dispose()\n }\n\n // Cleanup all components on this GameObject\n for (const component of this.components.values()) {\n component.cleanup()\n }\n\n // Clear components\n this.components.clear()\n\n // Remove from parent\n if (this.parent) {\n this.parent.remove(this)\n }\n\n // Dispose of any meshes/materials (for non-GameObject Three.js objects)\n this.traverse((object: THREE.Object3D) => {\n if (object instanceof THREE.Mesh) {\n object.geometry.dispose()\n if (object.material instanceof THREE.Material) {\n object.material.dispose()\n } else if (Array.isArray(object.material)) {\n object.material.forEach((material: THREE.Material) => material.dispose())\n }\n }\n })\n\n // Clear remaining children\n this.clear()\n }\n\n /**\n * Get the Three.js scene the GameObject is in\n */\n getScene(): THREE.Scene {\n return VenusGame.scene\n }\n\n /**\n * Three.js equivalent of setEnabled - uses visible property\n */\n setEnabled(value: boolean): void {\n const wasEnabled = this.isEnabled()\n\n // Set visibility\n this.visible = value\n\n const isNowEnabled = this.isEnabled()\n\n // If the effective enabled state actually changed, notify components and children\n if (wasEnabled !== isNowEnabled) {\n // GameObject enabled state changed (logging disabled)\n\n // Notify this GameObject's components\n this.notifyEnabledStateChanged(isNowEnabled)\n\n // Notify children recursively\n this.notifyChildrenEnabledStateChanged()\n }\n }\n\n /**\n * Three.js equivalent of isEnabled - checks visible property AND parent hierarchy\n */\n isEnabled(): boolean {\n // Check own visibility first\n if (!this.visible) {\n return false\n }\n\n // Check parent hierarchy - if any parent is disabled, this object is effectively disabled\n let current = this.parent\n while (current) {\n if (current instanceof GameObject && !current.visible) {\n return false\n }\n // Also check regular Three.js objects in the hierarchy\n if (current instanceof THREE.Object3D && !current.visible) {\n return false\n }\n current = current.parent\n }\n\n return true\n }\n\n /**\n * Override THREE.Object3D.add() to handle enabled state propagation\n * When adding a child to a disabled parent, the child should be effectively disabled too\n */\n add(...objects: THREE.Object3D[]): this {\n // Call parent implementation first\n super.add(...objects)\n\n // For each added object, check if we need to handle enabled state\n for (const object of objects) {\n if (object instanceof GameObject) {\n // Check the child's effective enabled state now that it has a new parent\n const childEffectiveState = object.isEnabled()\n\n // Notify the child's components about its effective state\n object.notifyEnabledStateChanged(childEffectiveState)\n\n // Also notify the child's descendants recursively\n object.notifyChildrenEnabledStateChanged()\n }\n }\n\n return this\n }\n\n /**\n * Recursively notify all children that their enabled state may have changed\n */\n protected notifyChildrenEnabledStateChanged(): void {\n for (const child of this.children) {\n if (child instanceof GameObject) {\n // Check the child's effective enabled state (now includes parent hierarchy)\n const childIsEnabled = child.isEnabled()\n\n // Child enabled state change (logging disabled)\n\n // Notify the child's components based on effective state\n child.notifyEnabledStateChanged(childIsEnabled)\n\n // Recursively notify grandchildren (they will also check their effective state)\n child.notifyChildrenEnabledStateChanged()\n }\n }\n }\n\n /**\n * Internal method to trigger enabled state change notifications\n * This causes components to receive onEnabled/onDisabled callbacks\n */\n protected notifyEnabledStateChanged(isEnabled: boolean): void {\n // Notify components (logging disabled)\n\n // Notify all components\n for (const component of this.components.values()) {\n if (isEnabled) {\n component.onEnabled()\n } else {\n component.onDisabled()\n }\n }\n }\n}\n\n/**\n * Three.js Component base class\n * Clean implementation without Babylon.js dependencies\n */\nexport abstract class Component {\n protected gameObject!: GameObject\n private _isAttached: boolean = false\n\n /**\n * Get the GameObject this component is attached to\n */\n public getGameObject(): GameObject {\n return this.gameObject\n }\n\n /**\n * Get the scene the GameObject is in\n */\n protected get scene(): THREE.Scene {\n return this.gameObject.getScene()\n }\n\n /**\n * Attach this component to a GameObject\n * @internal Called by GameObject.addComponent\n */\n attach(gameObject: GameObject): void {\n if (this._isAttached) {\n throw new Error(\"Component is already attached to a GameObject\")\n }\n\n this.gameObject = gameObject\n this._isAttached = true\n\n // Register for updates if the component has an update method\n if (this.update) {\n ComponentUpdater.registerComponent(this)\n }\n\n // Register for late updates if the component has a lateUpdate method\n if (this.lateUpdate) {\n ComponentUpdater.registerLateUpdateComponent(this)\n }\n\n // Call the onCreate lifecycle method\n this.onCreate()\n\n // Call onEnabled if the GameObject is currently enabled\n if (this.gameObject.isEnabled()) {\n this.onEnabled()\n }\n }\n\n /**\n * Clean up this component\n * @internal Called by GameObject when removing component\n */\n cleanup(): void {\n if (!this._isAttached) return\n\n // Unregister from updates\n ComponentUpdater.unregisterComponent(this)\n ComponentUpdater.unregisterLateUpdateComponent(this)\n\n // Call the onCleanup lifecycle method\n this.onCleanup()\n\n this._isAttached = false\n }\n\n /**\n * Called when the component is first added to a GameObject\n * Override this method to implement component initialization\n */\n protected onCreate(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called when the component is being removed/destroyed\n * Override this method to implement component cleanup\n */\n protected onCleanup(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called when the GameObject becomes enabled\n * Override this method to react to enable state changes\n */\n public onEnabled(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called when the GameObject becomes disabled\n * Override this method to react to enable state changes\n */\n public onDisabled(): void {\n // Default implementation does nothing\n }\n\n /**\n * Called every frame if the component's GameObject is enabled\n * Override this method to implement per-frame logic\n * @param deltaTime Time in seconds since last frame\n */\n public update?(deltaTime: number): void\n\n /**\n * Called every frame after all update() calls have completed\n * Perfect for camera movement, UI updates, and anything that should happen last\n * @param deltaTime Time in seconds since last frame\n */\n public lateUpdate?(deltaTime: number): void\n\n /**\n * Check if the component is attached to a GameObject\n */\n public isAttached(): boolean {\n return this._isAttached\n }\n\n /**\n * Gets a component of the specified type from the same GameObject\n * @returns The component if found, undefined otherwise\n */\n getComponent<T extends Component>(componentType: new (...args: any[]) => T): T | undefined {\n return this.gameObject.getComponent(componentType)\n }\n}\n","import * as THREE from \"three\"\nimport { PhysicsSystem } from \"@systems/physics/PhysicsSystem.ts\"\nimport { ComponentUpdater } from \"./ComponentUpdater\"\nimport { InputManager } from \"@systems/input\"\nimport { TweenSystem } from \"@systems/math\"\nimport { Platform, initializePlatformAsync, type PlatformType } from \"../../platform\"\nimport { AudioSystem } from \"@systems/audio\"\nimport { UISystem } from \"@systems/ui\"\nimport { InstancedMeshManager } from \"@engine/render/InstancedMeshManager\"\nimport { AnimationCullingManager } from \"@systems/animatrix/AnimationCullingManager\"\n\n/**\n * Configuration interface for VenusGame.\n * Override getConfig() in your game class to customize these settings.\n */\nexport interface VenusGameConfig {\n /** Background color as hex number (default: 0x000000) */\n backgroundColor?: number\n /** Enable antialiasing for smoother edges (default: true) */\n antialias?: boolean\n /** Enable shadow mapping (default: true) */\n shadowMapEnabled?: boolean\n /** Shadow map type: 'vsm' for smoother shadows, 'pcf_soft' for softer edges (default: 'vsm') */\n shadowMapType?: \"vsm\" | \"pcf_soft\"\n /** Tone mapping: 'aces' for filmic, 'linear' for basic, 'none' to disable (default: 'aces') */\n toneMapping?: \"aces\" | \"linear\" | \"none\"\n /** Tone mapping exposure (default: 1.0) */\n toneMappingExposure?: number\n /** Enable audio system and auto-create listener (default: true) */\n audioEnabled?: boolean\n /** Camera type: 'perspective' or 'orthographic' (default: 'perspective') */\n cameraType?: \"perspective\" | \"orthographic\"\n /** Orthographic camera frustum size — half-height in world units (default: 10) */\n orthoSize?: number\n}\n\n/** Default configuration values */\nconst DEFAULT_CONFIG: Required<VenusGameConfig> = {\n backgroundColor: 0x000000,\n antialias: true,\n shadowMapEnabled: true,\n shadowMapType: \"vsm\",\n toneMapping: \"aces\",\n toneMappingExposure: 1.0,\n audioEnabled: true,\n cameraType: \"perspective\",\n orthoSize: 10,\n}\n\n/**\n * Three.js version of VenusGame\n * Clean implementation without Babylon.js dependencies\n */\nexport abstract class VenusGame {\n // Static references for global access\n private static _instance: VenusGame\n private static _scene: THREE.Scene\n private static _renderer: THREE.WebGLRenderer\n private static _camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n\n // Instance properties\n protected canvas: HTMLCanvasElement\n protected renderer: THREE.WebGLRenderer\n protected scene: THREE.Scene\n private _instanceCamera!: THREE.PerspectiveCamera | THREE.OrthographicCamera\n\n /** Setting the camera also updates VenusGame.camera (static) */\n protected get camera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this._instanceCamera\n }\n protected set camera(cam: THREE.PerspectiveCamera | THREE.OrthographicCamera) {\n this._instanceCamera = cam\n VenusGame._camera = cam\n }\n private resizeListener: () => void\n private isDisposed: boolean = false\n private animationId: number | null = null\n private clock: THREE.Clock // Made private to prevent delta time issues\n private maxDeltaTime: number = 1 / 30 // Cap delta time at 33ms (30 FPS minimum)\n\n // Configuration\n protected config: Required<VenusGameConfig>\n\n // Audio listener (auto-created if audioEnabled)\n protected audioListener: THREE.AudioListener | null = null\n\n // Animation culling\n private animationCullingManager: AnimationCullingManager | null = null\n\n /**\n * Get the current elapsed time (not delta time)\n * NOTE: For delta time, use the parameter passed to preRender() method\n * This prevents accidental multiple getDelta() calls which cause frame rate dependent behavior\n */\n protected getElapsedTime(): number {\n return this.clock.getElapsedTime()\n }\n\n /**\n * Override this method to provide game-specific configuration.\n * The returned config is merged with DEFAULT_CONFIG.\n * @example\n * protected getConfig(): VenusGameConfig {\n * return {\n * backgroundColor: 0x0077b6,\n * toneMapping: \"aces\",\n * }\n * }\n */\n protected getConfig(): VenusGameConfig {\n return {}\n }\n\n /**\n * Get the active VenusGame instance\n */\n public static get instance(): VenusGame {\n return VenusGame._instance\n }\n\n /**\n * Get the active Three.js scene\n */\n public static get scene(): THREE.Scene {\n return VenusGame._scene\n }\n\n /**\n * Get the active Three.js renderer\n */\n public static get renderer(): THREE.WebGLRenderer {\n return VenusGame._renderer\n }\n\n /**\n * Get the active Three.js camera\n */\n public static get camera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return VenusGame._camera\n }\n\n // ===== Animation Culling API =====\n\n /**\n * Set the camera used for animation frustum culling.\n * When set, animation updates are skipped for characters outside the camera's view.\n * @param camera The camera to use for culling (pass null to disable)\n * @param frustumExpansion How much to expand the frustum (1.2 = 20% larger, avoids pop-in). Default: 1.2\n */\n public static setAnimationCullingCamera(\n camera: THREE.Camera | null,\n frustumExpansion: number = 1.2\n ): void {\n const instance = VenusGame._instance\n if (!instance) return\n\n if (camera) {\n instance.animationCullingManager = AnimationCullingManager.getInstance()\n instance.animationCullingManager.addCamera(camera, true)\n instance.animationCullingManager.setFrustumCullingEnabled(true)\n instance.animationCullingManager.setDistanceCullingEnabled(false)\n instance.animationCullingManager.setFrustumExpansion(frustumExpansion)\n } else {\n // Disable culling\n if (instance.animationCullingManager) {\n instance.animationCullingManager.setFrustumCullingEnabled(false)\n }\n }\n }\n\n /**\n * Get the animation culling manager for advanced configuration.\n * Use this to enable distance culling, add multiple cameras, adjust LOD settings, etc.\n */\n public static getAnimationCulling(): AnimationCullingManager {\n return AnimationCullingManager.getInstance()\n }\n\n /**\n * Static factory method to create, initialize and start a VenusGame instance\n * @param platformType - Optional platform type override (\"rundot\", \"capacitor\", or \"auto\")\n * @returns A fully initialized and running VenusGame instance\n */\n public static async create<T extends VenusGame>(\n this: new () => T,\n platformType: PlatformType = \"auto\"\n ): Promise<T> {\n // Create the instance\n const instance = new this()\n\n // Set static references\n VenusGame._instance = instance\n VenusGame._scene = instance.scene\n VenusGame._renderer = instance.renderer\n VenusGame._camera = instance.camera\n\n // Initialize the platform abstraction layer\n const platform = await initializePlatformAsync(platformType)\n const context = await platform.initializeAsync({\n usePreloader: true\n })\n console.log(\"[Rundot 3D] Platform initialized: \", platform.platformId, context)\n\n Platform.analytics.trackFunnelStep(1, \"Rundot Initialized\")\n\n // const insets = context?.\n // if (insets) {\n // console.log(`[DEBUG] Hud Insets: `, insets)\n // UISystem.setInsets(insets)\n // }\n\n Platform.lifecycles.onResume(() => {\n console.log(`[DEBUG] OnResume()`)\n window.focus()\n instance.resume()\n })\n\n Platform.lifecycles.onPause(() => {\n console.log(`[DEBUG] OnPause()`)\n instance.pause()\n })\n\n // Initialize physics system (will be Rapier)\n await PhysicsSystem.initialize()\n\n // Initialize input system\n InputManager.initialize()\n\n // Initialize lighting system\n LightingSystem.initialize(instance.scene)\n\n // Initialize component updater\n ComponentUpdater.initialize(instance.scene)\n\n // Initialize instanced mesh manager\n InstancedMeshManager.getInstance().initialize(instance.scene)\n\n // Set up audio listener (before game code runs so it can use audio)\n instance.setupAudioListener()\n\n // Call the custom implementation's onInitialize method\n await instance.onStart()\n\n // Start the render loop\n instance.startRenderLoop()\n\n await Platform.preloader.hideLoadScreen()\n\n window.focus()\n\n return instance\n }\n\n resume() {\n this.clock.getDelta()\n this.isPaused = false\n AudioSystem.mainListener?.setMasterVolume(this.prevMasterVolume ?? 1)\n }\n\n pause() {\n this.isPaused = true\n this.prevMasterVolume = AudioSystem.mainListener?.getMasterVolume()\n AudioSystem.mainListener?.setMasterVolume(0)\n }\n\n /**\n * Create a new VenusGame\n */\n constructor() {\n // Merge game config with defaults\n this.config = { ...DEFAULT_CONFIG, ...this.getConfig() }\n\n // Look for an existing canvas\n const existingCanvas = document.getElementById(\"renderCanvas\")\n\n if (existingCanvas instanceof HTMLCanvasElement) {\n // Use the existing canvas element\n this.canvas = existingCanvas\n } else {\n // Create a new canvas element\n const newCanvas = document.createElement(\"canvas\")\n newCanvas.id = \"renderCanvas\"\n newCanvas.style.width = \"100%\"\n newCanvas.style.height = \"100%\"\n newCanvas.style.display = \"block\"\n document.body.appendChild(newCanvas)\n this.canvas = newCanvas\n }\n\n // Create the Three.js renderer\n this.renderer = new THREE.WebGLRenderer({\n canvas: this.canvas,\n antialias: this.config.antialias,\n powerPreference: \"high-performance\",\n })\n this.renderer.setSize(window.innerWidth, window.innerHeight)\n\n // Cap pixel ratio for performance, especially on high-DPI mobile devices like iPhone\n // iPhone can have pixel ratios of 3 or higher which severely impacts performance\n // Use very low pixel ratio (1.0) for iPhone to ensure smooth 60fps gameplay\n let maxPixelRatio: number\n if (this.isIPhone()) {\n maxPixelRatio = 1.0 // Lowest quality for maximum performance on iPhone\n } else if (this.isMobileDevice()) {\n maxPixelRatio = 2 // Other mobile devices can handle a bit more\n } else {\n maxPixelRatio = window.devicePixelRatio // Desktop gets full resolution\n }\n const cappedPixelRatio = Math.min(window.devicePixelRatio, maxPixelRatio)\n this.renderer.setPixelRatio(cappedPixelRatio)\n console.log(\n `[Rundot 3D] Device pixel ratio: ${window.devicePixelRatio}, Using: ${cappedPixelRatio} (iPhone: ${this.isIPhone()})`\n )\n\n // Apply rendering configuration from config\n this.applyRenderingConfig()\n\n // Create the Three.js scene\n this.scene = new THREE.Scene()\n\n // Apply background color from config\n this.scene.background = new THREE.Color(this.config.backgroundColor)\n\n // Create the Three.js camera\n if (this.config.cameraType === \"orthographic\") {\n const aspect = window.innerWidth / window.innerHeight\n const size = this.config.orthoSize\n this.camera = new THREE.OrthographicCamera(\n -size * aspect, // left\n size * aspect, // right\n size, // top\n -size, // bottom\n 0.1, // near\n 1000 // far\n )\n } else {\n this.camera = new THREE.PerspectiveCamera(\n 75, // fov\n window.innerWidth / window.innerHeight, // aspect\n 0.1, // near\n 1000 // far\n )\n }\n\n // Create clock for delta time\n this.clock = new THREE.Clock()\n\n // Set up window resize handling\n this.resizeListener = () => {\n const aspect = window.innerWidth / window.innerHeight\n if (this.camera instanceof THREE.PerspectiveCamera) {\n this.camera.aspect = aspect\n } else if (this.camera instanceof THREE.OrthographicCamera) {\n const size = this.config.orthoSize\n this.camera.left = -size * aspect\n this.camera.right = size * aspect\n this.camera.top = size\n this.camera.bottom = -size\n }\n this.camera.updateProjectionMatrix()\n this.renderer.setSize(window.innerWidth, window.innerHeight)\n\n // Re-apply capped pixel ratio on resize\n let maxPixelRatio: number\n if (this.isIPhone()) {\n maxPixelRatio = 1.25 // Very conservative for iPhone\n } else if (this.isMobileDevice()) {\n maxPixelRatio = 2\n } else {\n maxPixelRatio = window.devicePixelRatio\n }\n const cappedPixelRatio = Math.min(window.devicePixelRatio, maxPixelRatio)\n this.renderer.setPixelRatio(cappedPixelRatio)\n }\n window.addEventListener(\"resize\", this.resizeListener)\n }\n\n /**\n * Apply rendering configuration from config\n */\n private applyRenderingConfig(): void {\n // Shadow map configuration\n this.renderer.shadowMap.enabled = this.config.shadowMapEnabled\n this.renderer.shadowMap.type =\n this.config.shadowMapType === \"pcf_soft\" ? THREE.PCFSoftShadowMap : THREE.VSMShadowMap\n this.renderer.shadowMap.autoUpdate = true\n\n // Color space\n this.renderer.outputColorSpace = THREE.SRGBColorSpace\n\n // Tone mapping\n if (this.config.toneMapping === \"none\") {\n this.renderer.toneMapping = THREE.NoToneMapping\n } else if (this.config.toneMapping === \"linear\") {\n this.renderer.toneMapping = THREE.LinearToneMapping\n this.renderer.toneMappingExposure = this.config.toneMappingExposure\n } else {\n // Default: ACES filmic\n this.renderer.toneMapping = THREE.ACESFilmicToneMapping\n this.renderer.toneMappingExposure = this.config.toneMappingExposure\n }\n }\n\n /**\n * Set up audio listener if enabled in config.\n * Attaches listener to camera and sets AudioSystem.mainListener.\n */\n private setupAudioListener(): void {\n if (!this.config.audioEnabled) return\n\n this.audioListener = new THREE.AudioListener()\n this.camera.add(this.audioListener)\n AudioSystem.mainListener = this.audioListener\n\n console.log(\"[Rundot 3D] Audio listener initialized and attached to camera\")\n }\n\n /**\n * Check if running on an iPhone/iPad specifically\n */\n private isIPhone(): boolean {\n return /iPhone|iPad|iPod/i.test(navigator.userAgent)\n }\n\n /**\n * Check if running on a mobile device\n */\n private isMobileDevice(): boolean {\n return (\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||\n \"ontouchstart\" in window ||\n navigator.maxTouchPoints > 0\n )\n }\n\n private isPaused: boolean = false\n private prevMasterVolume: number | undefined = undefined\n\n /**\n * Start the render loop\n */\n private startRenderLoop(): void {\n // Set up visibility handling to pause delta time when tab is hidden\n this.setupVisibilityHandling()\n\n const animate = () => {\n // IMPORTANT: Only call getDelta() once per frame here\n // This ensures consistent delta time throughout the entire frame\n let deltaTime = this.clock.getDelta()\n\n // Cap delta time to prevent physics explosions when returning from tab switch\n if (deltaTime > this.maxDeltaTime) {\n deltaTime = this.maxDeltaTime\n }\n\n if (!this.isPaused) {\n // Step physics simulation\n PhysicsSystem.step(deltaTime)\n\n // Update tween system (before component updates so tweens apply first)\n TweenSystem.update(deltaTime)\n\n // Update animation culling frustum BEFORE component updates\n // This allows AnimationGraphComponents to check visibility during their update()\n this.animationCullingManager?.beginFrame()\n\n // Update components\n ComponentUpdater.update(deltaTime)\n\n // Late update components\n ComponentUpdater.lateUpdate(deltaTime)\n\n // Update instanced mesh matrices\n InstancedMeshManager.getInstance().updateAllBatches()\n }\n\n // Pre-render hook\n this.preRender(deltaTime)\n\n // Render the scene (can be overridden for post-processing)\n this.animationId = requestAnimationFrame(animate)\n\n this.render()\n }\n animate()\n }\n\n /**\n * Setup visibility change handling to pause/resume delta time\n */\n private setupVisibilityHandling(): void {\n console.log(\"[DEBUG] setting up visibility handlers...\")\n\n // Handle tab visibility changes\n document.addEventListener(\"visibilitychange\", () => {\n if (document.hidden) {\n console.log(\"🌙 Tab hidden - pausing game time\")\n // Clock will continue but we'll clear the delta when we return\n } else {\n console.log(\"☀️ Tab visible - resuming with fresh delta time\")\n // Clear any accumulated delta time to prevent huge jumps\n this.clock.getDelta()\n }\n })\n\n // Handle window focus changes\n window.addEventListener(\"focus\", () => {\n console.log(\"🔄 Window focused - clearing delta time\")\n // Clear delta time to prevent any accumulated time from causing issues\n this.clock.getDelta()\n })\n\n window.addEventListener(\"blur\", () => {\n console.log(\"🔄 Window blurred\")\n // Just log for now - the delta will be cleared when focus returns\n })\n }\n\n /**\n * Render method. Can be overridden for custom rendering pipelines.\n */\n protected render(): void {\n this.renderer.render(this.scene, this.camera)\n }\n\n /**\n * Abstract method that derived classes must implement for game-specific initialization\n */\n protected abstract onStart(): Promise<void>\n\n /**\n * Abstract method called every frame before rendering\n * @param deltaTime Time in seconds since last frame - use this for all time-based calculations\n * IMPORTANT: Do NOT access this.clock.getDelta() directly - use the deltaTime parameter!\n */\n protected abstract preRender(deltaTime: number): void\n\n /**\n * Abstract method that derived classes must implement for game cleanup\n */\n protected abstract onDispose(): Promise<void>\n\n /**\n * Dispose of the game, cleaning up all resources\n * This will stop the render loop and clean up any created resources\n */\n public async dispose(): Promise<void> {\n if (this.isDisposed) {\n return // Already disposed\n }\n\n this.isDisposed = true\n\n // Stop the render loop\n if (this.animationId !== null) {\n cancelAnimationFrame(this.animationId)\n this.animationId = null\n }\n\n // Call the custom implementation's cleanup\n await this.onDispose()\n\n // Clean up systems\n PhysicsSystem.dispose()\n LightingSystem.dispose()\n ComponentUpdater.dispose()\n InstancedMeshManager.getInstance().dispose()\n\n // Remove event listeners\n window.removeEventListener(\"resize\", this.resizeListener)\n\n // Dispose of Three.js resources\n this.scene.traverse((object: THREE.Object3D) => {\n if (object instanceof THREE.Mesh) {\n object.geometry.dispose()\n if (object.material instanceof THREE.Material) {\n object.material.dispose()\n } else if (Array.isArray(object.material)) {\n object.material.forEach((material: THREE.Material) => material.dispose())\n }\n }\n })\n\n this.renderer.dispose()\n\n // If we created the canvas, remove it from the DOM\n if (this.canvas.id === \"renderCanvas\" && this.canvas.parentNode) {\n this.canvas.parentNode.removeChild(this.canvas)\n }\n }\n}\n\n// Placeholder classes for the Three.js systems (to be implemented)\n\nclass LightingSystem {\n static initialize(scene: THREE.Scene): void {\n // Three.js lighting is just adding lights to the scene - no complex system needed!\n }\n\n static dispose(): void {\n // Lights are disposed with the scene - no cleanup needed\n }\n}\n","import * as THREE from \"three\"\nimport { AudioSystem, AudioSystemInstance } from \"./AudioSystem\"\n\nexport const MusicBank: MusicBankType = {}\n\nexport type MusicBankType = {\n [key: string]: THREE.Audio\n}\n\nexport interface MusicSystemState {\n currentTrack: string | null\n isPlaying: boolean\n isPaused: boolean\n volume: number\n loop: boolean\n playlist: string[]\n playlistIndex: number\n playlistActive: boolean\n}\n\nexport const MusicSystem: MusicSystemState = {\n currentTrack: null,\n isPlaying: false,\n isPaused: false,\n volume: 0.5, // Default to 50% volume for background music\n loop: true,\n playlist: [],\n playlistIndex: 0,\n playlistActive: false,\n}\n\n/**\n * Populate the music bank with audio files\n * @param systemInstance - The audio system instance\n * @param musicBank - The music bank to populate\n * @param musicList - Array of music file paths\n */\nexport async function PopulateMusicBank(\n systemInstance: AudioSystemInstance,\n musicBank: MusicBankType,\n musicList: string[]\n): Promise<void> {\n const loadPromises = musicList.map((musicFile) => {\n return new Promise<void>((resolve, reject) => {\n if (systemInstance.mainListener) {\n musicBank[musicFile] = new THREE.Audio(systemInstance.mainListener)\n } else {\n console.error(\"Main listener is not set in AudioSystemInstance\")\n reject(new Error(`Main listener is not set for ${musicFile}`))\n return\n }\n\n const audioLoader = new THREE.AudioLoader()\n audioLoader.load(\n musicFile,\n function (buffer) {\n musicBank[musicFile].setBuffer(buffer)\n musicBank[musicFile].setLoop(true) // Music should loop by default\n musicBank[musicFile].setVolume(MusicSystem.volume)\n console.log(`✅ Music loaded: ${musicFile}`)\n resolve()\n },\n undefined, // progress callback\n function (error) {\n console.error(`Failed to load music file: ${musicFile}`, error)\n reject(error)\n }\n )\n })\n })\n\n await Promise.all(loadPromises)\n}\n\n/**\n * Play a music track\n * @param musicBank - The music bank\n * @param trackName - Name/path of the music track\n * @param loop - Whether to loop the track (default: true)\n */\nexport function PlayMusic(musicBank: MusicBankType, trackName: string, loop: boolean = true): void {\n if (!musicBank[trackName]) {\n throw new Error(`Music track not found in bank: ${trackName}`)\n }\n\n if (!musicBank[trackName].buffer) {\n throw new Error(`Music track not loaded yet: ${trackName}`)\n }\n\n // Stop current track if playing\n if (MusicSystem.currentTrack && MusicSystem.isPlaying) {\n StopMusic(musicBank)\n }\n\n // Set up new track\n const track = musicBank[trackName]\n track.setLoop(loop)\n track.setVolume(MusicSystem.volume)\n\n // Play the track\n track.play()\n\n // Update system state\n MusicSystem.currentTrack = trackName\n MusicSystem.isPlaying = true\n MusicSystem.isPaused = false\n MusicSystem.loop = loop\n\n console.log(`🎵 Playing music: ${trackName}`)\n}\n\n/**\n * Pause the currently playing music\n * @param musicBank - The music bank\n */\nexport function PauseMusic(musicBank: MusicBankType): void {\n if (MusicSystem.currentTrack && MusicSystem.isPlaying && !MusicSystem.isPaused) {\n const track = musicBank[MusicSystem.currentTrack]\n if (track) {\n track.pause()\n MusicSystem.isPaused = true\n console.log(`⏸️ Music paused: ${MusicSystem.currentTrack}`)\n }\n }\n}\n\n/**\n * Resume the currently paused music\n * @param musicBank - The music bank\n */\nexport function ResumeMusic(musicBank: MusicBankType): void {\n if (MusicSystem.currentTrack && MusicSystem.isPlaying && MusicSystem.isPaused) {\n const track = musicBank[MusicSystem.currentTrack]\n if (track) {\n track.play()\n MusicSystem.isPaused = false\n console.log(`▶️ Music resumed: ${MusicSystem.currentTrack}`)\n }\n }\n}\n\n/**\n * Stop the currently playing music\n * @param musicBank - The music bank\n */\nexport function StopMusic(musicBank: MusicBankType): void {\n if (MusicSystem.currentTrack && MusicSystem.isPlaying) {\n const track = musicBank[MusicSystem.currentTrack]\n if (track) {\n track.stop()\n console.log(`⏹️ Music stopped: ${MusicSystem.currentTrack}`)\n }\n }\n\n // Reset system state\n MusicSystem.currentTrack = null\n MusicSystem.isPlaying = false\n MusicSystem.isPaused = false\n}\n\n/**\n * Set the volume for music playback\n * @param volume - Volume level (0.0 to 1.0)\n * @param musicBank - The music bank\n */\nexport function SetMusicVolume(volume: number, musicBank: MusicBankType): void {\n // Clamp volume between 0 and 1\n volume = Math.max(0, Math.min(1, volume))\n MusicSystem.volume = volume\n\n // Update current playing track if any\n if (MusicSystem.currentTrack && MusicSystem.isPlaying) {\n const track = musicBank[MusicSystem.currentTrack]\n if (track) {\n track.setVolume(volume)\n }\n }\n\n console.log(`🔊 Music volume set to: ${Math.round(volume * 100)}%`)\n}\n\n/**\n * Toggle music playback (play/pause)\n * @param musicBank - The music bank\n */\nexport function ToggleMusic(musicBank: MusicBankType): void {\n if (MusicSystem.isPlaying && !MusicSystem.isPaused) {\n PauseMusic(musicBank)\n } else if (MusicSystem.isPlaying && MusicSystem.isPaused) {\n ResumeMusic(musicBank)\n }\n}\n\n/**\n * Check if a music track is ready to play\n * @param musicBank - The music bank\n * @param trackName - Name/path of the music track\n */\nexport function IsMusicReady(musicBank: MusicBankType, trackName: string): boolean {\n const track = musicBank[trackName]\n return track && !!track.buffer\n}\n\n/**\n * Get the current music system state\n */\nexport function GetMusicSystemState(): MusicSystemState {\n return { ...MusicSystem }\n}\n\n/**\n * Crossfade to a new music track\n * @param musicBank - The music bank\n * @param newTrackName - Name/path of the new music track\n * @param fadeDuration - Duration of the crossfade in milliseconds (default: 2000ms)\n * @param loop - Whether to loop the new track (default: true)\n */\nexport function CrossfadeToMusic(\n musicBank: MusicBankType,\n newTrackName: string,\n fadeDuration: number = 2000,\n loop: boolean = true\n): void {\n if (!musicBank[newTrackName]) {\n throw new Error(`Music track not found in bank: ${newTrackName}`)\n }\n\n if (!musicBank[newTrackName].buffer) {\n throw new Error(`Music track not loaded yet: ${newTrackName}`)\n }\n\n const oldTrack = MusicSystem.currentTrack ? musicBank[MusicSystem.currentTrack] : null\n const newTrack = musicBank[newTrackName]\n\n // Set up new track\n newTrack.setLoop(loop)\n newTrack.setVolume(0) // Start at 0 volume\n newTrack.play()\n\n // Update system state\n MusicSystem.currentTrack = newTrackName\n MusicSystem.isPlaying = true\n MusicSystem.isPaused = false\n MusicSystem.loop = loop\n\n // Perform crossfade\n const steps = 60 // 60 steps for smooth transition\n const stepDuration = fadeDuration / steps\n const volumeStep = MusicSystem.volume / steps\n\n let currentStep = 0\n\n const fadeInterval = setInterval(() => {\n currentStep++\n const progress = currentStep / steps\n\n // Fade out old track\n if (oldTrack) {\n oldTrack.setVolume(MusicSystem.volume * (1 - progress))\n }\n\n // Fade in new track\n newTrack.setVolume(MusicSystem.volume * progress)\n\n if (currentStep >= steps) {\n // Crossfade complete\n clearInterval(fadeInterval)\n\n // Stop old track\n if (oldTrack) {\n oldTrack.stop()\n }\n\n console.log(`🎵 Crossfade complete to: ${newTrackName}`)\n }\n }, stepDuration)\n}\n\n/**\n * Start music with automatic handling of browser autoplay policies\n * This utility function tries to play music immediately, and if blocked by autoplay policy,\n * it sets up event listeners to start music on first user interaction.\n *\n * @param musicBank - The music bank\n * @param trackName - Name/path of the music track to play\n * @param loop - Whether to loop the track (default: true)\n */\nexport function StartMusicWithAutoplayHandling(\n musicBank: MusicBankType,\n trackName: string,\n loop: boolean = true\n): void {\n // Try to start playing background music immediately\n try {\n PlayMusic(musicBank, trackName, loop)\n console.log(\"🎵 Background music started immediately\")\n return\n } catch (error) {\n console.log(\"🎵 Music blocked by autoplay policy, will start on user interaction\")\n }\n\n // Handle browser autoplay policy - start music on first user interaction\n const startMusicOnInteraction = () => {\n try {\n // Resume audio context if suspended\n const context = (AudioSystem.mainListener as any)?.context\n if (context && context.state === \"suspended\") {\n context.resume()\n }\n\n // Try to play music if not already playing\n if (!MusicSystem.isPlaying) {\n PlayMusic(musicBank, trackName, loop)\n console.log(\"🎵 Background music started after user interaction\")\n }\n\n // Remove event listeners after first successful interaction\n document.removeEventListener(\"click\", startMusicOnInteraction)\n document.removeEventListener(\"keydown\", startMusicOnInteraction)\n document.removeEventListener(\"touchstart\", startMusicOnInteraction)\n } catch (error) {\n console.warn(\"Failed to start music on interaction:\", error)\n }\n }\n\n // Add event listeners for user interaction\n document.addEventListener(\"click\", startMusicOnInteraction)\n document.addEventListener(\"keydown\", startMusicOnInteraction)\n document.addEventListener(\"touchstart\", startMusicOnInteraction) // For mobile devices\n\n console.log(\"🎵 Music queued to start on user interaction (click, keypress, or touch)\")\n}\n\n/**\n * Play the next track in the playlist\n * @param musicBank - The music bank\n */\nfunction playNextInPlaylist(musicBank: MusicBankType): void {\n if (!MusicSystem.playlistActive || MusicSystem.playlist.length === 0) {\n return\n }\n\n // Move to next track (with wrap-around)\n MusicSystem.playlistIndex = (MusicSystem.playlistIndex + 1) % MusicSystem.playlist.length\n const nextTrack = MusicSystem.playlist[MusicSystem.playlistIndex]\n\n console.log(\n `🎵 Playlist: playing next track (${MusicSystem.playlistIndex + 1}/${MusicSystem.playlist.length}): ${nextTrack}`\n )\n\n // Play the next track without looping, set up ended handler\n playPlaylistTrack(musicBank, nextTrack)\n}\n\n/**\n * Play a single track from the playlist (internal helper)\n * @param musicBank - The music bank\n * @param trackName - Track to play\n */\nfunction playPlaylistTrack(musicBank: MusicBankType, trackName: string): void {\n if (!musicBank[trackName]) {\n console.error(`Music track not found in bank: ${trackName}`)\n return\n }\n\n if (!musicBank[trackName].buffer) {\n console.error(`Music track not loaded yet: ${trackName}`)\n return\n }\n\n // Stop current track if playing\n if (MusicSystem.currentTrack && MusicSystem.isPlaying) {\n const currentTrack = musicBank[MusicSystem.currentTrack]\n if (currentTrack) {\n // Remove any existing ended listener\n currentTrack.source?.removeEventListener?.(\"ended\", () => {})\n currentTrack.stop()\n }\n }\n\n // Set up new track\n const track = musicBank[trackName]\n track.setLoop(false) // Don't loop - we'll play next track when ended\n track.setVolume(MusicSystem.volume)\n\n // Set up ended listener for playlist rotation\n const onEnded = () => {\n if (MusicSystem.playlistActive) {\n playNextInPlaylist(musicBank)\n }\n }\n\n // Play the track\n track.play()\n\n // THREE.Audio fires 'ended' when the track finishes\n if (track.source) {\n track.source.onended = onEnded\n }\n\n // Update system state\n MusicSystem.currentTrack = trackName\n MusicSystem.isPlaying = true\n MusicSystem.isPaused = false\n MusicSystem.loop = false\n}\n\n/**\n * Start playing a playlist of tracks in rotation\n * @param musicBank - The music bank\n * @param trackNames - Array of track names to play in rotation\n * @param startIndex - Index to start from (default: 0)\n */\nexport function StartPlaylist(\n musicBank: MusicBankType,\n trackNames: string[],\n startIndex: number = 0\n): void {\n if (trackNames.length === 0) {\n console.warn(\"StartPlaylist called with empty track list\")\n return\n }\n\n // Validate all tracks exist\n for (const trackName of trackNames) {\n if (!musicBank[trackName]) {\n console.error(`Music track not found in bank: ${trackName}`)\n return\n }\n }\n\n // Set up playlist state\n MusicSystem.playlist = [...trackNames]\n MusicSystem.playlistIndex = startIndex\n MusicSystem.playlistActive = true\n\n const firstTrack = MusicSystem.playlist[MusicSystem.playlistIndex]\n console.log(`🎵 Starting playlist with ${trackNames.length} tracks: ${trackNames.join(\", \")}`)\n\n // Start playing the first track\n playPlaylistTrack(musicBank, firstTrack)\n}\n\n/**\n * Stop the playlist and reset state\n * @param musicBank - The music bank\n */\nexport function StopPlaylist(musicBank: MusicBankType): void {\n MusicSystem.playlistActive = false\n MusicSystem.playlist = []\n MusicSystem.playlistIndex = 0\n StopMusic(musicBank)\n}\n\n/**\n * Start playlist with automatic handling of browser autoplay policies\n * @param musicBank - The music bank\n * @param trackNames - Array of track names to play in rotation\n */\nexport function StartPlaylistWithAutoplayHandling(\n musicBank: MusicBankType,\n trackNames: string[]\n): void {\n // Try to start playing playlist immediately\n try {\n StartPlaylist(musicBank, trackNames)\n console.log(\"🎵 Playlist started immediately\")\n return\n } catch (error) {\n console.log(\"🎵 Playlist blocked by autoplay policy, will start on user interaction\")\n }\n\n // Handle browser autoplay policy - start playlist on first user interaction\n const startPlaylistOnInteraction = () => {\n try {\n // Resume audio context if suspended\n const context = (AudioSystem.mainListener as any)?.context\n if (context && context.state === \"suspended\") {\n context.resume()\n }\n\n // Try to play playlist if not already playing\n if (!MusicSystem.isPlaying) {\n StartPlaylist(musicBank, trackNames)\n console.log(\"🎵 Playlist started after user interaction\")\n }\n\n // Remove event listeners after first successful interaction\n document.removeEventListener(\"click\", startPlaylistOnInteraction)\n document.removeEventListener(\"keydown\", startPlaylistOnInteraction)\n document.removeEventListener(\"touchstart\", startPlaylistOnInteraction)\n } catch (error) {\n console.warn(\"Failed to start playlist on interaction:\", error)\n }\n }\n\n // Add event listeners for user interaction\n document.addEventListener(\"click\", startPlaylistOnInteraction)\n document.addEventListener(\"keydown\", startPlaylistOnInteraction)\n document.addEventListener(\"touchstart\", startPlaylistOnInteraction)\n\n console.log(\"🎵 Playlist queued to start on user interaction (click, keypress, or touch)\")\n}\n","import * as THREE from \"three\"\nimport { GameObject } from \"@engine/core\"\n\n/**\n * Per-instance data stored in a batch\n */\ninterface InstanceData {\n id: string\n gameObject: GameObject\n matrix: THREE.Matrix4\n isActive: boolean\n isDynamic: boolean // Dynamic instances update every frame, static only when dirty\n isDirty: boolean // For static instances - needs matrix update\n}\n\n/**\n * A batch of instances sharing the same geometry and material\n */\ninterface InstanceBatch {\n batchKey: string\n instancedMesh: THREE.InstancedMesh\n dynamicInstances: InstanceData[] // Updated every frame\n staticInstances: InstanceData[] // Only updated when dirty\n instanceMap: Map<string, InstanceData> // O(1) lookup by ID\n maxInstances: number\n geometry: THREE.BufferGeometry\n material: THREE.Material\n needsRebuild: boolean // True when instances added/removed/visibility changed\n hasStaticDirty: boolean // True when any static instance needs update\n}\n\n/**\n * Statistics for debugging\n */\ninterface InstanceStats {\n batchKeys: string[]\n totalInstances: number\n batchCount: number\n instancesPerBatch: Map<string, number>\n}\n\n/**\n * Singleton manager for GPU-instanced meshes.\n *\n * This is a generic instancing system that works with any geometry + material combination.\n * Games provide the geometry and material when creating a batch, and the manager handles\n * the THREE.InstancedMesh creation and per-frame matrix updates.\n *\n * Performance optimizations:\n * - Reuses temporary Vector3/Quaternion/Matrix4 objects (no per-frame allocations)\n * - Uses Map for O(1) instance lookups\n * - Only updates GPU when batch is marked dirty\n * - Uses instancedMesh.count instead of writing zero-matrices\n *\n * Usage pattern:\n * ```typescript\n * // 1. Initialize (once, during game setup)\n * InstancedMeshManager.getInstance().initialize(scene)\n *\n * // 2. Register a batch (once per unique mesh type)\n * manager.getOrCreateBatch(\"burger\", burgerGeometry, burgerMaterial)\n *\n * // 3. Add instances (via InstancedRenderer component or directly)\n * const instanceId = manager.addInstance(\"burger\", gameObject)\n *\n * // 4. Update every frame\n * manager.updateAllBatches()\n * ```\n */\nexport class InstancedMeshManager {\n private static _instance: InstancedMeshManager | null = null\n\n private scene: THREE.Scene | null = null\n private batches: Map<string, InstanceBatch> = new Map()\n private isInitialized: boolean = false\n\n private static readonly INITIAL_CAPACITY = 16 // Start small, grow as needed\n private static readonly GROWTH_FACTOR = 2 // Double capacity when full\n\n // Reusable temp objects to avoid per-frame allocations\n private readonly _tempPosition = new THREE.Vector3()\n private readonly _tempQuaternion = new THREE.Quaternion()\n private readonly _tempScale = new THREE.Vector3()\n\n private constructor() {}\n\n /**\n * Get the singleton instance\n */\n public static getInstance(): InstancedMeshManager {\n if (!InstancedMeshManager._instance) {\n InstancedMeshManager._instance = new InstancedMeshManager()\n }\n return InstancedMeshManager._instance\n }\n\n /**\n * Initialize the manager with a scene reference.\n * Must be called before creating batches.\n * @param scene The THREE.Scene to add InstancedMesh objects to\n */\n public initialize(scene: THREE.Scene): void {\n if (this.isInitialized) {\n console.warn(\"InstancedMeshManager: Already initialized\")\n return\n }\n this.scene = scene\n this.isInitialized = true\n }\n\n /**\n * Check if the manager is initialized\n */\n public isReady(): boolean {\n return this.isInitialized && this.scene !== null\n }\n\n /**\n * Get or create a batch for a given key.\n * If the batch already exists, returns it (geometry/material params are ignored).\n * If not, creates a new batch with the provided geometry and material.\n *\n * @param batchKey Unique identifier for this batch (e.g., \"burger\", \"tree_pine\")\n * @param geometry BufferGeometry to use for all instances\n * @param material Material to use for all instances\n * @param castShadow Whether instances cast shadows (default: false)\n * @param receiveShadow Whether instances receive shadows (default: false)\n * @param initialCapacity Starting capacity (will grow automatically). Default: 16\n * @returns The batch, or null if manager not initialized\n */\n public getOrCreateBatch(\n batchKey: string,\n geometry: THREE.BufferGeometry,\n material: THREE.Material,\n castShadow: boolean = false,\n receiveShadow: boolean = false,\n initialCapacity: number = InstancedMeshManager.INITIAL_CAPACITY\n ): InstanceBatch | null {\n if (!this.isInitialized || !this.scene) {\n console.error(\"InstancedMeshManager: Not initialized. Call initialize(scene) first.\")\n return null\n }\n\n // Return existing batch if it exists\n const existing = this.batches.get(batchKey)\n if (existing) {\n return existing\n }\n\n // Round up to next power of 2 for efficient growth\n const capacity = this.nextPowerOf2(initialCapacity)\n\n // Create new InstancedMesh\n const instancedMesh = new THREE.InstancedMesh(geometry, material, capacity)\n instancedMesh.name = `instanced_${batchKey}`\n instancedMesh.castShadow = castShadow\n instancedMesh.receiveShadow = receiveShadow\n instancedMesh.frustumCulled = false // We handle culling ourselves if needed\n instancedMesh.count = 0 // Start with 0 visible instances\n\n // Add to scene\n this.scene.add(instancedMesh)\n\n // Create batch\n const batch: InstanceBatch = {\n batchKey,\n instancedMesh,\n dynamicInstances: [],\n staticInstances: [],\n instanceMap: new Map(), // O(1) lookup\n maxInstances: capacity,\n geometry,\n material,\n needsRebuild: false,\n hasStaticDirty: false,\n }\n\n this.batches.set(batchKey, batch)\n return batch\n }\n\n /**\n * Create a batch automatically from a GameObject's mesh.\n * Extracts geometry and material from the first Mesh found in the GameObject.\n */\n public getOrCreateBatchFromGameObject(\n batchKey: string,\n gameObject: GameObject,\n castShadow: boolean = false,\n receiveShadow: boolean = false,\n initialCapacity: number = InstancedMeshManager.INITIAL_CAPACITY\n ): InstanceBatch | null {\n // Return existing batch if it exists\n const existing = this.batches.get(batchKey)\n if (existing) {\n return existing\n }\n\n // Find the first mesh in the GameObject hierarchy\n let geometry: THREE.BufferGeometry | null = null\n let material: THREE.Material | null = null\n\n gameObject.traverse((child) => {\n if (!geometry && child instanceof THREE.Mesh) {\n geometry = child.geometry\n material = Array.isArray(child.material) ? child.material[0] : child.material\n }\n })\n\n if (!geometry || !material) {\n console.error(`InstancedMeshManager: No mesh found in GameObject for batch '${batchKey}'`)\n return null\n }\n\n return this.getOrCreateBatch(\n batchKey,\n geometry,\n material,\n castShadow,\n receiveShadow,\n initialCapacity\n )\n }\n\n /**\n * Round up to the next power of 2\n */\n private nextPowerOf2(n: number): number {\n if (n <= 0) return 1\n n--\n n |= n >> 1\n n |= n >> 2\n n |= n >> 4\n n |= n >> 8\n n |= n >> 16\n return n + 1\n }\n\n /**\n * Resize a batch to a new capacity (must be larger than current)\n */\n private resizeBatch(batch: InstanceBatch, newCapacity: number): void {\n if (!this.scene) return\n\n const capacity = this.nextPowerOf2(newCapacity)\n if (capacity <= batch.maxInstances) return\n\n // Create new larger InstancedMesh\n const newInstancedMesh = new THREE.InstancedMesh(batch.geometry, batch.material, capacity)\n newInstancedMesh.name = batch.instancedMesh.name\n newInstancedMesh.castShadow = batch.instancedMesh.castShadow\n newInstancedMesh.receiveShadow = batch.instancedMesh.receiveShadow\n newInstancedMesh.frustumCulled = false\n newInstancedMesh.count = batch.instancedMesh.count\n\n // Copy existing matrices to new mesh\n for (let i = 0; i < batch.instancedMesh.count; i++) {\n const matrix = new THREE.Matrix4()\n batch.instancedMesh.getMatrixAt(i, matrix)\n newInstancedMesh.setMatrixAt(i, matrix)\n }\n newInstancedMesh.instanceMatrix.needsUpdate = true\n\n // Swap in scene\n this.scene.remove(batch.instancedMesh)\n batch.instancedMesh.dispose()\n this.scene.add(newInstancedMesh)\n\n // Update batch\n batch.instancedMesh = newInstancedMesh\n batch.maxInstances = capacity\n\n console.log(`InstancedMeshManager: Resized batch '${batch.batchKey}' to ${capacity} instances`)\n }\n\n /**\n * Check if a batch exists for the given key\n */\n public hasBatch(batchKey: string): boolean {\n return this.batches.has(batchKey)\n }\n\n /**\n * Get a batch by key (without creating it)\n */\n public getBatch(batchKey: string): InstanceBatch | null {\n return this.batches.get(batchKey) || null\n }\n\n /**\n * Get total instance count for a batch\n */\n private getTotalInstanceCount(batch: InstanceBatch): number {\n return batch.dynamicInstances.length + batch.staticInstances.length\n }\n\n /**\n * Options for adding an instance\n */\n public static readonly AddInstanceOptions = {\n isDynamic: true,\n castShadow: false,\n receiveShadow: false,\n initialCapacity: undefined as number | undefined,\n }\n\n /**\n * Add an instance to a batch.\n * If no batch exists, creates one automatically from the GameObject's mesh.\n * If batch is full, automatically resizes to accommodate more instances.\n *\n * @param batchKey The batch to add to\n * @param gameObject The GameObject whose transform will be used\n * @param options Configuration options (isDynamic, castShadow, receiveShadow, initialCapacity)\n * @returns Instance ID, or null if failed\n */\n public addInstance(\n batchKey: string,\n gameObject: GameObject,\n options: {\n isDynamic?: boolean\n castShadow?: boolean\n receiveShadow?: boolean\n initialCapacity?: number\n } = {}\n ): string | null {\n const isDynamic = options.isDynamic ?? true\n const castShadow = options.castShadow ?? false\n const receiveShadow = options.receiveShadow ?? false\n const initialCapacity = options.initialCapacity ?? InstancedMeshManager.INITIAL_CAPACITY\n\n // Auto-create batch if it doesn't exist\n let batch: InstanceBatch | null = this.batches.get(batchKey) ?? null\n if (!batch) {\n batch = this.getOrCreateBatchFromGameObject(\n batchKey,\n gameObject,\n castShadow,\n receiveShadow,\n initialCapacity\n )\n if (!batch) {\n return null\n }\n }\n\n // Auto-resize if full\n if (this.getTotalInstanceCount(batch) >= batch.maxInstances) {\n this.resizeBatch(batch, batch.maxInstances * InstancedMeshManager.GROWTH_FACTOR)\n }\n\n const instanceId = `${batchKey}_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`\n\n const instanceData: InstanceData = {\n id: instanceId,\n gameObject,\n matrix: new THREE.Matrix4(),\n isActive: true,\n isDynamic,\n isDirty: true, // Initial update needed\n }\n\n // Set initial matrix from GameObject world transform\n this.updateInstanceMatrix(instanceData)\n\n // Add to appropriate array\n if (isDynamic) {\n batch.dynamicInstances.push(instanceData)\n } else {\n batch.staticInstances.push(instanceData)\n }\n\n batch.instanceMap.set(instanceId, instanceData)\n batch.needsRebuild = true // New instance added\n\n return instanceId\n }\n\n /**\n * Remove an instance from a batch\n * @param batchKey The batch to remove from\n * @param instanceId The instance ID to remove\n */\n public removeInstance(batchKey: string, instanceId: string): void {\n const batch = this.batches.get(batchKey)\n if (!batch) return\n\n // O(1) lookup\n const instance = batch.instanceMap.get(instanceId)\n if (!instance) return\n\n // Remove from appropriate array using swap-remove\n const targetArray = instance.isDynamic ? batch.dynamicInstances : batch.staticInstances\n const index = targetArray.indexOf(instance)\n if (index !== -1) {\n const lastIndex = targetArray.length - 1\n if (index !== lastIndex) {\n targetArray[index] = targetArray[lastIndex]\n }\n targetArray.pop()\n }\n\n // Remove from map\n batch.instanceMap.delete(instanceId)\n batch.needsRebuild = true // Instance removed\n }\n\n /**\n * Set the visibility of a specific instance\n * @param batchKey The batch containing the instance\n * @param instanceId The instance ID\n * @param visible Whether the instance should be visible\n */\n public setInstanceVisible(batchKey: string, instanceId: string, visible: boolean): void {\n const batch = this.batches.get(batchKey)\n if (!batch) return\n\n // O(1) lookup\n const instance = batch.instanceMap.get(instanceId)\n if (!instance) return\n\n if (instance.isActive !== visible) {\n instance.isActive = visible\n batch.needsRebuild = true // Visibility change affects instance count\n }\n }\n\n /**\n * Get the visibility of a specific instance\n */\n public getInstanceVisible(batchKey: string, instanceId: string): boolean {\n const batch = this.batches.get(batchKey)\n if (!batch) return false\n\n // O(1) lookup\n const instance = batch.instanceMap.get(instanceId)\n return instance?.isActive ?? false\n }\n\n /**\n * Mark a static instance as dirty (needs matrix update next frame).\n * Call this when a static instance's transform changes.\n * No-op for dynamic instances (they update every frame anyway).\n */\n public markInstanceDirty(batchKey: string, instanceId: string): void {\n const batch = this.batches.get(batchKey)\n if (!batch) return\n\n const instance = batch.instanceMap.get(instanceId)\n if (!instance || instance.isDynamic) return\n\n instance.isDirty = true\n batch.hasStaticDirty = true\n }\n\n /**\n * Set whether an instance is dynamic (updates every frame) or static (only when dirty).\n * Use this when an item transitions between moving and stationary states.\n */\n public setInstanceDynamic(batchKey: string, instanceId: string, isDynamic: boolean): void {\n const batch = this.batches.get(batchKey)\n if (!batch) return\n\n const instance = batch.instanceMap.get(instanceId)\n if (!instance || instance.isDynamic === isDynamic) return\n\n // Remove from current array\n const sourceArray = instance.isDynamic ? batch.dynamicInstances : batch.staticInstances\n const index = sourceArray.indexOf(instance)\n if (index !== -1) {\n const lastIndex = sourceArray.length - 1\n if (index !== lastIndex) {\n sourceArray[index] = sourceArray[lastIndex]\n }\n sourceArray.pop()\n }\n\n // Add to new array\n instance.isDynamic = isDynamic\n if (isDynamic) {\n batch.dynamicInstances.push(instance)\n } else {\n instance.isDirty = true // Ensure it gets one update\n batch.staticInstances.push(instance)\n batch.hasStaticDirty = true\n }\n }\n\n /**\n * Update the matrix for a single instance from its GameObject.\n * Uses reusable temp objects to avoid per-frame allocations.\n */\n private updateInstanceMatrix(instance: InstanceData): void {\n instance.gameObject.getWorldPosition(this._tempPosition)\n instance.gameObject.getWorldQuaternion(this._tempQuaternion)\n instance.gameObject.getWorldScale(this._tempScale)\n\n instance.matrix.compose(this._tempPosition, this._tempQuaternion, this._tempScale)\n }\n\n /**\n * Update a single batch - sync matrices and upload to GPU.\n * Optimized to only update what's necessary:\n * - Dynamic instances: always update matrix\n * - Static instances: only update if marked dirty\n * - GPU upload: only if anything changed\n */\n private updateBatch(batch: InstanceBatch): void {\n const hasDynamicActive = batch.dynamicInstances.some((i) => i.isActive)\n const needsGpuUpdate = hasDynamicActive || batch.needsRebuild || batch.hasStaticDirty\n\n // Early exit if nothing needs updating\n if (!needsGpuUpdate) {\n return\n }\n\n let visibleIndex = 0\n\n // Process dynamic instances (always update matrix)\n for (const instance of batch.dynamicInstances) {\n if (instance.isActive) {\n this.updateInstanceMatrix(instance)\n batch.instancedMesh.setMatrixAt(visibleIndex, instance.matrix)\n visibleIndex++\n }\n }\n\n // Process static instances (only update matrix if dirty OR rebuild needed)\n for (const instance of batch.staticInstances) {\n if (instance.isActive) {\n // Only recalculate matrix if this instance is dirty\n if (instance.isDirty || batch.needsRebuild) {\n this.updateInstanceMatrix(instance)\n instance.isDirty = false\n }\n batch.instancedMesh.setMatrixAt(visibleIndex, instance.matrix)\n visibleIndex++\n }\n }\n\n // Update GPU\n batch.instancedMesh.instanceMatrix.needsUpdate = true\n batch.instancedMesh.count = visibleIndex\n\n // Clear flags\n batch.needsRebuild = false\n batch.hasStaticDirty = false\n }\n\n /**\n * Update all batches - call this every frame.\n * Optimized to skip batches with no changes.\n */\n public updateAllBatches(): void {\n for (const batch of this.batches.values()) {\n this.updateBatch(batch)\n }\n }\n\n /**\n * Get statistics for debugging\n */\n public getStats(): InstanceStats {\n const instancesPerBatch = new Map<string, number>()\n let totalInstances = 0\n\n for (const [key, batch] of this.batches) {\n const dynamicActive = batch.dynamicInstances.filter((i) => i.isActive).length\n const staticActive = batch.staticInstances.filter((i) => i.isActive).length\n const activeCount = dynamicActive + staticActive\n instancesPerBatch.set(key, activeCount)\n totalInstances += activeCount\n }\n\n return {\n batchKeys: Array.from(this.batches.keys()),\n totalInstances,\n batchCount: this.batches.size,\n instancesPerBatch,\n }\n }\n\n /**\n * Print a debug report to console\n */\n public debugReport(): void {\n const stats = this.getStats()\n console.log(\"=== InstancedMeshManager Report ===\")\n console.log(`Batches: ${stats.batchCount}`)\n console.log(`Total instances: ${stats.totalInstances}`)\n for (const [key, count] of stats.instancesPerBatch) {\n const batch = this.batches.get(key)!\n const dynamicCount = batch.dynamicInstances.length\n const staticCount = batch.staticInstances.length\n console.log(\n ` ${key}: ${count}/${batch.maxInstances} active (${dynamicCount} dynamic, ${staticCount} static)`\n )\n }\n }\n\n /**\n * Remove a batch entirely\n */\n public removeBatch(batchKey: string): void {\n const batch = this.batches.get(batchKey)\n if (!batch) return\n\n // Remove from scene\n if (this.scene) {\n this.scene.remove(batch.instancedMesh)\n }\n\n // Dispose geometry and material if we created them\n // Note: We don't dispose here since the caller provided them\n // They're responsible for disposal if needed\n\n this.batches.delete(batchKey)\n }\n\n /**\n * Dispose of all batches and reset the manager\n */\n public dispose(): void {\n for (const [key] of this.batches) {\n this.removeBatch(key)\n }\n this.batches.clear()\n this.scene = null\n this.isInitialized = false\n }\n\n /**\n * Reset the singleton (for testing)\n */\n public static reset(): void {\n if (InstancedMeshManager._instance) {\n InstancedMeshManager._instance.dispose()\n InstancedMeshManager._instance = null\n }\n }\n}\n","import * as THREE from \"three\"\n\n/**\n * Animation Culling Manager\n * Handles frustum culling and distance-based optimization for animated characters\n */\nexport class AnimationCullingManager {\n private static instance: AnimationCullingManager | null = null\n\n // Cameras to use for frustum culling\n private cameras: Set<THREE.Camera> = new Set()\n private primaryCamera: THREE.Camera | null = null\n\n // Frustum for culling checks\n private readonly frustum = new THREE.Frustum()\n private readonly projScreenMatrix = new THREE.Matrix4()\n\n // Reusable temp objects\n private readonly _tempSphere = new THREE.Sphere()\n private readonly _tempBox = new THREE.Box3()\n private readonly _tempVec = new THREE.Vector3()\n\n // Settings\n private frustumCullingEnabled: boolean = true\n private distanceCullingEnabled: boolean = false\n private maxUpdateDistance: number = 100 // Units beyond which animations are skipped\n private lodDistance: number = 50 // Units beyond which animations update at reduced rate\n private frustumExpansion: number = 1.2 // Expand frustum by this factor to avoid pop-in\n\n // Frame counter for LOD updates\n private frameCounter: number = 0\n\n private constructor() {}\n\n public static getInstance(): AnimationCullingManager {\n if (!AnimationCullingManager.instance) {\n AnimationCullingManager.instance = new AnimationCullingManager()\n }\n return AnimationCullingManager.instance\n }\n\n /**\n * Add a camera for frustum culling\n */\n public addCamera(camera: THREE.Camera, isPrimary: boolean = false): void {\n this.cameras.add(camera)\n if (isPrimary || !this.primaryCamera) {\n this.primaryCamera = camera\n }\n }\n\n /**\n * Remove a camera from culling\n */\n public removeCamera(camera: THREE.Camera): void {\n this.cameras.delete(camera)\n if (this.primaryCamera === camera) {\n this.primaryCamera =\n this.cameras.size > 0 ? (this.cameras.values().next().value ?? null) : null\n }\n }\n\n /**\n * Set the primary camera (used for distance calculations)\n */\n public setPrimaryCamera(camera: THREE.Camera): void {\n this.addCamera(camera, true)\n }\n\n /**\n * Enable/disable frustum culling\n */\n public setFrustumCullingEnabled(enabled: boolean): void {\n this.frustumCullingEnabled = enabled\n }\n\n /**\n * Enable/disable distance-based culling\n */\n public setDistanceCullingEnabled(enabled: boolean): void {\n this.distanceCullingEnabled = enabled\n }\n\n /**\n * Set the maximum distance for animation updates\n */\n public setMaxUpdateDistance(distance: number): void {\n this.maxUpdateDistance = distance\n }\n\n /**\n * Set the LOD distance threshold\n */\n public setLodDistance(distance: number): void {\n this.lodDistance = distance\n }\n\n /**\n * Set the frustum expansion factor.\n * Values > 1.0 expand the frustum to avoid pop-in when characters enter view.\n * Default is 1.2 (20% larger frustum)\n */\n public setFrustumExpansion(factor: number): void {\n this.frustumExpansion = Math.max(1.0, factor)\n }\n\n /**\n * Call once per frame before animation updates\n */\n public beginFrame(): void {\n this.frameCounter++\n\n // Update frustum from primary camera\n if (this.primaryCamera && this.frustumCullingEnabled) {\n // Force update the entire camera hierarchy to ensure fresh matrices\n this.primaryCamera.updateMatrixWorld(true)\n\n // Ensure projection matrix is current (handles resize)\n if ((this.primaryCamera as THREE.PerspectiveCamera).isPerspectiveCamera) {\n ;(this.primaryCamera as THREE.PerspectiveCamera).updateProjectionMatrix()\n }\n\n this.projScreenMatrix.multiplyMatrices(\n this.primaryCamera.projectionMatrix,\n this.primaryCamera.matrixWorldInverse\n )\n this.frustum.setFromProjectionMatrix(this.projScreenMatrix)\n }\n }\n\n /**\n * Check if an object should have its animation updated this frame\n * @param object The object containing the animated model\n * @param boundingRadius Optional bounding radius for frustum check (default 2 units)\n * @returns { shouldUpdate: boolean, isLod: boolean }\n */\n public shouldUpdateAnimation(\n object: THREE.Object3D,\n boundingRadius: number = 2\n ): { shouldUpdate: boolean; isLod: boolean } {\n // No cameras - always update\n if (!this.primaryCamera || this.cameras.size === 0) {\n return { shouldUpdate: true, isLod: false }\n }\n\n // Get object world position (matrix should already be updated by scene graph)\n object.getWorldPosition(this._tempVec)\n\n // Distance culling check\n if (this.distanceCullingEnabled) {\n const cameraPos = this.primaryCamera.position\n const distSq = this._tempVec.distanceToSquared(cameraPos)\n const maxDistSq = this.maxUpdateDistance * this.maxUpdateDistance\n\n // Beyond max distance - skip update entirely\n if (distSq > maxDistSq) {\n return { shouldUpdate: false, isLod: false }\n }\n\n // In LOD range - update every other frame\n const lodDistSq = this.lodDistance * this.lodDistance\n if (distSq > lodDistSq) {\n // Update every 2nd frame for distant objects\n return { shouldUpdate: this.frameCounter % 2 === 0, isLod: true }\n }\n }\n\n // Frustum culling check\n if (this.frustumCullingEnabled) {\n this._tempSphere.center.copy(this._tempVec)\n // Expand the bounding sphere by the frustum expansion factor\n // This makes the \"visible area\" larger to avoid pop-in\n this._tempSphere.radius = boundingRadius * this.frustumExpansion\n\n // Check if in ANY camera's frustum\n let inFrustum = false\n\n // Check primary camera first (most common case)\n if (this.frustum.intersectsSphere(this._tempSphere)) {\n inFrustum = true\n } else {\n // Check other cameras\n for (const camera of this.cameras) {\n if (camera === this.primaryCamera) continue\n\n camera.updateMatrixWorld()\n this.projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse)\n this.frustum.setFromProjectionMatrix(this.projScreenMatrix)\n\n if (this.frustum.intersectsSphere(this._tempSphere)) {\n inFrustum = true\n break\n }\n }\n }\n\n if (!inFrustum) {\n return { shouldUpdate: false, isLod: false }\n }\n }\n\n return { shouldUpdate: true, isLod: false }\n }\n\n /**\n * Get debug stats\n */\n public getStats(): {\n cameraCount: number\n frustumCullingEnabled: boolean\n distanceCullingEnabled: boolean\n frameCounter: number\n } {\n return {\n cameraCount: this.cameras.size,\n frustumCullingEnabled: this.frustumCullingEnabled,\n distanceCullingEnabled: this.distanceCullingEnabled,\n frameCounter: this.frameCounter,\n }\n }\n}\n","import { Component } from \"@engine/core\"\nimport {\n PlayAudioOneShot2D,\n PlayAudioRandom2D,\n AudioSystem,\n Main2DAudioBank,\n AudioBank2D,\n} from \"./AudioSystem\"\n\n/**\n * A simple 2D audio component that can be attached to any GameObject.\n * Provides easy access to play 2D audio clips from a configured bank.\n */\nexport class Audio2D extends Component {\n private audioBank: AudioBank2D\n private availableClips: Set<string>\n\n /**\n * Creates a new Audio2D component\n * @param availableClips - Array of clip names this component can play (optional - if not provided, can play any clip in the bank)\n */\n constructor(availableClips?: string[]) {\n super()\n this.audioBank = Main2DAudioBank\n this.availableClips = availableClips ? new Set(availableClips) : new Set()\n }\n\n /**\n * Play a 2D audio clip\n * @param clipName - Name/path of the audio clip to play\n */\n public play(clipName: string): void {\n // If availableClips is specified, check if the clip is allowed\n if (this.availableClips.size > 0 && !this.availableClips.has(clipName)) {\n throw new Error(`Audio clip '${clipName}' is not available in this Audio2D component`)\n }\n\n PlayAudioOneShot2D(this.audioBank, clipName)\n }\n\n /**\n * Check if a clip is available and loaded\n * @param clipName - Name/path of the audio clip to check\n */\n public isClipReady(clipName: string): boolean {\n const audio = this.audioBank[clipName]\n return audio && !!audio.buffer\n }\n\n /**\n * Get list of available clips (if configured)\n */\n public getAvailableClips(): string[] {\n return Array.from(this.availableClips)\n }\n\n /**\n * Add a clip to the available clips list\n * @param clipName - Name/path of the audio clip to add\n */\n public addAvailableClip(clipName: string): void {\n this.availableClips.add(clipName)\n }\n\n /**\n * Remove a clip from the available clips list\n * @param clipName - Name/path of the audio clip to remove\n */\n public removeAvailableClip(clipName: string): void {\n this.availableClips.delete(clipName)\n }\n\n protected onCreate(): void {\n // Nothing special needed for creation\n }\n\n protected onCleanup(): void {\n // Clear references\n this.availableClips.clear()\n }\n}\n\n/**\n * A 2D audio component that plays a random clip from a provided list.\n * Uses the main 2D audio bank.\n */\nexport class RandomAudio2D extends Component {\n private audioBank: AudioBank2D\n private clipNames: string[]\n private avoidImmediateRepeat: boolean\n private lastPlayed: string | null\n\n /**\n * @param clipNames - List of clip paths to randomly play (must be in Main2DAudioBank)\n * @param avoidImmediateRepeat - If true, avoids choosing the same clip twice in a row when possible\n */\n constructor(clipNames: string[], avoidImmediateRepeat: boolean = true) {\n super()\n this.audioBank = Main2DAudioBank\n this.clipNames = clipNames.slice()\n this.avoidImmediateRepeat = avoidImmediateRepeat\n this.lastPlayed = null\n }\n\n /**\n * Play a random clip from the list. Returns the chosen clip name.\n */\n public play(): string {\n const candidates =\n this.avoidImmediateRepeat && this.lastPlayed && this.clipNames.length > 1\n ? this.clipNames.filter((n) => n !== this.lastPlayed)\n : this.clipNames\n\n const chosen = PlayAudioRandom2D(this.audioBank, candidates)\n this.lastPlayed = chosen\n return chosen\n }\n\n /** Replace the internal clip list. */\n public setClips(clipNames: string[]): void {\n this.clipNames = clipNames.slice()\n this.lastPlayed = null\n }\n\n /** Get the internal clip list. */\n public getClips(): string[] {\n return this.clipNames.slice()\n }\n\n /** Add a single clip to the list. */\n public addClip(clipName: string): void {\n if (!this.clipNames.includes(clipName)) this.clipNames.push(clipName)\n }\n\n /** Remove a single clip from the list. */\n public removeClip(clipName: string): void {\n this.clipNames = this.clipNames.filter((n) => n !== clipName)\n if (this.lastPlayed === clipName) this.lastPlayed = null\n }\n\n /** Check if all clips are present (and at least one is loaded) in the bank. */\n public isReady(): boolean {\n if (this.clipNames.length === 0) return false\n return this.clipNames.some((n) => {\n const audio = this.audioBank[n]\n return !!(audio && audio.buffer)\n })\n }\n\n protected onCreate(): void {}\n protected onCleanup(): void {}\n}\n","import * as THREE from \"three\"\nimport { FBXLoader } from \"three/examples/jsm/loaders/FBXLoader.js\"\nimport { SkeletonUtils } from \"three-stdlib\"\n\n/**\n * Instance-based cache system for skeletal/animated FBX models\n * Uses SkeletonUtils.clone() for proper bone/animation preservation\n * Used internally by AssetManager\n */\nexport class SkeletonCache {\n private loader = new FBXLoader()\n private originals: Map<string, THREE.Object3D> = new Map()\n private loading: Map<string, Promise<THREE.Object3D>> = new Map()\n\n public isLoaded(path: string): boolean {\n return this.originals.has(path)\n }\n\n /**\n * Preload a skeletal FBX model\n */\n public async preload(path: string): Promise<THREE.Object3D> {\n if (this.originals.has(path)) {\n return this.originals.get(path)!\n }\n if (this.loading.has(path)) {\n return this.loading.get(path)!\n }\n const p = this.loader\n .loadAsync(path)\n .then((object) => {\n this.originals.set(path, object)\n this.loading.delete(path)\n return object\n })\n .catch((err) => {\n this.loading.delete(path)\n throw err\n })\n\n this.loading.set(path, p)\n return p\n }\n\n /**\n * Register a skeletal model directly (for StowKit or other loaders)\n */\n public register(path: string, object: THREE.Object3D): void {\n if (this.originals.has(path)) {\n console.warn(`[SkeletonCache] Model '${path}' already registered`)\n return\n }\n this.originals.set(path, object)\n }\n\n /**\n * Get a properly cloned skeletal model\n * Uses SkeletonUtils.clone() to preserve bone relationships\n */\n public getClone(path: string): THREE.Object3D | null {\n const original = this.originals.get(path)\n if (!original) return null\n\n // Deep clone skinned meshes/skeletons safely\n const clone = SkeletonUtils.clone(original)\n return clone as THREE.Object3D\n }\n\n /**\n * Get the original (non-cloned) model\n */\n public getOriginal(path: string): THREE.Object3D | null {\n return this.originals.get(path) || null\n }\n\n /**\n * Clear all cached models (for cleanup/testing)\n */\n public clear(): void {\n this.originals.clear()\n this.loading.clear()\n }\n\n /**\n * Get all cached paths\n */\n public getCachedPaths(): string[] {\n return Array.from(this.originals.keys())\n }\n}\n","import * as THREE from \"three\"\nimport { GameObject } from \"@engine/core\"\nimport { GLTFLoader } from \"three/addons/loaders/GLTFLoader.js\"\nimport { OBJLoader } from \"three/addons/loaders/OBJLoader.js\"\nimport { MTLLoader } from \"three/addons/loaders/MTLLoader.js\"\nimport { FBXLoader } from \"three/examples/jsm/loaders/FBXLoader.js\"\nimport { SkeletonCache } from \"./SkeletonCache\"\n\n/**\n * Asset info for a loaded asset in Three.js\n */\ninterface AssetInfo {\n path: string // Full path to the asset\n group?: THREE.Group // The asset group when loaded\n gltf?: any // GLTF data for .glb files\n isLoaded: boolean // Whether the asset is loaded\n isLoading: boolean // Whether the asset is currently loading\n meshes: THREE.Mesh[] // All meshes from the asset\n materials: THREE.Material[] // All materials from the asset\n animations: THREE.AnimationClip[] // All animations from the asset\n}\n\n/**\n * GPU Instance batch for managing InstancedMesh objects\n */\ninterface GPUInstanceBatch {\n instancedMesh: THREE.InstancedMesh\n assetPath: string\n material: THREE.Material\n instances: GPUInstanceData[]\n maxInstances: number\n needsUpdate: boolean\n cullingRadius: number // Broad radius that encompasses the entire geometry\n hasDynamicObjects: boolean // Whether this batch contains any non-static objects\n}\n\n/**\n * Individual instance data within a GPU batch\n */\ninterface GPUInstanceData {\n id: string\n gameObject: GameObject // Reference to the original GameObject\n matrix: THREE.Matrix4\n isActive: boolean\n isStatic: boolean // Whether this instance is static (won't move after creation)\n}\n\n/**\n * Instance tracking for debugging and performance monitoring\n */\ninterface InstanceStats {\n totalInstances: number // Total instances created from this asset\n sharedInstances: number // Instances using shared geometry/materials (object-level)\n clonedInstances: number // Instances that were cloned\n brokenInstances: number // Instances that were converted from shared to cloned\n gpuInstances: number // Instances using GPU instancing (InstancedMesh)\n gpuBatches: number // Number of GPU batches for this asset\n}\n\n/**\n * Global instancing statistics for debug display\n */\ninterface GlobalInstanceStats {\n totalAssets: number\n loadedAssets: number\n totalInstances: number\n sharedInstances: number\n clonedInstances: number\n brokenInstances: number\n gpuInstances: number // NEW: GPU instanced objects\n gpuBatches: number // NEW: Total GPU batches\n geometryReuse: number // Average times each geometry is reused\n materialReuse: number // Average times each material is reused\n}\n\n/**\n * A Three.js asset manager optimized for preloading workflows\n * Compatible API with the original Babylon.js AssetManager\n *\n * RECOMMENDED USAGE PATTERN:\n * 1. Initialize: AssetManager.init(scene)\n * 2. Preload all assets: await AssetManager.preloadAssets([...paths])\n * 3. Use synchronously: AssetManager.getMesh() / getAssetGroup()\n * 4. Create renderers: new ObjRendererThree() (now fully synchronous)\n *\n * SUPPORTED FORMATS:\n * - .glb/.gltf (using GLTFLoader)\n * - .obj (using OBJLoader)\n * - .mtl (material files for OBJ)\n * - .fbx (using FBXLoader)\n * - .stow (using StowKitLoader)\n */\nexport class AssetManager {\n private static _scene: THREE.Scene\n private static _assets: Map<string, AssetInfo> = new Map()\n private static _instanceStats: Map<string, InstanceStats> = new Map()\n private static _gpuBatches: Map<string, GPUInstanceBatch[]> = new Map() // NEW: GPU batching\n private static _baseUrl: string = \"./\" // Default to relative path\n private static _gltfLoader: GLTFLoader\n private static _objLoader: OBJLoader\n private static _mtlLoader: MTLLoader\n private static _fbxLoader: FBXLoader\n private static _isPreloadingComplete: boolean = false\n private static _skeletonCache: SkeletonCache = new SkeletonCache()\n\n // Frustum culling settings\n private static _frustumCullingPadding: number = 1.5 // 50% padding by default to prevent over-culling\n private static _frustumCullingEnabled: boolean = false // Global frustum culling toggle - DISABLED by default for debugging\n\n /**\n * Initialize the AssetManager with a scene\n * @param scene The Three.js scene to use\n * @param renderer Optional WebGL renderer for StowKit texture support\n */\n public static init(scene: THREE.Scene, renderer?: THREE.WebGLRenderer): void {\n AssetManager._scene = scene\n\n // Initialize loaders\n AssetManager._gltfLoader = new GLTFLoader()\n AssetManager._objLoader = new OBJLoader()\n AssetManager._mtlLoader = new MTLLoader()\n AssetManager._fbxLoader = new FBXLoader()\n\n // AssetManager initialized\n }\n\n /**\n * Set base URL for resolving relative paths (optional - defaults to relative paths)\n * @param baseUrl The base URL to use\n */\n public static setBaseUrl(baseUrl: string): void {\n // Ensure baseUrl ends with a slash for proper path joining\n AssetManager._baseUrl = baseUrl.endsWith(\"/\") ? baseUrl : baseUrl + \"/\"\n }\n\n /**\n * Get the full path for an asset - automatically handles relative paths\n */\n public static getFullPath(path: string): string {\n // If it's already an absolute URL, return as-is\n if (path.startsWith(\"http://\") || path.startsWith(\"https://\")) {\n return path\n }\n\n // If it starts with a slash, it's an absolute path from root\n if (path.startsWith(\"/\")) {\n return path\n }\n\n // For relative paths, use the base URL (which defaults to \"./\")\n return AssetManager._baseUrl + path\n }\n\n /**\n * Preload multiple assets in bulk - RECOMMENDED WORKFLOW\n * Call this once at app startup, then use synchronous methods for the rest of the app\n * @param assetPaths Array of asset paths to preload\n * @param progressCallback Optional callback for overall progress (0-1)\n * @returns Promise that resolves when all assets are loaded (or failed)\n */\n public static async preloadAssets(\n assetPaths: string[],\n progressCallback?: (progress: number, loadedCount: number, totalCount: number) => void\n ): Promise<{ loaded: string[]; failed: string[] }> {\n // Starting asset preload\n AssetManager._isPreloadingComplete = false\n\n const results = { loaded: [] as string[], failed: [] as string[] }\n let completedCount = 0\n\n // Load all assets in parallel for maximum speed\n const loadPromises = assetPaths.map(async (assetPath) => {\n const success = await AssetManager.loadAsset(assetPath)\n\n completedCount++\n\n if (success) {\n results.loaded.push(assetPath)\n // Asset loaded\n } else {\n results.failed.push(assetPath)\n console.error(`❌ Failed: ${assetPath} (${completedCount}/${assetPaths.length})`)\n }\n\n // Update overall progress\n if (progressCallback) {\n const overallProgress = completedCount / assetPaths.length\n progressCallback(overallProgress, completedCount, assetPaths.length)\n }\n })\n\n // Wait for all assets to complete (loaded or failed)\n await Promise.all(loadPromises)\n\n AssetManager._isPreloadingComplete = true\n // Preloading complete\n\n if (results.failed.length > 0) {\n console.warn(\n `⚠️ ${results.failed.length} assets failed to load. ObjRendererThree will throw errors for these.`\n )\n }\n\n return results\n }\n\n /**\n * Check if preloading workflow has been completed\n * This doesn't guarantee all assets loaded successfully, just that preloading finished\n */\n public static isPreloadingComplete(): boolean {\n return AssetManager._isPreloadingComplete\n }\n\n /**\n * Load an asset by path (used internally by preloadAssets)\n * @param path Path to the asset\n * @param progressCallback Optional callback for loading progress\n */\n public static async loadAsset(\n path: string,\n progressCallback?: (progress: number) => void\n ): Promise<boolean> {\n if (!AssetManager._scene) {\n throw new Error(\"AssetManager is not initialized. Call AssetManager.init(scene) first.\")\n }\n\n // Skip if already loaded\n if (AssetManager._assets.has(path) && AssetManager._assets.get(path)!.isLoaded) {\n if (progressCallback) progressCallback(1)\n return true\n }\n\n // Skip if currently loading\n if (AssetManager._assets.has(path) && AssetManager._assets.get(path)!.isLoading) {\n return false\n }\n\n // Register the asset if not already registered\n if (!AssetManager._assets.has(path)) {\n AssetManager._assets.set(path, {\n path,\n isLoaded: false,\n isLoading: false,\n meshes: [],\n materials: [],\n animations: [],\n })\n }\n\n const asset = AssetManager._assets.get(path)!\n asset.isLoading = true\n\n try {\n const fullPath = AssetManager.getFullPath(path)\n const fileExtension = path.split(\".\").pop()?.toLowerCase() || \"\"\n\n let success = false\n\n switch (fileExtension) {\n case \"glb\":\n case \"gltf\":\n success = await AssetManager.loadGLTFAsset(asset, fullPath, progressCallback)\n break\n case \"obj\":\n success = await AssetManager.loadOBJAsset(asset, fullPath, progressCallback)\n break\n case \"fbx\":\n success = await AssetManager.loadFBXAsset(asset, fullPath, progressCallback)\n break\n case \"stow\":\n // .stow files are now loaded directly using StowKitLoader in game code\n console.error(\n \".stow files should be loaded using StowKitLoader.load() directly, not via AssetManager\"\n )\n success = false\n break\n default:\n console.error(`Unsupported file type: ${fileExtension}`)\n success = false\n }\n\n return success\n } catch (error) {\n console.error(`Failed to load asset '${path}':`, error)\n asset.isLoading = false\n\n if (progressCallback) progressCallback(0)\n\n return false\n }\n }\n\n /**\n * Check if an asset is loaded and throw an error if not\n * Use this for strict preloading workflows - RECOMMENDED for ObjRendererThree\n * @param path Path to the asset\n * @throws Error if asset is not preloaded\n */\n public static requireAsset(path: string): AssetInfo {\n const asset = AssetManager._assets.get(path)\n if (!asset || !asset.isLoaded) {\n throw new Error(\n `Asset '${path}' is not preloaded. ` +\n `Make sure to call AssetManager.preloadAssets([...]) with this path before creating renderers.`\n )\n }\n return asset\n }\n\n /**\n * Get a list of all preloaded asset paths\n */\n public static getPreloadedAssets(): string[] {\n return Array.from(AssetManager._assets.keys()).filter(\n (path) => AssetManager._assets.get(path)?.isLoaded\n )\n }\n\n /**\n * Get a list of all failed asset paths\n */\n public static getFailedAssets(): string[] {\n return Array.from(AssetManager._assets.keys()).filter((path) => {\n const asset = AssetManager._assets.get(path)\n return asset && !asset.isLoaded && !asset.isLoading\n })\n }\n\n /**\n * Get preloading statistics\n */\n public static getPreloadingStats(): {\n total: number\n loaded: number\n failed: number\n loading: number\n completionPercentage: number\n } {\n let loaded = 0\n let failed = 0\n let loading = 0\n const total = AssetManager._assets.size\n\n for (const asset of AssetManager._assets.values()) {\n if (asset.isLoaded) {\n loaded++\n } else if (asset.isLoading) {\n loading++\n } else {\n failed++\n }\n }\n\n const completionPercentage = total > 0 ? Math.round((loaded / total) * 100) : 100\n\n return { total, loaded, failed, loading, completionPercentage }\n }\n\n /**\n * Get GLTF data for a loaded GLTF/GLB asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns GLTF data or null if not a GLTF asset\n */\n public static getGLTF(path: string): any | null {\n const asset = AssetManager._assets.get(path)\n\n if (!asset || !asset.isLoaded) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return null\n }\n\n return asset.gltf || null\n }\n\n /**\n * Load GLTF/GLB asset\n * @private\n */\n private static loadGLTFAsset(\n asset: AssetInfo,\n fullPath: string,\n progressCallback?: (progress: number) => void\n ): Promise<boolean> {\n return new Promise((resolve) => {\n AssetManager._gltfLoader.load(\n fullPath,\n (gltf) => {\n // Store the GLTF data\n asset.gltf = gltf\n\n // Create a group to hold all the loaded content\n const group = new THREE.Group()\n group.name = `${asset.path}_group`\n\n // Add the scene to our group\n group.add(gltf.scene)\n\n // Extract meshes and materials\n asset.meshes = []\n asset.materials = []\n\n gltf.scene.traverse((object: THREE.Object3D) => {\n if (object instanceof THREE.Mesh) {\n asset.meshes.push(object)\n\n // Collect materials\n if (object.material) {\n if (Array.isArray(object.material)) {\n asset.materials.push(...object.material)\n } else {\n asset.materials.push(object.material)\n }\n }\n }\n })\n\n // Store animations\n asset.animations = gltf.animations || []\n\n // Store the group\n asset.group = group\n\n // Mark as loaded\n asset.isLoaded = true\n asset.isLoading = false\n\n if (progressCallback) progressCallback(1)\n\n // GLTF asset loaded\n resolve(true)\n },\n (progressEvent) => {\n if (progressCallback && progressEvent.lengthComputable) {\n const progress = progressEvent.loaded / progressEvent.total\n progressCallback(progress)\n }\n },\n (error) => {\n console.error(`Failed to load GLTF asset '${asset.path}':`, error)\n asset.isLoading = false\n\n if (progressCallback) progressCallback(0)\n resolve(false)\n }\n )\n })\n }\n\n /**\n * Load OBJ asset\n * @private\n */\n private static loadOBJAsset(\n asset: AssetInfo,\n fullPath: string,\n progressCallback?: (progress: number) => void\n ): Promise<boolean> {\n return new Promise((resolve) => {\n // First, try to load MTL file if it exists\n const mtlPath = fullPath.replace(\".obj\", \".mtl\")\n\n // Check if MTL file exists by trying to load it\n AssetManager._mtlLoader.load(\n mtlPath,\n (materials) => {\n // MTL file exists, apply materials\n materials.preload()\n AssetManager._objLoader.setMaterials(materials)\n AssetManager.loadOBJWithMaterials(asset, fullPath, resolve, progressCallback)\n },\n undefined,\n () => {\n // MTL file doesn't exist, load OBJ without materials\n AssetManager.loadOBJWithMaterials(asset, fullPath, resolve, progressCallback)\n }\n )\n })\n }\n\n /**\n * Load OBJ with or without materials\n * @private\n */\n private static loadOBJWithMaterials(\n asset: AssetInfo,\n fullPath: string,\n resolve: (value: boolean) => void,\n progressCallback?: (progress: number) => void\n ): void {\n AssetManager._objLoader.load(\n fullPath,\n (object) => {\n // Store the object as a group\n asset.group = object\n\n // Extract meshes and materials\n asset.meshes = []\n asset.materials = []\n\n object.traverse((child: THREE.Object3D) => {\n // Handle different types of objects that OBJ loader might create\n if (child instanceof THREE.Mesh) {\n asset.meshes.push(child)\n\n // Collect materials\n if (child.material) {\n if (Array.isArray(child.material)) {\n asset.materials.push(...child.material)\n } else {\n asset.materials.push(child.material)\n }\n }\n } else if (child.type === \"Mesh\") {\n // Sometimes OBJ loader creates objects with type 'Mesh' but not instanceof THREE.Mesh\n asset.meshes.push(child as THREE.Mesh)\n\n // Collect materials\n const mesh = child as any\n if (mesh.material) {\n if (Array.isArray(mesh.material)) {\n asset.materials.push(...mesh.material)\n } else {\n asset.materials.push(mesh.material)\n }\n }\n } else if ((child as any).geometry && (child as any).material) {\n // Fallback: if it has geometry and material, treat it as a mesh\n asset.meshes.push(child as THREE.Mesh)\n\n const mesh = child as any\n if (Array.isArray(mesh.material)) {\n asset.materials.push(...mesh.material)\n } else {\n asset.materials.push(mesh.material)\n }\n }\n })\n\n // OBJ files don't have animations\n asset.animations = []\n\n // Mark as loaded\n asset.isLoaded = true\n asset.isLoading = false\n\n if (progressCallback) progressCallback(1)\n\n // OBJ asset loaded\n resolve(true)\n },\n (progressEvent) => {\n if (progressCallback && progressEvent.lengthComputable) {\n const progress = progressEvent.loaded / progressEvent.total\n progressCallback(progress)\n }\n },\n (error) => {\n console.error(`Failed to load OBJ asset '${asset.path}':`, error)\n asset.isLoading = false\n\n if (progressCallback) progressCallback(0)\n resolve(false)\n }\n )\n }\n\n /**\n * Load FBX asset\n * @private\n */\n private static loadFBXAsset(\n asset: AssetInfo,\n fullPath: string,\n progressCallback?: (progress: number) => void\n ): Promise<boolean> {\n return new Promise((resolve) => {\n AssetManager._fbxLoader.load(\n fullPath,\n (object) => {\n // FBX loader returns a Group\n asset.group = object\n\n // Extract meshes and materials\n asset.meshes = []\n asset.materials = []\n\n object.traverse((child: THREE.Object3D) => {\n if (child instanceof THREE.Mesh) {\n asset.meshes.push(child)\n\n // Collect materials\n if (child.material) {\n if (Array.isArray(child.material)) {\n asset.materials.push(...child.material)\n } else {\n asset.materials.push(child.material)\n }\n }\n }\n })\n\n // FBX files can have animations\n asset.animations = object.animations || []\n\n // Mark as loaded\n asset.isLoaded = true\n asset.isLoading = false\n\n if (progressCallback) progressCallback(1)\n\n // FBX asset loaded\n resolve(true)\n },\n (progressEvent) => {\n if (progressCallback && progressEvent.lengthComputable) {\n const progress = progressEvent.loaded / progressEvent.total\n progressCallback(progress)\n }\n },\n (error) => {\n console.error(`Failed to load FBX asset '${asset.path}':`, error)\n asset.isLoading = false\n\n if (progressCallback) progressCallback(0)\n resolve(false)\n }\n )\n })\n }\n\n /**\n * Get the asset group for a loaded asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns The Group for the asset or null if not loaded\n */\n public static getAssetGroup(path: string): THREE.Group | null {\n if (!AssetManager._scene) {\n throw new Error(\"AssetManager is not initialized. Call AssetManager.init(scene) first.\")\n }\n\n const asset = AssetManager._assets.get(path)\n\n if (!asset) {\n console.error(`Asset '${path}' not found. Use AssetManager.preloadAssets() first.`)\n return null\n }\n\n if (!asset.isLoaded || !asset.group) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return null\n }\n\n return asset.group\n }\n\n /**\n * Get the primary mesh from a loaded asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns The primary Mesh from the asset or null if not found\n */\n public static getMesh(path: string): THREE.Mesh | null {\n const asset = AssetManager._assets.get(path)\n\n if (!asset || !asset.isLoaded) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return null\n }\n\n if (asset.meshes.length === 0) {\n console.error(`No meshes found in asset '${path}'`)\n return null\n }\n\n return asset.meshes[0]\n }\n\n /**\n * Get all meshes from a loaded asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns Array of meshes from the asset\n */\n public static getMeshes(path: string): THREE.Mesh[] {\n const asset = AssetManager._assets.get(path)\n\n if (!asset || !asset.isLoaded) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return []\n }\n\n return asset.meshes\n }\n\n /**\n * Get all materials from a loaded asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns Array of materials from the asset\n */\n public static getMaterials(path: string): THREE.Material[] {\n const asset = AssetManager._assets.get(path)\n\n if (!asset || !asset.isLoaded) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return []\n }\n\n return asset.materials\n }\n\n /**\n * Get all animations from a loaded asset - SYNCHRONOUS (use after preloading)\n * @param path Path to the asset\n * @returns Array of animation clips from the asset\n */\n public static getAnimations(path: string): THREE.AnimationClip[] {\n const asset = AssetManager._assets.get(path)\n\n if (!asset || !asset.isLoaded) {\n console.error(`Asset '${path}' not loaded. Use AssetManager.preloadAssets() first.`)\n return []\n }\n\n return asset.animations\n }\n\n /**\n * Register a StowKit-loaded asset for compatibility with existing code\n * Allows StowKit assets to be accessed via the same AssetManager.getAssetGroup() API\n * @param path Virtual path to register the asset under (e.g. 'v2/restaurant_display_default.fbx')\n * @param group The THREE.Group loaded from StowKit\n */\n public static registerStowKitAsset(path: string, group: THREE.Group): void {\n // Extract meshes and materials from the group\n const meshes: THREE.Mesh[] = []\n const materials: THREE.Material[] = []\n\n group.traverse((obj) => {\n if (obj instanceof THREE.Mesh) {\n meshes.push(obj)\n if (Array.isArray(obj.material)) {\n materials.push(...obj.material)\n } else {\n materials.push(obj.material)\n }\n }\n })\n\n // Register as a loaded asset\n AssetManager._assets.set(path, {\n path: path,\n group: group,\n isLoaded: true,\n isLoading: false,\n meshes: meshes,\n materials: materials,\n animations: [], // StowKit assets don't have animations in this context\n })\n }\n\n // Store for StowKit textures\n private static _stowkitTextures: Map<string, THREE.Texture> = new Map()\n\n /**\n * Register a StowKit-loaded texture for use by materials\n * @param name Texture name/ID\n * @param texture The THREE.Texture loaded from StowKit\n */\n public static registerStowKitTexture(name: string, texture: THREE.Texture): void {\n AssetManager._stowkitTextures.set(name, texture)\n }\n\n /**\n * Get a StowKit-loaded texture by name\n * @param name Texture name/ID\n * @returns The texture or null if not found\n */\n public static getStowKitTexture(name: string): THREE.Texture | null {\n return AssetManager._stowkitTextures.get(name) || null\n }\n\n /**\n * Unload an asset to free memory\n * @param path Path to the asset\n */\n public static unloadAsset(path: string): void {\n const asset = AssetManager._assets.get(path)\n if (!asset) {\n return\n }\n\n // Dispose of materials\n for (const material of asset.materials) {\n material.dispose()\n }\n\n // Dispose of geometries\n for (const mesh of asset.meshes) {\n mesh.geometry.dispose()\n }\n\n // Remove from scene if added\n if (asset.group && asset.group.parent) {\n asset.group.parent.remove(asset.group)\n }\n\n AssetManager._assets.delete(path)\n console.log(`🗑️ Asset '${path}' unloaded`)\n }\n\n /**\n * Check if an asset is loaded\n * @param path Path to the asset\n */\n public static isLoaded(path: string): boolean {\n const asset = AssetManager._assets.get(path)\n return asset?.isLoaded || false\n }\n\n /**\n * Get the current base URL being used\n */\n public static getBaseUrl(): string {\n return AssetManager._baseUrl\n }\n\n /**\n * Reset to default relative path behavior\n */\n public static useRelativePaths(): void {\n AssetManager._baseUrl = \"./\"\n }\n\n /**\n * Get loading progress for all assets\n * @returns Object with loading statistics\n * @deprecated Use getPreloadingStats() instead for better information\n */\n public static getLoadingStats(): {\n loaded: number\n loading: number\n total: number\n } {\n let loaded = 0\n let loading = 0\n const total = AssetManager._assets.size\n\n for (const asset of AssetManager._assets.values()) {\n if (asset.isLoaded) {\n loaded++\n } else if (asset.isLoading) {\n loading++\n }\n }\n\n return { loaded, loading, total }\n }\n\n // === INSTANCE TRACKING METHODS ===\n\n /**\n * Track when a shared instance is converted to cloned (broken instancing)\n * @param assetPath Path to the asset\n */\n public static trackInstanceBroken(assetPath: string): void {\n if (!AssetManager._instanceStats.has(assetPath)) {\n return // Shouldn't happen, but be safe\n }\n\n const stats = AssetManager._instanceStats.get(assetPath)!\n stats.sharedInstances--\n stats.clonedInstances++\n stats.brokenInstances++\n }\n\n /**\n * Get instance statistics for a specific asset\n * @param assetPath Path to the asset\n */\n public static getAssetInstanceStats(assetPath: string): InstanceStats {\n return (\n AssetManager._instanceStats.get(assetPath) || {\n totalInstances: 0,\n sharedInstances: 0,\n clonedInstances: 0,\n brokenInstances: 0,\n gpuInstances: 0,\n gpuBatches: 0,\n }\n )\n }\n\n /**\n * Get global instancing statistics for debug display\n */\n public static getGlobalInstanceStats(): GlobalInstanceStats {\n const totalAssets = AssetManager._assets.size\n const loadedAssets = Array.from(AssetManager._assets.values()).filter(\n (asset) => asset.isLoaded\n ).length\n\n let totalInstances = 0\n let sharedInstances = 0\n let clonedInstances = 0\n let brokenInstances = 0\n let gpuInstances = 0\n let gpuBatches = 0\n\n for (const stats of AssetManager._instanceStats.values()) {\n totalInstances += stats.totalInstances\n sharedInstances += stats.sharedInstances\n clonedInstances += stats.clonedInstances\n brokenInstances += stats.brokenInstances\n gpuInstances += stats.gpuInstances\n gpuBatches += stats.gpuBatches\n }\n\n // Calculate geometry and material reuse\n let totalGeometries = 0\n let totalMaterials = 0\n let geometryInstances = 0\n let materialInstances = 0\n\n for (const [assetPath, asset] of AssetManager._assets.entries()) {\n if (!asset.isLoaded) continue\n\n const instanceStats = AssetManager._instanceStats.get(assetPath)\n const instances = instanceStats ? instanceStats.sharedInstances : 0\n\n totalGeometries += asset.meshes.length\n totalMaterials += asset.materials.length\n geometryInstances += asset.meshes.length * instances\n materialInstances += asset.materials.length * instances\n }\n\n const geometryReuse =\n totalGeometries > 0 ? Math.round((geometryInstances / totalGeometries) * 100) / 100 : 0\n const materialReuse =\n totalMaterials > 0 ? Math.round((materialInstances / totalMaterials) * 100) / 100 : 0\n\n return {\n totalAssets,\n loadedAssets,\n totalInstances,\n sharedInstances,\n clonedInstances,\n brokenInstances,\n gpuInstances,\n gpuBatches,\n geometryReuse,\n materialReuse,\n }\n }\n\n /**\n * Get detailed instancing report for debugging\n */\n public static getInstanceReport(): string {\n const globalStats = AssetManager.getGlobalInstanceStats()\n const lines = [\n `=== INSTANCING REPORT ===`,\n `Assets: ${globalStats.loadedAssets}/${globalStats.totalAssets} loaded`,\n `Instances: ${globalStats.totalInstances} total`,\n ` - GPU: ${globalStats.gpuInstances} in ${globalStats.gpuBatches} batches (${Math.round((globalStats.gpuInstances / Math.max(globalStats.totalInstances, 1)) * 100)}%)`,\n ` - Shared: ${globalStats.sharedInstances} (${Math.round((globalStats.sharedInstances / Math.max(globalStats.totalInstances, 1)) * 100)}%)`,\n ` - Cloned: ${globalStats.clonedInstances} (${Math.round((globalStats.clonedInstances / Math.max(globalStats.totalInstances, 1)) * 100)}%)`,\n ` - Broken: ${globalStats.brokenInstances} (${Math.round((globalStats.brokenInstances / Math.max(globalStats.totalInstances, 1)) * 100)}%)`,\n `Reuse: Geometry ${globalStats.geometryReuse}x, Material ${globalStats.materialReuse}x`,\n ``,\n `=== PER-ASSET BREAKDOWN ===`,\n ]\n\n for (const [assetPath, stats] of AssetManager._instanceStats.entries()) {\n if (stats.totalInstances > 0) {\n lines.push(\n `${assetPath}: ${stats.totalInstances} total (${stats.gpuInstances} GPU in ${stats.gpuBatches} batches, ${stats.sharedInstances} shared, ${stats.clonedInstances} cloned, ${stats.brokenInstances} broken)`\n )\n }\n }\n\n return lines.join(\"\\n\")\n }\n\n // === GPU INSTANCING METHODS ===\n\n /**\n * Create or get a GPU instance batch for an asset\n * @param assetPath Path to the asset\n * @param material Material to use for the batch\n * @param maxInstances Maximum instances in this batch (default: 1000)\n */\n public static getOrCreateGPUBatch(\n assetPath: string,\n material: THREE.Material,\n maxInstances: number = 1000\n ): GPUInstanceBatch | null {\n const asset = AssetManager.requireAsset(assetPath)\n const primaryMesh = AssetManager.getMesh(assetPath)\n\n if (!primaryMesh) {\n console.error(`❌ No mesh found for GPU instancing: ${assetPath}`)\n return null\n }\n\n // Get or create batch array for this asset\n if (!AssetManager._gpuBatches.has(assetPath)) {\n AssetManager._gpuBatches.set(assetPath, [])\n }\n\n const batches = AssetManager._gpuBatches.get(assetPath)!\n\n // Find an existing batch with space and matching material\n for (const batch of batches) {\n if (batch.material === material && batch.instances.length < batch.maxInstances) {\n return batch\n }\n }\n\n // Create new batch if none found with space\n const instancedMesh = new THREE.InstancedMesh(primaryMesh.geometry, material, maxInstances)\n instancedMesh.name = `${assetPath}_gpu_batch_${batches.length}`\n instancedMesh.castShadow = true\n instancedMesh.receiveShadow = true\n instancedMesh.frustumCulled = false // Disable Three.js built-in frustum culling since we handle it manually\n\n // Add to scene\n AssetManager._scene.add(instancedMesh)\n\n // Calculate proper bounding sphere and box from geometry\n const geometry = primaryMesh.geometry\n\n // Compute bounding sphere and box if not already computed\n if (!geometry.boundingSphere) {\n geometry.computeBoundingSphere()\n }\n\n if (!geometry.boundingBox) {\n geometry.computeBoundingBox()\n }\n\n // Calculate broad culling radius that encompasses the entire geometry\n // Use the diagonal of the bounding box for maximum coverage\n // This is faster than bounding box intersection tests while being slightly less accurate\n let cullingRadius = 1.0 // Default fallback\n\n if (geometry.boundingBox) {\n const size = geometry.boundingBox.getSize(new THREE.Vector3())\n // Use full diagonal length instead of half for more conservative culling\n cullingRadius = size.length()\n } else if (geometry.boundingSphere) {\n // Double the bounding sphere radius for more conservative culling\n cullingRadius = geometry.boundingSphere.radius * 2\n }\n\n const newBatch: GPUInstanceBatch = {\n instancedMesh,\n assetPath,\n material,\n instances: [],\n maxInstances,\n needsUpdate: false,\n cullingRadius,\n hasDynamicObjects: false, // Initialize as false\n }\n\n batches.push(newBatch)\n\n return newBatch\n }\n\n /**\n * Add a GPU instance to a batch\n * @param assetPath Path to the asset\n * @param gameObject GameObject to instance\n * @param material Material to use\n * @param isStatic Whether this instance is static (won't move after creation)\n * @returns Instance ID or null if failed\n */\n public static addGPUInstance(\n assetPath: string,\n gameObject: GameObject,\n material: THREE.Material,\n isStatic: boolean = false\n ): string | null {\n const batch = AssetManager.getOrCreateGPUBatch(assetPath, material)\n if (!batch) {\n return null\n }\n\n if (batch.instances.length >= batch.maxInstances) {\n console.warn(`GPU batch full for '${assetPath}', consider increasing maxInstances`)\n return null\n }\n\n const instanceId = `${assetPath}_gpu_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`\n\n const instanceData: GPUInstanceData = {\n id: instanceId,\n gameObject,\n matrix: new THREE.Matrix4(),\n isActive: true,\n isStatic: isStatic,\n }\n\n // Set initial transform from GameObject (use world transform for correct positioning)\n const worldPosition = new THREE.Vector3()\n const worldQuaternion = new THREE.Quaternion()\n const worldScale = new THREE.Vector3()\n\n gameObject.getWorldPosition(worldPosition)\n gameObject.getWorldQuaternion(worldQuaternion)\n gameObject.getWorldScale(worldScale)\n\n instanceData.matrix.compose(worldPosition, worldQuaternion, worldScale)\n\n batch.instances.push(instanceData)\n batch.needsUpdate = true\n\n // Track if this batch has dynamic objects\n if (!isStatic) {\n batch.hasDynamicObjects = true\n }\n\n // Update instance matrix\n AssetManager.updateGPUBatch(batch)\n\n // Track instance creation (create stats if needed)\n AssetManager.trackInstanceCreated(assetPath, false, true) // GPU instance\n\n // Update batch statistics AFTER instance stats exist\n AssetManager.updateGPUBatchStats(assetPath)\n\n return instanceId\n }\n\n /**\n * Remove a GPU instance from its batch\n * @param assetPath Path to the asset\n * @param instanceId Instance ID to remove\n */\n public static removeGPUInstance(assetPath: string, instanceId: string): void {\n const batches = AssetManager._gpuBatches.get(assetPath)\n if (!batches) return\n\n for (const batch of batches) {\n const instanceIndex = batch.instances.findIndex((inst) => inst.id === instanceId)\n if (instanceIndex !== -1) {\n batch.instances.splice(instanceIndex, 1)\n batch.needsUpdate = true\n AssetManager.updateGPUBatch(batch)\n\n // Track instance destruction\n AssetManager.trackInstanceDestroyed(assetPath, false, true) // GPU instance\n return\n }\n }\n }\n\n /**\n * Set the visibility of a specific GPU instance\n * @param assetPath Path to the asset\n * @param instanceId Instance ID to show/hide\n * @param visible Whether the instance should be visible\n */\n public static setGPUInstanceVisible(\n assetPath: string,\n instanceId: string,\n visible: boolean\n ): void {\n const batches = AssetManager._gpuBatches.get(assetPath)\n if (!batches) return\n\n for (const batch of batches) {\n const instance = batch.instances.find((inst) => inst.id === instanceId)\n if (instance) {\n instance.isActive = visible\n batch.needsUpdate = true\n\n // Force immediate batch update to ensure visibility changes are applied\n AssetManager.updateGPUBatch(batch)\n return\n }\n }\n }\n\n /**\n * Get the visibility of a specific GPU instance\n * @param assetPath Path to the asset\n * @param instanceId Instance ID to check\n * @returns Whether the instance is visible\n */\n public static getGPUInstanceVisible(assetPath: string, instanceId: string): boolean {\n const batches = AssetManager._gpuBatches.get(assetPath)\n if (!batches) return false\n\n for (const batch of batches) {\n const instance = batch.instances.find((inst) => inst.id === instanceId)\n if (instance) {\n return instance.isActive\n }\n }\n return false\n }\n\n /**\n * Convert a GPU instance to object-level instance (for scaling, etc.)\n * @param assetPath Path to the asset\n * @param instanceId Instance ID to convert\n * @returns New GameObject with ObjRenderer or null if failed\n */\n public static convertGPUToObjectLevel(assetPath: string, instanceId: string): any | null {\n const batches = AssetManager._gpuBatches.get(assetPath)\n if (!batches) return null\n\n for (const batch of batches) {\n const instanceIndex = batch.instances.findIndex((inst) => inst.id === instanceId)\n if (instanceIndex !== -1) {\n const instanceData = batch.instances[instanceIndex]\n\n // Remove from GPU batch\n batch.instances.splice(instanceIndex, 1)\n batch.needsUpdate = true\n AssetManager.updateGPUBatch(batch)\n\n // Create new object-level instance\n // Note: This would need to be integrated with the actual GameObject/Component system\n console.log(`🔄 Converting GPU instance '${instanceId}' to object-level for scaling`)\n\n // Track the conversion\n AssetManager.trackInstanceDestroyed(assetPath, false, true) // Remove GPU\n AssetManager.trackInstanceCreated(assetPath, false, false) // Add object-level\n AssetManager.trackInstanceBroken(assetPath) // Mark as broken\n\n return instanceData.gameObject\n }\n }\n\n return null\n }\n\n /**\n * Update GPU batch matrices and upload to GPU\n * @param batch GPU batch to update\n * @param camera Optional camera for frustum culling\n */\n public static updateGPUBatch(batch: GPUInstanceBatch, camera?: THREE.Camera): void {\n if (!batch.needsUpdate) return\n\n const activeInstances = batch.instances.filter((inst) => inst.isActive)\n\n // Update matrices only for dynamic objects (static optimization preserved)\n activeInstances.forEach((instance) => {\n // Only update matrix for dynamic (non-static) objects\n if (!instance.isStatic) {\n // Update matrix from GameObject transform (use world transform for correct positioning)\n const worldPosition = new THREE.Vector3()\n const worldQuaternion = new THREE.Quaternion()\n const worldScale = new THREE.Vector3()\n\n instance.gameObject.getWorldPosition(worldPosition)\n instance.gameObject.getWorldQuaternion(worldQuaternion)\n instance.gameObject.getWorldScale(worldScale)\n\n instance.matrix.compose(worldPosition, worldQuaternion, worldScale)\n }\n // For static objects, matrix was set once during creation and doesn't change\n })\n\n let visibleInstances = activeInstances\n\n // Optional frustum culling to reduce triangle count (can be globally disabled)\n if (AssetManager._frustumCullingEnabled && camera && batch.cullingRadius > 0) {\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 visibleInstances = activeInstances.filter((instance) => {\n // Use updated matrix for accurate culling\n const worldMatrix = instance.matrix\n const position = new THREE.Vector3().setFromMatrixPosition(worldMatrix)\n const scale = new THREE.Vector3().setFromMatrixScale(worldMatrix)\n\n // Calculate proper radius based on geometry bounding sphere and instance scale\n const maxScale = Math.max(scale.x, scale.y, scale.z)\n const actualRadius = batch.cullingRadius * maxScale\n\n // Add generous padding to prevent aggressive culling of visible objects\n const paddedRadius = actualRadius * AssetManager._frustumCullingPadding\n\n // Test sphere intersection with frustum\n const sphere = new THREE.Sphere(position, paddedRadius)\n const isVisible = frustum.intersectsSphere(sphere)\n\n return isVisible\n })\n }\n\n // Set matrices for visible instances (matrices already updated above)\n visibleInstances.forEach((instance, index) => {\n batch.instancedMesh.setMatrixAt(index, instance.matrix)\n })\n\n // Hide unused instances by setting them to zero scale\n for (let i = visibleInstances.length; i < batch.maxInstances; i++) {\n const zeroMatrix = new THREE.Matrix4().makeScale(0, 0, 0)\n batch.instancedMesh.setMatrixAt(i, zeroMatrix)\n }\n\n // Mark for GPU upload\n batch.instancedMesh.instanceMatrix.needsUpdate = true\n batch.instancedMesh.count = visibleInstances.length // Only render visible instances!\n batch.needsUpdate = false\n }\n\n /**\n * Update GPU batch statistics\n * @param assetPath Path to the asset\n */\n private static updateGPUBatchStats(assetPath: string): void {\n const batches = AssetManager._gpuBatches.get(assetPath)\n const hasInstanceStats = AssetManager._instanceStats.has(assetPath)\n\n if (!batches || !hasInstanceStats) return\n\n const stats = AssetManager._instanceStats.get(assetPath)!\n stats.gpuBatches = batches.length\n\n let totalGPUInstances = 0\n for (const batch of batches) {\n totalGPUInstances += batch.instances.filter((inst) => inst.isActive).length\n }\n stats.gpuInstances = totalGPUInstances\n }\n\n /**\n * Track when an instance is created from an asset\n * @param assetPath Path to the asset\n * @param isShared Whether this is a shared instance (true) or cloned (false)\n * @param isGPU Whether this is a GPU instance (true) or object-level (false)\n */\n public static trackInstanceCreated(\n assetPath: string,\n isShared: boolean,\n isGPU: boolean = false\n ): void {\n if (!AssetManager._instanceStats.has(assetPath)) {\n AssetManager._instanceStats.set(assetPath, {\n totalInstances: 0,\n sharedInstances: 0,\n clonedInstances: 0,\n brokenInstances: 0,\n gpuInstances: 0,\n gpuBatches: 0,\n })\n }\n\n const stats = AssetManager._instanceStats.get(assetPath)!\n stats.totalInstances++\n\n if (isGPU) {\n stats.gpuInstances++\n } else if (isShared) {\n stats.sharedInstances++\n } else {\n stats.clonedInstances++\n }\n }\n\n /**\n * Track when an instance is destroyed\n * @param assetPath Path to the asset\n * @param wasShared Whether this was a shared instance\n * @param wasGPU Whether this was a GPU instance\n */\n public static trackInstanceDestroyed(\n assetPath: string,\n wasShared: boolean,\n wasGPU: boolean = false\n ): void {\n if (!AssetManager._instanceStats.has(assetPath)) {\n return // Shouldn't happen, but be safe\n }\n\n const stats = AssetManager._instanceStats.get(assetPath)!\n stats.totalInstances--\n\n if (wasGPU) {\n stats.gpuInstances--\n } else if (wasShared) {\n stats.sharedInstances--\n } else {\n stats.clonedInstances--\n }\n }\n\n /**\n * Update all GPU batches with optional frustum culling\n * Now uses separated static/dynamic logic for optimal performance\n * @param camera Optional camera for frustum culling\n * @param debug Whether to log frustum culling statistics (default: false)\n */\n public static updateAllGPUBatches(camera?: THREE.Camera, debug: boolean = false): void {\n // Update both static and dynamic batches (for compatibility/testing)\n AssetManager.updateDynamicGPUBatches(camera, debug)\n }\n\n /**\n * DEBUG: Force update all GPU batches\n * Call this from console to manually trigger batch updates\n */\n public static debugUpdateAllGPUBatches(): void {\n console.log(\"🔧 DEBUG: Force updating all GPU batches...\")\n let totalBatches = 0\n let totalInstances = 0\n\n for (const [assetPath, batches] of AssetManager._gpuBatches.entries()) {\n console.log(`🔧 Updating batches for '${assetPath}': ${batches.length} batches`)\n\n batches.forEach((batch, batchIndex) => {\n batch.needsUpdate = true\n AssetManager.updateGPUBatch(batch)\n totalBatches++\n totalInstances += batch.instances.length\n\n console.log(\n `🔧 Batch ${batchIndex} for '${assetPath}': ${batch.instances.length} instances, InstancedMesh count: ${batch.instancedMesh.count}`\n )\n })\n }\n\n console.log(`🔧 DEBUG: Updated ${totalBatches} batches with ${totalInstances} total instances`)\n }\n\n /**\n * Update only dynamic GPU batches (called every frame for immediate updates)\n * @param camera Optional camera for frustum culling\n * @param debug Whether to log statistics (default: false)\n */\n public static updateDynamicGPUBatches(camera?: THREE.Camera, debug: boolean = false): void {\n let totalInstancesBefore = 0\n let totalInstancesAfter = 0\n let batchesUpdated = 0\n\n for (const [assetPath, batches] of AssetManager._gpuBatches.entries()) {\n batches.forEach((batch) => {\n // Only update batches that contain dynamic objects\n if (batch.hasDynamicObjects) {\n totalInstancesBefore += batch.instancedMesh.count\n batch.needsUpdate = true\n AssetManager.updateGPUBatch(batch, camera)\n batchesUpdated++\n totalInstancesAfter += batch.instancedMesh.count\n }\n })\n }\n\n if (debug && batchesUpdated > 0) {\n console.log(`🔄 Dynamic GPU Batch Update: ${batchesUpdated} dynamic batches updated`)\n if (camera && totalInstancesBefore !== totalInstancesAfter) {\n const reduction = totalInstancesBefore - totalInstancesAfter\n const percentReduction =\n totalInstancesBefore > 0 ? Math.round((reduction / totalInstancesBefore) * 100) : 0\n console.log(\n `🎯 Dynamic frustum culling: ${totalInstancesAfter}/${totalInstancesBefore} instances visible (${percentReduction}% culled)`\n )\n }\n }\n }\n\n /**\n * DEBUG: Show static vs dynamic batch breakdown\n */\n public static debugBatchTypes(): void {\n console.log(\"🔍 === GPU BATCH TYPE BREAKDOWN ===\")\n\n let totalStaticBatches = 0\n let totalDynamicBatches = 0\n let totalStaticInstances = 0\n let totalDynamicInstances = 0\n\n for (const [assetPath, batches] of AssetManager._gpuBatches.entries()) {\n batches.forEach((batch) => {\n const instanceCount = batch.instances.length\n\n if (batch.hasDynamicObjects) {\n totalDynamicBatches++\n totalDynamicInstances += instanceCount\n console.log(`🔄 DYNAMIC: ${assetPath} - ${instanceCount} instances`)\n } else {\n totalStaticBatches++\n totalStaticInstances += instanceCount\n console.log(`🏛️ STATIC: ${assetPath} - ${instanceCount} instances`)\n }\n })\n }\n\n console.log(\n `📊 Summary: ${totalDynamicBatches} dynamic batches (${totalDynamicInstances} instances), ${totalStaticBatches} static batches (${totalStaticInstances} instances)`\n )\n console.log(`💡 Dynamic batches update every frame, static batches only on camera movement`)\n }\n\n /**\n * Set frustum culling padding multiplier\n * Higher values = less aggressive culling (fewer false positives)\n * Lower values = more aggressive culling (more performance, more false positives)\n * @param padding Padding multiplier (default: 1.2 = 20% padding)\n */\n public static setFrustumCullingPadding(padding: number): void {\n AssetManager._frustumCullingPadding = Math.max(1.0, padding) // Minimum 1.0 (no shrinking)\n console.log(\n `🎯 Frustum culling padding set to ${AssetManager._frustumCullingPadding.toFixed(2)}x`\n )\n }\n\n /**\n * Get current frustum culling padding multiplier\n */\n public static getFrustumCullingPadding(): number {\n return AssetManager._frustumCullingPadding\n }\n\n /**\n * Enable or disable frustum culling globally\n * @param enabled Whether frustum culling should be enabled\n */\n public static setFrustumCullingEnabled(enabled: boolean): void {\n AssetManager._frustumCullingEnabled = enabled\n\n if (enabled) {\n console.log(\"✅ Frustum culling ENABLED\")\n } else {\n console.log(\"🚫 Frustum culling DISABLED\")\n }\n\n // Force update all batches\n for (const [assetPath, batches] of AssetManager._gpuBatches.entries()) {\n batches.forEach((batch) => {\n batch.needsUpdate = true\n })\n }\n }\n\n /**\n * Get current frustum culling enabled state\n */\n public static isFrustumCullingEnabled(): boolean {\n return AssetManager._frustumCullingEnabled\n }\n\n /**\n * DEBUG: Test frustum culling by temporarily disabling it\n * @param disabled Whether to disable frustum culling entirely (for testing)\n */\n public static debugFrustumCulling(disabled: boolean = false): void {\n AssetManager.setFrustumCullingEnabled(!disabled)\n console.log(\n `🎯 Current frustum culling state: ${AssetManager._frustumCullingEnabled ? \"ENABLED\" : \"DISABLED\"}`\n )\n }\n\n // ========== Skeletal Model Management ==========\n\n /**\n * Preload a skeletal FBX model using SkeletonCache\n * Use this for character models that need proper bone cloning\n */\n public static async preloadSkeletalModel(path: string): Promise<THREE.Object3D> {\n return AssetManager._skeletonCache.preload(path)\n }\n\n /**\n * Register a skeletal model directly (for StowKit or other loaders)\n * Use this for character models loaded from StowKit\n */\n public static registerSkeletalModel(path: string, object: THREE.Object3D): void {\n AssetManager._skeletonCache.register(path, object)\n }\n\n /**\n * Get a properly cloned skeletal model\n * Uses SkeletonUtils.clone() to preserve bone relationships for animation\n */\n public static getSkeletalClone(path: string): THREE.Object3D | null {\n return AssetManager._skeletonCache.getClone(path)\n }\n\n /**\n * Check if a skeletal model is loaded\n */\n public static isSkeletalModelLoaded(path: string): boolean {\n return AssetManager._skeletonCache.isLoaded(path)\n }\n\n /**\n * Get the original skeletal model (for reference, not for use)\n */\n public static getSkeletalOriginal(path: string): THREE.Object3D | null {\n return AssetManager._skeletonCache.getOriginal(path)\n }\n\n /**\n * Clear all global state (for testing) - now includes skeleton cache\n */\n public static reset(): void {\n AssetManager._assets.clear()\n AssetManager._instanceStats.clear()\n AssetManager._gpuBatches.clear()\n AssetManager._isPreloadingComplete = false\n AssetManager._frustumCullingEnabled = false\n AssetManager._frustumCullingPadding = 1.5\n AssetManager._skeletonCache.clear()\n }\n}\n","import * as THREE from \"three\"\nimport { Component, GameObject } from \"@engine/core\"\nimport { PhysicsSystem } from \"./PhysicsSystem\"\n//\nimport {\n ActiveCollisionTypes,\n ActiveEvents,\n Collider,\n ColliderDesc,\n Cuboid,\n RigidBody,\n RigidBodyDesc,\n ShapeType,\n} from \"@dimforge/rapier3d\"\n\nexport enum RigidBodyType {\n DYNAMIC = \"dynamic\",\n STATIC = \"static\",\n KINEMATIC = \"kinematic\",\n}\n\nexport enum ColliderShape {\n BOX = \"box\",\n SPHERE = \"sphere\",\n CAPSULE = \"capsule\",\n CONVEX_HULL = \"convex_hull\",\n}\n\n// General collision group utilities (game-agnostic)\n\n// Helper function to create collision group value (membership in high 16 bits, filter in low 16 bits)\nexport function createCollisionGroup(membership: number, filter: number): number {\n return (membership << 16) | filter\n}\n\nexport interface RigidBodyOptions {\n type?: RigidBodyType\n shape?: ColliderShape\n size?: THREE.Vector3 // For box: width, height, depth\n radius?: number // For sphere/capsule\n height?: number // For capsule\n mass?: number\n restitution?: number // Bounciness\n friction?: number\n isSensor?: boolean // For trigger colliders\n vertices?: Float32Array // For convex hull: raw vertex positions (x,y,z,x,y,z,...)\n\n // Auto-sizing from mesh bounds\n fitToMesh?: boolean // If true, automatically calculate size from mesh bounds\n\n // Collider center positioning\n centerOffset?: THREE.Vector3 // Offset for collider center relative to GameObject\n\n // Damping for smoother movement\n linearDamping?: number // Damping for linear velocity (0-1, higher = more damping)\n angularDamping?: number // Damping for angular velocity (0-1, higher = more damping)\n\n // Rotation locking options\n lockRotationX?: boolean // Lock rotation around X axis\n lockRotationY?: boolean // Lock rotation around Y axis\n lockRotationZ?: boolean // Lock rotation around Z axis\n\n // Translation locking options\n lockTranslationX?: boolean // Lock translation along X axis\n lockTranslationY?: boolean // Lock translation along Y axis\n lockTranslationZ?: boolean // Lock translation along Z axis\n\n // Collision event generation (automatically handles ActiveEvents + ActiveCollisionTypes)\n enableCollisionEvents?: boolean // Enable collision events (defaults: true for sensors and kinematic/dynamic, false for non-sensor static)\n\n // Collision groups for filtering interactions (16-bit membership + 16-bit filter)\n collisionGroups?: number // Packed 32-bit: membership (high 16 bits) + filter (low 16 bits)\n}\n\n/**\n * Simple component for adding Rapier physics to GameObjects\n * Automatically syncs GameObject position with physics body\n */\nexport class RigidBodyComponentThree extends Component {\n private rigidBody: RigidBody | null = null\n private collider: Collider | null = null\n private options: RigidBodyOptions\n private bodyId: string\n\n private static _tempVec3 = new THREE.Vector3()\n private static _tempQuat = new THREE.Quaternion()\n\n // Trigger event callbacks - use proper type for GameObject\n private onTriggerEnterCallback: ((other: any) => void) | null = null\n private onTriggerExitCallback: ((other: any) => void) | null = null\n private isRegisteredWithPhysics: boolean = false\n\n constructor(options: RigidBodyOptions = {}) {\n super()\n this.options = {\n type: RigidBodyType.DYNAMIC,\n shape: ColliderShape.BOX,\n size: new THREE.Vector3(1, 1, 1),\n radius: 0.5,\n height: 1,\n mass: 1,\n restitution: 0.2,\n friction: 0.5,\n isSensor: false,\n linearDamping: 0.0, // Default no damping\n angularDamping: 0.0, // Default no damping\n ...options,\n }\n\n // Generate unique ID for this physics body\n this.bodyId = `rb_${Math.random().toString(36).substr(2, 9)}`\n }\n\n protected onCreate(): void {\n if (!PhysicsSystem.isReady()) {\n console.warn(\"⚠️ PhysicsSystem not ready - physics body will not be created\")\n return\n }\n\n this.createPhysicsBody()\n\n if (this.rigidBody) {\n // Apply rotation locking after body creation\n if (this.options.lockRotationX || this.options.lockRotationY || this.options.lockRotationZ) {\n // Enable/disable rotations - false means locked\n this.rigidBody.setEnabledRotations(\n !this.options.lockRotationX, // if lockRotationX is true, enable should be false\n !this.options.lockRotationY,\n !this.options.lockRotationZ,\n true // wake up\n )\n }\n\n // Apply translation locking after body creation\n if (\n this.options.lockTranslationX ||\n this.options.lockTranslationY ||\n this.options.lockTranslationZ\n ) {\n // Enable/disable translations - false means locked\n this.rigidBody.setEnabledTranslations(\n !this.options.lockTranslationX, // if lockTranslationX is true, enable should be false\n !this.options.lockTranslationY,\n !this.options.lockTranslationZ,\n true // wake up\n )\n }\n\n // Set initial enabled state based on GameObject's enabled state\n this.setEnabled(this.gameObject.isEnabled())\n\n // Always register GameObject mapping (for collision detection)\n PhysicsSystem.registerGameObject(this.bodyId, this.gameObject)\n\n // Physics body created\n } else {\n console.error(`❌ Failed to create rigid body for ${this.gameObject.name}`)\n }\n }\n\n private createPhysicsBody(): void {\n // Create rigid body descriptor\n let bodyDesc: RigidBodyDesc\n\n switch (this.options.type) {\n case RigidBodyType.STATIC:\n bodyDesc = RigidBodyDesc.fixed()\n break\n case RigidBodyType.KINEMATIC:\n bodyDesc = RigidBodyDesc.kinematicPositionBased()\n break\n case RigidBodyType.DYNAMIC:\n default:\n bodyDesc = RigidBodyDesc.dynamic()\n break\n }\n\n // Body position = gameObject world position (no offset).\n // The collider offset is applied via colliderDesc.setTranslation below.\n this.gameObject.updateMatrixWorld(true)\n const pos = this.gameObject.getWorldPosition(new THREE.Vector3())\n\n bodyDesc.setTranslation(pos.x, pos.y, pos.z)\n\n // Set initial rotation from GameObject\n // Use world rotation to account for parent transformations (important for child objects)\n const worldQuat = this.gameObject.getWorldQuaternion(new THREE.Quaternion())\n bodyDesc.setRotation({\n x: worldQuat.x,\n y: worldQuat.y,\n z: worldQuat.z,\n w: worldQuat.w,\n })\n\n // Calculate size from mesh bounds if requested\n if (this.options.fitToMesh) {\n const meshBounds = RigidBodyComponentThree.getMeshBounds(this.gameObject)\n this.options.size = meshBounds\n\n // For sphere and capsule, calculate radius/height from bounds\n if (this.options.shape === ColliderShape.SPHERE) {\n this.options.radius = Math.max(meshBounds.x, meshBounds.y, meshBounds.z) / 2\n } else if (this.options.shape === ColliderShape.CAPSULE) {\n this.options.height = meshBounds.y\n this.options.radius = Math.max(meshBounds.x, meshBounds.z) / 2\n }\n }\n\n // Create collider descriptor\n let colliderDesc: ColliderDesc = null!\n\n switch (this.options.shape) {\n case ColliderShape.SPHERE:\n colliderDesc = ColliderDesc.ball(this.options.radius!)\n break\n case ColliderShape.CAPSULE:\n colliderDesc = ColliderDesc.capsule(this.options.height! / 2, this.options.radius!)\n break\n case ColliderShape.CONVEX_HULL: {\n let hullCreated = false\n if (this.options.vertices && this.options.vertices.length >= 9) {\n const hullDesc = ColliderDesc.convexHull(this.options.vertices)\n if (hullDesc) {\n colliderDesc = hullDesc\n hullCreated = true\n }\n }\n if (!hullCreated) {\n console.warn(\"Convex hull creation failed, falling back to box collider\")\n const fallbackSize = this.options.size ?? new THREE.Vector3(1, 1, 1)\n colliderDesc = ColliderDesc.cuboid(fallbackSize.x / 2, fallbackSize.y / 2, fallbackSize.z / 2)\n }\n break\n }\n case ColliderShape.BOX:\n default:\n const size = this.options.size!\n colliderDesc = ColliderDesc.cuboid(size.x / 2, size.y / 2, size.z / 2)\n break\n }\n\n // Apply collider center offset (relative to body).\n // The body sits at gameObject worldPos; the collider is offset within the body.\n const colliderOffset = new THREE.Vector3(0, 0, 0)\n\n if (this.options.centerOffset) {\n colliderOffset.copy(this.options.centerOffset)\n } else {\n // Default behavior: offset by half the height so bottom sits at GameObject position\n if (this.options.shape === ColliderShape.BOX) {\n colliderOffset.y = this.options.size!.y / 2\n } else if (this.options.shape === ColliderShape.CAPSULE) {\n colliderOffset.y = this.options.height! / 2\n } else if (this.options.shape === ColliderShape.SPHERE) {\n colliderOffset.y = this.options.radius!\n }\n }\n\n colliderDesc.setTranslation(colliderOffset.x, colliderOffset.y, colliderOffset.z)\n\n // Set collider properties\n colliderDesc.setRestitution(this.options.restitution!)\n colliderDesc.setFriction(this.options.friction!)\n colliderDesc.setSensor(this.options.isSensor!)\n\n // Auto-configure collision events: always on for sensors (they need events to fire\n // trigger callbacks), otherwise on for kinematic/dynamic and off for static.\n const shouldEnableCollisionEvents =\n this.options.enableCollisionEvents ??\n (this.options.isSensor || this.options.type !== RigidBodyType.STATIC)\n\n if (shouldEnableCollisionEvents) {\n // Enable collision events for all interactions\n colliderDesc.setActiveEvents(ActiveEvents.COLLISION_EVENTS)\n\n // For kinematic bodies, also enable collision with static bodies (sensors)\n if (this.options.type === RigidBodyType.KINEMATIC) {\n colliderDesc.setActiveCollisionTypes(\n ActiveCollisionTypes.DEFAULT |\n ActiveCollisionTypes.KINEMATIC_FIXED |\n ActiveCollisionTypes.KINEMATIC_KINEMATIC\n )\n }\n }\n\n // Set collision groups if specified (for filtering what can collide with what)\n if (this.options.collisionGroups !== undefined) {\n colliderDesc.setCollisionGroups(this.options.collisionGroups)\n }\n\n // Create the physics body\n const result = PhysicsSystem.createRigidBody(this.bodyId, bodyDesc, colliderDesc)\n\n if (result) {\n this.rigidBody = result.rigidBody\n this.collider = result.collider!\n\n // Set mass for dynamic bodies\n if (this.options.type === RigidBodyType.DYNAMIC) {\n this.rigidBody.setAdditionalMass(this.options.mass!, true)\n\n // Apply damping for smoother movement\n if (this.options.linearDamping !== undefined && this.options.linearDamping > 0) {\n this.rigidBody.setLinearDamping(this.options.linearDamping)\n }\n if (this.options.angularDamping !== undefined && this.options.angularDamping > 0) {\n this.rigidBody.setAngularDamping(this.options.angularDamping)\n }\n }\n }\n }\n\n /**\n * Update syncs between GameObject and physics body based on rigidbody type\n * - DYNAMIC: Physics drives GameObject position (physics simulation)\n * - KINEMATIC: GameObject drives physics position (nav agents, scripts)\n * - STATIC: No updates needed\n */\n public update(_: number): void {\n if (!this.rigidBody) return\n\n if (this.options.type === RigidBodyType.DYNAMIC) {\n // DYNAMIC: Update GameObject position from physics body\n // Interpolate between previous and current physics states for smooth visuals\n const alpha = PhysicsSystem.getInterpolationAlpha?.() ?? 1\n\n // Current transform\n const curPos = this.rigidBody.translation()\n const curRot = this.rigidBody.rotation()\n\n // For simplicity, use body's predicted next position by integrating linear velocity\n // This gives a lightweight approximation for interpolation when alpha > 0\n const linvel = this.rigidBody.linvel()\n const angvel = this.rigidBody.angvel()\n const h = (PhysicsSystem as any).fixedTimeStep || 1 / 120\n\n const nextPos = new THREE.Vector3(\n curPos.x + linvel.x * h,\n curPos.y + linvel.y * h,\n curPos.z + linvel.z * h\n )\n\n const curQuat = new THREE.Quaternion(curRot.x, curRot.y, curRot.z, curRot.w)\n const angAxis = new THREE.Vector3(angvel.x, angvel.y, angvel.z)\n const angSpeed = angAxis.length()\n const nextQuat = curQuat.clone()\n if (angSpeed > 0.0001) {\n angAxis.normalize()\n const angle = angSpeed * h\n const deltaQ = new THREE.Quaternion().setFromAxisAngle(angAxis, angle)\n nextQuat.multiply(deltaQ).normalize()\n }\n\n // Lerp/Slerp by alpha\n const lerpPos = new THREE.Vector3(curPos.x, curPos.y, curPos.z).lerp(nextPos, alpha)\n const slerpQuat = curQuat.clone().slerp(nextQuat, alpha)\n\n // Body position equals gameObject position (offset is on the collider, not the body)\n this.gameObject.position.copy(lerpPos)\n this.gameObject.quaternion.copy(slerpQuat)\n } else if (this.options.type === RigidBodyType.KINEMATIC) {\n // KINEMATIC: Update physics body position from GameObject\n // This is for nav agents, scripted movement, etc.\n\n // Use world-space transforms so parented GameObjects sync correctly\n // Body position equals gameObject position (offset is on the collider, not the body)\n this.gameObject.updateMatrixWorld(true)\n const worldPos = this.gameObject.getWorldPosition(RigidBodyComponentThree._tempVec3)\n const worldQuat = this.gameObject.getWorldQuaternion(RigidBodyComponentThree._tempQuat)\n\n this.rigidBody.setTranslation(\n { x: worldPos.x, y: worldPos.y, z: worldPos.z },\n true\n )\n this.rigidBody.setRotation(\n {\n x: worldQuat.x,\n y: worldQuat.y,\n z: worldQuat.z,\n w: worldQuat.w,\n },\n true\n )\n }\n\n // STATIC bodies don't need updates - they never move\n }\n\n /**\n * Apply force to the rigid body\n */\n public applyForce(force: THREE.Vector3, point?: THREE.Vector3): void {\n if (!this.rigidBody || this.options.type !== RigidBodyType.DYNAMIC) return\n\n if (point) {\n this.rigidBody.addForceAtPoint(\n { x: force.x, y: force.y, z: force.z },\n { x: point.x, y: point.y, z: point.z },\n true\n )\n } else {\n this.rigidBody.addForce({ x: force.x, y: force.y, z: force.z }, true)\n }\n }\n\n /**\n * Apply impulse to the rigid body\n */\n public applyImpulse(impulse: THREE.Vector3, point?: THREE.Vector3): void {\n if (!this.rigidBody || this.options.type !== RigidBodyType.DYNAMIC) return\n\n if (point) {\n this.rigidBody.applyImpulseAtPoint(\n { x: impulse.x, y: impulse.y, z: impulse.z },\n { x: point.x, y: point.y, z: point.z },\n true\n )\n } else {\n this.rigidBody.applyImpulse({ x: impulse.x, y: impulse.y, z: impulse.z }, true)\n }\n }\n\n /**\n * Set the velocity of the rigid body\n */\n public setVelocity(velocity: THREE.Vector3): void {\n if (this.rigidBody && this.options.type === RigidBodyType.DYNAMIC) {\n this.rigidBody.setLinvel({ x: velocity.x, y: velocity.y, z: velocity.z }, true)\n }\n }\n\n /**\n * Get linear velocity into the provided output vector (zero allocation)\n */\n public getVelocity(out: THREE.Vector3): void {\n if (!this.rigidBody) {\n out.set(0, 0, 0)\n return\n }\n const vel = this.rigidBody.linvel()\n out.set(vel.x, vel.y, vel.z)\n }\n\n /**\n * Set angular velocity\n */\n public setAngularVelocity(velocity: THREE.Vector3): void {\n if (!this.rigidBody || this.options.type !== RigidBodyType.DYNAMIC) return\n\n this.rigidBody.setAngvel({ x: velocity.x, y: velocity.y, z: velocity.z }, true)\n }\n\n /**\n * Get the rigid body for advanced operations\n */\n public getRigidBody(): RigidBody | null {\n return this.rigidBody\n }\n\n /**\n * Get the collider for advanced operations\n */\n public getCollider(): Collider | null {\n return this.collider\n }\n\n /**\n * Enable/disable the rigid body\n */\n public setEnabled(enabled: boolean): void {\n if (!this.rigidBody) return\n\n this.rigidBody.setEnabled(enabled)\n // Physics body enabled/disabled\n }\n\n /**\n * Check if the rigid body is enabled\n */\n public isEnabled(): boolean {\n if (!this.rigidBody) return false\n\n return this.rigidBody.isEnabled()\n }\n\n /**\n * Get the unique body ID for this physics body\n */\n public getBodyId(): string {\n return this.bodyId\n }\n\n /**\n * Register a callback for when objects enter this trigger\n * @param callback Function to call when an object enters this trigger\n */\n public registerOnTriggerEnter(callback: (other: any) => void): void {\n this.onTriggerEnterCallback = callback\n this.ensureRegisteredWithPhysicsSystem()\n }\n\n /**\n * Register a callback for when objects exit this trigger\n * @param callback Function to call when an object exits this trigger\n */\n public registerOnTriggerExit(callback: (other: any) => void): void {\n this.onTriggerExitCallback = callback\n this.ensureRegisteredWithPhysicsSystem()\n }\n\n /**\n * Unregister trigger enter callback\n */\n public unregisterOnTriggerEnter(): void {\n this.onTriggerEnterCallback = null\n this.checkIfShouldUnregisterFromPhysics()\n }\n\n /**\n * Unregister trigger exit callback\n */\n public unregisterOnTriggerExit(): void {\n this.onTriggerExitCallback = null\n this.checkIfShouldUnregisterFromPhysics()\n }\n\n /**\n * Called by physics system when an object enters this trigger\n */\n public onTriggerEnter(other: any): void {\n if (this.onTriggerEnterCallback) {\n this.onTriggerEnterCallback(other)\n }\n }\n\n /**\n * Called by physics system when an object exits this trigger\n */\n public onTriggerExit(other: any): void {\n if (this.onTriggerExitCallback) {\n this.onTriggerExitCallback(other)\n }\n }\n\n /**\n * Ensure this RigidBody is registered with physics system if it has any trigger callbacks\n */\n private ensureRegisteredWithPhysicsSystem(): void {\n if (\n (this.onTriggerEnterCallback || this.onTriggerExitCallback) &&\n !this.isRegisteredWithPhysics\n ) {\n PhysicsSystem.registerTriggerComponent(this.bodyId, this)\n this.isRegisteredWithPhysics = true\n }\n }\n\n /**\n * Check if we should unregister from physics system (no more callbacks)\n */\n private checkIfShouldUnregisterFromPhysics(): void {\n if (\n !this.onTriggerEnterCallback &&\n !this.onTriggerExitCallback &&\n this.isRegisteredWithPhysics\n ) {\n PhysicsSystem.unregisterTriggerComponent(this.bodyId)\n this.isRegisteredWithPhysics = false\n }\n }\n\n /**\n * Create a RigidBodyComponent from bounds size\n * @param bounds The size vector from renderer.getBounds()\n * @param options Physics options (size will be overridden by bounds)\n * @returns A new RigidBodyComponentThree with bounds-fitted size\n */\n public static fromBounds(\n bounds: THREE.Vector3,\n options: Omit<RigidBodyOptions, \"fitToMesh\" | \"size\"> = {}\n ): RigidBodyComponentThree {\n return new RigidBodyComponentThree({\n ...options,\n size: bounds,\n })\n }\n\n /**\n * Get the bounding box dimensions of all meshes in a GameObject hierarchy\n * @param gameObject The GameObject to analyze\n * @returns Vector3 containing width, height, depth of the combined mesh bounds\n */\n public static getMeshBounds(gameObject: GameObject): THREE.Vector3 {\n // Fallback: calculate bounds from instantiated meshes\n const boundingBox = new THREE.Box3()\n let meshCount = 0\n\n // Force update world matrix first\n gameObject.updateMatrixWorld(true)\n\n console.log(`🔍 Analyzing mesh bounds for ${gameObject.name}...`)\n\n // Calculate bounding box for all meshes in the hierarchy\n gameObject.traverse((child: THREE.Object3D) => {\n if (child instanceof THREE.Mesh && child.geometry) {\n meshCount++\n console.log(` 📦 Found mesh: ${child.name || \"unnamed\"}`)\n\n // Ensure geometry has bounding box computed\n if (!child.geometry.boundingBox) {\n child.geometry.computeBoundingBox()\n }\n\n if (child.geometry.boundingBox) {\n // Get local bounding box size for debugging\n const localSize = new THREE.Vector3()\n child.geometry.boundingBox.getSize(localSize)\n console.log(` Local geometry size:`, localSize)\n\n // Transform bounding box to world space\n child.updateMatrixWorld(true)\n const transformedBox = child.geometry.boundingBox.clone().applyMatrix4(child.matrixWorld)\n\n // Get transformed size for debugging\n const transformedSize = new THREE.Vector3()\n transformedBox.getSize(transformedSize)\n console.log(` World transformed size:`, transformedSize)\n\n boundingBox.union(transformedBox)\n } else {\n console.warn(` No bounding box for mesh: ${child.name}`)\n }\n }\n })\n\n console.log(` 📊 Total meshes found: ${meshCount}`)\n\n // If no meshes found, return default size\n if (boundingBox.isEmpty()) {\n console.warn(`❌ No meshes found in ${gameObject.name}, using default size (2,2,2)`)\n return new THREE.Vector3(2, 2, 2) // Larger default\n }\n\n // Return the size (not the bounds)\n const size = new THREE.Vector3()\n boundingBox.getSize(size)\n\n console.log(`📏 Final calculated bounds for ${gameObject.name}:`, size)\n console.log(`📏 Bounding box min:`, boundingBox.min)\n console.log(`📏 Bounding box max:`, boundingBox.max)\n\n return size\n }\n\n /**\n * Called when GameObject becomes enabled\n */\n public onEnabled(): void {\n // Enhanced logging for debugging table physics issue\n if (\n this.gameObject.name.includes(\"Station\") ||\n this.gameObject.name.includes(\"Player\") ||\n this.gameObject.name.includes(\"Table\")\n ) {\n // Physics enabled\n }\n this.setEnabled(true)\n }\n\n public getBounds(): THREE.Box3 {\n // TODO: Handle other shapes\n // TODO: Handle MULTIPLE colliders\n const bounds = new THREE.Box3()\n if (!this.collider) return bounds\n\n const shape = this.collider.shape\n if (shape.type === ShapeType.Cuboid) {\n const cuboid = shape as Cuboid\n const halfExtents = cuboid.halfExtents\n\n // Center is at 0,0,0\n const center = new THREE.Vector3() // THREE.Vector3\n\n bounds.min.set(center.x - halfExtents.x, center.y - halfExtents.y, center.z - halfExtents.z)\n\n bounds.max.set(center.x + halfExtents.x, center.y + halfExtents.y, center.z + halfExtents.z)\n }\n\n return bounds\n }\n\n /**\n * Called when GameObject becomes disabled\n */\n public onDisabled(): void {\n // Enhanced logging for debugging table physics issue\n if (\n this.gameObject.name.includes(\"Station\") ||\n this.gameObject.name.includes(\"Player\") ||\n this.gameObject.name.includes(\"Table\")\n ) {\n // Physics disabled\n }\n this.setEnabled(false)\n }\n\n protected onCleanup(): void {\n if (this.bodyId) {\n // Always unregister GameObject mapping\n PhysicsSystem.unregisterGameObject(this.bodyId)\n\n // Unregister trigger callbacks\n this.unregisterOnTriggerEnter()\n this.unregisterOnTriggerExit()\n\n // Reset registration flag\n this.isRegisteredWithPhysics = false\n\n PhysicsSystem.removeRigidBody(this.bodyId)\n }\n\n this.rigidBody = null\n this.collider = null\n }\n}\n","import type { Component } from \"../../engine/core/GameObject\"\nimport type { PrefabNode } from \"./PrefabNode\"\n\nexport type ComponentJSON = Record<string, unknown> & { type: string }\n\nexport interface PrefabComponentFactory {\n fromPrefabJSON(json: ComponentJSON, node: PrefabNode): Component | null\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type PrefabComponentConstructor = (new (...args: any[]) => Component) &\n PrefabComponentFactory\n\nclass ComponentRegistryImpl {\n private registry = new Map<string, PrefabComponentConstructor>()\n\n register(typeName: string, componentClass: PrefabComponentConstructor): void {\n if (this.registry.has(typeName)) {\n console.warn(`Component type \"${typeName}\" is already registered. Overwriting.`)\n }\n this.registry.set(typeName, componentClass)\n }\n\n get(typeName: string): PrefabComponentConstructor | undefined {\n return this.registry.get(typeName)\n }\n\n has(typeName: string): boolean {\n return this.registry.has(typeName)\n }\n\n getRegisteredTypes(): string[] {\n return Array.from(this.registry.keys())\n }\n}\n\nexport const ComponentRegistry = new ComponentRegistryImpl()\n","import { ComponentRegistry, type PrefabComponentConstructor } from \"./ComponentRegistry\"\n\nexport function PrefabComponent(typeName: string) {\n return function <T extends PrefabComponentConstructor>(target: T): T {\n ComponentRegistry.register(typeName, target)\n return target\n }\n}\n","export interface PrefabCollectionJSON {\n prefabs: PrefabJSON[]\n}\n\nexport interface PrefabJSON {\n schema: string\n version: number\n meta: {\n name: string\n created: string\n }\n mounts: PrefabMountJSON[]\n root: PrefabNodeJSON\n}\n\nexport interface PrefabMountJSON {\n alias: string\n path: string\n}\n\nexport interface TransformComponentJSON {\n type: \"transform\"\n position: number[]\n rotation: number[]\n scale: number[]\n [key: string]: unknown\n}\n\nexport interface PrefabComponentJSON {\n type: string\n [key: string]: unknown\n}\n\nexport interface PrefabNodeJSON {\n name: string\n components?: PrefabComponentJSON[]\n children?: PrefabNodeJSON[]\n}\n\nexport function isTransformComponent(c: PrefabComponentJSON): c is TransformComponentJSON {\n return c.type === \"transform\"\n}\n","import * as THREE from \"three\"\nimport type { PrefabNodeJSON, PrefabComponentJSON, TransformComponentJSON } from \"./types\"\nimport { isTransformComponent } from \"./types\"\n\nexport class PrefabNode {\n public static createFromJSON(json: PrefabNodeJSON): PrefabNode {\n const name = json.name\n\n let transform: TransformComponentJSON | null = null\n const components: PrefabComponentJSON[] = []\n\n if (json.components) {\n for (const component of json.components) {\n if (isTransformComponent(component)) {\n transform = component\n } else {\n components.push(component)\n }\n }\n }\n\n if (!transform) {\n throw new Error(`PrefabNode \"${name}\" is missing a transform component`)\n }\n\n const children: PrefabNode[] = []\n if (json.children) {\n for (const childJSON of json.children) {\n children.push(PrefabNode.createFromJSON(childJSON))\n }\n }\n\n return new PrefabNode(name, transform, components, children)\n }\n\n private readonly _name: string\n private readonly _transform: TransformComponentJSON\n private readonly _components: PrefabComponentJSON[]\n private readonly _children: PrefabNode[]\n private readonly _childByNameLookup: Map<string, PrefabNode> = new Map()\n private readonly _nodeByPathLookup: Map<string, PrefabNode> = new Map()\n\n constructor(\n name: string,\n transform: TransformComponentJSON,\n components: PrefabComponentJSON[],\n children: PrefabNode[]\n ) {\n this._name = name\n this._transform = transform\n this._components = components\n this._children = children\n\n for (const child of children) {\n this._childByNameLookup.set(child.name, child)\n this.mapDescendant(child, `/${child.name}`)\n }\n }\n\n public get name(): string {\n return this._name\n }\n\n public get id(): string {\n return this._name\n }\n\n public get transform(): TransformComponentJSON {\n return this._transform\n }\n\n public get components(): ReadonlyArray<PrefabComponentJSON> {\n return this._components\n }\n\n public get children(): ReadonlyArray<PrefabNode> {\n return this._children\n }\n\n public get position(): THREE.Vector3 {\n return new THREE.Vector3(\n this._transform.position[0],\n this._transform.position[1],\n this._transform.position[2]\n )\n }\n\n public get rotation(): THREE.Euler {\n return new THREE.Euler(\n (this._transform.rotation[0] * Math.PI) / 180,\n (this._transform.rotation[1] * Math.PI) / 180,\n (this._transform.rotation[2] * Math.PI) / 180\n )\n }\n\n public get scale(): THREE.Vector3 {\n return new THREE.Vector3(\n this._transform.scale[0],\n this._transform.scale[1],\n this._transform.scale[2]\n )\n }\n\n public getChildByName(name: string): PrefabNode | undefined {\n return this._childByNameLookup.get(name)\n }\n\n public getNodeByPath(path: string): PrefabNode | undefined {\n if (!path.startsWith(\"/\")) path = `/${path}`\n return this._nodeByPathLookup.get(path)\n }\n\n public get descendants(): MapIterator<[string, PrefabNode]> {\n return this._nodeByPathLookup.entries()\n }\n\n public depthFirstSearchForNode(nodeName: string): PrefabNode | undefined {\n for (const child of this._children) {\n if (child.name === nodeName) return child\n const found = child.depthFirstSearchForNode(nodeName)\n if (found) return found\n }\n return undefined\n }\n\n public getComponentData<T extends PrefabComponentJSON>(type: string): T | undefined {\n return this._components.find((c) => c.type === type) as T | undefined\n }\n\n public applyTransformTo(object: THREE.Object3D): void {\n object.position.copy(this.position)\n object.rotation.copy(this.rotation)\n object.scale.copy(this.scale)\n }\n\n private mapDescendant(node: PrefabNode, path: string): void {\n this._nodeByPathLookup.set(path, node)\n for (const child of node.children) {\n this.mapDescendant(child, `${path}/${child.name}`)\n }\n }\n}\n","import type { PrefabJSON } from \"./types\"\nimport { PrefabNode } from \"./PrefabNode\"\n\nexport class Prefab {\n public static createFromJSON(json: PrefabJSON): Prefab {\n const name = json.meta.name\n const root = PrefabNode.createFromJSON(json.root)\n return new Prefab(name, root, json.mounts)\n }\n\n private readonly _name: string\n private readonly _root: PrefabNode\n private readonly _mounts: { alias: string; path: string }[]\n\n constructor(name: string, root: PrefabNode, mounts: { alias: string; path: string }[]) {\n this._name = name\n this._root = root\n this._mounts = mounts\n }\n\n public get name(): string {\n return this._name\n }\n\n public get root(): PrefabNode {\n return this._root\n }\n\n public get mounts(): ReadonlyArray<{ alias: string; path: string }> {\n return this._mounts\n }\n\n public getNodeByPath(path: string): PrefabNode | undefined {\n return this._root.getNodeByPath(path)\n }\n}\n","import type { PrefabCollectionJSON } from \"./types\"\nimport { Prefab } from \"./Prefab\"\nimport { PrefabNode } from \"./PrefabNode\"\n\nexport class PrefabCollection {\n public static createFromJSON(json: PrefabCollectionJSON): PrefabCollection {\n const prefabs = json.prefabs.map((p) => Prefab.createFromJSON(p))\n return new PrefabCollection(prefabs)\n }\n\n private readonly _prefabsByName = new Map<string, Prefab>()\n\n constructor(prefabs: Iterable<Prefab>) {\n for (const prefab of prefabs) {\n this._prefabsByName.set(prefab.name, prefab)\n }\n }\n\n public get prefabs(): IterableIterator<Prefab> {\n return this._prefabsByName.values()\n }\n\n public getPrefabByName(name: string): Prefab | undefined {\n return this._prefabsByName.get(name)\n }\n\n public getAllComponentTypes(): Set<string> {\n const types = new Set<string>()\n this.traverseNodes((node) => {\n for (const component of node.components) {\n types.add(component.type)\n }\n })\n return types\n }\n\n /**\n * Get all unique mounts from all prefabs in the collection.\n * Mounts define StowKit pack aliases and CDN paths.\n * @returns Array of mount points with alias and path\n */\n public getMounts(): Array<{ alias: string; path: string }> {\n const mountsByAlias = new Map<string, { alias: string; path: string }>()\n\n for (const prefab of this.prefabs) {\n for (const mount of prefab.mounts) {\n // Use alias as key to deduplicate\n if (!mountsByAlias.has(mount.alias)) {\n mountsByAlias.set(mount.alias, { alias: mount.alias, path: mount.path })\n }\n }\n }\n\n return Array.from(mountsByAlias.values())\n }\n\n private traverseNodes(callback: (node: PrefabNode) => void): void {\n for (const prefab of this.prefabs) {\n const root = prefab.root\n callback(root)\n for (const [, descendant] of root.descendants) {\n callback(descendant)\n }\n }\n }\n}\n","import * as THREE from \"three\"\nimport { GameObject, Component } from \"../../engine/core/GameObject\"\nimport { PrefabNode } from \"./PrefabNode\"\nimport { ComponentRegistry, type ComponentJSON } from \"./ComponentRegistry\"\n\n/**\n * Options for prefab instantiation\n */\nexport interface PrefabInstantiateOptions {\n /** Whether meshes should cast shadows (default: true) */\n castShadow?: boolean\n /** Whether meshes should receive shadows (default: true) */\n receiveShadow?: boolean\n}\n\nexport class PrefabInstance {\n /**\n * Current instantiation options - used by components during creation\n * Components like MeshRenderer can read this to apply shadow settings\n */\n public static currentOptions: PrefabInstantiateOptions | null = null\n\n public static instantiate(\n prefabNode: PrefabNode,\n parent: GameObject | null = null,\n options?: PrefabInstantiateOptions\n ): PrefabInstance {\n // Set options context for components to read during creation\n const isRootCall = PrefabInstance.currentOptions === null\n if (isRootCall && options) {\n PrefabInstance.currentOptions = options\n }\n\n const gameObject = new GameObject(prefabNode.name)\n prefabNode.applyTransformTo(gameObject)\n\n if (parent) {\n parent.add(gameObject)\n }\n\n const components: Component[] = []\n\n for (const componentJSON of prefabNode.components) {\n const component = PrefabInstance.createComponent(componentJSON, prefabNode)\n if (component) {\n gameObject.addComponent(component)\n components.push(component)\n }\n }\n\n const children: PrefabInstance[] = []\n for (const childNode of prefabNode.children) {\n const childInstance = PrefabInstance.instantiate(childNode, gameObject, options)\n children.push(childInstance)\n }\n\n const instance = new PrefabInstance(prefabNode, gameObject, components, children)\n\n // NOTE: Shadow settings are now applied per-mesh by MeshRenderer using JSON properties.\n // The applyShadowOptions() call was removed because it overwrote per-mesh settings.\n // Use instantiate options only as a fallback when JSON doesn't specify shadow settings.\n\n // Clear options context when root call completes\n if (isRootCall) {\n PrefabInstance.currentOptions = null\n }\n\n return instance\n }\n\n /**\n * Apply shadow options to all meshes in the prefab tree.\n * Call this after meshes have loaded if shadows aren't being applied correctly.\n */\n public setShadows(castShadow: boolean, receiveShadow?: boolean): void {\n this._gameObject.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n child.castShadow = castShadow\n if (receiveShadow !== undefined) {\n child.receiveShadow = receiveShadow\n }\n }\n })\n }\n\n private applyShadowOptions(options: PrefabInstantiateOptions): void {\n this._gameObject.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n if (options.castShadow !== undefined) {\n child.castShadow = options.castShadow\n }\n if (options.receiveShadow !== undefined) {\n child.receiveShadow = options.receiveShadow\n }\n }\n })\n }\n\n private static createComponent(componentJSON: ComponentJSON, node: PrefabNode): Component | null {\n const factory = ComponentRegistry.get(componentJSON.type)\n if (!factory) {\n console.warn(`Unknown component type: \"${componentJSON.type}\" - skipping`)\n return null\n }\n\n try {\n return factory.fromPrefabJSON(componentJSON, node)\n } catch (error) {\n console.error(`Failed to create component \"${componentJSON.type}\":`, error)\n return null\n }\n }\n\n private readonly _prefabNode: PrefabNode\n private readonly _gameObject: GameObject\n private readonly _components: Component[]\n private readonly _childrenByName: Map<string, PrefabInstance> = new Map()\n private readonly _descendantsByPath: Map<string, PrefabInstance> = new Map()\n\n constructor(\n prefabNode: PrefabNode,\n gameObject: GameObject,\n components: Component[],\n children: PrefabInstance[]\n ) {\n this._prefabNode = prefabNode\n this._gameObject = gameObject\n this._components = components\n\n for (const child of children) {\n this._childrenByName.set(child.name, child)\n this._descendantsByPath.set(`/${child.name}`, child)\n for (const [path, descendant] of child.descendants) {\n this._descendantsByPath.set(`/${child.name}${path}`, descendant)\n }\n }\n }\n\n public get name(): string {\n return this._prefabNode.name\n }\n\n public get gameObject(): GameObject {\n return this._gameObject\n }\n\n public get prefabNode(): PrefabNode {\n return this._prefabNode\n }\n\n public get components(): ReadonlyArray<Component> {\n return this._components\n }\n\n public get children(): ReadonlyArray<PrefabInstance> {\n return Array.from(this._childrenByName.values())\n }\n\n public get descendants(): MapIterator<[string, PrefabInstance]> {\n return this._descendantsByPath.entries()\n }\n\n public getComponent<T extends Component>(\n componentType: new (...args: any[]) => T\n ): T | undefined {\n return this._gameObject.getComponent(componentType)\n }\n\n public getChildByName(name: string): PrefabInstance | undefined {\n return this._childrenByName.get(name)\n }\n\n public getDescendantByPath(path: string): PrefabInstance | undefined {\n if (!path.startsWith(\"/\")) path = `/${path}`\n return this._descendantsByPath.get(path)\n }\n\n public getDescendantByPathOrThrow(path: string): PrefabInstance {\n const instance = this.getDescendantByPath(path)\n if (!instance) throw new Error(`Prefab descendant not found at path: ${path}`)\n return instance\n }\n\n public dispose(): void {\n this._gameObject.dispose()\n }\n}\n","import type { PrefabCollectionJSON } from \"./types\"\nimport { PrefabCollection } from \"./PrefabCollection\"\nimport { Prefab } from \"./Prefab\"\nimport { PrefabNode } from \"./PrefabNode\"\nimport { PrefabInstance, type PrefabInstantiateOptions } from \"./PrefabInstance\"\nimport { ComponentRegistry } from \"./ComponentRegistry\"\nimport type { GameObject } from \"../../engine/core/GameObject\"\n\nexport class PrefabLoader {\n public static loadCollection(json: PrefabCollectionJSON): PrefabCollection {\n return PrefabCollection.createFromJSON(json)\n }\n\n public static instantiate(\n prefabNode: PrefabNode,\n parent: GameObject | null = null,\n options?: PrefabInstantiateOptions\n ): PrefabInstance {\n return PrefabInstance.instantiate(prefabNode, parent, options)\n }\n\n public static instantiatePrefab(\n prefab: Prefab,\n parent: GameObject | null = null,\n options?: PrefabInstantiateOptions\n ): PrefabInstance {\n return PrefabInstance.instantiate(prefab.root, parent, options)\n }\n\n public static validateCollection(collection: PrefabCollection): string[] {\n const missingTypes: string[] = []\n const allTypes = collection.getAllComponentTypes()\n\n for (const type of allTypes) {\n if (type !== \"transform\" && !ComponentRegistry.has(type)) {\n missingTypes.push(type)\n }\n }\n\n return missingTypes\n }\n\n public static getRegisteredComponentTypes(): string[] {\n return ComponentRegistry.getRegisteredTypes()\n }\n}\n","import type { StowKitPack } from \"@series-inc/stowkit-three-loader\"\nimport { StowKitLoader } from \"@series-inc/stowkit-three-loader\"\nimport { PerfLogger } from \"@series-inc/stowkit-reader\"\nimport * as THREE from \"three\"\nimport { AudioSystem } from \"@systems/audio\"\nimport { InstancedMeshManager } from \"@engine/render/InstancedMeshManager\"\nimport { PrefabCollection, PrefabNode } from \"@systems/prefabs\"\n\n/**\n * Configuration for loading from build.json.\n */\nexport interface StowKitLoadConfig {\n /**\n * Material converter function - called when cloning meshes.\n * Game provides this to apply custom materials (e.g., toon shaders).\n * If not provided, materials are used as-is.\n */\n materialConverter?: (material: THREE.Material) => THREE.Material\n\n /**\n * Function to fetch blob data from CDN.\n * Required for loading packs from mount paths.\n */\n fetchBlob: (path: string) => Promise<Blob>\n\n /**\n * Decoder paths for StowKit loaders.\n */\n decoderPaths?: {\n basis?: string // default: \"basis/\"\n draco?: string // default: \"stowkit/draco/\"\n wasm?: string // default: \"stowkit_reader.wasm\"\n }\n}\n\nconst DEFAULT_DECODER_PATHS = {\n basis: \"basis/\",\n draco: \"stowkit/draco/\",\n wasm: \"stowkit_reader.wasm\",\n}\n\n/**\n * StowKitSystem - Simple asset loading from build.json.\n *\n * Usage:\n * ```typescript\n * // Load everything from build.json - that's it!\n * const prefabs = await StowKitSystem.getInstance().loadFromBuildJson(buildJson, {\n * materialConverter: (mat) => MaterialUtils.convertToToon(mat),\n * fetchBlob: (path) => Platform.cdn.fetchBlob(path)\n * })\n *\n * // Register instancing batches (optional, for frequently spawned items)\n * await StowKitSystem.getInstance().registerMeshForInstancing(\"burger\", \"restaurant_display_Burger\", 100)\n *\n * // Use prefabs - meshes load automatically\n * const burgerStation = PrefabLoader.instantiate(prefabs.getPrefabByName(\"burger_station\"))\n * ```\n */\nexport class StowKitSystem {\n private static _instance: StowKitSystem | null = null\n\n // Configuration\n private materialConverter?: (material: THREE.Material) => THREE.Material\n private decoderPaths = { ...DEFAULT_DECODER_PATHS }\n private fetchBlob?: (path: string) => Promise<Blob>\n\n // Loaded packs by alias\n private packs: Map<string, StowKitPack> = new Map()\n\n // Asset caches\n private meshes: Map<string, THREE.Group> = new Map()\n private textures: Map<string, THREE.Texture> = new Map()\n private animations: Map<string, THREE.AnimationClip> = new Map()\n private audioFiles: Map<string, THREE.Audio> = new Map()\n\n // Prefab collection\n private _prefabCollection: PrefabCollection | null = null\n\n // Loading state\n private loadMeshPromises: Map<string, Promise<THREE.Group>> = new Map()\n private loadTexturePromises: Map<string, Promise<THREE.Texture>> = new Map()\n private loadAudioPromises: Map<string, Promise<THREE.Audio>> = new Map()\n private loadAnimationPromises: Map<string, Promise<THREE.AnimationClip>> = new Map()\n\n private constructor() {}\n\n public static getInstance(): StowKitSystem {\n if (!StowKitSystem._instance) {\n StowKitSystem._instance = new StowKitSystem()\n }\n return StowKitSystem._instance\n }\n\n /**\n * Get the material converter function (if configured).\n */\n public getMaterialConverter(): ((material: THREE.Material) => THREE.Material) | undefined {\n return this.materialConverter\n }\n\n // ============================================\n // Main Loading API\n // ============================================\n\n /**\n * Load everything from build.json.\n * This is the main entry point - loads prefab collection and all packs from mounts.\n *\n * @param buildJson The build.json content (import directly or fetch)\n * @param config Configuration including material converter and CDN fetch function\n * @returns The loaded PrefabCollection\n */\n public async loadFromBuildJson(\n buildJson: unknown,\n config: StowKitLoadConfig\n ): Promise<PrefabCollection> {\n // Store config\n this.materialConverter = config.materialConverter\n this.fetchBlob = config.fetchBlob\n if (config.decoderPaths) {\n this.decoderPaths = { ...DEFAULT_DECODER_PATHS, ...config.decoderPaths }\n }\n\n // Load prefab collection\n const prefabCollection = PrefabCollection.createFromJSON(\n buildJson as Parameters<typeof PrefabCollection.createFromJSON>[0]\n )\n this._prefabCollection = prefabCollection\n\n // Load all packs from mounts\n const mounts = prefabCollection.getMounts()\n console.log(`[StowKitSystem] Loading ${mounts.length} packs from mounts...`)\n\n PerfLogger.disable()\n\n for (const mount of mounts) {\n if (this.packs.has(mount.alias)) {\n continue // Already loaded\n }\n\n console.log(`[StowKitSystem] Loading pack \"${mount.alias}\" from ${mount.path}`)\n const blob = await config.fetchBlob(mount.path)\n const arrayBuffer = await blob.arrayBuffer()\n\n const pack = await StowKitLoader.loadFromMemory(arrayBuffer, {\n basisPath: this.decoderPaths.basis,\n dracoPath: this.decoderPaths.draco,\n wasmPath: this.decoderPaths.wasm,\n })\n\n this.packs.set(mount.alias, pack)\n }\n\n console.log(`[StowKitSystem] All packs loaded`)\n return prefabCollection\n }\n\n /**\n * Load an additional pack by path.\n * Use this for packs not referenced in prefab mounts (e.g., character packs).\n *\n * @param alias Unique alias for this pack\n * @param path CDN path to the .stow file\n */\n public async loadPack(alias: string, path: string): Promise<void> {\n if (this.packs.has(alias)) {\n console.log(`[StowKitSystem] Pack \"${alias}\" already loaded, skipping`)\n return\n }\n\n if (!this.fetchBlob) {\n throw new Error(\"StowKitSystem: fetchBlob not configured. Call loadFromBuildJson first.\")\n }\n\n console.log(`[StowKitSystem] Loading pack \"${alias}\" from ${path}`)\n const blob = await this.fetchBlob(path)\n const arrayBuffer = await blob.arrayBuffer()\n\n const pack = await StowKitLoader.loadFromMemory(arrayBuffer, {\n basisPath: this.decoderPaths.basis,\n dracoPath: this.decoderPaths.draco,\n wasmPath: this.decoderPaths.wasm,\n })\n\n this.packs.set(alias, pack)\n console.log(`[StowKitSystem] Pack \"${alias}\" loaded`)\n }\n\n /**\n * Get the prefab collection.\n */\n public getPrefabCollection(): PrefabCollection {\n if (!this._prefabCollection) {\n throw new Error(\"StowKitSystem: Not loaded. Call loadFromBuildJson() first.\")\n }\n return this._prefabCollection\n }\n\n /**\n * Get a prefab node by path from the \"restaurant\" prefab.\n * Convenience method for game code.\n */\n public getPrefab(path: string): PrefabNode {\n const collection = this.getPrefabCollection()\n const restaurantPrefab = collection.getPrefabByName(\"restaurant\")\n if (!restaurantPrefab) {\n throw new Error(\"StowKitSystem: Restaurant prefab not found\")\n }\n\n const prefab = restaurantPrefab.getNodeByPath(path)\n if (prefab == null) {\n throw new Error(`StowKitSystem: Prefab not found: ${path}`)\n }\n return prefab\n }\n\n // ============================================\n // Pack Access\n // ============================================\n\n /**\n * Get a loaded pack by alias.\n */\n public getPack(alias: string): StowKitPack | null {\n return this.packs.get(alias) ?? null\n }\n\n /**\n * Check if a pack is loaded.\n */\n public isPackLoaded(alias: string): boolean {\n return this.packs.has(alias)\n }\n\n // ============================================\n // Mesh Access (On-Demand Loading)\n // ============================================\n\n /**\n * Get a mesh by name. Loads on-demand if not cached.\n * For synchronous access, use getMeshSync() after ensuring it's loaded.\n */\n public async getMesh(name: string): Promise<THREE.Group> {\n // Return cached\n const cached = this.meshes.get(name)\n if (cached) return cached\n\n // Check in-flight\n const existing = this.loadMeshPromises.get(name)\n if (existing) return existing\n\n // Load from packs\n const promise = this.loadMeshFromPacks(name)\n this.loadMeshPromises.set(name, promise)\n\n try {\n const mesh = await promise\n this.meshes.set(name, mesh)\n return mesh\n } finally {\n this.loadMeshPromises.delete(name)\n }\n }\n\n /**\n * Get a mesh synchronously. Returns null if not loaded yet.\n */\n public getMeshSync(name: string): THREE.Group | null {\n return this.meshes.get(name) ?? null\n }\n\n /**\n * Check if a mesh is loaded.\n */\n public isMeshLoaded(name: string): boolean {\n return this.meshes.has(name)\n }\n\n private async loadMeshFromPacks(name: string): Promise<THREE.Group> {\n for (const [, pack] of this.packs) {\n try {\n const mesh = await pack.loadMesh(name)\n this.fixTextureWrapping(mesh)\n return mesh\n } catch {\n // Try next pack\n }\n }\n throw new Error(`StowKitSystem: Mesh \"${name}\" not found in any pack`)\n }\n\n /**\n * Load a skinned mesh (for characters).\n */\n public async getSkinnedMesh(name: string, scale: number = 1): Promise<THREE.Group> {\n // Return cached\n const cached = this.meshes.get(name)\n if (cached) return cached\n\n // Check in-flight\n const existing = this.loadMeshPromises.get(name)\n if (existing) return existing\n\n // Load from packs\n const promise = this.loadSkinnedMeshFromPacks(name, scale)\n this.loadMeshPromises.set(name, promise)\n\n try {\n const mesh = await promise\n this.meshes.set(name, mesh)\n return mesh\n } finally {\n this.loadMeshPromises.delete(name)\n }\n }\n\n private async loadSkinnedMeshFromPacks(name: string, scale: number): Promise<THREE.Group> {\n for (const [, pack] of this.packs) {\n try {\n const mesh = await pack.loadSkinnedMesh(name)\n if (scale !== 1) {\n mesh.scale.setScalar(scale)\n mesh.updateMatrixWorld(true)\n }\n\n this.fixTextureWrapping(mesh)\n\n // Apply material converter to skinned meshes (same as regular meshes)\n if (this.materialConverter) {\n mesh.traverse((child) => {\n if ((child as THREE.Mesh).isMesh) {\n const meshChild = child as THREE.Mesh\n if (Array.isArray(meshChild.material)) {\n meshChild.material = meshChild.material.map((m) => this.materialConverter!(m))\n } else if (meshChild.material) {\n meshChild.material = this.materialConverter!(meshChild.material)\n }\n }\n })\n }\n\n return mesh\n } catch {\n // Try next pack\n }\n }\n throw new Error(`StowKitSystem: Skinned mesh \"${name}\" not found in any pack`)\n }\n\n /**\n * Clone a mesh with material conversion and shadow settings.\n */\n public async cloneMesh(\n meshName: string,\n castShadow: boolean = true,\n receiveShadow: boolean = true\n ): Promise<THREE.Group> {\n const original = await this.getMesh(meshName)\n return this.cloneMeshSync(original, castShadow, receiveShadow)\n }\n\n /**\n * Clone an already-loaded mesh synchronously.\n */\n public cloneMeshSync(\n original: THREE.Group,\n castShadow: boolean = true,\n receiveShadow: boolean = true\n ): THREE.Group {\n const cloned = original.clone()\n\n cloned.traverse((child) => {\n if ((child as THREE.Mesh).isMesh) {\n const mesh = child as THREE.Mesh\n\n // Apply material conversion if configured\n if (this.materialConverter) {\n const originalMaterial = mesh.material as THREE.Material\n if (originalMaterial) {\n mesh.material = this.materialConverter(originalMaterial)\n }\n }\n\n mesh.castShadow = castShadow\n mesh.receiveShadow = receiveShadow\n }\n })\n\n return cloned\n }\n\n // ============================================\n // Texture Access (On-Demand Loading)\n // ============================================\n\n /**\n * Get a texture by name. Loads on-demand if not cached.\n */\n public async getTexture(name: string): Promise<THREE.Texture> {\n // Return cached\n const cached = this.textures.get(name)\n if (cached) return cached\n\n // Check in-flight\n const existing = this.loadTexturePromises.get(name)\n if (existing) return existing\n\n // Load from packs\n const promise = this.loadTextureFromPacks(name)\n this.loadTexturePromises.set(name, promise)\n\n try {\n const texture = await promise\n this.textures.set(name, texture)\n return texture\n } finally {\n this.loadTexturePromises.delete(name)\n }\n }\n\n /**\n * Get a texture synchronously. Returns null if not loaded yet.\n */\n public getTextureSync(name: string): THREE.Texture | null {\n return this.textures.get(name) ?? null\n }\n\n private async loadTextureFromPacks(name: string): Promise<THREE.Texture> {\n for (const [, pack] of this.packs) {\n try {\n const tex = await pack.loadTexture(name)\n // colorSpace is set by stowkit-three-loader (sRGB for color textures, linear for data)\n tex.anisotropy = 8\n tex.wrapS = THREE.RepeatWrapping\n tex.wrapT = THREE.RepeatWrapping\n return tex\n } catch {\n // Try next pack\n }\n }\n throw new Error(`StowKitSystem: Texture \"${name}\" not found in any pack`)\n }\n\n // ============================================\n // Animation Access (On-Demand Loading)\n // ============================================\n\n /**\n * Get an animation by name. Loads on-demand if not cached.\n * @param name Animation name\n * @param meshName Mesh to load animation with (required for first load)\n */\n public async getAnimation(name: string, meshName?: string): Promise<THREE.AnimationClip> {\n // Return cached\n const cached = this.animations.get(name)\n if (cached) return cached\n\n // Check in-flight\n const existing = this.loadAnimationPromises.get(name)\n if (existing) return existing\n\n if (!meshName) {\n throw new Error(`StowKitSystem: Animation \"${name}\" not loaded. Provide meshName to load it.`)\n }\n\n // Load\n const promise = this.loadAnimationFromPacks(name, meshName)\n this.loadAnimationPromises.set(name, promise)\n\n try {\n const clip = await promise\n this.animations.set(name, clip)\n return clip\n } finally {\n this.loadAnimationPromises.delete(name)\n }\n }\n\n /**\n * Get an animation synchronously. Returns null if not loaded yet.\n */\n public getAnimationSync(name: string): THREE.AnimationClip | null {\n return this.animations.get(name) ?? null\n }\n\n /**\n * Get all loaded animations.\n */\n public getAllAnimations(): Map<string, THREE.AnimationClip> {\n return this.animations\n }\n\n private async loadAnimationFromPacks(\n name: string,\n meshName: string\n ): Promise<THREE.AnimationClip> {\n const mesh = await this.getMesh(meshName)\n\n for (const [, pack] of this.packs) {\n try {\n const { clip } = await pack.loadAnimation(mesh, name)\n return clip\n } catch {\n // Try next pack\n }\n }\n throw new Error(`StowKitSystem: Animation \"${name}\" not found in any pack`)\n }\n\n // ============================================\n // Audio Access (On-Demand Loading)\n // ============================================\n\n /**\n * Get audio by name. Loads on-demand if not cached.\n */\n public async getAudio(name: string): Promise<THREE.Audio> {\n // Return cached\n const cached = this.audioFiles.get(name)\n if (cached) return cached\n\n // Check in-flight\n const existing = this.loadAudioPromises.get(name)\n if (existing) return existing\n\n // Load from packs\n const promise = this.loadAudioFromPacks(name)\n this.loadAudioPromises.set(name, promise)\n\n try {\n const audio = await promise\n this.audioFiles.set(name, audio)\n return audio\n } finally {\n this.loadAudioPromises.delete(name)\n }\n }\n\n /**\n * Get audio synchronously. Returns null if not loaded yet.\n */\n public getAudioSync(name: string): THREE.Audio | null {\n return this.audioFiles.get(name) ?? null\n }\n\n /**\n * Get all loaded audio.\n */\n public getAllAudio(): Map<string, THREE.Audio> {\n return this.audioFiles\n }\n\n private async loadAudioFromPacks(name: string): Promise<THREE.Audio> {\n const audioListener = AudioSystem.mainListener\n if (!audioListener) {\n throw new Error(\"StowKitSystem: AudioSystem.mainListener not set\")\n }\n\n for (const [, pack] of this.packs) {\n try {\n return await pack.loadAudio(name, audioListener)\n } catch {\n // Try next pack\n }\n }\n throw new Error(`StowKitSystem: Audio \"${name}\" not found in any pack`)\n }\n\n // ============================================\n // GPU Instancing\n // ============================================\n\n /**\n * Register a mesh for GPU instancing.\n * Batch auto-grows as needed, so initialCapacity is optional.\n */\n public async registerMeshForInstancing(\n batchKey: string,\n meshName: string,\n castShadow: boolean = false,\n receiveShadow: boolean = false,\n initialCapacity: number = 16\n ): Promise<boolean> {\n const meshGroup = await this.getMesh(meshName)\n\n // Extract geometry\n const geometry = this.extractGeometry(meshGroup)\n if (!geometry) {\n console.error(`StowKitSystem: Could not extract geometry from \"${meshName}\"`)\n return false\n }\n\n // Create material with converter applied\n const material = this.createMaterial(meshGroup)\n if (!material) {\n console.error(`StowKitSystem: Could not create material for \"${meshName}\"`)\n return false\n }\n\n // Register batch\n const manager = InstancedMeshManager.getInstance()\n const batch = manager.getOrCreateBatch(\n batchKey,\n geometry,\n material,\n castShadow,\n receiveShadow,\n initialCapacity\n )\n\n if (!batch) {\n console.error(`StowKitSystem: Failed to create batch \"${batchKey}\"`)\n return false\n }\n\n return true\n }\n\n /**\n * Register a batch for GPU instancing from a prefab.\n * Extracts the mesh name from the prefab's stow_mesh component.\n * Batch auto-grows as needed, so initialCapacity is optional.\n */\n public async registerBatchFromPrefab(\n prefabName: string,\n castShadow: boolean = false,\n receiveShadow: boolean = false,\n initialCapacity: number = 16\n ): Promise<boolean> {\n const prefabCollection = this.getPrefabCollection()\n const prefab = prefabCollection.getPrefabByName(prefabName)\n\n if (!prefab) {\n console.error(`[StowKitSystem] Prefab \"${prefabName}\" not found`)\n return false\n }\n\n // Find the stow_mesh component in the prefab root\n const stowMeshComponent = prefab.root.components.find(\n (c: { type: string }) => c.type === \"stow_mesh\"\n ) as { type: string; mesh?: { pack?: string; assetId?: string } } | undefined\n\n if (!stowMeshComponent?.mesh?.assetId) {\n console.error(\n `[StowKitSystem] Prefab \"${prefabName}\" has no stow_mesh component with mesh.assetId`\n )\n return false\n }\n\n const meshName = stowMeshComponent.mesh.assetId\n return this.registerMeshForInstancing(\n prefabName,\n meshName,\n castShadow,\n receiveShadow,\n initialCapacity\n )\n }\n\n private extractGeometry(meshGroup: THREE.Group): THREE.BufferGeometry | null {\n let geometry: THREE.BufferGeometry | null = null\n\n meshGroup.traverse((child) => {\n if (!geometry && (child as THREE.Mesh).isMesh) {\n const mesh = child as THREE.Mesh\n if (mesh.geometry) {\n geometry = mesh.geometry\n }\n }\n })\n\n return geometry\n }\n\n private createMaterial(meshGroup: THREE.Group): THREE.Material | null {\n let material: THREE.Material | null = null\n\n meshGroup.traverse((child) => {\n if (!material && (child as THREE.Mesh).isMesh) {\n const mesh = child as THREE.Mesh\n const originalMaterial = mesh.material as THREE.Material\n\n if (originalMaterial) {\n if (this.materialConverter) {\n material = this.materialConverter(originalMaterial)\n } else {\n material = originalMaterial.clone()\n }\n }\n }\n })\n\n return material\n }\n\n // ============================================\n // Utilities\n // ============================================\n\n /**\n * Fix texture wrapping on all materials in a mesh group.\n * stowkit-three-loader doesn't set wrapS/wrapT, so Three.js defaults to\n * ClampToEdgeWrapping. Game assets expect RepeatWrapping.\n */\n private fixTextureWrapping(group: THREE.Group): void {\n group.traverse((child) => {\n if (!(child as THREE.Mesh).isMesh) return\n const mesh = child as THREE.Mesh\n const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material]\n for (const mat of materials) {\n if (!mat) continue\n const m = mat as any\n // Cover all standard texture slots\n const slots = [\"map\", \"normalMap\", \"roughnessMap\", \"metalnessMap\", \"aoMap\", \"emissiveMap\", \"alphaMap\", \"bumpMap\", \"displacementMap\", \"envMap\", \"lightMap\"]\n for (const slot of slots) {\n const tex = m[slot] as THREE.Texture | undefined\n if (tex) {\n tex.wrapS = THREE.RepeatWrapping\n tex.wrapT = THREE.RepeatWrapping\n }\n }\n }\n })\n }\n\n /**\n * Get bounds of a mesh group.\n */\n public getBounds(meshGroup: THREE.Group): THREE.Vector3 {\n const boundingBox = new THREE.Box3()\n let foundMesh = false\n\n meshGroup.traverse((child) => {\n if (child instanceof THREE.Mesh && child.geometry) {\n foundMesh = true\n\n if (!child.geometry.boundingBox) {\n child.geometry.computeBoundingBox()\n }\n\n if (child.geometry.boundingBox) {\n const localBox = child.geometry.boundingBox.clone()\n if (child.position.length() > 0 || child.scale.length() !== Math.sqrt(3)) {\n localBox.applyMatrix4(child.matrix)\n }\n boundingBox.union(localBox)\n }\n }\n })\n\n if (!foundMesh || boundingBox.isEmpty()) {\n console.warn(\"StowKitSystem: No mesh geometry found for bounds calculation\")\n return new THREE.Vector3(1, 1, 1)\n }\n\n const size = new THREE.Vector3()\n boundingBox.getSize(size)\n return size\n }\n\n /**\n * Dispose of all loaded assets and reset the system.\n */\n public dispose(): void {\n // Dispose textures\n for (const texture of this.textures.values()) {\n texture.dispose()\n }\n this.textures.clear()\n\n // Dispose meshes\n for (const mesh of this.meshes.values()) {\n mesh.traverse((child) => {\n if (child instanceof THREE.Mesh) {\n child.geometry?.dispose()\n if (child.material) {\n if (Array.isArray(child.material)) {\n child.material.forEach((m) => m.dispose())\n } else {\n child.material.dispose()\n }\n }\n }\n })\n }\n this.meshes.clear()\n\n // Clear other caches\n this.animations.clear()\n this.audioFiles.clear()\n this.packs.clear()\n\n this.materialConverter = undefined\n this.decoderPaths = { ...DEFAULT_DECODER_PATHS }\n this._prefabCollection = null\n }\n}\n"],"mappings":";AAAA,YAAY,WAAW;AACvB,SAAS,sBAAsB;AAC/B;AAAA,EAIE;AAAA,EACA;AAAA,EAEA;AAAA,OACK;AAMA,IAAM,gBAAN,MAAM,eAAc;AAAA,EACzB,OAAe,QAAsB;AAAA,EACrC,OAAe,gBAAyB;AAAA,EACxC,OAAe,cAAsC,oBAAI,IAAI;AAAA,EAC7D,OAAe,YAAmC,oBAAI,IAAI;AAAA;AAAA,EAG1D,OAAe,gBAAwB,IAAI;AAAA;AAAA,EAC3C,OAAe,cAAsB;AAAA;AAAA,EACrC,OAAe,cAAsB;AAAA,EACrC,OAAe,QAAgB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK/B,OAAc,UAAU,SAA2D,CAAC,GAAS;AAC3F,QAAI,OAAO,OAAO,kBAAkB,YAAY,OAAO,gBAAgB,GAAG;AACxE,qBAAc,gBAAgB,OAAO;AAAA,IACvC;AACA,QAAI,OAAO,OAAO,gBAAgB,YAAY,OAAO,eAAe,GAAG;AACrE,qBAAc,cAAc,OAAO;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,wBAAgC;AAC5C,WAAO,eAAc;AAAA,EACvB;AAAA;AAAA,EAGA,OAAe,aAAgC;AAAA,EAC/C,OAAe,4BAA8C,oBAAI,IAAI;AAAA;AAAA,EACrE,OAAe,qBAA0C,oBAAI,IAAI;AAAA;AAAA,EACjE,OAAe,yBAA2C,oBAAI,IAAI;AAAA;AAAA;AAAA,EAGlE,OAAe,eAAwB;AAAA,EACvC,OAAe,aAAiC;AAAA,EAChD,OAAe,cAAuC,oBAAI,IAAI;AAAA,EAC9D,OAAe,gBAAuC;AAAA;AAAA;AAAA;AAAA,EAKtD,aAAoB,aAA4B;AAC9C,QAAI,eAAc,eAAe;AAC/B;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,SAAS,MAAM,OAAO,oBAAoB;AAGhD,YAAM,UAAU,IAAI,OAAO,QAAQ,GAAK,OAAO,CAAG;AAClD,qBAAc,QAAQ,IAAI,OAAO,MAAM,OAAO;AAG9C,qBAAc,aAAa,IAAI,OAAO,WAAW,IAAI;AAErD,qBAAc,gBAAgB;AAAA,IAChC,SAAS,OAAO;AACd,cAAQ,MAAM,8CAAyC,KAAK;AAAA,IAC9D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,WAAyB;AACrC,WAAO,eAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,UAAmB;AAC/B,WAAO,eAAc,iBAAiB,eAAc,UAAU;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,KAAK,WAAyB;AAC1C,QAAI,CAAC,eAAc,OAAO;AACxB;AAAA,IACF;AAGA,mBAAc,eAAe;AAC7B,UAAM,IAAI,eAAc;AACxB,UAAM,UAAU,eAAc,cAAc;AAC5C,QAAI,eAAc,cAAc,SAAS;AAEvC,qBAAc,cAAc;AAAA,IAC9B;AAEA,QAAI,WAAW;AACf,WAAO,eAAc,eAAe,GAAG;AAErC;AAAC,MAAC,eAAc,MAAc,WAAW;AACzC,UAAI,eAAc,YAAY;AAC5B,uBAAc,MAAM,KAAK,eAAc,UAAU;AACjD,uBAAc,uBAAuB;AAAA,MACvC,OAAO;AACL,uBAAc,MAAM,KAAK;AAAA,MAC3B;AAEA,qBAAc,eAAe;AAC7B;AAAA,IACF;AAGA,mBAAc,QAAQ,eAAc,cAAc;AAGlD,mBAAc,kBAAkB;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBACZ,IACA,eACA,cACsD;AACtD,QAAI,CAAC,eAAc,MAAO,QAAO;AAGjC,UAAM,YAAY,eAAc,MAAM,gBAAgB,aAAa;AACnE,mBAAc,YAAY,IAAI,IAAI,SAAS;AAE3C,QAAI;AACJ,QAAI,cAAc;AAChB,iBAAW,eAAc,MAAM,eAAe,cAAc,SAAS;AACrE,qBAAc,UAAU,IAAI,IAAI,QAAQ;AAGxC,qBAAc,aAAa,EAAE;AAAA,IAC/B;AAEA,WAAO,EAAE,WAAW,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,mBAAmB,YAAoB,YAAuB;AAC1E,mBAAc,uBAAuB,IAAI,YAAY,UAAU;AAG/D,UAAM,WAAW,eAAc,UAAU,IAAI,UAAU;AACvD,QAAI,UAAU;AACZ,YAAM,SAAS,SAAS;AAExB,qBAAc,mBAAmB,IAAI,QAAQ,UAAU;AAEvD,eAAS,gBAAgB,aAAa,gBAAgB;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,qBAAqB,YAA0B;AAC3D,mBAAc,uBAAuB,OAAO,UAAU;AAGtD,UAAM,WAAW,eAAc,UAAU,IAAI,UAAU;AACvD,QAAI,UAAU;AACZ,YAAM,SAAS,SAAS;AACxB,qBAAc,mBAAmB,OAAO,MAAM;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,yBAAyB,YAAoB,WAAsB;AAE/E,UAAM,WAAW,eAAc,UAAU,IAAI,UAAU;AACvD,QAAI,UAAU;AACZ,YAAM,SAAS,SAAS;AAExB,qBAAc,0BAA0B,IAAI,QAAQ,SAAS;AAAA,IAE/D,OAAO;AACL,cAAQ,MAAM,4DAAqD,UAAU,EAAE;AAC/E,cAAQ;AAAA,QACN,qCAA8B,MAAM,KAAK,eAAc,UAAU,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,2BAA2B,YAA0B;AACjE,UAAM,WAAW,eAAc,UAAU,IAAI,UAAU;AACvD,QAAI,UAAU;AACZ,YAAM,SAAS,SAAS;AAExB,qBAAc,0BAA0B,OAAO,MAAM;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,yBAA+B;AAC5C,QAAI,CAAC,eAAc,WAAY;AAE/B,QAAI,aAAa;AAGjB,mBAAc,WAAW,qBAAqB,CAAC,SAAS,SAAS,YAAY;AAC3E;AAGA,YAAM,aAAa,eAAc,0BAA0B,IAAI,OAAO;AACtE,YAAM,aAAa,eAAc,0BAA0B,IAAI,OAAO;AACtE,YAAM,MAAM,eAAc,mBAAmB,IAAI,OAAO;AACxD,YAAM,MAAM,eAAc,mBAAmB,IAAI,OAAO;AAGxD,YAAM,cAAc,eAAc,uBAAuB,IAAI,OAAO,EAAE;AACtE,YAAM,cAAc,eAAc,uBAAuB,IAAI,OAAO,EAAE;AAMtE,YAAM,YAAY,eAAc,UAAU,IAAI,OAAO,EAAE;AACvD,YAAM,YAAY,eAAc,UAAU,IAAI,OAAO,EAAE;AAEvD,UAAI,CAAC,aAAa,CAAC,WAAW;AAC5B;AAAA,MACF;AAEA,YAAM,oBAAoB,UAAU,SAAS;AAC7C,YAAM,oBAAoB,UAAU,SAAS;AAK7C,UAAI,qBAAqB,YAAY;AACnC,cAAM,kBACJ,YAAY,cAAc,eAAc,uBAAuB,IAAI,OAAO,EAAE;AAC9E,YAAI,iBAAiB;AACnB,cAAI,WAAW,WAAW,gBAAgB;AACxC,uBAAW,eAAe,eAAe;AAAA,UAC3C,WAAW,CAAC,WAAW,WAAW,eAAe;AAC/C,uBAAW,cAAc,eAAe;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAGA,UAAI,qBAAqB,YAAY;AACnC,cAAM,kBACJ,YAAY,cAAc,eAAc,uBAAuB,IAAI,OAAO,EAAE;AAC9E,YAAI,iBAAiB;AACnB,cAAI,WAAW,WAAW,gBAAgB;AACxC,uBAAW,eAAe,eAAe;AAAA,UAC3C,WAAW,CAAC,WAAW,WAAW,eAAe;AAC/C,uBAAW,cAAc,eAAe;AAAA,UAC1C;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EAGH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBAAgB,IAAkB;AAC9C,QAAI,CAAC,eAAc,MAAO;AAG1B,mBAAc,gBAAgB,EAAE;AAEhC,UAAM,YAAY,eAAc,YAAY,IAAI,EAAE;AAClD,QAAI,WAAW;AACb,qBAAc,MAAM,gBAAgB,SAAS;AAC7C,qBAAc,YAAY,OAAO,EAAE;AAAA,IACrC;AAEA,UAAM,WAAW,eAAc,UAAU,IAAI,EAAE;AAC/C,QAAI,UAAU;AACZ,qBAAc,MAAM,eAAe,UAAU,IAAI;AACjD,qBAAc,UAAU,OAAO,EAAE;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAa,IAA8B;AACvD,WAAO,eAAc,YAAY,IAAI,EAAE,KAAK;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,YAAY,IAA6B;AACrD,WAAO,eAAc,UAAU,IAAI,EAAE,KAAK;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,oBAAoB,QAAwB,WAAsB,UAA2B;AACzG,UAAM,cAAc,UAAU,YAAY;AAC1C,UAAM,WAAW,UAAU,SAAS;AAGpC,WAAO,SAAS,IAAI,YAAY,GAAG,YAAY,GAAG,YAAY,CAAC;AAC/D,WAAO,WAAW,IAAI,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAGpE,QAAI,UAAU;AACZ,YAAM,KAAK,SAAS,YAAY;AAChC,aAAO,SAAS,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,oBAAoB,WAAsB,QAA8B;AACpF,UAAM,WAAW,OAAO;AACxB,UAAM,aAAa,OAAO;AAG1B,cAAU,eAAe,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI;AAC9E,cAAU;AAAA,MACR;AAAA,QACE,GAAG,WAAW;AAAA,QACd,GAAG,WAAW;AAAA,QACd,GAAG,WAAW;AAAA,QACd,GAAG,WAAW;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aACZ,OAAe,IACsC;AACrD,QAAI,CAAC,eAAc,MAAO,QAAO;AAGjC,UAAM,iBAAiB,cAAc,MAAM,EAAE,eAAe,GAAG,GAAG,CAAC;AAGnE,UAAM,qBAAqB,aAAa,OAAO,OAAO,GAAG,KAAK,OAAO,CAAC;AAEtE,UAAM,SAAS,eAAc,gBAAgB,UAAU,gBAAgB,kBAAkB;AACzF,WAAO,SAAS,EAAE,WAAW,OAAO,WAAW,UAAU,OAAO,SAAU,IAAI;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,UACZ,IACA,UACA,MACA,YAAqB,MACgC;AACrD,QAAI,CAAC,eAAc,MAAO,QAAO;AAGjC,UAAM,WAAW,YAAY,cAAc,QAAQ,IAAI,cAAc,MAAM;AAE3E,aAAS,eAAe,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAG1D,UAAM,eAAe,aAAa,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC;AAE3E,UAAM,SAAS,eAAc,gBAAgB,IAAI,UAAU,YAAY;AACvE,WAAO,SAAS,EAAE,WAAW,OAAO,WAAW,UAAU,OAAO,SAAU,IAAI;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aACZ,IACA,UACA,QACA,YAAqB,MACgC;AACrD,QAAI,CAAC,eAAc,MAAO,QAAO;AAGjC,UAAM,WAAW,YAAY,cAAc,QAAQ,IAAI,cAAc,MAAM;AAE3E,aAAS,eAAe,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAG1D,UAAM,eAAe,aAAa,KAAK,MAAM;AAE7C,UAAM,SAAS,eAAc,gBAAgB,IAAI,UAAU,YAAY;AACvE,WAAO,SAAS,EAAE,WAAW,OAAO,WAAW,UAAU,OAAO,SAAU,IAAI;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBAAgB,OAA0B;AACtD,mBAAc,aAAa;AAG3B,mBAAc,gBAAgB,IAAU,wBAAkB;AAAA,MACxD,OAAO;AAAA,MACP,WAAW;AAAA,MACX,aAAa;AAAA,MACb,SAAS;AAAA,MACT,WAAW;AAAA;AAAA,MACX,YAAY;AAAA;AAAA,IACd,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,gBAAgB,SAAwB;AACpD,mBAAc,eAAe;AAE7B,QAAI,SAAS;AACX,qBAAc,mBAAmB;AAAA,IACnC,OAAO;AACL,qBAAc,mBAAmB;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,iBAA0B;AACtC,WAAO,eAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,gBAAgB,IAAY,UAAuC;AAChF,QAAI,CAAC,eAAc,iBAAiB,CAAC,eAAc,WAAY,QAAO;AAEtE,UAAM,QAAQ,SAAS;AACvB,QAAI,WAAwC;AAG5C,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,cAAM,SAAU,MAAc;AAC9B,mBAAW,IAAU,qBAAe,QAAQ,IAAI,EAAE;AAClD;AAAA,MAEF,KAAK;AACH,cAAM,cAAe,MAAc;AACnC,mBAAW,IAAU,kBAAY,YAAY,IAAI,GAAG,YAAY,IAAI,GAAG,YAAY,IAAI,CAAC;AACxF;AAAA,MAEF,KAAK;AACH,cAAM,gBAAiB,MAAc;AACrC,cAAM,oBAAqB,MAAc;AACzC,cAAM,kBAAkB,IAAU;AAAA,UAChC;AAAA,UACA,oBAAoB;AAAA,UACpB;AAAA,UACA;AAAA,QACF;AACA,mBAAW;AACX;AAAA,MAEF,KAAK,GAAG;AACN,cAAM,SAAS;AACf,cAAM,WAAW,OAAO;AACxB,YAAI,YAAY,SAAS,UAAU,GAAG;AACpC,gBAAM,SAA0B,CAAC;AACjC,mBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC3C,mBAAO,KAAK,IAAU,cAAQ,SAAS,CAAC,GAAG,SAAS,IAAI,CAAC,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC;AAAA,UAC9E;AACA,qBAAW,IAAI,eAAe,MAAM;AAAA,QACtC;AACA;AAAA,MACF;AAAA,MAEA;AAEE,mBAAW,IAAU,kBAAY,GAAG,GAAG,CAAC;AACxC,gBAAQ,KAAK,oCAAoC,MAAM,IAAI,sBAAsB;AACjF;AAAA,IACJ;AAEA,QAAI,CAAC,SAAU,QAAO;AAGtB,UAAM,YAAY,IAAU,WAAK,UAAU,eAAc,aAAa;AACtE,cAAU,OAAO,SAAS,EAAE;AAG5B,UAAM,YAAY,eAAc,YAAY,IAAI,EAAE;AAClD,QAAI,WAAW;AACb,qBAAc,oBAAoB,WAAW,WAAW,QAAQ;AAAA,IAClE;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,aAAa,IAAkB;AAC5C,QAAI,CAAC,eAAc,cAAc,eAAc,YAAY,IAAI,EAAE,EAAG;AAEpE,UAAM,WAAW,eAAc,UAAU,IAAI,EAAE;AAC/C,QAAI,CAAC,SAAU;AAEf,UAAM,YAAY,eAAc,gBAAgB,IAAI,QAAQ;AAC5D,QAAI,WAAW;AACb,qBAAc,YAAY,IAAI,IAAI,SAAS;AAE3C,UAAI,eAAc,cAAc;AAC9B,uBAAc,WAAW,IAAI,SAAS;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,gBAAgB,IAAkB;AAC/C,UAAM,YAAY,eAAc,YAAY,IAAI,EAAE;AAClD,QAAI,WAAW;AACb,UAAI,eAAc,YAAY;AAC5B,uBAAc,WAAW,OAAO,SAAS;AAAA,MAC3C;AACA,gBAAU,SAAS,QAAQ;AAC3B,qBAAc,YAAY,OAAO,EAAE;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,qBAA2B;AACxC,QAAI,CAAC,eAAc,WAAY;AAE/B,mBAAc,YAAY,QAAQ,CAAC,SAAS;AAC1C,qBAAc,WAAY,IAAI,IAAI;AAAA,IACpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAe,qBAA2B;AACxC,QAAI,CAAC,eAAc,WAAY;AAE/B,mBAAc,YAAY,QAAQ,CAAC,SAAS;AAC1C,qBAAc,WAAY,OAAO,IAAI;AAAA,IACvC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,oBAA0B;AACtC,QAAI,CAAC,eAAc,gBAAgB,CAAC,eAAc,WAAY;AAE9D,mBAAc,YAAY,QAAQ,CAAC,MAAM,OAAO;AAC9C,YAAM,YAAY,eAAc,YAAY,IAAI,EAAE;AAClD,UAAI,WAAW;AAEb,cAAM,YAAY,UAAU,UAAU;AAEtC,YAAI,WAAW;AAEb,gBAAM,WAAW,eAAc,UAAU,IAAI,EAAE;AAC/C,yBAAc,oBAAoB,MAAM,WAAW,YAAY,MAAS;AACxE,cAAI,CAAC,eAAc,WAAY,SAAS,SAAS,IAAI,GAAG;AACtD,2BAAc,WAAY,IAAI,IAAI;AAAA,UACpC;AAAA,QACF,OAAO;AAEL,cAAI,eAAc,WAAY,SAAS,SAAS,IAAI,GAAG;AACrD,2BAAc,WAAY,OAAO,IAAI;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,UAAgB;AAE5B,mBAAc,YAAY,QAAQ,CAAC,SAAS;AAC1C,UAAI,eAAc,YAAY;AAC5B,uBAAc,WAAW,OAAO,IAAI;AAAA,MACtC;AACA,WAAK,SAAS,QAAQ;AAAA,IACxB,CAAC;AACD,mBAAc,YAAY,MAAM;AAEhC,QAAI,eAAc,eAAe;AAC/B,qBAAc,cAAc,QAAQ;AACpC,qBAAc,gBAAgB;AAAA,IAChC;AAEA,mBAAc,aAAa;AAC3B,mBAAc,eAAe;AAE7B,QAAI,eAAc,OAAO;AACvB,qBAAc,MAAM,KAAK;AACzB,qBAAc,QAAQ;AAAA,IACxB;AAEA,QAAI,eAAc,YAAY;AAC5B,qBAAc,WAAW,KAAK;AAC9B,qBAAc,aAAa;AAAA,IAC7B;AAEA,mBAAc,YAAY,MAAM;AAChC,mBAAc,UAAU,MAAM;AAC9B,mBAAc,0BAA0B,MAAM;AAC9C,mBAAc,mBAAmB,MAAM;AACvC,mBAAc,gBAAgB;AAE9B,YAAQ,IAAI,kCAA2B;AAAA,EACzC;AACF;;;AC5oBO,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EAC5B,OAAe,uBAAuB,oBAAI,IAAe;AAAA,EACzD,OAAe,2BAA2B,oBAAI,IAAe;AAAA,EAC7D,OAAe,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM7B,OAAO,kBAAkB,WAA4B;AACnD,sBAAiB,qBAAqB,IAAI,SAAS;AAAA,EAErD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,oBAAoB,WAA4B;AACrD,sBAAiB,qBAAqB,OAAO,SAAS;AAAA,EAExD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,4BAA4B,WAA4B;AAC7D,sBAAiB,yBAAyB,IAAI,SAAS;AACvD,YAAQ;AAAA,MACN,0CAAmC,UAAU,YAAY,IAAI,6BAA6B,kBAAiB,yBAAyB,IAAI;AAAA,IAC1I;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,8BAA8B,WAA4B;AAC/D,sBAAiB,yBAAyB,OAAO,SAAS;AAAA,EAE5D;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAW,OAA0B;AAAA,EAE5C;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAO,WAAyB;AACrC,SAAK;AACL,eAAW,aAAa,kBAAiB,sBAAsB;AAC7D,UAAI,UAAU,cAAc,EAAE,SAAS;AACrC,YAAI;AACF,oBAAU,SAAS,SAAS;AAAA,QAC9B,SAAS,OAAO;AACd,kBAAQ,MAAM,mCAA8B,UAAU,YAAY,IAAI,KAAK,KAAK;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAW,WAAyB;AACzC,eAAW,aAAa,kBAAiB,0BAA0B;AACjE,UAAI,UAAU,cAAc,EAAE,SAAS;AACrC,YAAI;AACF,oBAAU,aAAa,SAAS;AAAA,QAClC,SAAS,OAAO;AACd,kBAAQ,MAAM,wCAAmC,UAAU,YAAY,IAAI,KAAK,KAAK;AAAA,QACvF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAgB;AACrB,sBAAiB,qBAAqB,MAAM;AAC5C,sBAAiB,yBAAyB,MAAM;AAChD,YAAQ,IAAI,qCAA8B;AAAA,EAC5C;AACF;;;AC3FO,IAAK,cAAL,kBAAKA,iBAAL;AACL,EAAAA,aAAA,kBAAe;AACf,EAAAA,aAAA,mBAAgB;AAChB,EAAAA,aAAA,eAAY;AACZ,EAAAA,aAAA,gBAAa;AACb,EAAAA,aAAA,SAAM;AALI,SAAAA;AAAA,GAAA;AAWL,IAAM,uBAAoD;AAAA,EAC/D,CAAC,iCAAwB,GAAG;AAAA,EAC5B,CAAC,mCAAyB,GAAG;AAAA,EAC7B,CAAC,2BAAqB,GAAG;AAAA,EACzB,CAAC,6BAAsB,GAAG;AAAA,EAC1B,CAAC,eAAe,GAAG;AACrB;AAMO,IAAM,eAAN,MAAM,cAAa;AAAA,EACxB,OAAe;AAAA;AAAA,EAGP,aAAa,oBAAI,IAAY;AAAA,EAC7B,cAA2C;AAAA,IACjD,GAAG;AAAA,EACL;AAAA,EACQ,YAAY;AAAA;AAAA,EAGZ,eAAe,KAAK,UAAU,KAAK,IAAI;AAAA,EACvC,aAAa,KAAK,QAAQ,KAAK,IAAI;AAAA,EACnC,kBAAkB,KAAK,aAAa,KAAK,IAAI;AAAA,EAE7C,cAAc;AACpB,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,cAA4B;AACxC,QAAI,CAAC,cAAa,UAAU;AAC1B,oBAAa,WAAW,IAAI,cAAa;AAAA,IAC3C;AACA,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAmB;AAC/B,kBAAa,YAAY;AAAA,EAE3B;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAA4B;AAClC,aAAS,iBAAiB,WAAW,KAAK,YAAY;AACtD,aAAS,iBAAiB,SAAS,KAAK,UAAU;AAClD,WAAO,iBAAiB,QAAQ,KAAK,eAAe;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,OAA4B;AAC5C,QAAI,CAAC,KAAK,UAAW;AAGrB,QAAI,KAAK,UAAU,MAAM,IAAI,GAAG;AAC9B,YAAM,eAAe;AAAA,IACvB;AAEA,SAAK,WAAW,IAAI,MAAM,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKQ,QAAQ,OAA4B;AAC1C,SAAK,WAAW,OAAO,MAAM,IAAI;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,SAAK,WAAW,MAAM;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKO,gBAAgB,QAA8B;AACnD,QAAI,CAAC,KAAK,UAAW,QAAO;AAE5B,UAAM,UAAU,KAAK,YAAY,MAAM;AACvC,WAAO,KAAK,WAAW,IAAI,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,SAA0B;AAC5C,WAAO,KAAK,aAAa,KAAK,WAAW,IAAI,OAAO;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKO,WAAW,SAAwB;AACxC,SAAK,YAAY;AACjB,QAAI,CAAC,SAAS;AACZ,WAAK,WAAW,MAAM;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,cAAc,QAAqB,SAAuB;AAC/D,SAAK,YAAY,MAAM,IAAI;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAU,SAA0B;AAC1C,WAAO,OAAO,OAAO,KAAK,WAAW,EAAE,SAAS,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKO,gBAA0B;AAC/B,WAAO,MAAM,KAAK,KAAK,UAAU;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,aAAS,oBAAoB,WAAW,KAAK,YAAY;AACzD,aAAS,oBAAoB,SAAS,KAAK,UAAU;AACrD,WAAO,oBAAoB,QAAQ,KAAK,eAAe;AACvD,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;AAGO,IAAM,QAAQ;AAAA,EACnB,WAAW,CAAC,WAAwB,aAAa,YAAY,EAAE,gBAAgB,MAAM;AAAA,EACrF,cAAc,CAAC,YAAoB,aAAa,YAAY,EAAE,aAAa,OAAO;AAAA,EAClF,YAAY,CAAC,YAAqB,aAAa,YAAY,EAAE,WAAW,OAAO;AACjF;;;ACnKO,IAAM,WAAN,MAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpB,OAAO,KAAK,SAAiB,QAAgB,QAAwB;AACnE,WAAO,WAAW,SAAS,WAAW;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,YAAY,SAAiB,QAAgB,UAA0B;AAC5E,UAAM,OAAO,SAAS;AACtB,QAAI,KAAK,IAAI,IAAI,KAAK,UAAU;AAC9B,aAAO;AAAA,IACT;AACA,WAAO,UAAU,KAAK,KAAK,IAAI,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,MAAM,OAAe,KAAa,KAAqB;AAC5D,WAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,cAAc,GAAW,GAAW,UAAkB,MAAgB;AAC3E,WAAO,KAAK,IAAI,IAAI,CAAC,IAAI;AAAA,EAC3B;AACF;;;AChDO,IAAM,SAAN,MAAM,QAAO;AAAA,EAClB,OAAO,OAAO,GAAmB;AAC/B,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,WAAW,GAAmB;AACnC,WAAO,IAAI;AAAA,EACb;AAAA,EAEA,OAAO,YAAY,GAAmB;AACpC,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,OAAO,cAAc,GAAmB;AACtC,WAAO,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK;AAAA,EAClD;AAAA,EAEA,OAAO,YAAY,GAAmB;AACpC,WAAO,IAAI,IAAI;AAAA,EACjB;AAAA,EAEA,OAAO,aAAa,GAAmB;AACrC,WAAO,EAAE,IAAI,IAAI,IAAI;AAAA,EACvB;AAAA,EAEA,OAAO,eAAe,GAAmB;AACvC,WAAO,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK;AAAA,EACzE;AAAA;AAAA,EAGA,OAAO,OAAO,GAAW,UAAkB,KAAK,YAAoB,MAAc;AAChF,WAAO,IAAI,KAAK,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,YAAY,IAAI,KAAK,KAAK,CAAC;AAAA,EAC1E;AAAA;AAAA,EAGA,OAAO,eAAe,GAAmB;AACvC,UAAM,KAAM,IAAI,KAAK,KAAM;AAC3B,WAAO,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,QAAQ,EAAE,IAAI;AAAA,EAC7F;AAAA;AAAA,EAGA,OAAO,WAAW,GAAW,IAAY,SAAiB;AACxD,WAAO,IAAI,MAAM,IAAI,KAAK,IAAI;AAAA,EAChC;AAAA,EAEA,OAAO,YAAY,GAAW,IAAY,SAAiB;AACzD,QAAI,IAAI;AACR,WAAO,IAAI,IAAI,MAAM,IAAI,KAAK,IAAI;AAAA,EACpC;AAAA;AAAA,EAGA,OAAO,oBAAoB,GAAW,IAAY,KAAa;AAC7D,QAAI,IAAI,KAAK;AACX,aAAO,MAAM,QAAO,WAAW,IAAI,GAAG,CAAC;AAAA,IACzC;AACA,WAAO,MAAM,QAAO,YAAY,IAAI,IAAI,GAAG,CAAC,IAAI;AAAA,EAClD;AACF;AAKO,IAAM,QAAN,MAAY;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAkB;AAAA,EAE1B,YACE,QACA,UACA,UACA,UACA,iBAAwC,OAAO,QAC/C;AACA,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,aAAa,OAAO,QAAQ;AACjC,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,iBAAiB;AAEtB,QAAI,YAAY,cAAc;AAC5B,cAAQ;AAAA,QACN,6BAA6B,QAAQ,WAAW,KAAK,UAAU,SAAS,QAAQ,cAAc,QAAQ;AAAA,MACxG;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,UAA6B;AAC9C,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,UAA0C;AACzD,SAAK,WAAW;AAChB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,OAAO,WAA4B;AAExC,QAAI,CAAC,KAAK,OAAQ,QAAO;AAEzB,SAAK,WAAW;AAGhB,QAAI,KAAK,UAAU,KAAK,UAAU;AAChC,YAAM,IAAI,KAAK,UAAU,KAAK;AAC9B,YAAM,SAAS,KAAK,eAAe,CAAC;AACpC,YAAM,eAAe,KAAK,cAAc,KAAK,WAAW,KAAK,cAAc;AAC3E,WAAK,OAAO,KAAK,QAAQ,IAAI;AAG7B,UAAI,KAAK,UAAU;AACjB,aAAK,SAAS,YAAY;AAAA,MAC5B;AAGA,UAAI,YAAY,gBAAgB,KAAK,OAAO,IAAI,MAAM;AACpD,gBAAQ;AAAA,UACN,qBAAqB,KAAK,QAAQ,IAAI,aAAa,QAAQ,CAAC,CAAC,MAAM,IAAI,KAAK,QAAQ,CAAC,CAAC;AAAA,QACxF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAGA,SAAK,OAAO,KAAK,QAAQ,IAAI,KAAK;AAClC,SAAK,SAAS;AAEd,QAAI,YAAY,cAAc;AAC5B,cAAQ,IAAI,sBAAsB,KAAK,QAAQ,IAAI,KAAK,QAAQ,EAAE;AAAA,IACpE;AAGA,QAAI,KAAK,YAAY;AACnB,WAAK,WAAW;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,OAAa;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKO,WAAoB;AACzB,WAAO,KAAK;AAAA,EACd;AACF;AAKO,IAAM,cAAN,MAAkB;AAAA,EACvB,OAAe,SAAkB,CAAC;AAAA,EAClC,OAAe,gBAAyB,CAAC;AAAA;AAAA,EACzC,OAAc,eAAwB;AAAA;AAAA,EACtC,OAAe,kBAA0B;AAAA,EACzC,OAAe,aAAqB;AAAA;AAAA;AAAA;AAAA,EAKpC,OAAO,MACL,QACA,UACA,UACA,UACA,gBACO;AACP,UAAM,QAAQ,IAAI,MAAM,QAAQ,UAAU,UAAU,UAAU,cAAc;AAG5E,QAAI,KAAK,cAAc,SAAS,KAAK,KAAK,aAAa,KAAK,kBAAkB,GAAG;AAC/E,WAAK,cAAc,KAAK,KAAK;AAAA,IAC/B,OAAO;AACL,WAAK,OAAO,KAAK,KAAK;AAAA,IACxB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,OAAO,WAAyB;AACrC,SAAK;AAGL,QAAI,KAAK,OAAO,WAAW,KAAK,KAAK,cAAc,WAAW,GAAG;AAE/D;AAAA,IACF;AAEA,SAAK,kBAAkB,KAAK;AAG5B,QAAI,KAAK,gBAAgB,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,SAAS,GAAG;AACvE,cAAQ,IAAI,0BAA0B,KAAK,OAAO,MAAM,0BAA0B,SAAS,EAAE;AAAA,IAC/F;AAGA,UAAM,eAAwB,CAAC;AAC/B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,WAAW,MAAM,OAAO,SAAS;AACvC,UAAI,UAAU;AACZ,qBAAa,KAAK,KAAK;AAAA,MACzB;AAAA,IACF;AAGA,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,mBAAa,KAAK,GAAG,KAAK,aAAa;AACvC,WAAK,gBAAgB,CAAC;AAAA,IACxB;AAEA,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAAgB;AACrB,SAAK,OAAO,QAAQ,CAAC,UAAU,MAAM,KAAK,CAAC;AAC3C,SAAK,SAAS,CAAC;AACf,SAAK,gBAAgB,CAAC;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,iBAAyB;AAC9B,WAAO,KAAK,OAAO,SAAS,KAAK,cAAc;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAAoB;AACzB,WAAO,KAAK,OAAO,SAAS,KAAK,KAAK,cAAc,SAAS;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,WAKL;AACA,WAAO;AAAA,MACL,QAAQ,KAAK,OAAO;AAAA,MACpB,SAAS,KAAK,cAAc;AAAA,MAC5B,iBAAiB,KAAK;AAAA,MACtB,cAAc,KAAK;AAAA,IACrB;AAAA,EACF;AACF;;;AC5RA,YAAYC,YAAW;AAOhB,IAAM,sBAAN,MAA0B;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,YAAY,GAAW,GAAW,GAAW,eAA8B,IAAU,eAAQ,GAAG;AAE9F,UAAM,KAAK,KAAK;AAChB,UAAM,IAAI,IAAI,KAAK;AACnB,UAAM,IAAI,IAAI,KAAK,KAAK,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC;AAE3C,SAAK,KAAK,KAAK,KAAK;AACpB,SAAK,KAAK,KAAK,IAAI;AACnB,SAAK,KAAM,IAAI,IAAK;AAGpB,SAAK,KAAK,aAAa,MAAM;AAC7B,SAAK,IAAI,aAAa,MAAM;AAC5B,SAAK,KAAK,IAAU,eAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,GAAkB,WAAkC;AACzD,QAAI,cAAc,GAAG;AACnB,aAAO,KAAK,EAAE,MAAM;AAAA,IACtB;AAGA,UAAM,KAAK,IAAU,eAAQ,EAAE,WAAW,GAAG,KAAK,EAAE,EAAE,aAAa,SAAS;AAE5E,SAAK,GAAG,KAAK,CAAC;AAGd,UAAM,IAAI,KAAK,IAAI,WAAW,IAAI;AAGlC,SAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAGjC,UAAM,eAAe,IAAU,eAAQ,EACpC,gBAAgB,GAAG,CAAC,EACpB,gBAAgB,IAAI,KAAK,EAAE,EAC3B,gBAAgB,KAAK,GAAG,EAAE,EAC1B,gBAAgB,KAAK,IAAI,CAAC,KAAK,EAAE,EACjC,aAAa,KAAK,EAAE;AAEvB,SAAK,GAAG,gBAAgB,cAAc,CAAC;AAEvC,WAAO,KAAK,EAAE,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAoC;AAClC,WAAO,KAAK,EAAE,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAoC;AAClC,WAAO,KAAK,GAAG,MAAM;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAA+B;AACnC,SAAK,GAAG,KAAK,QAAQ;AACrB,SAAK,EAAE,KAAK,QAAQ;AACpB,SAAK,GAAG,IAAI,GAAG,GAAG,CAAC;AAAA,EACrB;AACF;AAKO,IAAM,wBAAN,MAA4B;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EAER,YAAY,GAAW,GAAW,GAAW,eAAuB,GAAG;AACrE,UAAM,KAAK,KAAK;AAChB,UAAM,IAAI,IAAI,KAAK;AAEnB,SAAK,KAAK,KAAK,KAAK;AACpB,SAAK,KAAK,KAAK,IAAI;AACnB,SAAK,KAAM,IAAI,IAAK;AAEpB,SAAK,KAAK;AACV,SAAK,IAAI;AACT,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,OAAO,GAAW,WAA2B;AAC3C,QAAI,cAAc,EAAG,QAAO,KAAK;AAEjC,UAAM,MAAM,IAAI,KAAK,MAAM;AAC3B,SAAK,KAAK;AAEV,UAAM,IAAI,KAAK,IAAI,WAAW,IAAI;AAElC,SAAK,KAAK,KAAK,KAAK;AAEpB,UAAM,gBAAgB,IAAI,KAAK,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,MAAM,KAAK;AAC5E,SAAK,MAAM,eAAe;AAE1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,kBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA6B;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAqB;AACzB,SAAK,KAAK;AACV,SAAK,IAAI;AACT,SAAK,KAAK;AAAA,EACZ;AACF;;;AC9IA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AACnC,SAAS,WAAW;AACpB,SAAS,oBAAoB;AAiB7B,IAAM,aAAa;AAGnB,SAAS,uBAAuB,KAAqB;AACnD,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,YAAS,QAAQ,KAAK,OAAQ;AAC9B,WAAO,OAAO;AAAA,EAChB;AACA,SAAO,KAAK,IAAI,IAAI;AACtB;AAKO,IAAM,oBAAN,MAAmD;AAAA,EAC/C,aAAa;AAAA;AAAA,EAGb,UAA2B;AAAA,IAClC,SAAS,OAAO,QAAwC;AACtD,cAAQ,IAAI,GAAG,UAAU,qBAAqB,GAAG,IAAI;AACrD,YAAM,EAAE,MAAM,IAAI,MAAM,YAAY,IAAI,EAAE,IAAI,CAAC;AAC/C,cAAQ,IAAI,GAAG,UAAU,qBAAqB,GAAG,SAAS,QAAQ,IAAI,MAAM,UAAU,GAAG,EAAE,CAAC,GAAG,MAAM,SAAS,KAAK,QAAQ,EAAE,MAAM,MAAM;AACzI,aAAO;AAAA,IACT;AAAA,IACA,SAAS,OAAO,KAAa,UAAiC;AAC5D,cAAQ,IAAI,GAAG,UAAU,qBAAqB,GAAG,OAAO,MAAM,UAAU,GAAG,EAAE,CAAC,GAAG,MAAM,SAAS,KAAK,QAAQ,EAAE,IAAI;AACnH,YAAM,YAAY,IAAI,EAAE,KAAK,MAAM,CAAC;AAAA,IACtC;AAAA,IACA,YAAY,OAAO,QAA+B;AAChD,cAAQ,IAAI,GAAG,UAAU,wBAAwB,GAAG,IAAI;AACxD,YAAM,YAAY,OAAO,EAAE,IAAI,CAAC;AAAA,IAClC;AAAA,IACA,QAAQ,YAA6B;AAEnC,YAAM,EAAE,KAAK,IAAI,MAAM,YAAY,KAAK;AACxC,cAAQ,IAAI,GAAG,UAAU,wBAAwB,KAAK,MAAM,EAAE;AAC9D,aAAO,KAAK;AAAA,IACd;AAAA,IACA,KAAK,OAAO,UAA0C;AACpD,YAAM,EAAE,KAAK,IAAI,MAAM,YAAY,KAAK;AACxC,YAAM,MAAM,KAAK,KAAK,KAAK;AAC3B,cAAQ,IAAI,GAAG,UAAU,gBAAgB,KAAK,SAAS,GAAG,GAAG;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGS,QAAuB;AAAA,IAC9B,SAAS,OAAO,QAAwC;AACtD,cAAQ,IAAI,GAAG,UAAU,mBAAmB,GAAG,IAAI;AACnD,YAAM,EAAE,MAAM,IAAI,MAAM,YAAY,IAAI,EAAE,KAAK,SAAS,GAAG,GAAG,CAAC;AAC/D,cAAQ,IAAI,GAAG,UAAU,mBAAmB,GAAG,SAAS,QAAQ,IAAI,MAAM,UAAU,GAAG,EAAE,CAAC,SAAS,MAAM;AACzG,aAAO;AAAA,IACT;AAAA,IACA,SAAS,OAAO,KAAa,UAAiC;AAC5D,cAAQ,IAAI,GAAG,UAAU,mBAAmB,GAAG,OAAO,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO;AACnF,YAAM,YAAY,IAAI,EAAE,KAAK,SAAS,GAAG,IAAI,MAAM,CAAC;AAAA,IACtD;AAAA,IACA,YAAY,OAAO,QAA+B;AAChD,cAAQ,IAAI,GAAG,UAAU,sBAAsB,GAAG,IAAI;AACtD,YAAM,YAAY,OAAO,EAAE,KAAK,SAAS,GAAG,GAAG,CAAC;AAAA,IAClD;AAAA,EACF;AAAA;AAAA,EAGQ,kBAA4L;AAAA;AAAA,EAG3L,YAA+B;AAAA,IACtC,iBAAiB,CAAC,MAAc,SAAiB;AAC/C,cAAQ,IAAI,GAAG,UAAU,8BAA8B,IAAI,MAAM,IAAI,IAAI;AACzE,WAAK,mBAAmB,eAAe,IAAI,IAAI,EAAE,YAAY,KAAK,CAAC;AAAA,IACrE;AAAA,IACA,mBAAmB,CAAC,WAAmB,WAAqC;AAC1E,cAAQ,IAAI,GAAG,UAAU,iCAAiC,SAAS,MAAM,MAAM;AAC/E,WAAK,mBAAmB,WAAW,UAAU,CAAC,CAAC;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,mBAAmB,WAAmB,YAA2C;AACvF,QAAI,CAAC,KAAK,gBAAiB;AAC3B,SAAK,gBAAgB,UAAU,SAAS,EAAE,WAAW,WAAW,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnF;AAAA;AAAA;AAAA,EAIS,MAAmB;AAAA,IAC1B,qBAAqB,YAA8B;AACjD,cAAQ,IAAI,GAAG,UAAU,iEAAiE;AAE1F,aAAO;AAAA,IACT;AAAA,IACA,oBAAoB,YAA8B;AAChD,cAAQ,IAAI,GAAG,UAAU,gEAAgE;AACzF,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA,EAIS,MAAmB;AAAA,IAC1B,wBAAwB,YAA6B;AACnD,YAAM,EAAE,MAAM,IAAI,MAAM,YAAY,IAAI,EAAE,KAAK,mBAAmB,CAAC;AACnE,YAAM,UAAU,QAAQ,SAAS,OAAO,EAAE,IAAI;AAC9C,cAAQ,IAAI,GAAG,UAAU,oCAAoC,OAAO,EAAE;AACtE,aAAO;AAAA,IACT;AAAA,IACA,eAAe,OAAO,WAAmB,WAAkC;AACzE,cAAQ,IAAI,GAAG,UAAU,uBAAuB,SAAS,MAAM,MAAM,GAAG;AACxE,YAAM,UAAU,MAAM,KAAK,IAAI,uBAAuB;AACtD,UAAI,UAAU,QAAQ;AACpB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AACA,YAAM,YAAY,IAAI,EAAE,KAAK,oBAAoB,QAAQ,UAAU,QAAQ,SAAS,EAAE,CAAC;AAAA,IACzF;AAAA,IACA,WAAW,YAA2B;AACpC,cAAQ,IAAI,GAAG,UAAU,wCAAwC;AAAA,IAEnE;AAAA,EACF;AAAA;AAAA;AAAA,EAIS,MAAmB;AAAA,IAC1B,YAAY,OAAO,SAAgC;AAEjD,UAAI,YAAY;AAQhB,UAAI,KAAK,WAAW,SAAS,KAAK,KAAK,WAAW,UAAU,GAAG;AAC7D,oBAAY;AAAA,MACd,WAAW,KAAK,WAAW,GAAG,GAAG;AAC/B,oBAAY;AAAA,MACd,WAAW,KAAK,WAAW,IAAI,GAAG;AAChC,oBAAY;AAAA,MACd,WAAW,KAAK,WAAW,aAAa,GAAG;AACzC,oBAAY,KAAK,IAAI;AAAA,MACvB,OAAO;AAGL,oBAAY,gBAAgB,IAAI;AAAA,MAClC;AAEA,cAAQ,IAAI,GAAG,UAAU,oBAAoB,IAAI,wBAAwB,SAAS,GAAG;AAErF,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,SAAS;AACtC,YAAI,CAAC,SAAS,IAAI;AAChB,kBAAQ,MAAM,GAAG,UAAU,oBAAoB,IAAI,cAAc,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AACzG,gBAAM,IAAI,MAAM,0BAA0B,IAAI,UAAU,SAAS,MAAM,GAAG;AAAA,QAC5E;AACA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,gBAAQ,IAAI,GAAG,UAAU,oBAAoB,IAAI,kBAAkB,KAAK,IAAI,iBAAiB,KAAK,IAAI,GAAG;AACzG,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,GAAG,UAAU,oBAAoB,IAAI,gBAAgB,KAAK;AACxE,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,WAAW,OAAO,SAAgC;AAChD,aAAO,KAAK,IAAI,WAAW,IAAI;AAAA,IACjC;AAAA,EACF;AAAA;AAAA,EAGQ,6BAA6B;AAAA,EAErC,MAAc,4BAA2C;AACvD,QAAI,KAAK,2BAA4B;AAErC,QAAI;AAEF,YAAM,mBAAmB,cAAc;AAAA,QACrC,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,aAAa;AAAA,QACb,YAAY;AAAA;AAAA,QACZ,YAAY;AAAA;AAAA,QACZ,OAAO;AAAA,QACP,WAAW;AAAA,MACb,CAAC;AACD,WAAK,6BAA6B;AAClC,cAAQ,IAAI,GAAG,UAAU,iCAAiC;AAAA,IAC5D,SAAS,OAAO;AAEd,cAAQ,IAAI,GAAG,UAAU,wEAAwE;AACjG,WAAK,6BAA6B;AAAA,IACpC;AAAA,EACF;AAAA;AAAA,EAGS,gBAAuC;AAAA,IAC9C,eAAe,OACb,OACA,MACA,cACA,mBACkB;AAClB,YAAM,KAAK,iBAAiB,uBAAuB,cAAc,IAAI,KAAK,IAAI;AAC9E,cAAQ,IAAI,GAAG,UAAU,iCAAiC,KAAK,OAAO,IAAI,MAAM,YAAY,SAAS,EAAE,GAAG;AAE1G,UAAI;AAEF,cAAM,aAAa,MAAM,mBAAmB,mBAAmB;AAC/D,gBAAQ,IAAI,GAAG,UAAU,uCAAuC,WAAW,OAAO;AAElF,YAAI,WAAW,YAAY,WAAW;AACpC,kBAAQ,KAAK,GAAG,UAAU,2CAA2C,WAAW,OAAO,GAAG;AAC1F;AAAA,QACF;AAGA,cAAM,KAAK,0BAA0B;AAErC,cAAM,gBAAgB,IAAI,KAAK,KAAK,IAAI,IAAI,eAAe,GAAI;AAC/D,gBAAQ,IAAI,GAAG,UAAU,kCAAkC,cAAc,YAAY,CAAC,EAAE;AAExF,cAAM,mBAAmB,SAAS;AAAA,UAChC,eAAe;AAAA,YACb;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU,EAAE,IAAI,cAAc;AAAA,cAC9B,WAAW;AAAA;AAAA,cACX,WAAW;AAAA;AAAA,cACX,WAAW;AAAA,YACb;AAAA,UACF;AAAA,QACF,CAAC;AAGD,cAAM,UAAU,MAAM,mBAAmB,WAAW;AACpD,gBAAQ,IAAI,GAAG,UAAU,4EAA4E,QAAQ,cAAc,MAAM,EAAE;AAAA,MACrI,SAAS,OAAO;AACd,gBAAQ,MAAM,GAAG,UAAU,4CAA4C,KAAK;AAAA,MAC9E;AAAA,IACF;AAAA,IACA,oBAAoB,OAAO,mBAA0C;AACnE,YAAM,KAAK,uBAAuB,cAAc;AAChD,cAAQ,IAAI,GAAG,UAAU,sCAAsC,cAAc,YAAY,EAAE,EAAE;AAE7F,UAAI;AACF,cAAM,mBAAmB,OAAO;AAAA,UAC9B,eAAe,CAAC,EAAE,GAAG,CAAC;AAAA,QACxB,CAAC;AACD,gBAAQ,IAAI,GAAG,UAAU,+DAA+D;AAAA,MAC1F,SAAS,OAAO;AACd,gBAAQ,MAAM,GAAG,UAAU,iDAAiD,KAAK;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGQ,kBAAkC,CAAC;AAAA,EACnC,iBAAiC,CAAC;AAAA,EAClC,mBAAmB;AAAA,EAElB,aAAiC;AAAA,IACxC,UAAU,CAAC,aAAyB;AAClC,cAAQ,IAAI,GAAG,UAAU,8CAA8C;AACvE,WAAK,gBAAgB,KAAK,QAAQ;AAAA,IACpC;AAAA,IACA,SAAS,CAAC,aAAyB;AACjC,cAAQ,IAAI,GAAG,UAAU,6CAA6C;AACtE,WAAK,eAAe,KAAK,QAAQ;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAc,qBAAoC;AAChD,YAAQ,IAAI,GAAG,UAAU,2DAA2D;AAEpF,UAAM,SAAU,YAAoB,KAAK;AACzC,QAAI,CAAC,UAAU,WAAW,qBAAqB;AAC7C,cAAQ,KAAK,GAAG,UAAU,0EAA0E;AACpG;AAAA,IACF;AACA,YAAQ,IAAI,GAAG,UAAU,uCAAuC,OAAO,MAAM,GAAG;AAEhF,QAAI;AACF,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,4BAA4B;AAC/D,WAAK,kBAAkB,EAAE,UAAU;AACnC,cAAQ,IAAI,GAAG,UAAU,2BAA2B;AAEpD,YAAM,QAAS,YAAoB,KAAK;AACxC,YAAM,UAAW,YAAoB,KAAK,yBAAyB,UAAW,YAAoB,KAAK,QAAQ;AAE/G,YAAM,UAAU,QAAQ;AAAA,QACtB;AAAA,QACA,OAAO,SAAS;AAAA,QAChB;AAAA,QACA,6BAA6B;AAAA,QAC7B,4BAA4B;AAAA,QAC5B,oBAAoB;AAAA,MACtB,CAAC;AACD,cAAQ,IAAI,GAAG,UAAU,iCAAiC;AAG1D,YAAM,UAAU,SAAS,EAAE,WAAW,YAAY,YAAY,EAAE,cAAc,KAAK,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC;AACvG,cAAQ,IAAI,GAAG,UAAU,iCAAiC;AAAA,IAC5D,SAAS,KAAK;AACZ,cAAQ,MAAM,GAAG,UAAU,2BAA2B,GAAG;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA,EAGS,YAA+B;AAAA,IACtC,gBAAgB,YAA2B;AACzC,cAAQ,IAAI,GAAG,UAAU,6BAA6B;AACtD,UAAI;AACF,cAAM,aAAa,KAAK;AACxB,gBAAQ,IAAI,GAAG,UAAU,qDAAqD;AAAA,MAChF,SAAS,OAAO;AACd,gBAAQ,IAAI,GAAG,UAAU,oEAAoE;AAAA,MAC/F;AAGA,YAAM,SAAS,SAAS,eAAe,gBAAgB;AACvD,UAAI,QAAQ;AACV,eAAO,MAAM,UAAU;AACvB,gBAAQ,IAAI,GAAG,UAAU,2DAA2D;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,gBAAgB,SAAgE;AACpF,YAAQ,IAAI,GAAG,UAAU,sBAAsB,OAAO;AAGtD,QAAI,UAAU,iBAAiB,GAAG;AAChC,YAAM,KAAK,mBAAmB;AAAA,IAChC;AAGA,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,mBAAmB;AAExB,UAAI;AACF,YAAI,YAAY,kBAAkB,CAAC,EAAE,SAAS,MAAM;AAClD,cAAI,UAAU;AACZ,oBAAQ,IAAI,GAAG,UAAU,gCAAgC,KAAK,gBAAgB,MAAM,mBAAmB;AACvG,iBAAK,gBAAgB,QAAQ,QAAM,GAAG,CAAC;AAAA,UACzC,OAAO;AACL,oBAAQ,IAAI,GAAG,UAAU,kCAAkC,KAAK,eAAe,MAAM,kBAAkB;AACvG,iBAAK,eAAe,QAAQ,QAAM,GAAG,CAAC;AAAA,UACxC;AAAA,QACF,CAAC;AACD,gBAAQ,IAAI,GAAG,UAAU,oCAAoC;AAAA,MAC/D,SAAS,OAAO;AACd,gBAAQ,IAAI,GAAG,UAAU,qEAAqE;AAE9F,iBAAS,iBAAiB,oBAAoB,MAAM;AAClD,cAAI,SAAS,QAAQ;AACnB,oBAAQ,IAAI,GAAG,UAAU,+CAA+C;AACxE,iBAAK,eAAe,QAAQ,QAAM,GAAG,CAAC;AAAA,UACxC,OAAO;AACL,oBAAQ,IAAI,GAAG,UAAU,iDAAiD;AAC1E,iBAAK,gBAAgB,QAAQ,QAAM,GAAG,CAAC;AAAA,UACzC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,YAAQ,IAAI,GAAG,UAAU,2CAAsC;AAE/D,WAAO;AAAA,MACL,aAAa;AAAA,MACb,MAAM,EAAE,UAAU,YAAY;AAAA,IAChC;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,YAAoB,MAAuB;AAC7C,YAAQ,IAAI,GAAG,UAAU,SAAS,SAAS,GAAG,IAAI;AAAA,EACpD;AACF;;;AC9WA,IAAI,mBAA2C;AAK/C,SAAS,iBAA+B;AAItC,MAAI,OAAO,WAAW,eAAe,OAAO,OAAO,UAAU,aAAa,UAAU;AAClF,UAAM,OAAO,OAAO,SAAS,SAAS,YAAY;AAClD,QAAI,KAAK,SAAS,aAAa,KAAK,KAAK,SAAS,qBAAqB,GAAG;AACxE,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,OAAO,WAAW,eAAgB,OAAe,WAAW;AAC9D,WAAO;AAAA,EACT;AAIA,MAAI,OAAO,gBAAgB,eAAgB,YAAoB,KAAK,kBAAkB,aAAa;AACjG,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAMA,eAAe,oBAAoB,MAA8C;AAC/E,MAAI,eAAe,SAAS,SAAS,eAAe,IAAI;AAGxD,QAAM,mBACJ,OAAQ,YAAoB,QAAQ,eACnC,YAAoB,KAAK,kBAAkB;AAC9C,MAAI,oBAAoB,iBAAiB,UAAU;AACjD,YAAQ,IAAI,4EAA4E;AACxF,mBAAe;AAAA,EACjB;AAEA,UAAQ,cAAc;AAAA,IACpB,KAAK;AACH,cAAQ,IAAI,oCAAoC;AAChD,aAAO,IAAI,kBAAkB;AAAA,IAC/B,KAAK;AAAA,IACL;AACE,cAAQ,IAAI,kDAAkD;AAC9D,YAAM,EAAE,eAAe,IAAI,MAAM,OAAO,8BAAkB;AAC1D,aAAO,IAAI,eAAe;AAAA,EAC9B;AACF;AA2BA,eAAsB,wBAAwB,OAAqB,QAAkC;AACnG,MAAI,kBAAkB;AACpB,YAAQ,KAAK,6DAA6D;AAC1E,WAAO;AAAA,EACT;AAEA,qBAAmB,MAAM,oBAAoB,IAAI;AACjD,SAAO;AACT;AASO,SAAS,mBAAmB,OAAqB,QAAyB;AAC/E,MAAI,kBAAkB;AACpB,YAAQ,KAAK,6DAA6D;AAC1E,WAAO;AAAA,EACT;AAGA,QAAM,eAAe,SAAS,SAAS,eAAe,IAAI;AAC1D,MAAI,iBAAiB,aAAa;AAChC,uBAAmB,IAAI,kBAAkB;AACzC,WAAO;AAAA,EACT;AAGA,QAAM,IAAI;AAAA,IACR;AAAA,EAGF;AACF;AAMO,SAAS,cAA+B;AAC7C,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,wBAAiC;AAC/C,SAAO,qBAAqB;AAC9B;AAKO,SAAS,gBAAsB;AACpC,qBAAmB;AACrB;AAeO,IAAM,WAA4B,IAAI,MAAM,CAAC,GAAsB;AAAA,EACxE,IAAI,SAAS,MAA6B;AACxC,QAAI,CAAC,kBAAkB;AAErB,YAAM,eAAe,eAAe;AACpC,UAAI,iBAAiB,aAAa;AAChC,gBAAQ,IAAI,gEAAgE;AAC5E,2BAAmB,IAAI,kBAAkB;AAAA,MAC3C,OAAO;AACL,cAAM,IAAI;AAAA,UACR;AAAA,QAEF;AAAA,MACF;AAAA,IACF;AACA,WAAO,iBAAiB,IAAI;AAAA,EAC9B;AACF,CAAC;;;ACnOD,YAAYC,YAAW;AAEhB,IAAM,cAAmC;AAAA,EAC9C,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAMd,aAAmB;AACjB,QAAI,gBAAgB;AAEpB,UAAM,2BAA2B,YAAY;AAC3C,UAAI,cAAe;AAEnB,UAAI;AAEF,cAAM,cAAe,YAAY,cAAsB;AACvD,YAAI,eAAe,YAAY,UAAU,aAAa;AACpD,gBAAM,YAAY,OAAO;AACzB,kBAAQ,IAAI,iCAA0B;AAAA,QACxC;AAEA,wBAAgB;AAGhB,iBAAS,oBAAoB,SAAS,wBAAwB;AAC9D,iBAAS,oBAAoB,WAAW,wBAAwB;AAChE,iBAAS,oBAAoB,cAAc,wBAAwB;AAEnE,gBAAQ,IAAI,oCAA6B;AAAA,MAC3C,SAAS,OAAO;AACd,gBAAQ,KAAK,+BAA+B,KAAK;AAAA,MACnD;AAAA,IACF;AAGA,aAAS,iBAAiB,SAAS,wBAAwB;AAC3D,aAAS,iBAAiB,WAAW,wBAAwB;AAC7D,aAAS,iBAAiB,cAAc,wBAAwB;AAEhE,YAAQ,IAAI,6DAAsD;AAAA,EACpE;AACF;AAEO,IAAM,kBAA+B,CAAC;AACtC,IAAM,kBAA+B,CAAC;AAQ7C,IAAI,iBAAyB;AAC7B,IAAI,gBAAyB;AAoB7B,eAAsB,oBACpB,gBACA,WACA,OACe;AACf,QAAM,eAAe,MAAM,IAAI,CAAC,QAAQ;AACtC,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,UAAI,eAAe,cAAc;AAC/B,kBAAU,IAAI,IAAI,IAAI,IAAU,aAAM,eAAe,YAAY;AAAA,MACnE,OAAO;AACL,gBAAQ,MAAM,iDAAiD;AAC/D,eAAO,IAAI,MAAM,gCAAgC,IAAI,IAAI,EAAE,CAAC;AAC5D;AAAA,MACF;AACA,YAAM,cAAc,IAAU,mBAAY;AAC1C,kBAAY;AAAA,QACV,IAAI;AAAA,QACJ,SAAU,QAAQ;AAChB,oBAAU,IAAI,IAAI,EAAE,UAAU,MAAM;AACpC,oBAAU,IAAI,IAAI,EAAE,QAAQ,KAAK;AACjC,gBAAM,aAAa,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS;AACjE,oBAAU,IAAI,IAAI,EAAE,UAAU,UAAU;AACxC,kBAAQ;AAAA,QACV;AAAA,QACA;AAAA;AAAA,QACA,SAAU,OAAO;AACf,kBAAQ,MAAM,8BAA8B,IAAI,IAAI,IAAI,KAAK;AAC7D,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,QAAM,QAAQ,IAAI,YAAY;AAChC;AAEA,eAAsB,oBACpB,gBACA,WACA,OACe;AACf,QAAM,eAAe,MAAM,IAAI,CAAC,QAAQ;AACtC,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,UAAI,eAAe,cAAc;AAC/B,kBAAU,IAAI,IAAI,IAAI,IAAU,uBAAgB,eAAe,YAAY;AAAA,MAC7E,OAAO;AACL,gBAAQ,MAAM,iDAAiD;AAC/D,eAAO,IAAI,MAAM,gCAAgC,IAAI,IAAI,EAAE,CAAC;AAC5D;AAAA,MACF;AACA,YAAM,cAAc,IAAU,mBAAY;AAC1C,kBAAY;AAAA,QACV,IAAI;AAAA,QACJ,SAAU,QAAQ;AAChB,oBAAU,IAAI,IAAI,EAAE,UAAU,MAAM;AACpC,oBAAU,IAAI,IAAI,EAAE,eAAe,EAAE;AACrC,oBAAU,IAAI,IAAI,EAAE,QAAQ,KAAK;AACjC,gBAAM,aAAa,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS;AACjE,oBAAU,IAAI,IAAI,EAAE,UAAU,UAAU;AACxC,kBAAQ;AAAA,QACV;AAAA,QACA;AAAA;AAAA,QACA,SAAU,OAAO;AACf,kBAAQ,MAAM,8BAA8B,IAAI,IAAI,IAAI,KAAK;AAC7D,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,QAAM,QAAQ,IAAI,YAAY;AAChC;AAEO,SAAS,mBAAmB,WAAwB,WAAmB;AAC5E,MAAI,CAAC,UAAU,SAAS,GAAG;AACzB,UAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,EAC9D;AAEA,MAAI,CAAC,UAAU,SAAS,EAAE,QAAQ;AAChC,UAAM,IAAI,MAAM,8BAA8B,SAAS,EAAE;AAAA,EAC3D;AAEA,YAAU,SAAS,EAAE,KAAK;AAC5B;AAOO,SAAS,kBAAkB,WAAwB,WAA6B;AACrF,MAAI,CAAC,MAAM,QAAQ,SAAS,KAAK,UAAU,WAAW,GAAG;AACvD,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AAGA,QAAM,aAAa,UAAU,OAAO,CAAC,SAAS;AAC5C,UAAM,QAAQ,UAAU,IAAI;AAC5B,WAAO,CAAC,EAAE,SAAS,MAAM;AAAA,EAC3B,CAAC;AAED,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AAEA,QAAM,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,WAAW,MAAM;AAC1D,QAAM,SAAS,WAAW,KAAK;AAC/B,qBAAmB,WAAW,MAAM;AACpC,SAAO;AACT;AAEO,SAAS,mBACd,WACA,WACA,cACA;AACA,MAAI,CAAC,UAAU,SAAS,GAAG;AACzB,UAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,EAC9D;AAEA,MAAI,CAAC,UAAU,SAAS,EAAE,QAAQ;AAChC,UAAM,IAAI,MAAM,8BAA8B,SAAS,EAAE;AAAA,EAC3D;AAEA,eAAa,IAAI,UAAU,SAAS,CAAC;AACrC,YAAU,SAAS,EAAE,KAAK;AAC5B;AAGO,SAAS,gBAAgB,QAAsB;AACpD,QAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACzC,mBAAiB;AAEjB,MAAI,YAAY,cAAc;AAC5B,gBAAY,aAAa,gBAAgB,gBAAgB,IAAI,CAAC;AAAA,EAChE;AACF;AAGO,SAAS,kBAA0B;AACxC,SAAO;AACT;AAGO,SAAS,cAAc,OAAsB;AAClD,kBAAgB,CAAC,CAAC;AAElB,MAAI,YAAY,cAAc;AAC5B,gBAAY,aAAa,gBAAgB,gBAAgB,IAAI,cAAc;AAAA,EAC7E;AACF;AAGO,SAAS,eAAwB;AACtC,SAAO;AACT;;;ACtOA,YAAYC,YAAW;;;ACAvB,YAAYC,YAAW;;;ACAvB,YAAYC,YAAW;AAGhB,IAAM,YAA2B,CAAC;AAiBlC,IAAM,cAAgC;AAAA,EAC3C,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,QAAQ;AAAA;AAAA,EACR,MAAM;AAAA,EACN,UAAU,CAAC;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAClB;AAQA,eAAsB,kBACpB,gBACA,WACA,WACe;AACf,QAAM,eAAe,UAAU,IAAI,CAAC,cAAc;AAChD,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,UAAI,eAAe,cAAc;AAC/B,kBAAU,SAAS,IAAI,IAAU,aAAM,eAAe,YAAY;AAAA,MACpE,OAAO;AACL,gBAAQ,MAAM,iDAAiD;AAC/D,eAAO,IAAI,MAAM,gCAAgC,SAAS,EAAE,CAAC;AAC7D;AAAA,MACF;AAEA,YAAM,cAAc,IAAU,mBAAY;AAC1C,kBAAY;AAAA,QACV;AAAA,QACA,SAAU,QAAQ;AAChB,oBAAU,SAAS,EAAE,UAAU,MAAM;AACrC,oBAAU,SAAS,EAAE,QAAQ,IAAI;AACjC,oBAAU,SAAS,EAAE,UAAU,YAAY,MAAM;AACjD,kBAAQ,IAAI,wBAAmB,SAAS,EAAE;AAC1C,kBAAQ;AAAA,QACV;AAAA,QACA;AAAA;AAAA,QACA,SAAU,OAAO;AACf,kBAAQ,MAAM,8BAA8B,SAAS,IAAI,KAAK;AAC9D,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAED,QAAM,QAAQ,IAAI,YAAY;AAChC;AAQO,SAAS,UAAU,WAA0B,WAAmB,OAAgB,MAAY;AACjG,MAAI,CAAC,UAAU,SAAS,GAAG;AACzB,UAAM,IAAI,MAAM,kCAAkC,SAAS,EAAE;AAAA,EAC/D;AAEA,MAAI,CAAC,UAAU,SAAS,EAAE,QAAQ;AAChC,UAAM,IAAI,MAAM,+BAA+B,SAAS,EAAE;AAAA,EAC5D;AAGA,MAAI,YAAY,gBAAgB,YAAY,WAAW;AACrD,cAAU,SAAS;AAAA,EACrB;AAGA,QAAM,QAAQ,UAAU,SAAS;AACjC,QAAM,QAAQ,IAAI;AAClB,QAAM,UAAU,YAAY,MAAM;AAGlC,QAAM,KAAK;AAGX,cAAY,eAAe;AAC3B,cAAY,YAAY;AACxB,cAAY,WAAW;AACvB,cAAY,OAAO;AAEnB,UAAQ,IAAI,4BAAqB,SAAS,EAAE;AAC9C;AAMO,SAAS,WAAW,WAAgC;AACzD,MAAI,YAAY,gBAAgB,YAAY,aAAa,CAAC,YAAY,UAAU;AAC9E,UAAM,QAAQ,UAAU,YAAY,YAAY;AAChD,QAAI,OAAO;AACT,YAAM,MAAM;AACZ,kBAAY,WAAW;AACvB,cAAQ,IAAI,8BAAoB,YAAY,YAAY,EAAE;AAAA,IAC5D;AAAA,EACF;AACF;AAMO,SAAS,YAAY,WAAgC;AAC1D,MAAI,YAAY,gBAAgB,YAAY,aAAa,YAAY,UAAU;AAC7E,UAAM,QAAQ,UAAU,YAAY,YAAY;AAChD,QAAI,OAAO;AACT,YAAM,KAAK;AACX,kBAAY,WAAW;AACvB,cAAQ,IAAI,+BAAqB,YAAY,YAAY,EAAE;AAAA,IAC7D;AAAA,EACF;AACF;AAMO,SAAS,UAAU,WAAgC;AACxD,MAAI,YAAY,gBAAgB,YAAY,WAAW;AACrD,UAAM,QAAQ,UAAU,YAAY,YAAY;AAChD,QAAI,OAAO;AACT,YAAM,KAAK;AACX,cAAQ,IAAI,+BAAqB,YAAY,YAAY,EAAE;AAAA,IAC7D;AAAA,EACF;AAGA,cAAY,eAAe;AAC3B,cAAY,YAAY;AACxB,cAAY,WAAW;AACzB;AAOO,SAAS,eAAe,QAAgB,WAAgC;AAE7E,WAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AACxC,cAAY,SAAS;AAGrB,MAAI,YAAY,gBAAgB,YAAY,WAAW;AACrD,UAAM,QAAQ,UAAU,YAAY,YAAY;AAChD,QAAI,OAAO;AACT,YAAM,UAAU,MAAM;AAAA,IACxB;AAAA,EACF;AAEA,UAAQ,IAAI,kCAA2B,KAAK,MAAM,SAAS,GAAG,CAAC,GAAG;AACpE;AAMO,SAAS,YAAY,WAAgC;AAC1D,MAAI,YAAY,aAAa,CAAC,YAAY,UAAU;AAClD,eAAW,SAAS;AAAA,EACtB,WAAW,YAAY,aAAa,YAAY,UAAU;AACxD,gBAAY,SAAS;AAAA,EACvB;AACF;AAOO,SAAS,aAAa,WAA0B,WAA4B;AACjF,QAAM,QAAQ,UAAU,SAAS;AACjC,SAAO,SAAS,CAAC,CAAC,MAAM;AAC1B;AAKO,SAAS,sBAAwC;AACtD,SAAO,EAAE,GAAG,YAAY;AAC1B;AASO,SAAS,iBACd,WACA,cACA,eAAuB,KACvB,OAAgB,MACV;AACN,MAAI,CAAC,UAAU,YAAY,GAAG;AAC5B,UAAM,IAAI,MAAM,kCAAkC,YAAY,EAAE;AAAA,EAClE;AAEA,MAAI,CAAC,UAAU,YAAY,EAAE,QAAQ;AACnC,UAAM,IAAI,MAAM,+BAA+B,YAAY,EAAE;AAAA,EAC/D;AAEA,QAAM,WAAW,YAAY,eAAe,UAAU,YAAY,YAAY,IAAI;AAClF,QAAM,WAAW,UAAU,YAAY;AAGvC,WAAS,QAAQ,IAAI;AACrB,WAAS,UAAU,CAAC;AACpB,WAAS,KAAK;AAGd,cAAY,eAAe;AAC3B,cAAY,YAAY;AACxB,cAAY,WAAW;AACvB,cAAY,OAAO;AAGnB,QAAM,QAAQ;AACd,QAAM,eAAe,eAAe;AACpC,QAAM,aAAa,YAAY,SAAS;AAExC,MAAI,cAAc;AAElB,QAAM,eAAe,YAAY,MAAM;AACrC;AACA,UAAM,WAAW,cAAc;AAG/B,QAAI,UAAU;AACZ,eAAS,UAAU,YAAY,UAAU,IAAI,SAAS;AAAA,IACxD;AAGA,aAAS,UAAU,YAAY,SAAS,QAAQ;AAEhD,QAAI,eAAe,OAAO;AAExB,oBAAc,YAAY;AAG1B,UAAI,UAAU;AACZ,iBAAS,KAAK;AAAA,MAChB;AAEA,cAAQ,IAAI,oCAA6B,YAAY,EAAE;AAAA,IACzD;AAAA,EACF,GAAG,YAAY;AACjB;AAWO,SAAS,+BACd,WACA,WACA,OAAgB,MACV;AAEN,MAAI;AACF,cAAU,WAAW,WAAW,IAAI;AACpC,YAAQ,IAAI,gDAAyC;AACrD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,IAAI,4EAAqE;AAAA,EACnF;AAGA,QAAM,0BAA0B,MAAM;AACpC,QAAI;AAEF,YAAM,UAAW,YAAY,cAAsB;AACnD,UAAI,WAAW,QAAQ,UAAU,aAAa;AAC5C,gBAAQ,OAAO;AAAA,MACjB;AAGA,UAAI,CAAC,YAAY,WAAW;AAC1B,kBAAU,WAAW,WAAW,IAAI;AACpC,gBAAQ,IAAI,2DAAoD;AAAA,MAClE;AAGA,eAAS,oBAAoB,SAAS,uBAAuB;AAC7D,eAAS,oBAAoB,WAAW,uBAAuB;AAC/D,eAAS,oBAAoB,cAAc,uBAAuB;AAAA,IACpE,SAAS,OAAO;AACd,cAAQ,KAAK,yCAAyC,KAAK;AAAA,IAC7D;AAAA,EACF;AAGA,WAAS,iBAAiB,SAAS,uBAAuB;AAC1D,WAAS,iBAAiB,WAAW,uBAAuB;AAC5D,WAAS,iBAAiB,cAAc,uBAAuB;AAE/D,UAAQ,IAAI,iFAA0E;AACxF;AAMA,SAAS,mBAAmB,WAAgC;AAC1D,MAAI,CAAC,YAAY,kBAAkB,YAAY,SAAS,WAAW,GAAG;AACpE;AAAA,EACF;AAGA,cAAY,iBAAiB,YAAY,gBAAgB,KAAK,YAAY,SAAS;AACnF,QAAM,YAAY,YAAY,SAAS,YAAY,aAAa;AAEhE,UAAQ;AAAA,IACN,2CAAoC,YAAY,gBAAgB,CAAC,IAAI,YAAY,SAAS,MAAM,MAAM,SAAS;AAAA,EACjH;AAGA,oBAAkB,WAAW,SAAS;AACxC;AAOA,SAAS,kBAAkB,WAA0B,WAAyB;AAC5E,MAAI,CAAC,UAAU,SAAS,GAAG;AACzB,YAAQ,MAAM,kCAAkC,SAAS,EAAE;AAC3D;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,SAAS,EAAE,QAAQ;AAChC,YAAQ,MAAM,+BAA+B,SAAS,EAAE;AACxD;AAAA,EACF;AAGA,MAAI,YAAY,gBAAgB,YAAY,WAAW;AACrD,UAAM,eAAe,UAAU,YAAY,YAAY;AACvD,QAAI,cAAc;AAEhB,mBAAa,QAAQ,sBAAsB,SAAS,MAAM;AAAA,MAAC,CAAC;AAC5D,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,QAAQ,UAAU,SAAS;AACjC,QAAM,QAAQ,KAAK;AACnB,QAAM,UAAU,YAAY,MAAM;AAGlC,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY,gBAAgB;AAC9B,yBAAmB,SAAS;AAAA,IAC9B;AAAA,EACF;AAGA,QAAM,KAAK;AAGX,MAAI,MAAM,QAAQ;AAChB,UAAM,OAAO,UAAU;AAAA,EACzB;AAGA,cAAY,eAAe;AAC3B,cAAY,YAAY;AACxB,cAAY,WAAW;AACvB,cAAY,OAAO;AACrB;AAQO,SAAS,cACd,WACA,YACA,aAAqB,GACf;AACN,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,KAAK,4CAA4C;AACzD;AAAA,EACF;AAGA,aAAW,aAAa,YAAY;AAClC,QAAI,CAAC,UAAU,SAAS,GAAG;AACzB,cAAQ,MAAM,kCAAkC,SAAS,EAAE;AAC3D;AAAA,IACF;AAAA,EACF;AAGA,cAAY,WAAW,CAAC,GAAG,UAAU;AACrC,cAAY,gBAAgB;AAC5B,cAAY,iBAAiB;AAE7B,QAAM,aAAa,YAAY,SAAS,YAAY,aAAa;AACjE,UAAQ,IAAI,oCAA6B,WAAW,MAAM,YAAY,WAAW,KAAK,IAAI,CAAC,EAAE;AAG7F,oBAAkB,WAAW,UAAU;AACzC;AAMO,SAAS,aAAa,WAAgC;AAC3D,cAAY,iBAAiB;AAC7B,cAAY,WAAW,CAAC;AACxB,cAAY,gBAAgB;AAC5B,YAAU,SAAS;AACrB;AAOO,SAAS,kCACd,WACA,YACM;AAEN,MAAI;AACF,kBAAc,WAAW,UAAU;AACnC,YAAQ,IAAI,wCAAiC;AAC7C;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,IAAI,+EAAwE;AAAA,EACtF;AAGA,QAAM,6BAA6B,MAAM;AACvC,QAAI;AAEF,YAAM,UAAW,YAAY,cAAsB;AACnD,UAAI,WAAW,QAAQ,UAAU,aAAa;AAC5C,gBAAQ,OAAO;AAAA,MACjB;AAGA,UAAI,CAAC,YAAY,WAAW;AAC1B,sBAAc,WAAW,UAAU;AACnC,gBAAQ,IAAI,mDAA4C;AAAA,MAC1D;AAGA,eAAS,oBAAoB,SAAS,0BAA0B;AAChE,eAAS,oBAAoB,WAAW,0BAA0B;AAClE,eAAS,oBAAoB,cAAc,0BAA0B;AAAA,IACvE,SAAS,OAAO;AACd,cAAQ,KAAK,4CAA4C,KAAK;AAAA,IAChE;AAAA,EACF;AAGA,WAAS,iBAAiB,SAAS,0BAA0B;AAC7D,WAAS,iBAAiB,WAAW,0BAA0B;AAC/D,WAAS,iBAAiB,cAAc,0BAA0B;AAElE,UAAQ,IAAI,oFAA6E;AAC3F;;;ACtfA,YAAYC,YAAW;AAqEhB,IAAM,uBAAN,MAAM,sBAAqB;AAAA,EAChC,OAAe,YAAyC;AAAA,EAEhD,QAA4B;AAAA,EAC5B,UAAsC,oBAAI,IAAI;AAAA,EAC9C,gBAAyB;AAAA,EAEjC,OAAwB,mBAAmB;AAAA;AAAA,EAC3C,OAAwB,gBAAgB;AAAA;AAAA;AAAA,EAGvB,gBAAgB,IAAU,eAAQ;AAAA,EAClC,kBAAkB,IAAU,kBAAW;AAAA,EACvC,aAAa,IAAU,eAAQ;AAAA,EAExC,cAAc;AAAA,EAAC;AAAA;AAAA;AAAA;AAAA,EAKvB,OAAc,cAAoC;AAChD,QAAI,CAAC,sBAAqB,WAAW;AACnC,4BAAqB,YAAY,IAAI,sBAAqB;AAAA,IAC5D;AACA,WAAO,sBAAqB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,WAAW,OAA0B;AAC1C,QAAI,KAAK,eAAe;AACtB,cAAQ,KAAK,2CAA2C;AACxD;AAAA,IACF;AACA,SAAK,QAAQ;AACb,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKO,UAAmB;AACxB,WAAO,KAAK,iBAAiB,KAAK,UAAU;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeO,iBACL,UACA,UACA,UACA,aAAsB,OACtB,gBAAyB,OACzB,kBAA0B,sBAAqB,kBACzB;AACtB,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,OAAO;AACtC,cAAQ,MAAM,sEAAsE;AACpF,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,KAAK,QAAQ,IAAI,QAAQ;AAC1C,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,KAAK,aAAa,eAAe;AAGlD,UAAM,gBAAgB,IAAU,qBAAc,UAAU,UAAU,QAAQ;AAC1E,kBAAc,OAAO,aAAa,QAAQ;AAC1C,kBAAc,aAAa;AAC3B,kBAAc,gBAAgB;AAC9B,kBAAc,gBAAgB;AAC9B,kBAAc,QAAQ;AAGtB,SAAK,MAAM,IAAI,aAAa;AAG5B,UAAM,QAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA,kBAAkB,CAAC;AAAA,MACnB,iBAAiB,CAAC;AAAA,MAClB,aAAa,oBAAI,IAAI;AAAA;AAAA,MACrB,cAAc;AAAA,MACd;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AAEA,SAAK,QAAQ,IAAI,UAAU,KAAK;AAChC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,+BACL,UACA,YACA,aAAsB,OACtB,gBAAyB,OACzB,kBAA0B,sBAAqB,kBACzB;AAEtB,UAAM,WAAW,KAAK,QAAQ,IAAI,QAAQ;AAC1C,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAGA,QAAI,WAAwC;AAC5C,QAAI,WAAkC;AAEtC,eAAW,SAAS,CAAC,UAAU;AAC7B,UAAI,CAAC,YAAY,iBAAuB,aAAM;AAC5C,mBAAW,MAAM;AACjB,mBAAW,MAAM,QAAQ,MAAM,QAAQ,IAAI,MAAM,SAAS,CAAC,IAAI,MAAM;AAAA,MACvE;AAAA,IACF,CAAC;AAED,QAAI,CAAC,YAAY,CAAC,UAAU;AAC1B,cAAQ,MAAM,gEAAgE,QAAQ,GAAG;AACzF,aAAO;AAAA,IACT;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,GAAmB;AACtC,QAAI,KAAK,EAAG,QAAO;AACnB;AACA,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AACV,SAAK,KAAK;AACV,WAAO,IAAI;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,OAAsB,aAA2B;AACnE,QAAI,CAAC,KAAK,MAAO;AAEjB,UAAM,WAAW,KAAK,aAAa,WAAW;AAC9C,QAAI,YAAY,MAAM,aAAc;AAGpC,UAAM,mBAAmB,IAAU,qBAAc,MAAM,UAAU,MAAM,UAAU,QAAQ;AACzF,qBAAiB,OAAO,MAAM,cAAc;AAC5C,qBAAiB,aAAa,MAAM,cAAc;AAClD,qBAAiB,gBAAgB,MAAM,cAAc;AACrD,qBAAiB,gBAAgB;AACjC,qBAAiB,QAAQ,MAAM,cAAc;AAG7C,aAAS,IAAI,GAAG,IAAI,MAAM,cAAc,OAAO,KAAK;AAClD,YAAM,SAAS,IAAU,eAAQ;AACjC,YAAM,cAAc,YAAY,GAAG,MAAM;AACzC,uBAAiB,YAAY,GAAG,MAAM;AAAA,IACxC;AACA,qBAAiB,eAAe,cAAc;AAG9C,SAAK,MAAM,OAAO,MAAM,aAAa;AACrC,UAAM,cAAc,QAAQ;AAC5B,SAAK,MAAM,IAAI,gBAAgB;AAG/B,UAAM,gBAAgB;AACtB,UAAM,eAAe;AAErB,YAAQ,IAAI,wCAAwC,MAAM,QAAQ,QAAQ,QAAQ,YAAY;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,UAA2B;AACzC,WAAO,KAAK,QAAQ,IAAI,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,UAAwC;AACtD,WAAO,KAAK,QAAQ,IAAI,QAAQ,KAAK;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,OAA8B;AAC1D,WAAO,MAAM,iBAAiB,SAAS,MAAM,gBAAgB;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,OAAuB,qBAAqB;AAAA,IAC1C,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,iBAAiB;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYO,YACL,UACA,YACA,UAKI,CAAC,GACU;AACf,UAAM,YAAY,QAAQ,aAAa;AACvC,UAAM,aAAa,QAAQ,cAAc;AACzC,UAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,UAAM,kBAAkB,QAAQ,mBAAmB,sBAAqB;AAGxE,QAAI,QAA8B,KAAK,QAAQ,IAAI,QAAQ,KAAK;AAChE,QAAI,CAAC,OAAO;AACV,cAAQ,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,CAAC,OAAO;AACV,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,KAAK,sBAAsB,KAAK,KAAK,MAAM,cAAc;AAC3D,WAAK,YAAY,OAAO,MAAM,eAAe,sBAAqB,aAAa;AAAA,IACjF;AAEA,UAAM,aAAa,GAAG,QAAQ,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAE1F,UAAM,eAA6B;AAAA,MACjC,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ,IAAU,eAAQ;AAAA,MAC1B,UAAU;AAAA,MACV;AAAA,MACA,SAAS;AAAA;AAAA,IACX;AAGA,SAAK,qBAAqB,YAAY;AAGtC,QAAI,WAAW;AACb,YAAM,iBAAiB,KAAK,YAAY;AAAA,IAC1C,OAAO;AACL,YAAM,gBAAgB,KAAK,YAAY;AAAA,IACzC;AAEA,UAAM,YAAY,IAAI,YAAY,YAAY;AAC9C,UAAM,eAAe;AAErB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,eAAe,UAAkB,YAA0B;AAChE,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAGZ,UAAM,WAAW,MAAM,YAAY,IAAI,UAAU;AACjD,QAAI,CAAC,SAAU;AAGf,UAAM,cAAc,SAAS,YAAY,MAAM,mBAAmB,MAAM;AACxE,UAAM,QAAQ,YAAY,QAAQ,QAAQ;AAC1C,QAAI,UAAU,IAAI;AAChB,YAAM,YAAY,YAAY,SAAS;AACvC,UAAI,UAAU,WAAW;AACvB,oBAAY,KAAK,IAAI,YAAY,SAAS;AAAA,MAC5C;AACA,kBAAY,IAAI;AAAA,IAClB;AAGA,UAAM,YAAY,OAAO,UAAU;AACnC,UAAM,eAAe;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,mBAAmB,UAAkB,YAAoB,SAAwB;AACtF,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAGZ,UAAM,WAAW,MAAM,YAAY,IAAI,UAAU;AACjD,QAAI,CAAC,SAAU;AAEf,QAAI,SAAS,aAAa,SAAS;AACjC,eAAS,WAAW;AACpB,YAAM,eAAe;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAmB,UAAkB,YAA6B;AACvE,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO,QAAO;AAGnB,UAAM,WAAW,MAAM,YAAY,IAAI,UAAU;AACjD,WAAO,UAAU,YAAY;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,kBAAkB,UAAkB,YAA0B;AACnE,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAEZ,UAAM,WAAW,MAAM,YAAY,IAAI,UAAU;AACjD,QAAI,CAAC,YAAY,SAAS,UAAW;AAErC,aAAS,UAAU;AACnB,UAAM,iBAAiB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBAAmB,UAAkB,YAAoB,WAA0B;AACxF,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAEZ,UAAM,WAAW,MAAM,YAAY,IAAI,UAAU;AACjD,QAAI,CAAC,YAAY,SAAS,cAAc,UAAW;AAGnD,UAAM,cAAc,SAAS,YAAY,MAAM,mBAAmB,MAAM;AACxE,UAAM,QAAQ,YAAY,QAAQ,QAAQ;AAC1C,QAAI,UAAU,IAAI;AAChB,YAAM,YAAY,YAAY,SAAS;AACvC,UAAI,UAAU,WAAW;AACvB,oBAAY,KAAK,IAAI,YAAY,SAAS;AAAA,MAC5C;AACA,kBAAY,IAAI;AAAA,IAClB;AAGA,aAAS,YAAY;AACrB,QAAI,WAAW;AACb,YAAM,iBAAiB,KAAK,QAAQ;AAAA,IACtC,OAAO;AACL,eAAS,UAAU;AACnB,YAAM,gBAAgB,KAAK,QAAQ;AACnC,YAAM,iBAAiB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,UAA8B;AACzD,aAAS,WAAW,iBAAiB,KAAK,aAAa;AACvD,aAAS,WAAW,mBAAmB,KAAK,eAAe;AAC3D,aAAS,WAAW,cAAc,KAAK,UAAU;AAEjD,aAAS,OAAO,QAAQ,KAAK,eAAe,KAAK,iBAAiB,KAAK,UAAU;AAAA,EACnF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YAAY,OAA4B;AAC9C,UAAM,mBAAmB,MAAM,iBAAiB,KAAK,CAAC,MAAM,EAAE,QAAQ;AACtE,UAAM,iBAAiB,oBAAoB,MAAM,gBAAgB,MAAM;AAGvE,QAAI,CAAC,gBAAgB;AACnB;AAAA,IACF;AAEA,QAAI,eAAe;AAGnB,eAAW,YAAY,MAAM,kBAAkB;AAC7C,UAAI,SAAS,UAAU;AACrB,aAAK,qBAAqB,QAAQ;AAClC,cAAM,cAAc,YAAY,cAAc,SAAS,MAAM;AAC7D;AAAA,MACF;AAAA,IACF;AAGA,eAAW,YAAY,MAAM,iBAAiB;AAC5C,UAAI,SAAS,UAAU;AAErB,YAAI,SAAS,WAAW,MAAM,cAAc;AAC1C,eAAK,qBAAqB,QAAQ;AAClC,mBAAS,UAAU;AAAA,QACrB;AACA,cAAM,cAAc,YAAY,cAAc,SAAS,MAAM;AAC7D;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAc,eAAe,cAAc;AACjD,UAAM,cAAc,QAAQ;AAG5B,UAAM,eAAe;AACrB,UAAM,iBAAiB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,mBAAyB;AAC9B,eAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AACzC,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,WAA0B;AAC/B,UAAM,oBAAoB,oBAAI,IAAoB;AAClD,QAAI,iBAAiB;AAErB,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,SAAS;AACvC,YAAM,gBAAgB,MAAM,iBAAiB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE;AACvE,YAAM,eAAe,MAAM,gBAAgB,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE;AACrE,YAAM,cAAc,gBAAgB;AACpC,wBAAkB,IAAI,KAAK,WAAW;AACtC,wBAAkB;AAAA,IACpB;AAEA,WAAO;AAAA,MACL,WAAW,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,MACzC;AAAA,MACA,YAAY,KAAK,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,cAAoB;AACzB,UAAM,QAAQ,KAAK,SAAS;AAC5B,YAAQ,IAAI,qCAAqC;AACjD,YAAQ,IAAI,YAAY,MAAM,UAAU,EAAE;AAC1C,YAAQ,IAAI,oBAAoB,MAAM,cAAc,EAAE;AACtD,eAAW,CAAC,KAAK,KAAK,KAAK,MAAM,mBAAmB;AAClD,YAAM,QAAQ,KAAK,QAAQ,IAAI,GAAG;AAClC,YAAM,eAAe,MAAM,iBAAiB;AAC5C,YAAM,cAAc,MAAM,gBAAgB;AAC1C,cAAQ;AAAA,QACN,KAAK,GAAG,KAAK,KAAK,IAAI,MAAM,YAAY,YAAY,YAAY,aAAa,WAAW;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,UAAwB;AACzC,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,CAAC,MAAO;AAGZ,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,OAAO,MAAM,aAAa;AAAA,IACvC;AAMA,SAAK,QAAQ,OAAO,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AACrB,eAAW,CAAC,GAAG,KAAK,KAAK,SAAS;AAChC,WAAK,YAAY,GAAG;AAAA,IACtB;AACA,SAAK,QAAQ,MAAM;AACnB,SAAK,QAAQ;AACb,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,QAAc;AAC1B,QAAI,sBAAqB,WAAW;AAClC,4BAAqB,UAAU,QAAQ;AACvC,4BAAqB,YAAY;AAAA,IACnC;AAAA,EACF;AACF;;;AChoBA,YAAYC,YAAW;AAMhB,IAAM,0BAAN,MAAM,yBAAwB;AAAA,EACnC,OAAe,WAA2C;AAAA;AAAA,EAGlD,UAA6B,oBAAI,IAAI;AAAA,EACrC,gBAAqC;AAAA;AAAA,EAG5B,UAAU,IAAU,eAAQ;AAAA,EAC5B,mBAAmB,IAAU,eAAQ;AAAA;AAAA,EAGrC,cAAc,IAAU,cAAO;AAAA,EAC/B,WAAW,IAAU,YAAK;AAAA,EAC1B,WAAW,IAAU,eAAQ;AAAA;AAAA,EAGtC,wBAAiC;AAAA,EACjC,yBAAkC;AAAA,EAClC,oBAA4B;AAAA;AAAA,EAC5B,cAAsB;AAAA;AAAA,EACtB,mBAA2B;AAAA;AAAA;AAAA,EAG3B,eAAuB;AAAA,EAEvB,cAAc;AAAA,EAAC;AAAA,EAEvB,OAAc,cAAuC;AACnD,QAAI,CAAC,yBAAwB,UAAU;AACrC,+BAAwB,WAAW,IAAI,yBAAwB;AAAA,IACjE;AACA,WAAO,yBAAwB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,QAAsB,YAAqB,OAAa;AACvE,SAAK,QAAQ,IAAI,MAAM;AACvB,QAAI,aAAa,CAAC,KAAK,eAAe;AACpC,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,QAA4B;AAC9C,SAAK,QAAQ,OAAO,MAAM;AAC1B,QAAI,KAAK,kBAAkB,QAAQ;AACjC,WAAK,gBACH,KAAK,QAAQ,OAAO,IAAK,KAAK,QAAQ,OAAO,EAAE,KAAK,EAAE,SAAS,OAAQ;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,QAA4B;AAClD,SAAK,UAAU,QAAQ,IAAI;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKO,yBAAyB,SAAwB;AACtD,SAAK,wBAAwB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKO,0BAA0B,SAAwB;AACvD,SAAK,yBAAyB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKO,qBAAqB,UAAwB;AAClD,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKO,eAAe,UAAwB;AAC5C,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,oBAAoB,QAAsB;AAC/C,SAAK,mBAAmB,KAAK,IAAI,GAAK,MAAM;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA,EAKO,aAAmB;AACxB,SAAK;AAGL,QAAI,KAAK,iBAAiB,KAAK,uBAAuB;AAEpD,WAAK,cAAc,kBAAkB,IAAI;AAGzC,UAAK,KAAK,cAA0C,qBAAqB;AACvE;AAAC,QAAC,KAAK,cAA0C,uBAAuB;AAAA,MAC1E;AAEA,WAAK,iBAAiB;AAAA,QACpB,KAAK,cAAc;AAAA,QACnB,KAAK,cAAc;AAAA,MACrB;AACA,WAAK,QAAQ,wBAAwB,KAAK,gBAAgB;AAAA,IAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,sBACL,QACA,iBAAyB,GACkB;AAE3C,QAAI,CAAC,KAAK,iBAAiB,KAAK,QAAQ,SAAS,GAAG;AAClD,aAAO,EAAE,cAAc,MAAM,OAAO,MAAM;AAAA,IAC5C;AAGA,WAAO,iBAAiB,KAAK,QAAQ;AAGrC,QAAI,KAAK,wBAAwB;AAC/B,YAAM,YAAY,KAAK,cAAc;AACrC,YAAM,SAAS,KAAK,SAAS,kBAAkB,SAAS;AACxD,YAAM,YAAY,KAAK,oBAAoB,KAAK;AAGhD,UAAI,SAAS,WAAW;AACtB,eAAO,EAAE,cAAc,OAAO,OAAO,MAAM;AAAA,MAC7C;AAGA,YAAM,YAAY,KAAK,cAAc,KAAK;AAC1C,UAAI,SAAS,WAAW;AAEtB,eAAO,EAAE,cAAc,KAAK,eAAe,MAAM,GAAG,OAAO,KAAK;AAAA,MAClE;AAAA,IACF;AAGA,QAAI,KAAK,uBAAuB;AAC9B,WAAK,YAAY,OAAO,KAAK,KAAK,QAAQ;AAG1C,WAAK,YAAY,SAAS,iBAAiB,KAAK;AAGhD,UAAI,YAAY;AAGhB,UAAI,KAAK,QAAQ,iBAAiB,KAAK,WAAW,GAAG;AACnD,oBAAY;AAAA,MACd,OAAO;AAEL,mBAAW,UAAU,KAAK,SAAS;AACjC,cAAI,WAAW,KAAK,cAAe;AAEnC,iBAAO,kBAAkB;AACzB,eAAK,iBAAiB,iBAAiB,OAAO,kBAAkB,OAAO,kBAAkB;AACzF,eAAK,QAAQ,wBAAwB,KAAK,gBAAgB;AAE1D,cAAI,KAAK,QAAQ,iBAAiB,KAAK,WAAW,GAAG;AACnD,wBAAY;AACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,WAAW;AACd,eAAO,EAAE,cAAc,OAAO,OAAO,MAAM;AAAA,MAC7C;AAAA,IACF;AAEA,WAAO,EAAE,cAAc,MAAM,OAAO,MAAM;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKO,WAKL;AACA,WAAO;AAAA,MACL,aAAa,KAAK,QAAQ;AAAA,MAC1B,uBAAuB,KAAK;AAAA,MAC5B,wBAAwB,KAAK;AAAA,MAC7B,cAAc,KAAK;AAAA,IACrB;AAAA,EACF;AACF;;;AHvLA,IAAM,iBAA4C;AAAA,EAChD,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,WAAW;AACb;AAMO,IAAe,YAAf,MAAe,WAAU;AAAA;AAAA,EAE9B,OAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA;AAAA,EAGL;AAAA,EACA;AAAA,EACA;AAAA,EACF;AAAA;AAAA,EAGR,IAAc,SAA6D;AACzE,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAc,OAAO,KAAyD;AAC5E,SAAK,kBAAkB;AACvB,eAAU,UAAU;AAAA,EACtB;AAAA,EACQ;AAAA,EACA,aAAsB;AAAA,EACtB,cAA6B;AAAA,EAC7B;AAAA;AAAA,EACA,eAAuB,IAAI;AAAA;AAAA;AAAA,EAGzB;AAAA;AAAA,EAGA,gBAA4C;AAAA;AAAA,EAG9C,0BAA0D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,iBAAyB;AACjC,WAAO,KAAK,MAAM,eAAe;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaU,YAA6B;AACrC,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKA,WAAkB,WAAsB;AACtC,WAAO,WAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAkB,QAAqB;AACrC,WAAO,WAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAkB,WAAgC;AAChD,WAAO,WAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAkB,SAA6D;AAC7E,WAAO,WAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAc,0BACZ,QACA,mBAA2B,KACrB;AACN,UAAM,WAAW,WAAU;AAC3B,QAAI,CAAC,SAAU;AAEf,QAAI,QAAQ;AACV,eAAS,0BAA0B,wBAAwB,YAAY;AACvE,eAAS,wBAAwB,UAAU,QAAQ,IAAI;AACvD,eAAS,wBAAwB,yBAAyB,IAAI;AAC9D,eAAS,wBAAwB,0BAA0B,KAAK;AAChE,eAAS,wBAAwB,oBAAoB,gBAAgB;AAAA,IACvE,OAAO;AAEL,UAAI,SAAS,yBAAyB;AACpC,iBAAS,wBAAwB,yBAAyB,KAAK;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,sBAA+C;AAC3D,WAAO,wBAAwB,YAAY;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAoB,OAElB,eAA6B,QACjB;AAEZ,UAAM,WAAW,IAAI,KAAK;AAG1B,eAAU,YAAY;AACtB,eAAU,SAAS,SAAS;AAC5B,eAAU,YAAY,SAAS;AAC/B,eAAU,UAAU,SAAS;AAG7B,UAAM,WAAW,MAAM,wBAAwB,YAAY;AAC3D,UAAM,UAAU,MAAM,SAAS,gBAAgB;AAAA,MAC7C,cAAc;AAAA,IAChB,CAAC;AACD,YAAQ,IAAI,sCAAsC,SAAS,YAAY,OAAO;AAE9E,aAAS,UAAU,gBAAgB,GAAG,oBAAoB;AAQ1D,aAAS,WAAW,SAAS,MAAM;AACjC,cAAQ,IAAI,oBAAoB;AAChC,aAAO,MAAM;AACb,eAAS,OAAO;AAAA,IAClB,CAAC;AAED,aAAS,WAAW,QAAQ,MAAM;AAChC,cAAQ,IAAI,mBAAmB;AAC/B,eAAS,MAAM;AAAA,IACjB,CAAC;AAGD,UAAM,cAAc,WAAW;AAG/B,iBAAa,WAAW;AAGxB,mBAAe,WAAW,SAAS,KAAK;AAGxC,qBAAiB,WAAW,SAAS,KAAK;AAG1C,yBAAqB,YAAY,EAAE,WAAW,SAAS,KAAK;AAG5D,aAAS,mBAAmB;AAG5B,UAAM,SAAS,QAAQ;AAGvB,aAAS,gBAAgB;AAEzB,UAAM,SAAS,UAAU,eAAe;AAExC,WAAO,MAAM;AAEb,WAAO;AAAA,EACT;AAAA,EAEA,SAAS;AACP,SAAK,MAAM,SAAS;AACpB,SAAK,WAAW;AAChB,gBAAY,cAAc,gBAAgB,KAAK,oBAAoB,CAAC;AAAA,EACtE;AAAA,EAEA,QAAQ;AACN,SAAK,WAAW;AAChB,SAAK,mBAAmB,YAAY,cAAc,gBAAgB;AAClE,gBAAY,cAAc,gBAAgB,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc;AAEZ,SAAK,SAAS,EAAE,GAAG,gBAAgB,GAAG,KAAK,UAAU,EAAE;AAGvD,UAAM,iBAAiB,SAAS,eAAe,cAAc;AAE7D,QAAI,0BAA0B,mBAAmB;AAE/C,WAAK,SAAS;AAAA,IAChB,OAAO;AAEL,YAAM,YAAY,SAAS,cAAc,QAAQ;AACjD,gBAAU,KAAK;AACf,gBAAU,MAAM,QAAQ;AACxB,gBAAU,MAAM,SAAS;AACzB,gBAAU,MAAM,UAAU;AAC1B,eAAS,KAAK,YAAY,SAAS;AACnC,WAAK,SAAS;AAAA,IAChB;AAGA,SAAK,WAAW,IAAU,qBAAc;AAAA,MACtC,QAAQ,KAAK;AAAA,MACb,WAAW,KAAK,OAAO;AAAA,MACvB,iBAAiB;AAAA,IACnB,CAAC;AACD,SAAK,SAAS,QAAQ,OAAO,YAAY,OAAO,WAAW;AAK3D,QAAI;AACJ,QAAI,KAAK,SAAS,GAAG;AACnB,sBAAgB;AAAA,IAClB,WAAW,KAAK,eAAe,GAAG;AAChC,sBAAgB;AAAA,IAClB,OAAO;AACL,sBAAgB,OAAO;AAAA,IACzB;AACA,UAAM,mBAAmB,KAAK,IAAI,OAAO,kBAAkB,aAAa;AACxE,SAAK,SAAS,cAAc,gBAAgB;AAC5C,YAAQ;AAAA,MACN,mCAAmC,OAAO,gBAAgB,YAAY,gBAAgB,aAAa,KAAK,SAAS,CAAC;AAAA,IACpH;AAGA,SAAK,qBAAqB;AAG1B,SAAK,QAAQ,IAAU,aAAM;AAG7B,SAAK,MAAM,aAAa,IAAU,aAAM,KAAK,OAAO,eAAe;AAGnE,QAAI,KAAK,OAAO,eAAe,gBAAgB;AAC7C,YAAM,SAAS,OAAO,aAAa,OAAO;AAC1C,YAAM,OAAO,KAAK,OAAO;AACzB,WAAK,SAAS,IAAU;AAAA,QACtB,CAAC,OAAO;AAAA;AAAA,QACR,OAAO;AAAA;AAAA,QACP;AAAA;AAAA,QACA,CAAC;AAAA;AAAA,QACD;AAAA;AAAA,QACA;AAAA;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,SAAS,IAAU;AAAA,QACtB;AAAA;AAAA,QACA,OAAO,aAAa,OAAO;AAAA;AAAA,QAC3B;AAAA;AAAA,QACA;AAAA;AAAA,MACF;AAAA,IACF;AAGA,SAAK,QAAQ,IAAU,aAAM;AAG7B,SAAK,iBAAiB,MAAM;AAC1B,YAAM,SAAS,OAAO,aAAa,OAAO;AAC1C,UAAI,KAAK,kBAAwB,0BAAmB;AAClD,aAAK,OAAO,SAAS;AAAA,MACvB,WAAW,KAAK,kBAAwB,2BAAoB;AAC1D,cAAM,OAAO,KAAK,OAAO;AACzB,aAAK,OAAO,OAAO,CAAC,OAAO;AAC3B,aAAK,OAAO,QAAQ,OAAO;AAC3B,aAAK,OAAO,MAAM;AAClB,aAAK,OAAO,SAAS,CAAC;AAAA,MACxB;AACA,WAAK,OAAO,uBAAuB;AACnC,WAAK,SAAS,QAAQ,OAAO,YAAY,OAAO,WAAW;AAG3D,UAAIC;AACJ,UAAI,KAAK,SAAS,GAAG;AACnB,QAAAA,iBAAgB;AAAA,MAClB,WAAW,KAAK,eAAe,GAAG;AAChC,QAAAA,iBAAgB;AAAA,MAClB,OAAO;AACL,QAAAA,iBAAgB,OAAO;AAAA,MACzB;AACA,YAAMC,oBAAmB,KAAK,IAAI,OAAO,kBAAkBD,cAAa;AACxE,WAAK,SAAS,cAAcC,iBAAgB;AAAA,IAC9C;AACA,WAAO,iBAAiB,UAAU,KAAK,cAAc;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKQ,uBAA6B;AAEnC,SAAK,SAAS,UAAU,UAAU,KAAK,OAAO;AAC9C,SAAK,SAAS,UAAU,OACtB,KAAK,OAAO,kBAAkB,aAAmB,0BAAyB;AAC5E,SAAK,SAAS,UAAU,aAAa;AAGrC,SAAK,SAAS,mBAAyB;AAGvC,QAAI,KAAK,OAAO,gBAAgB,QAAQ;AACtC,WAAK,SAAS,cAAoB;AAAA,IACpC,WAAW,KAAK,OAAO,gBAAgB,UAAU;AAC/C,WAAK,SAAS,cAAoB;AAClC,WAAK,SAAS,sBAAsB,KAAK,OAAO;AAAA,IAClD,OAAO;AAEL,WAAK,SAAS,cAAoB;AAClC,WAAK,SAAS,sBAAsB,KAAK,OAAO;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,OAAO,aAAc;AAE/B,SAAK,gBAAgB,IAAU,qBAAc;AAC7C,SAAK,OAAO,IAAI,KAAK,aAAa;AAClC,gBAAY,eAAe,KAAK;AAEhC,YAAQ,IAAI,+DAA+D;AAAA,EAC7E;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAoB;AAC1B,WAAO,oBAAoB,KAAK,UAAU,SAAS;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAA0B;AAChC,WACE,iEAAiE,KAAK,UAAU,SAAS,KACzF,kBAAkB,UAClB,UAAU,iBAAiB;AAAA,EAE/B;AAAA,EAEQ,WAAoB;AAAA,EACpB,mBAAuC;AAAA;AAAA;AAAA;AAAA,EAKvC,kBAAwB;AAE9B,SAAK,wBAAwB;AAE7B,UAAM,UAAU,MAAM;AAGpB,UAAI,YAAY,KAAK,MAAM,SAAS;AAGpC,UAAI,YAAY,KAAK,cAAc;AACjC,oBAAY,KAAK;AAAA,MACnB;AAEA,UAAI,CAAC,KAAK,UAAU;AAElB,sBAAc,KAAK,SAAS;AAG5B,oBAAY,OAAO,SAAS;AAI5B,aAAK,yBAAyB,WAAW;AAGzC,yBAAiB,OAAO,SAAS;AAGjC,yBAAiB,WAAW,SAAS;AAGrC,6BAAqB,YAAY,EAAE,iBAAiB;AAAA,MACtD;AAGA,WAAK,UAAU,SAAS;AAGxB,WAAK,cAAc,sBAAsB,OAAO;AAEhD,WAAK,OAAO;AAAA,IACd;AACA,YAAQ;AAAA,EACV;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAAgC;AACtC,YAAQ,IAAI,2CAA2C;AAGvD,aAAS,iBAAiB,oBAAoB,MAAM;AAClD,UAAI,SAAS,QAAQ;AACnB,gBAAQ,IAAI,0CAAmC;AAAA,MAEjD,OAAO;AACL,gBAAQ,IAAI,2DAAiD;AAE7D,aAAK,MAAM,SAAS;AAAA,MACtB;AAAA,IACF,CAAC;AAGD,WAAO,iBAAiB,SAAS,MAAM;AACrC,cAAQ,IAAI,gDAAyC;AAErD,WAAK,MAAM,SAAS;AAAA,IACtB,CAAC;AAED,WAAO,iBAAiB,QAAQ,MAAM;AACpC,cAAQ,IAAI,0BAAmB;AAAA,IAEjC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKU,SAAe;AACvB,SAAK,SAAS,OAAO,KAAK,OAAO,KAAK,MAAM;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,MAAa,UAAyB;AACpC,QAAI,KAAK,YAAY;AACnB;AAAA,IACF;AAEA,SAAK,aAAa;AAGlB,QAAI,KAAK,gBAAgB,MAAM;AAC7B,2BAAqB,KAAK,WAAW;AACrC,WAAK,cAAc;AAAA,IACrB;AAGA,UAAM,KAAK,UAAU;AAGrB,kBAAc,QAAQ;AACtB,mBAAe,QAAQ;AACvB,qBAAiB,QAAQ;AACzB,yBAAqB,YAAY,EAAE,QAAQ;AAG3C,WAAO,oBAAoB,UAAU,KAAK,cAAc;AAGxD,SAAK,MAAM,SAAS,CAAC,WAA2B;AAC9C,UAAI,kBAAwB,aAAM;AAChC,eAAO,SAAS,QAAQ;AACxB,YAAI,OAAO,oBAA0B,iBAAU;AAC7C,iBAAO,SAAS,QAAQ;AAAA,QAC1B,WAAW,MAAM,QAAQ,OAAO,QAAQ,GAAG;AACzC,iBAAO,SAAS,QAAQ,CAAC,aAA6B,SAAS,QAAQ,CAAC;AAAA,QAC1E;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,SAAS,QAAQ;AAGtB,QAAI,KAAK,OAAO,OAAO,kBAAkB,KAAK,OAAO,YAAY;AAC/D,WAAK,OAAO,WAAW,YAAY,KAAK,MAAM;AAAA,IAChD;AAAA,EACF;AACF;AAIA,IAAM,iBAAN,MAAqB;AAAA,EACnB,OAAO,WAAW,OAA0B;AAAA,EAE5C;AAAA,EAEA,OAAO,UAAgB;AAAA,EAEvB;AACF;;;ADllBO,IAAM,aAAN,MAAM,oBAAyB,gBAAS;AAAA,EACrC,aAAa,oBAAI,IAAkD;AAAA,EACnE,cAAuB;AAAA,EAC/B,OAAe,YAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnC,YAAY,MAAe;AACzB,UAAM;AAGN,SAAK,OAAO,QAAQ,cAAc,YAAW,WAAW;AAGxD,cAAU,MAAM,IAAI,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAkC,WAAiB;AACjD,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,8CAA8C;AAAA,IAChE;AAEA,UAAM,gBAAgB,UAAU;AAEhC,QAAI,KAAK,WAAW,IAAI,aAAa,GAAG;AACtC,YAAM,IAAI,MAAM,aAAa,cAAc,IAAI,iCAAiC,KAAK,IAAI,EAAE;AAAA,IAC7F;AAEA,QAAI;AAEF,gBAAU,OAAO,IAAI;AACrB,WAAK,WAAW,IAAI,eAAe,SAAS;AAE5C,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,cAAQ;AAAA,QACN,kCAA6B,cAAc,IAAI,mBAAmB,KAAK,IAAI;AAAA,QAC3E;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAkC,eAAyD;AACzF,WAAO,KAAK,WAAW,IAAI,aAAa;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAkC,eAAmD;AACnF,WAAO,KAAK,WAAW,IAAI,aAAa;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAA0C,eAAyD;AACjG,QAAI,UAAiC;AACrC,WAAO,SAAS;AACd,UAAI,mBAAmB,aAAY;AACjC,cAAM,OAAO,QAAQ,aAAa,aAAa;AAC/C,YAAI,KAAM,QAAO;AAAA,MACnB;AACA,gBAAU,QAAQ;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,uBAA4C,eAAyD;AACnG,UAAM,OAAO,KAAK,aAAa,aAAa;AAC5C,QAAI,KAAM,QAAO;AAEjB,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,iBAAiB,aAAY;AAC/B,cAAM,QAAQ,MAAM,uBAAuB,aAAa;AACxD,YAAI,MAAO,QAAO;AAAA,MACpB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAA6C,eAA+C;AAC1F,UAAM,UAAe,CAAC;AACtB,UAAM,OAAO,KAAK,aAAa,aAAa;AAC5C,QAAI,KAAM,SAAQ,KAAK,IAAI;AAE3B,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,iBAAiB,aAAY;AAC/B,gBAAQ,KAAK,GAAG,MAAM,wBAAwB,aAAa,CAAC;AAAA,MAC9D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAqC,eAAmD;AACtF,UAAM,YAAY,KAAK,WAAW,IAAI,aAAa;AACnD,QAAI,CAAC,UAAW,QAAO;AAGvB,cAAU,QAAQ;AAClB,SAAK,WAAW,OAAO,aAAa;AACpC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI,KAAK,YAAa;AACtB,SAAK,cAAc;AAInB,UAAM,mBAAiC,CAAC;AACxC,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,iBAAiB,aAAY;AAC/B,yBAAiB,KAAK,KAAK;AAAA,MAC7B;AAAA,IACF;AAGA,eAAW,SAAS,kBAAkB;AACpC,YAAM,QAAQ;AAAA,IAChB;AAGA,eAAW,aAAa,KAAK,WAAW,OAAO,GAAG;AAChD,gBAAU,QAAQ;AAAA,IACpB;AAGA,SAAK,WAAW,MAAM;AAGtB,QAAI,KAAK,QAAQ;AACf,WAAK,OAAO,OAAO,IAAI;AAAA,IACzB;AAGA,SAAK,SAAS,CAAC,WAA2B;AACxC,UAAI,kBAAwB,aAAM;AAChC,eAAO,SAAS,QAAQ;AACxB,YAAI,OAAO,oBAA0B,iBAAU;AAC7C,iBAAO,SAAS,QAAQ;AAAA,QAC1B,WAAW,MAAM,QAAQ,OAAO,QAAQ,GAAG;AACzC,iBAAO,SAAS,QAAQ,CAAC,aAA6B,SAAS,QAAQ,CAAC;AAAA,QAC1E;AAAA,MACF;AAAA,IACF,CAAC;AAGD,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,WAAwB;AACtB,WAAO,UAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,OAAsB;AAC/B,UAAM,aAAa,KAAK,UAAU;AAGlC,SAAK,UAAU;AAEf,UAAM,eAAe,KAAK,UAAU;AAGpC,QAAI,eAAe,cAAc;AAI/B,WAAK,0BAA0B,YAAY;AAG3C,WAAK,kCAAkC;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AAEnB,QAAI,CAAC,KAAK,SAAS;AACjB,aAAO;AAAA,IACT;AAGA,QAAI,UAAU,KAAK;AACnB,WAAO,SAAS;AACd,UAAI,mBAAmB,eAAc,CAAC,QAAQ,SAAS;AACrD,eAAO;AAAA,MACT;AAEA,UAAI,mBAAyB,mBAAY,CAAC,QAAQ,SAAS;AACzD,eAAO;AAAA,MACT;AACA,gBAAU,QAAQ;AAAA,IACpB;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,SAAiC;AAEtC,UAAM,IAAI,GAAG,OAAO;AAGpB,eAAW,UAAU,SAAS;AAC5B,UAAI,kBAAkB,aAAY;AAEhC,cAAM,sBAAsB,OAAO,UAAU;AAG7C,eAAO,0BAA0B,mBAAmB;AAGpD,eAAO,kCAAkC;AAAA,MAC3C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKU,oCAA0C;AAClD,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,iBAAiB,aAAY;AAE/B,cAAM,iBAAiB,MAAM,UAAU;AAKvC,cAAM,0BAA0B,cAAc;AAG9C,cAAM,kCAAkC;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,0BAA0B,WAA0B;AAI5D,eAAW,aAAa,KAAK,WAAW,OAAO,GAAG;AAChD,UAAI,WAAW;AACb,kBAAU,UAAU;AAAA,MACtB,OAAO;AACL,kBAAU,WAAW;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAe,YAAf,MAAyB;AAAA,EACpB;AAAA,EACF,cAAuB;AAAA;AAAA;AAAA;AAAA,EAKxB,gBAA4B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAc,QAAqB;AACjC,WAAO,KAAK,WAAW,SAAS;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,YAA8B;AACnC,QAAI,KAAK,aAAa;AACpB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAEA,SAAK,aAAa;AAClB,SAAK,cAAc;AAGnB,QAAI,KAAK,QAAQ;AACf,uBAAiB,kBAAkB,IAAI;AAAA,IACzC;AAGA,QAAI,KAAK,YAAY;AACnB,uBAAiB,4BAA4B,IAAI;AAAA,IACnD;AAGA,SAAK,SAAS;AAGd,QAAI,KAAK,WAAW,UAAU,GAAG;AAC/B,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAgB;AACd,QAAI,CAAC,KAAK,YAAa;AAGvB,qBAAiB,oBAAoB,IAAI;AACzC,qBAAiB,8BAA8B,IAAI;AAGnD,SAAK,UAAU;AAEf,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,WAAiB;AAAA,EAE3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,YAAkB;AAAA,EAE5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,YAAkB;AAAA,EAEzB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,aAAmB;AAAA,EAE1B;AAAA;AAAA;AAAA;AAAA,EAmBO,aAAsB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAkC,eAAyD;AACzF,WAAO,KAAK,WAAW,aAAa,aAAa;AAAA,EACnD;AACF;;;AKzaO,IAAM,UAAN,cAAsB,UAAU;AAAA,EAC7B;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,gBAA2B;AACrC,UAAM;AACN,SAAK,YAAY;AACjB,SAAK,iBAAiB,iBAAiB,IAAI,IAAI,cAAc,IAAI,oBAAI,IAAI;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,KAAK,UAAwB;AAElC,QAAI,KAAK,eAAe,OAAO,KAAK,CAAC,KAAK,eAAe,IAAI,QAAQ,GAAG;AACtE,YAAM,IAAI,MAAM,eAAe,QAAQ,8CAA8C;AAAA,IACvF;AAEA,uBAAmB,KAAK,WAAW,QAAQ;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,YAAY,UAA2B;AAC5C,UAAM,QAAQ,KAAK,UAAU,QAAQ;AACrC,WAAO,SAAS,CAAC,CAAC,MAAM;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKO,oBAA8B;AACnC,WAAO,MAAM,KAAK,KAAK,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,iBAAiB,UAAwB;AAC9C,SAAK,eAAe,IAAI,QAAQ;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,oBAAoB,UAAwB;AACjD,SAAK,eAAe,OAAO,QAAQ;AAAA,EACrC;AAAA,EAEU,WAAiB;AAAA,EAE3B;AAAA,EAEU,YAAkB;AAE1B,SAAK,eAAe,MAAM;AAAA,EAC5B;AACF;AAMO,IAAM,gBAAN,cAA4B,UAAU;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,WAAqB,uBAAgC,MAAM;AACrE,UAAM;AACN,SAAK,YAAY;AACjB,SAAK,YAAY,UAAU,MAAM;AACjC,SAAK,uBAAuB;AAC5B,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKO,OAAe;AACpB,UAAM,aACJ,KAAK,wBAAwB,KAAK,cAAc,KAAK,UAAU,SAAS,IACpE,KAAK,UAAU,OAAO,CAAC,MAAM,MAAM,KAAK,UAAU,IAClD,KAAK;AAEX,UAAM,SAAS,kBAAkB,KAAK,WAAW,UAAU;AAC3D,SAAK,aAAa;AAClB,WAAO;AAAA,EACT;AAAA;AAAA,EAGO,SAAS,WAA2B;AACzC,SAAK,YAAY,UAAU,MAAM;AACjC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA,EAGO,WAAqB;AAC1B,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AAAA;AAAA,EAGO,QAAQ,UAAwB;AACrC,QAAI,CAAC,KAAK,UAAU,SAAS,QAAQ,EAAG,MAAK,UAAU,KAAK,QAAQ;AAAA,EACtE;AAAA;AAAA,EAGO,WAAW,UAAwB;AACxC,SAAK,YAAY,KAAK,UAAU,OAAO,CAAC,MAAM,MAAM,QAAQ;AAC5D,QAAI,KAAK,eAAe,SAAU,MAAK,aAAa;AAAA,EACtD;AAAA;AAAA,EAGO,UAAmB;AACxB,QAAI,KAAK,UAAU,WAAW,EAAG,QAAO;AACxC,WAAO,KAAK,UAAU,KAAK,CAAC,MAAM;AAChC,YAAM,QAAQ,KAAK,UAAU,CAAC;AAC9B,aAAO,CAAC,EAAE,SAAS,MAAM;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEU,WAAiB;AAAA,EAAC;AAAA,EAClB,YAAkB;AAAA,EAAC;AAC/B;;;ACtJA,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAOvB,IAAM,gBAAN,MAAoB;AAAA,EACjB,SAAS,IAAI,UAAU;AAAA,EACvB,YAAyC,oBAAI,IAAI;AAAA,EACjD,UAAgD,oBAAI,IAAI;AAAA,EAEzD,SAAS,MAAuB;AACrC,WAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,QAAQ,MAAuC;AAC1D,QAAI,KAAK,UAAU,IAAI,IAAI,GAAG;AAC5B,aAAO,KAAK,UAAU,IAAI,IAAI;AAAA,IAChC;AACA,QAAI,KAAK,QAAQ,IAAI,IAAI,GAAG;AAC1B,aAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC9B;AACA,UAAM,IAAI,KAAK,OACZ,UAAU,IAAI,EACd,KAAK,CAAC,WAAW;AAChB,WAAK,UAAU,IAAI,MAAM,MAAM;AAC/B,WAAK,QAAQ,OAAO,IAAI;AACxB,aAAO;AAAA,IACT,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,WAAK,QAAQ,OAAO,IAAI;AACxB,YAAM;AAAA,IACR,CAAC;AAEH,SAAK,QAAQ,IAAI,MAAM,CAAC;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,SAAS,MAAc,QAA8B;AAC1D,QAAI,KAAK,UAAU,IAAI,IAAI,GAAG;AAC5B,cAAQ,KAAK,0BAA0B,IAAI,sBAAsB;AACjE;AAAA,IACF;AACA,SAAK,UAAU,IAAI,MAAM,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,SAAS,MAAqC;AACnD,UAAM,WAAW,KAAK,UAAU,IAAI,IAAI;AACxC,QAAI,CAAC,SAAU,QAAO;AAGtB,UAAM,QAAQ,cAAc,MAAM,QAAQ;AAC1C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,MAAqC;AACtD,WAAO,KAAK,UAAU,IAAI,IAAI,KAAK;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKO,QAAc;AACnB,SAAK,UAAU,MAAM;AACrB,SAAK,QAAQ,MAAM;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKO,iBAA2B;AAChC,WAAO,MAAM,KAAK,KAAK,UAAU,KAAK,CAAC;AAAA,EACzC;AACF;;;ACzFA,YAAYC,YAAW;AAEvB,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAC1B,SAAS,aAAAC,kBAAiB;AAuFnB,IAAM,eAAN,MAAM,cAAa;AAAA,EACxB,OAAe;AAAA,EACf,OAAe,UAAkC,oBAAI,IAAI;AAAA,EACzD,OAAe,iBAA6C,oBAAI,IAAI;AAAA,EACpE,OAAe,cAA+C,oBAAI,IAAI;AAAA;AAAA,EACtE,OAAe,WAAmB;AAAA;AAAA,EAClC,OAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe;AAAA,EACf,OAAe,wBAAiC;AAAA,EAChD,OAAe,iBAAgC,IAAI,cAAc;AAAA;AAAA,EAGjE,OAAe,yBAAiC;AAAA;AAAA,EAChD,OAAe,yBAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjD,OAAc,KAAK,OAAoB,UAAsC;AAC3E,kBAAa,SAAS;AAGtB,kBAAa,cAAc,IAAI,WAAW;AAC1C,kBAAa,aAAa,IAAI,UAAU;AACxC,kBAAa,aAAa,IAAI,UAAU;AACxC,kBAAa,aAAa,IAAIC,WAAU;AAAA,EAG1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,WAAW,SAAuB;AAE9C,kBAAa,WAAW,QAAQ,SAAS,GAAG,IAAI,UAAU,UAAU;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,YAAY,MAAsB;AAE9C,QAAI,KAAK,WAAW,SAAS,KAAK,KAAK,WAAW,UAAU,GAAG;AAC7D,aAAO;AAAA,IACT;AAGA,QAAI,KAAK,WAAW,GAAG,GAAG;AACxB,aAAO;AAAA,IACT;AAGA,WAAO,cAAa,WAAW;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAoB,cAClB,YACA,kBACiD;AAEjD,kBAAa,wBAAwB;AAErC,UAAM,UAAU,EAAE,QAAQ,CAAC,GAAe,QAAQ,CAAC,EAAc;AACjE,QAAI,iBAAiB;AAGrB,UAAM,eAAe,WAAW,IAAI,OAAO,cAAc;AACvD,YAAM,UAAU,MAAM,cAAa,UAAU,SAAS;AAEtD;AAEA,UAAI,SAAS;AACX,gBAAQ,OAAO,KAAK,SAAS;AAAA,MAE/B,OAAO;AACL,gBAAQ,OAAO,KAAK,SAAS;AAC7B,gBAAQ,MAAM,kBAAa,SAAS,KAAK,cAAc,IAAI,WAAW,MAAM,GAAG;AAAA,MACjF;AAGA,UAAI,kBAAkB;AACpB,cAAM,kBAAkB,iBAAiB,WAAW;AACpD,yBAAiB,iBAAiB,gBAAgB,WAAW,MAAM;AAAA,MACrE;AAAA,IACF,CAAC;AAGD,UAAM,QAAQ,IAAI,YAAY;AAE9B,kBAAa,wBAAwB;AAGrC,QAAI,QAAQ,OAAO,SAAS,GAAG;AAC7B,cAAQ;AAAA,QACN,gBAAM,QAAQ,OAAO,MAAM;AAAA,MAC7B;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,uBAAgC;AAC5C,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAoB,UAClB,MACA,kBACkB;AAClB,QAAI,CAAC,cAAa,QAAQ;AACxB,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAGA,QAAI,cAAa,QAAQ,IAAI,IAAI,KAAK,cAAa,QAAQ,IAAI,IAAI,EAAG,UAAU;AAC9E,UAAI,iBAAkB,kBAAiB,CAAC;AACxC,aAAO;AAAA,IACT;AAGA,QAAI,cAAa,QAAQ,IAAI,IAAI,KAAK,cAAa,QAAQ,IAAI,IAAI,EAAG,WAAW;AAC/E,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,cAAa,QAAQ,IAAI,IAAI,GAAG;AACnC,oBAAa,QAAQ,IAAI,MAAM;AAAA,QAC7B;AAAA,QACA,UAAU;AAAA,QACV,WAAW;AAAA,QACX,QAAQ,CAAC;AAAA,QACT,WAAW,CAAC;AAAA,QACZ,YAAY,CAAC;AAAA,MACf,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAC3C,UAAM,YAAY;AAElB,QAAI;AACF,YAAM,WAAW,cAAa,YAAY,IAAI;AAC9C,YAAM,gBAAgB,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,YAAY,KAAK;AAE9D,UAAI,UAAU;AAEd,cAAQ,eAAe;AAAA,QACrB,KAAK;AAAA,QACL,KAAK;AACH,oBAAU,MAAM,cAAa,cAAc,OAAO,UAAU,gBAAgB;AAC5E;AAAA,QACF,KAAK;AACH,oBAAU,MAAM,cAAa,aAAa,OAAO,UAAU,gBAAgB;AAC3E;AAAA,QACF,KAAK;AACH,oBAAU,MAAM,cAAa,aAAa,OAAO,UAAU,gBAAgB;AAC3E;AAAA,QACF,KAAK;AAEH,kBAAQ;AAAA,YACN;AAAA,UACF;AACA,oBAAU;AACV;AAAA,QACF;AACE,kBAAQ,MAAM,0BAA0B,aAAa,EAAE;AACvD,oBAAU;AAAA,MACd;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,yBAAyB,IAAI,MAAM,KAAK;AACtD,YAAM,YAAY;AAElB,UAAI,iBAAkB,kBAAiB,CAAC;AAExC,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,aAAa,MAAyB;AAClD,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAC3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,YAAM,IAAI;AAAA,QACR,UAAU,IAAI;AAAA,MAEhB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,qBAA+B;AAC3C,WAAO,MAAM,KAAK,cAAa,QAAQ,KAAK,CAAC,EAAE;AAAA,MAC7C,CAAC,SAAS,cAAa,QAAQ,IAAI,IAAI,GAAG;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,kBAA4B;AACxC,WAAO,MAAM,KAAK,cAAa,QAAQ,KAAK,CAAC,EAAE,OAAO,CAAC,SAAS;AAC9D,YAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAC3C,aAAO,SAAS,CAAC,MAAM,YAAY,CAAC,MAAM;AAAA,IAC5C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,qBAMZ;AACA,QAAI,SAAS;AACb,QAAI,SAAS;AACb,QAAI,UAAU;AACd,UAAM,QAAQ,cAAa,QAAQ;AAEnC,eAAW,SAAS,cAAa,QAAQ,OAAO,GAAG;AACjD,UAAI,MAAM,UAAU;AAClB;AAAA,MACF,WAAW,MAAM,WAAW;AAC1B;AAAA,MACF,OAAO;AACL;AAAA,MACF;AAAA,IACF;AAEA,UAAM,uBAAuB,QAAQ,IAAI,KAAK,MAAO,SAAS,QAAS,GAAG,IAAI;AAE9E,WAAO,EAAE,OAAO,QAAQ,QAAQ,SAAS,qBAAqB;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,QAAQ,MAA0B;AAC9C,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,QAAQ;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,cACb,OACA,UACA,kBACkB;AAClB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,oBAAa,YAAY;AAAA,QACvB;AAAA,QACA,CAAC,SAAS;AAER,gBAAM,OAAO;AAGb,gBAAM,QAAQ,IAAU,aAAM;AAC9B,gBAAM,OAAO,GAAG,MAAM,IAAI;AAG1B,gBAAM,IAAI,KAAK,KAAK;AAGpB,gBAAM,SAAS,CAAC;AAChB,gBAAM,YAAY,CAAC;AAEnB,eAAK,MAAM,SAAS,CAAC,WAA2B;AAC9C,gBAAI,kBAAwB,aAAM;AAChC,oBAAM,OAAO,KAAK,MAAM;AAGxB,kBAAI,OAAO,UAAU;AACnB,oBAAI,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAClC,wBAAM,UAAU,KAAK,GAAG,OAAO,QAAQ;AAAA,gBACzC,OAAO;AACL,wBAAM,UAAU,KAAK,OAAO,QAAQ;AAAA,gBACtC;AAAA,cACF;AAAA,YACF;AAAA,UACF,CAAC;AAGD,gBAAM,aAAa,KAAK,cAAc,CAAC;AAGvC,gBAAM,QAAQ;AAGd,gBAAM,WAAW;AACjB,gBAAM,YAAY;AAElB,cAAI,iBAAkB,kBAAiB,CAAC;AAGxC,kBAAQ,IAAI;AAAA,QACd;AAAA,QACA,CAAC,kBAAkB;AACjB,cAAI,oBAAoB,cAAc,kBAAkB;AACtD,kBAAM,WAAW,cAAc,SAAS,cAAc;AACtD,6BAAiB,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,QACA,CAAC,UAAU;AACT,kBAAQ,MAAM,8BAA8B,MAAM,IAAI,MAAM,KAAK;AACjE,gBAAM,YAAY;AAElB,cAAI,iBAAkB,kBAAiB,CAAC;AACxC,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,aACb,OACA,UACA,kBACkB;AAClB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAE9B,YAAM,UAAU,SAAS,QAAQ,QAAQ,MAAM;AAG/C,oBAAa,WAAW;AAAA,QACtB;AAAA,QACA,CAAC,cAAc;AAEb,oBAAU,QAAQ;AAClB,wBAAa,WAAW,aAAa,SAAS;AAC9C,wBAAa,qBAAqB,OAAO,UAAU,SAAS,gBAAgB;AAAA,QAC9E;AAAA,QACA;AAAA,QACA,MAAM;AAEJ,wBAAa,qBAAqB,OAAO,UAAU,SAAS,gBAAgB;AAAA,QAC9E;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,qBACb,OACA,UACA,SACA,kBACM;AACN,kBAAa,WAAW;AAAA,MACtB;AAAA,MACA,CAAC,WAAW;AAEV,cAAM,QAAQ;AAGd,cAAM,SAAS,CAAC;AAChB,cAAM,YAAY,CAAC;AAEnB,eAAO,SAAS,CAAC,UAA0B;AAEzC,cAAI,iBAAuB,aAAM;AAC/B,kBAAM,OAAO,KAAK,KAAK;AAGvB,gBAAI,MAAM,UAAU;AAClB,kBAAI,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjC,sBAAM,UAAU,KAAK,GAAG,MAAM,QAAQ;AAAA,cACxC,OAAO;AACL,sBAAM,UAAU,KAAK,MAAM,QAAQ;AAAA,cACrC;AAAA,YACF;AAAA,UACF,WAAW,MAAM,SAAS,QAAQ;AAEhC,kBAAM,OAAO,KAAK,KAAmB;AAGrC,kBAAM,OAAO;AACb,gBAAI,KAAK,UAAU;AACjB,kBAAI,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChC,sBAAM,UAAU,KAAK,GAAG,KAAK,QAAQ;AAAA,cACvC,OAAO;AACL,sBAAM,UAAU,KAAK,KAAK,QAAQ;AAAA,cACpC;AAAA,YACF;AAAA,UACF,WAAY,MAAc,YAAa,MAAc,UAAU;AAE7D,kBAAM,OAAO,KAAK,KAAmB;AAErC,kBAAM,OAAO;AACb,gBAAI,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChC,oBAAM,UAAU,KAAK,GAAG,KAAK,QAAQ;AAAA,YACvC,OAAO;AACL,oBAAM,UAAU,KAAK,KAAK,QAAQ;AAAA,YACpC;AAAA,UACF;AAAA,QACF,CAAC;AAGD,cAAM,aAAa,CAAC;AAGpB,cAAM,WAAW;AACjB,cAAM,YAAY;AAElB,YAAI,iBAAkB,kBAAiB,CAAC;AAGxC,gBAAQ,IAAI;AAAA,MACd;AAAA,MACA,CAAC,kBAAkB;AACjB,YAAI,oBAAoB,cAAc,kBAAkB;AACtD,gBAAM,WAAW,cAAc,SAAS,cAAc;AACtD,2BAAiB,QAAQ;AAAA,QAC3B;AAAA,MACF;AAAA,MACA,CAAC,UAAU;AACT,gBAAQ,MAAM,6BAA6B,MAAM,IAAI,MAAM,KAAK;AAChE,cAAM,YAAY;AAElB,YAAI,iBAAkB,kBAAiB,CAAC;AACxC,gBAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,aACb,OACA,UACA,kBACkB;AAClB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,oBAAa,WAAW;AAAA,QACtB;AAAA,QACA,CAAC,WAAW;AAEV,gBAAM,QAAQ;AAGd,gBAAM,SAAS,CAAC;AAChB,gBAAM,YAAY,CAAC;AAEnB,iBAAO,SAAS,CAAC,UAA0B;AACzC,gBAAI,iBAAuB,aAAM;AAC/B,oBAAM,OAAO,KAAK,KAAK;AAGvB,kBAAI,MAAM,UAAU;AAClB,oBAAI,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjC,wBAAM,UAAU,KAAK,GAAG,MAAM,QAAQ;AAAA,gBACxC,OAAO;AACL,wBAAM,UAAU,KAAK,MAAM,QAAQ;AAAA,gBACrC;AAAA,cACF;AAAA,YACF;AAAA,UACF,CAAC;AAGD,gBAAM,aAAa,OAAO,cAAc,CAAC;AAGzC,gBAAM,WAAW;AACjB,gBAAM,YAAY;AAElB,cAAI,iBAAkB,kBAAiB,CAAC;AAGxC,kBAAQ,IAAI;AAAA,QACd;AAAA,QACA,CAAC,kBAAkB;AACjB,cAAI,oBAAoB,cAAc,kBAAkB;AACtD,kBAAM,WAAW,cAAc,SAAS,cAAc;AACtD,6BAAiB,QAAQ;AAAA,UAC3B;AAAA,QACF;AAAA,QACA,CAAC,UAAU;AACT,kBAAQ,MAAM,6BAA6B,MAAM,IAAI,MAAM,KAAK;AAChE,gBAAM,YAAY;AAElB,cAAI,iBAAkB,kBAAiB,CAAC;AACxC,kBAAQ,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,cAAc,MAAkC;AAC5D,QAAI,CAAC,cAAa,QAAQ;AACxB,YAAM,IAAI,MAAM,uEAAuE;AAAA,IACzF;AAEA,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,OAAO;AACV,cAAQ,MAAM,UAAU,IAAI,sDAAsD;AAClF,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,MAAM,YAAY,CAAC,MAAM,OAAO;AACnC,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO;AAAA,IACT;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,QAAQ,MAAiC;AACrD,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,OAAO,WAAW,GAAG;AAC7B,cAAQ,MAAM,6BAA6B,IAAI,GAAG;AAClD,aAAO;AAAA,IACT;AAEA,WAAO,MAAM,OAAO,CAAC;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,UAAU,MAA4B;AAClD,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,aAAa,MAAgC;AACzD,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,cAAc,MAAqC;AAC/D,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAE3C,QAAI,CAAC,SAAS,CAAC,MAAM,UAAU;AAC7B,cAAQ,MAAM,UAAU,IAAI,uDAAuD;AACnF,aAAO,CAAC;AAAA,IACV;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,qBAAqB,MAAc,OAA0B;AAEzE,UAAM,SAAuB,CAAC;AAC9B,UAAM,YAA8B,CAAC;AAErC,UAAM,SAAS,CAAC,QAAQ;AACtB,UAAI,eAAqB,aAAM;AAC7B,eAAO,KAAK,GAAG;AACf,YAAI,MAAM,QAAQ,IAAI,QAAQ,GAAG;AAC/B,oBAAU,KAAK,GAAG,IAAI,QAAQ;AAAA,QAChC,OAAO;AACL,oBAAU,KAAK,IAAI,QAAQ;AAAA,QAC7B;AAAA,MACF;AAAA,IACF,CAAC;AAGD,kBAAa,QAAQ,IAAI,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,YAAY,CAAC;AAAA;AAAA,IACf,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,OAAe,mBAA+C,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtE,OAAc,uBAAuB,MAAc,SAA8B;AAC/E,kBAAa,iBAAiB,IAAI,MAAM,OAAO;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,kBAAkB,MAAoC;AAClE,WAAO,cAAa,iBAAiB,IAAI,IAAI,KAAK;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,YAAY,MAAoB;AAC5C,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAC3C,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAGA,eAAW,YAAY,MAAM,WAAW;AACtC,eAAS,QAAQ;AAAA,IACnB;AAGA,eAAW,QAAQ,MAAM,QAAQ;AAC/B,WAAK,SAAS,QAAQ;AAAA,IACxB;AAGA,QAAI,MAAM,SAAS,MAAM,MAAM,QAAQ;AACrC,YAAM,MAAM,OAAO,OAAO,MAAM,KAAK;AAAA,IACvC;AAEA,kBAAa,QAAQ,OAAO,IAAI;AAChC,YAAQ,IAAI,0BAAc,IAAI,YAAY;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,SAAS,MAAuB;AAC5C,UAAM,QAAQ,cAAa,QAAQ,IAAI,IAAI;AAC3C,WAAO,OAAO,YAAY;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,aAAqB;AACjC,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,mBAAyB;AACrC,kBAAa,WAAW;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,kBAIZ;AACA,QAAI,SAAS;AACb,QAAI,UAAU;AACd,UAAM,QAAQ,cAAa,QAAQ;AAEnC,eAAW,SAAS,cAAa,QAAQ,OAAO,GAAG;AACjD,UAAI,MAAM,UAAU;AAClB;AAAA,MACF,WAAW,MAAM,WAAW;AAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,QAAQ,SAAS,MAAM;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,oBAAoB,WAAyB;AACzD,QAAI,CAAC,cAAa,eAAe,IAAI,SAAS,GAAG;AAC/C;AAAA,IACF;AAEA,UAAM,QAAQ,cAAa,eAAe,IAAI,SAAS;AACvD,UAAM;AACN,UAAM;AACN,UAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,sBAAsB,WAAkC;AACpE,WACE,cAAa,eAAe,IAAI,SAAS,KAAK;AAAA,MAC5C,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,YAAY;AAAA,IACd;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,yBAA8C;AAC1D,UAAM,cAAc,cAAa,QAAQ;AACzC,UAAM,eAAe,MAAM,KAAK,cAAa,QAAQ,OAAO,CAAC,EAAE;AAAA,MAC7D,CAAC,UAAU,MAAM;AAAA,IACnB,EAAE;AAEF,QAAI,iBAAiB;AACrB,QAAI,kBAAkB;AACtB,QAAI,kBAAkB;AACtB,QAAI,kBAAkB;AACtB,QAAI,eAAe;AACnB,QAAI,aAAa;AAEjB,eAAW,SAAS,cAAa,eAAe,OAAO,GAAG;AACxD,wBAAkB,MAAM;AACxB,yBAAmB,MAAM;AACzB,yBAAmB,MAAM;AACzB,yBAAmB,MAAM;AACzB,sBAAgB,MAAM;AACtB,oBAAc,MAAM;AAAA,IACtB;AAGA,QAAI,kBAAkB;AACtB,QAAI,iBAAiB;AACrB,QAAI,oBAAoB;AACxB,QAAI,oBAAoB;AAExB,eAAW,CAAC,WAAW,KAAK,KAAK,cAAa,QAAQ,QAAQ,GAAG;AAC/D,UAAI,CAAC,MAAM,SAAU;AAErB,YAAM,gBAAgB,cAAa,eAAe,IAAI,SAAS;AAC/D,YAAM,YAAY,gBAAgB,cAAc,kBAAkB;AAElE,yBAAmB,MAAM,OAAO;AAChC,wBAAkB,MAAM,UAAU;AAClC,2BAAqB,MAAM,OAAO,SAAS;AAC3C,2BAAqB,MAAM,UAAU,SAAS;AAAA,IAChD;AAEA,UAAM,gBACJ,kBAAkB,IAAI,KAAK,MAAO,oBAAoB,kBAAmB,GAAG,IAAI,MAAM;AACxF,UAAM,gBACJ,iBAAiB,IAAI,KAAK,MAAO,oBAAoB,iBAAkB,GAAG,IAAI,MAAM;AAEtF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,oBAA4B;AACxC,UAAM,cAAc,cAAa,uBAAuB;AACxD,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA,WAAW,YAAY,YAAY,IAAI,YAAY,WAAW;AAAA,MAC9D,cAAc,YAAY,cAAc;AAAA,MACxC,YAAY,YAAY,YAAY,OAAO,YAAY,UAAU,aAAa,KAAK,MAAO,YAAY,eAAe,KAAK,IAAI,YAAY,gBAAgB,CAAC,IAAK,GAAG,CAAC;AAAA,MACpK,eAAe,YAAY,eAAe,KAAK,KAAK,MAAO,YAAY,kBAAkB,KAAK,IAAI,YAAY,gBAAgB,CAAC,IAAK,GAAG,CAAC;AAAA,MACxI,eAAe,YAAY,eAAe,KAAK,KAAK,MAAO,YAAY,kBAAkB,KAAK,IAAI,YAAY,gBAAgB,CAAC,IAAK,GAAG,CAAC;AAAA,MACxI,eAAe,YAAY,eAAe,KAAK,KAAK,MAAO,YAAY,kBAAkB,KAAK,IAAI,YAAY,gBAAgB,CAAC,IAAK,GAAG,CAAC;AAAA,MACxI,mBAAmB,YAAY,aAAa,eAAe,YAAY,aAAa;AAAA,MACpF;AAAA,MACA;AAAA,IACF;AAEA,eAAW,CAAC,WAAW,KAAK,KAAK,cAAa,eAAe,QAAQ,GAAG;AACtE,UAAI,MAAM,iBAAiB,GAAG;AAC5B,cAAM;AAAA,UACJ,GAAG,SAAS,KAAK,MAAM,cAAc,WAAW,MAAM,YAAY,WAAW,MAAM,UAAU,aAAa,MAAM,eAAe,YAAY,MAAM,eAAe,YAAY,MAAM,eAAe;AAAA,QACnM;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAc,oBACZ,WACA,UACA,eAAuB,KACE;AACzB,UAAM,QAAQ,cAAa,aAAa,SAAS;AACjD,UAAM,cAAc,cAAa,QAAQ,SAAS;AAElD,QAAI,CAAC,aAAa;AAChB,cAAQ,MAAM,4CAAuC,SAAS,EAAE;AAChE,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,cAAa,YAAY,IAAI,SAAS,GAAG;AAC5C,oBAAa,YAAY,IAAI,WAAW,CAAC,CAAC;AAAA,IAC5C;AAEA,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AAGtD,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,aAAa,YAAY,MAAM,UAAU,SAAS,MAAM,cAAc;AAC9E,eAAO;AAAA,MACT;AAAA,IACF;AAGA,UAAM,gBAAgB,IAAU,qBAAc,YAAY,UAAU,UAAU,YAAY;AAC1F,kBAAc,OAAO,GAAG,SAAS,cAAc,QAAQ,MAAM;AAC7D,kBAAc,aAAa;AAC3B,kBAAc,gBAAgB;AAC9B,kBAAc,gBAAgB;AAG9B,kBAAa,OAAO,IAAI,aAAa;AAGrC,UAAM,WAAW,YAAY;AAG7B,QAAI,CAAC,SAAS,gBAAgB;AAC5B,eAAS,sBAAsB;AAAA,IACjC;AAEA,QAAI,CAAC,SAAS,aAAa;AACzB,eAAS,mBAAmB;AAAA,IAC9B;AAKA,QAAI,gBAAgB;AAEpB,QAAI,SAAS,aAAa;AACxB,YAAM,OAAO,SAAS,YAAY,QAAQ,IAAU,eAAQ,CAAC;AAE7D,sBAAgB,KAAK,OAAO;AAAA,IAC9B,WAAW,SAAS,gBAAgB;AAElC,sBAAgB,SAAS,eAAe,SAAS;AAAA,IACnD;AAEA,UAAM,WAA6B;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,CAAC;AAAA,MACZ;AAAA,MACA,aAAa;AAAA,MACb;AAAA,MACA,mBAAmB;AAAA;AAAA,IACrB;AAEA,YAAQ,KAAK,QAAQ;AAErB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAc,eACZ,WACA,YACA,UACA,WAAoB,OACL;AACf,UAAM,QAAQ,cAAa,oBAAoB,WAAW,QAAQ;AAClE,QAAI,CAAC,OAAO;AACV,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,UAAU,UAAU,MAAM,cAAc;AAChD,cAAQ,KAAK,uBAAuB,SAAS,qCAAqC;AAClF,aAAO;AAAA,IACT;AAEA,UAAM,aAAa,GAAG,SAAS,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC,CAAC;AAE/F,UAAM,eAAgC;AAAA,MACpC,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ,IAAU,eAAQ;AAAA,MAC1B,UAAU;AAAA,MACV;AAAA,IACF;AAGA,UAAM,gBAAgB,IAAU,eAAQ;AACxC,UAAM,kBAAkB,IAAU,kBAAW;AAC7C,UAAM,aAAa,IAAU,eAAQ;AAErC,eAAW,iBAAiB,aAAa;AACzC,eAAW,mBAAmB,eAAe;AAC7C,eAAW,cAAc,UAAU;AAEnC,iBAAa,OAAO,QAAQ,eAAe,iBAAiB,UAAU;AAEtE,UAAM,UAAU,KAAK,YAAY;AACjC,UAAM,cAAc;AAGpB,QAAI,CAAC,UAAU;AACb,YAAM,oBAAoB;AAAA,IAC5B;AAGA,kBAAa,eAAe,KAAK;AAGjC,kBAAa,qBAAqB,WAAW,OAAO,IAAI;AAGxD,kBAAa,oBAAoB,SAAS;AAE1C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,kBAAkB,WAAmB,YAA0B;AAC3E,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AACtD,QAAI,CAAC,QAAS;AAEd,eAAW,SAAS,SAAS;AAC3B,YAAM,gBAAgB,MAAM,UAAU,UAAU,CAAC,SAAS,KAAK,OAAO,UAAU;AAChF,UAAI,kBAAkB,IAAI;AACxB,cAAM,UAAU,OAAO,eAAe,CAAC;AACvC,cAAM,cAAc;AACpB,sBAAa,eAAe,KAAK;AAGjC,sBAAa,uBAAuB,WAAW,OAAO,IAAI;AAC1D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,sBACZ,WACA,YACA,SACM;AACN,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AACtD,QAAI,CAAC,QAAS;AAEd,eAAW,SAAS,SAAS;AAC3B,YAAM,WAAW,MAAM,UAAU,KAAK,CAAC,SAAS,KAAK,OAAO,UAAU;AACtE,UAAI,UAAU;AACZ,iBAAS,WAAW;AACpB,cAAM,cAAc;AAGpB,sBAAa,eAAe,KAAK;AACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,sBAAsB,WAAmB,YAA6B;AAClF,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AACtD,QAAI,CAAC,QAAS,QAAO;AAErB,eAAW,SAAS,SAAS;AAC3B,YAAM,WAAW,MAAM,UAAU,KAAK,CAAC,SAAS,KAAK,OAAO,UAAU;AACtE,UAAI,UAAU;AACZ,eAAO,SAAS;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,wBAAwB,WAAmB,YAAgC;AACvF,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AACtD,QAAI,CAAC,QAAS,QAAO;AAErB,eAAW,SAAS,SAAS;AAC3B,YAAM,gBAAgB,MAAM,UAAU,UAAU,CAAC,SAAS,KAAK,OAAO,UAAU;AAChF,UAAI,kBAAkB,IAAI;AACxB,cAAM,eAAe,MAAM,UAAU,aAAa;AAGlD,cAAM,UAAU,OAAO,eAAe,CAAC;AACvC,cAAM,cAAc;AACpB,sBAAa,eAAe,KAAK;AAIjC,gBAAQ,IAAI,sCAA+B,UAAU,+BAA+B;AAGpF,sBAAa,uBAAuB,WAAW,OAAO,IAAI;AAC1D,sBAAa,qBAAqB,WAAW,OAAO,KAAK;AACzD,sBAAa,oBAAoB,SAAS;AAE1C,eAAO,aAAa;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,eAAe,OAAyB,QAA6B;AACjF,QAAI,CAAC,MAAM,YAAa;AAExB,UAAM,kBAAkB,MAAM,UAAU,OAAO,CAAC,SAAS,KAAK,QAAQ;AAGtE,oBAAgB,QAAQ,CAAC,aAAa;AAEpC,UAAI,CAAC,SAAS,UAAU;AAEtB,cAAM,gBAAgB,IAAU,eAAQ;AACxC,cAAM,kBAAkB,IAAU,kBAAW;AAC7C,cAAM,aAAa,IAAU,eAAQ;AAErC,iBAAS,WAAW,iBAAiB,aAAa;AAClD,iBAAS,WAAW,mBAAmB,eAAe;AACtD,iBAAS,WAAW,cAAc,UAAU;AAE5C,iBAAS,OAAO,QAAQ,eAAe,iBAAiB,UAAU;AAAA,MACpE;AAAA,IAEF,CAAC;AAED,QAAI,mBAAmB;AAGvB,QAAI,cAAa,0BAA0B,UAAU,MAAM,gBAAgB,GAAG;AAC5E,YAAM,UAAU,IAAU,eAAQ;AAClC,YAAM,eAAe,IAAU,eAAQ,EAAE;AAAA,QACvC,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AACA,cAAQ,wBAAwB,YAAY;AAE5C,yBAAmB,gBAAgB,OAAO,CAAC,aAAa;AAEtD,cAAM,cAAc,SAAS;AAC7B,cAAM,WAAW,IAAU,eAAQ,EAAE,sBAAsB,WAAW;AACtE,cAAM,QAAQ,IAAU,eAAQ,EAAE,mBAAmB,WAAW;AAGhE,cAAM,WAAW,KAAK,IAAI,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACnD,cAAM,eAAe,MAAM,gBAAgB;AAG3C,cAAM,eAAe,eAAe,cAAa;AAGjD,cAAM,SAAS,IAAU,cAAO,UAAU,YAAY;AACtD,cAAM,YAAY,QAAQ,iBAAiB,MAAM;AAEjD,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAGA,qBAAiB,QAAQ,CAAC,UAAU,UAAU;AAC5C,YAAM,cAAc,YAAY,OAAO,SAAS,MAAM;AAAA,IACxD,CAAC;AAGD,aAAS,IAAI,iBAAiB,QAAQ,IAAI,MAAM,cAAc,KAAK;AACjE,YAAM,aAAa,IAAU,eAAQ,EAAE,UAAU,GAAG,GAAG,CAAC;AACxD,YAAM,cAAc,YAAY,GAAG,UAAU;AAAA,IAC/C;AAGA,UAAM,cAAc,eAAe,cAAc;AACjD,UAAM,cAAc,QAAQ,iBAAiB;AAC7C,UAAM,cAAc;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,oBAAoB,WAAyB;AAC1D,UAAM,UAAU,cAAa,YAAY,IAAI,SAAS;AACtD,UAAM,mBAAmB,cAAa,eAAe,IAAI,SAAS;AAElE,QAAI,CAAC,WAAW,CAAC,iBAAkB;AAEnC,UAAM,QAAQ,cAAa,eAAe,IAAI,SAAS;AACvD,UAAM,aAAa,QAAQ;AAE3B,QAAI,oBAAoB;AACxB,eAAW,SAAS,SAAS;AAC3B,2BAAqB,MAAM,UAAU,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE;AAAA,IACvE;AACA,UAAM,eAAe;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,qBACZ,WACA,UACA,QAAiB,OACX;AACN,QAAI,CAAC,cAAa,eAAe,IAAI,SAAS,GAAG;AAC/C,oBAAa,eAAe,IAAI,WAAW;AAAA,QACzC,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,cAAa,eAAe,IAAI,SAAS;AACvD,UAAM;AAEN,QAAI,OAAO;AACT,YAAM;AAAA,IACR,WAAW,UAAU;AACnB,YAAM;AAAA,IACR,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,uBACZ,WACA,WACA,SAAkB,OACZ;AACN,QAAI,CAAC,cAAa,eAAe,IAAI,SAAS,GAAG;AAC/C;AAAA,IACF;AAEA,UAAM,QAAQ,cAAa,eAAe,IAAI,SAAS;AACvD,UAAM;AAEN,QAAI,QAAQ;AACV,YAAM;AAAA,IACR,WAAW,WAAW;AACpB,YAAM;AAAA,IACR,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,oBAAoB,QAAuB,QAAiB,OAAa;AAErF,kBAAa,wBAAwB,QAAQ,KAAK;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,2BAAiC;AAC7C,YAAQ,IAAI,oDAA6C;AACzD,QAAI,eAAe;AACnB,QAAI,iBAAiB;AAErB,eAAW,CAAC,WAAW,OAAO,KAAK,cAAa,YAAY,QAAQ,GAAG;AACrE,cAAQ,IAAI,mCAA4B,SAAS,MAAM,QAAQ,MAAM,UAAU;AAE/E,cAAQ,QAAQ,CAAC,OAAO,eAAe;AACrC,cAAM,cAAc;AACpB,sBAAa,eAAe,KAAK;AACjC;AACA,0BAAkB,MAAM,UAAU;AAElC,gBAAQ;AAAA,UACN,mBAAY,UAAU,SAAS,SAAS,MAAM,MAAM,UAAU,MAAM,oCAAoC,MAAM,cAAc,KAAK;AAAA,QACnI;AAAA,MACF,CAAC;AAAA,IACH;AAEA,YAAQ,IAAI,4BAAqB,YAAY,iBAAiB,cAAc,kBAAkB;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,wBAAwB,QAAuB,QAAiB,OAAa;AACzF,QAAI,uBAAuB;AAC3B,QAAI,sBAAsB;AAC1B,QAAI,iBAAiB;AAErB,eAAW,CAAC,WAAW,OAAO,KAAK,cAAa,YAAY,QAAQ,GAAG;AACrE,cAAQ,QAAQ,CAAC,UAAU;AAEzB,YAAI,MAAM,mBAAmB;AAC3B,kCAAwB,MAAM,cAAc;AAC5C,gBAAM,cAAc;AACpB,wBAAa,eAAe,OAAO,MAAM;AACzC;AACA,iCAAuB,MAAM,cAAc;AAAA,QAC7C;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,SAAS,iBAAiB,GAAG;AAC/B,cAAQ,IAAI,uCAAgC,cAAc,0BAA0B;AACpF,UAAI,UAAU,yBAAyB,qBAAqB;AAC1D,cAAM,YAAY,uBAAuB;AACzC,cAAM,mBACJ,uBAAuB,IAAI,KAAK,MAAO,YAAY,uBAAwB,GAAG,IAAI;AACpF,gBAAQ;AAAA,UACN,sCAA+B,mBAAmB,IAAI,oBAAoB,uBAAuB,gBAAgB;AAAA,QACnH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,kBAAwB;AACpC,YAAQ,IAAI,4CAAqC;AAEjD,QAAI,qBAAqB;AACzB,QAAI,sBAAsB;AAC1B,QAAI,uBAAuB;AAC3B,QAAI,wBAAwB;AAE5B,eAAW,CAAC,WAAW,OAAO,KAAK,cAAa,YAAY,QAAQ,GAAG;AACrE,cAAQ,QAAQ,CAAC,UAAU;AACzB,cAAM,gBAAgB,MAAM,UAAU;AAEtC,YAAI,MAAM,mBAAmB;AAC3B;AACA,mCAAyB;AACzB,kBAAQ,IAAI,sBAAe,SAAS,MAAM,aAAa,YAAY;AAAA,QACrE,OAAO;AACL;AACA,kCAAwB;AACxB,kBAAQ,IAAI,2BAAe,SAAS,MAAM,aAAa,YAAY;AAAA,QACrE;AAAA,MACF,CAAC;AAAA,IACH;AAEA,YAAQ;AAAA,MACN,sBAAe,mBAAmB,qBAAqB,qBAAqB,gBAAgB,kBAAkB,oBAAoB,oBAAoB;AAAA,IACxJ;AACA,YAAQ,IAAI,sFAA+E;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,yBAAyB,SAAuB;AAC5D,kBAAa,yBAAyB,KAAK,IAAI,GAAK,OAAO;AAC3D,YAAQ;AAAA,MACN,4CAAqC,cAAa,uBAAuB,QAAQ,CAAC,CAAC;AAAA,IACrF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,2BAAmC;AAC/C,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,yBAAyB,SAAwB;AAC7D,kBAAa,yBAAyB;AAEtC,QAAI,SAAS;AACX,cAAQ,IAAI,gCAA2B;AAAA,IACzC,OAAO;AACL,cAAQ,IAAI,oCAA6B;AAAA,IAC3C;AAGA,eAAW,CAAC,WAAW,OAAO,KAAK,cAAa,YAAY,QAAQ,GAAG;AACrE,cAAQ,QAAQ,CAAC,UAAU;AACzB,cAAM,cAAc;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,0BAAmC;AAC/C,WAAO,cAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,oBAAoB,WAAoB,OAAa;AACjE,kBAAa,yBAAyB,CAAC,QAAQ;AAC/C,YAAQ;AAAA,MACN,4CAAqC,cAAa,yBAAyB,YAAY,UAAU;AAAA,IACnG;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAoB,qBAAqB,MAAuC;AAC9E,WAAO,cAAa,eAAe,QAAQ,IAAI;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,sBAAsB,MAAc,QAA8B;AAC9E,kBAAa,eAAe,SAAS,MAAM,MAAM;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAc,iBAAiB,MAAqC;AAClE,WAAO,cAAa,eAAe,SAAS,IAAI;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,sBAAsB,MAAuB;AACzD,WAAO,cAAa,eAAe,SAAS,IAAI;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,oBAAoB,MAAqC;AACrE,WAAO,cAAa,eAAe,YAAY,IAAI;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAc,QAAc;AAC1B,kBAAa,QAAQ,MAAM;AAC3B,kBAAa,eAAe,MAAM;AAClC,kBAAa,YAAY,MAAM;AAC/B,kBAAa,wBAAwB;AACrC,kBAAa,yBAAyB;AACtC,kBAAa,yBAAyB;AACtC,kBAAa,eAAe,MAAM;AAAA,EACpC;AACF;;;AC/kDA,YAAYC,aAAW;AAIvB;AAAA,EACE;AAAA,EACA,gBAAAC;AAAA,EAEA,gBAAAC;AAAA,EAGA,iBAAAC;AAAA,EACA;AAAA,OACK;AAEA,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,aAAU;AACV,EAAAA,eAAA,YAAS;AACT,EAAAA,eAAA,eAAY;AAHF,SAAAA;AAAA,GAAA;AAML,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,SAAM;AACN,EAAAA,eAAA,YAAS;AACT,EAAAA,eAAA,aAAU;AACV,EAAAA,eAAA,iBAAc;AAJJ,SAAAA;AAAA,GAAA;AAUL,SAAS,qBAAqB,YAAoB,QAAwB;AAC/E,SAAQ,cAAc,KAAM;AAC9B;AA6CO,IAAM,0BAAN,MAAM,iCAAgC,UAAU;AAAA,EAC7C,YAA8B;AAAA,EAC9B,WAA4B;AAAA,EAC5B;AAAA,EACA;AAAA,EAER,OAAe,YAAY,IAAU,gBAAQ;AAAA,EAC7C,OAAe,YAAY,IAAU,mBAAW;AAAA;AAAA,EAGxC,yBAAwD;AAAA,EACxD,wBAAuD;AAAA,EACvD,0BAAmC;AAAA,EAE3C,YAAY,UAA4B,CAAC,GAAG;AAC1C,UAAM;AACN,SAAK,UAAU;AAAA,MACb,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAAA,MAC/B,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,MACV,eAAe;AAAA;AAAA,MACf,gBAAgB;AAAA;AAAA,MAChB,GAAG;AAAA,IACL;AAGA,SAAK,SAAS,MAAM,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,EAC7D;AAAA,EAEU,WAAiB;AACzB,QAAI,CAAC,cAAc,QAAQ,GAAG;AAC5B,cAAQ,KAAK,yEAA+D;AAC5E;AAAA,IACF;AAEA,SAAK,kBAAkB;AAEvB,QAAI,KAAK,WAAW;AAElB,UAAI,KAAK,QAAQ,iBAAiB,KAAK,QAAQ,iBAAiB,KAAK,QAAQ,eAAe;AAE1F,aAAK,UAAU;AAAA,UACb,CAAC,KAAK,QAAQ;AAAA;AAAA,UACd,CAAC,KAAK,QAAQ;AAAA,UACd,CAAC,KAAK,QAAQ;AAAA,UACd;AAAA;AAAA,QACF;AAAA,MACF;AAGA,UACE,KAAK,QAAQ,oBACb,KAAK,QAAQ,oBACb,KAAK,QAAQ,kBACb;AAEA,aAAK,UAAU;AAAA,UACb,CAAC,KAAK,QAAQ;AAAA;AAAA,UACd,CAAC,KAAK,QAAQ;AAAA,UACd,CAAC,KAAK,QAAQ;AAAA,UACd;AAAA;AAAA,QACF;AAAA,MACF;AAGA,WAAK,WAAW,KAAK,WAAW,UAAU,CAAC;AAG3C,oBAAc,mBAAmB,KAAK,QAAQ,KAAK,UAAU;AAAA,IAG/D,OAAO;AACL,cAAQ,MAAM,0CAAqC,KAAK,WAAW,IAAI,EAAE;AAAA,IAC3E;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAEhC,QAAI;AAEJ,YAAQ,KAAK,QAAQ,MAAM;AAAA,MACzB,KAAK;AACH,mBAAWF,eAAc,MAAM;AAC/B;AAAA,MACF,KAAK;AACH,mBAAWA,eAAc,uBAAuB;AAChD;AAAA,MACF,KAAK;AAAA,MACL;AACE,mBAAWA,eAAc,QAAQ;AACjC;AAAA,IACJ;AAIA,SAAK,WAAW,kBAAkB,IAAI;AACtC,UAAM,MAAM,KAAK,WAAW,iBAAiB,IAAU,gBAAQ,CAAC;AAEhE,aAAS,eAAe,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAI3C,UAAM,YAAY,KAAK,WAAW,mBAAmB,IAAU,mBAAW,CAAC;AAC3E,aAAS,YAAY;AAAA,MACnB,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,MACb,GAAG,UAAU;AAAA,IACf,CAAC;AAGD,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,aAAa,yBAAwB,cAAc,KAAK,UAAU;AACxE,WAAK,QAAQ,OAAO;AAGpB,UAAI,KAAK,QAAQ,UAAU,uBAAsB;AAC/C,aAAK,QAAQ,SAAS,KAAK,IAAI,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC,IAAI;AAAA,MAC7E,WAAW,KAAK,QAAQ,UAAU,yBAAuB;AACvD,aAAK,QAAQ,SAAS,WAAW;AACjC,aAAK,QAAQ,SAAS,KAAK,IAAI,WAAW,GAAG,WAAW,CAAC,IAAI;AAAA,MAC/D;AAAA,IACF;AAGA,QAAI,eAA6B;AAEjC,YAAQ,KAAK,QAAQ,OAAO;AAAA,MAC1B,KAAK;AACH,uBAAeD,cAAa,KAAK,KAAK,QAAQ,MAAO;AACrD;AAAA,MACF,KAAK;AACH,uBAAeA,cAAa,QAAQ,KAAK,QAAQ,SAAU,GAAG,KAAK,QAAQ,MAAO;AAClF;AAAA,MACF,KAAK,iCAA2B;AAC9B,YAAI,cAAc;AAClB,YAAI,KAAK,QAAQ,YAAY,KAAK,QAAQ,SAAS,UAAU,GAAG;AAC9D,gBAAM,WAAWA,cAAa,WAAW,KAAK,QAAQ,QAAQ;AAC9D,cAAI,UAAU;AACZ,2BAAe;AACf,0BAAc;AAAA,UAChB;AAAA,QACF;AACA,YAAI,CAAC,aAAa;AAChB,kBAAQ,KAAK,2DAA2D;AACxE,gBAAM,eAAe,KAAK,QAAQ,QAAQ,IAAU,gBAAQ,GAAG,GAAG,CAAC;AACnE,yBAAeA,cAAa,OAAO,aAAa,IAAI,GAAG,aAAa,IAAI,GAAG,aAAa,IAAI,CAAC;AAAA,QAC/F;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL;AACE,cAAM,OAAO,KAAK,QAAQ;AAC1B,uBAAeA,cAAa,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC;AACrE;AAAA,IACJ;AAIA,UAAM,iBAAiB,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAEhD,QAAI,KAAK,QAAQ,cAAc;AAC7B,qBAAe,KAAK,KAAK,QAAQ,YAAY;AAAA,IAC/C,OAAO;AAEL,UAAI,KAAK,QAAQ,UAAU,iBAAmB;AAC5C,uBAAe,IAAI,KAAK,QAAQ,KAAM,IAAI;AAAA,MAC5C,WAAW,KAAK,QAAQ,UAAU,yBAAuB;AACvD,uBAAe,IAAI,KAAK,QAAQ,SAAU;AAAA,MAC5C,WAAW,KAAK,QAAQ,UAAU,uBAAsB;AACtD,uBAAe,IAAI,KAAK,QAAQ;AAAA,MAClC;AAAA,IACF;AAEA,iBAAa,eAAe,eAAe,GAAG,eAAe,GAAG,eAAe,CAAC;AAGhF,iBAAa,eAAe,KAAK,QAAQ,WAAY;AACrD,iBAAa,YAAY,KAAK,QAAQ,QAAS;AAC/C,iBAAa,UAAU,KAAK,QAAQ,QAAS;AAI7C,UAAM,8BACJ,KAAK,QAAQ,0BACZ,KAAK,QAAQ,YAAY,KAAK,QAAQ,SAAS;AAElD,QAAI,6BAA6B;AAE/B,mBAAa,gBAAgBD,cAAa,gBAAgB;AAG1D,UAAI,KAAK,QAAQ,SAAS,6BAAyB;AACjD,qBAAa;AAAA,UACX,qBAAqB,UACrB,qBAAqB,kBACrB,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,QAAQ,oBAAoB,QAAW;AAC9C,mBAAa,mBAAmB,KAAK,QAAQ,eAAe;AAAA,IAC9D;AAGA,UAAM,SAAS,cAAc,gBAAgB,KAAK,QAAQ,UAAU,YAAY;AAEhF,QAAI,QAAQ;AACV,WAAK,YAAY,OAAO;AACxB,WAAK,WAAW,OAAO;AAGvB,UAAI,KAAK,QAAQ,SAAS,yBAAuB;AAC/C,aAAK,UAAU,kBAAkB,KAAK,QAAQ,MAAO,IAAI;AAGzD,YAAI,KAAK,QAAQ,kBAAkB,UAAa,KAAK,QAAQ,gBAAgB,GAAG;AAC9E,eAAK,UAAU,iBAAiB,KAAK,QAAQ,aAAa;AAAA,QAC5D;AACA,YAAI,KAAK,QAAQ,mBAAmB,UAAa,KAAK,QAAQ,iBAAiB,GAAG;AAChF,eAAK,UAAU,kBAAkB,KAAK,QAAQ,cAAc;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,OAAO,GAAiB;AAC7B,QAAI,CAAC,KAAK,UAAW;AAErB,QAAI,KAAK,QAAQ,SAAS,yBAAuB;AAG/C,YAAM,QAAQ,cAAc,wBAAwB,KAAK;AAGzD,YAAM,SAAS,KAAK,UAAU,YAAY;AAC1C,YAAM,SAAS,KAAK,UAAU,SAAS;AAIvC,YAAM,SAAS,KAAK,UAAU,OAAO;AACrC,YAAM,SAAS,KAAK,UAAU,OAAO;AACrC,YAAM,IAAK,cAAsB,iBAAiB,IAAI;AAEtD,YAAM,UAAU,IAAU;AAAA,QACxB,OAAO,IAAI,OAAO,IAAI;AAAA,QACtB,OAAO,IAAI,OAAO,IAAI;AAAA,QACtB,OAAO,IAAI,OAAO,IAAI;AAAA,MACxB;AAEA,YAAM,UAAU,IAAU,mBAAW,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC3E,YAAM,UAAU,IAAU,gBAAQ,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAC9D,YAAM,WAAW,QAAQ,OAAO;AAChC,YAAM,WAAW,QAAQ,MAAM;AAC/B,UAAI,WAAW,MAAQ;AACrB,gBAAQ,UAAU;AAClB,cAAM,QAAQ,WAAW;AACzB,cAAM,SAAS,IAAU,mBAAW,EAAE,iBAAiB,SAAS,KAAK;AACrE,iBAAS,SAAS,MAAM,EAAE,UAAU;AAAA,MACtC;AAGA,YAAM,UAAU,IAAU,gBAAQ,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC,EAAE,KAAK,SAAS,KAAK;AACnF,YAAM,YAAY,QAAQ,MAAM,EAAE,MAAM,UAAU,KAAK;AAGvD,WAAK,WAAW,SAAS,KAAK,OAAO;AACrC,WAAK,WAAW,WAAW,KAAK,SAAS;AAAA,IAC3C,WAAW,KAAK,QAAQ,SAAS,6BAAyB;AAMxD,WAAK,WAAW,kBAAkB,IAAI;AACtC,YAAM,WAAW,KAAK,WAAW,iBAAiB,yBAAwB,SAAS;AACnF,YAAM,YAAY,KAAK,WAAW,mBAAmB,yBAAwB,SAAS;AAEtF,WAAK,UAAU;AAAA,QACb,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE;AAAA,QAC9C;AAAA,MACF;AACA,WAAK,UAAU;AAAA,QACb;AAAA,UACE,GAAG,UAAU;AAAA,UACb,GAAG,UAAU;AAAA,UACb,GAAG,UAAU;AAAA,UACb,GAAG,UAAU;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EAGF;AAAA;AAAA;AAAA;AAAA,EAKO,WAAW,OAAsB,OAA6B;AACnE,QAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,SAAS,wBAAuB;AAEpE,QAAI,OAAO;AACT,WAAK,UAAU;AAAA,QACb,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,QACrC,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,QACrC;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,UAAU,SAAS,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE,GAAG,IAAI;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,SAAwB,OAA6B;AACvE,QAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,SAAS,wBAAuB;AAEpE,QAAI,OAAO;AACT,WAAK,UAAU;AAAA,QACb,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,GAAG,GAAG,QAAQ,EAAE;AAAA,QAC3C,EAAE,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,EAAE;AAAA,QACrC;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,UAAU,aAAa,EAAE,GAAG,QAAQ,GAAG,GAAG,QAAQ,GAAG,GAAG,QAAQ,EAAE,GAAG,IAAI;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,UAA+B;AAChD,QAAI,KAAK,aAAa,KAAK,QAAQ,SAAS,yBAAuB;AACjE,WAAK,UAAU,UAAU,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI;AAAA,IAChF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,KAA0B;AAC3C,QAAI,CAAC,KAAK,WAAW;AACnB,UAAI,IAAI,GAAG,GAAG,CAAC;AACf;AAAA,IACF;AACA,UAAM,MAAM,KAAK,UAAU,OAAO;AAClC,QAAI,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAmB,UAA+B;AACvD,QAAI,CAAC,KAAK,aAAa,KAAK,QAAQ,SAAS,wBAAuB;AAEpE,SAAK,UAAU,UAAU,EAAE,GAAG,SAAS,GAAG,GAAG,SAAS,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI;AAAA,EAChF;AAAA;AAAA;AAAA;AAAA,EAKO,eAAiC;AACtC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,cAA+B;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKO,WAAW,SAAwB;AACxC,QAAI,CAAC,KAAK,UAAW;AAErB,SAAK,UAAU,WAAW,OAAO;AAAA,EAEnC;AAAA;AAAA;AAAA;AAAA,EAKO,YAAqB;AAC1B,QAAI,CAAC,KAAK,UAAW,QAAO;AAE5B,WAAO,KAAK,UAAU,UAAU;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,YAAoB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,uBAAuB,UAAsC;AAClE,SAAK,yBAAyB;AAC9B,SAAK,kCAAkC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,sBAAsB,UAAsC;AACjE,SAAK,wBAAwB;AAC7B,SAAK,kCAAkC;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKO,2BAAiC;AACtC,SAAK,yBAAyB;AAC9B,SAAK,mCAAmC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKO,0BAAgC;AACrC,SAAK,wBAAwB;AAC7B,SAAK,mCAAmC;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKO,eAAe,OAAkB;AACtC,QAAI,KAAK,wBAAwB;AAC/B,WAAK,uBAAuB,KAAK;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,cAAc,OAAkB;AACrC,QAAI,KAAK,uBAAuB;AAC9B,WAAK,sBAAsB,KAAK;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oCAA0C;AAChD,SACG,KAAK,0BAA0B,KAAK,0BACrC,CAAC,KAAK,yBACN;AACA,oBAAc,yBAAyB,KAAK,QAAQ,IAAI;AACxD,WAAK,0BAA0B;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qCAA2C;AACjD,QACE,CAAC,KAAK,0BACN,CAAC,KAAK,yBACN,KAAK,yBACL;AACA,oBAAc,2BAA2B,KAAK,MAAM;AACpD,WAAK,0BAA0B;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAc,WACZ,QACA,UAAwD,CAAC,GAChC;AACzB,WAAO,IAAI,yBAAwB;AAAA,MACjC,GAAG;AAAA,MACH,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAc,cAAc,YAAuC;AAEjE,UAAM,cAAc,IAAU,aAAK;AACnC,QAAI,YAAY;AAGhB,eAAW,kBAAkB,IAAI;AAEjC,YAAQ,IAAI,uCAAgC,WAAW,IAAI,KAAK;AAGhE,eAAW,SAAS,CAAC,UAA0B;AAC7C,UAAI,iBAAuB,gBAAQ,MAAM,UAAU;AACjD;AACA,gBAAQ,IAAI,2BAAoB,MAAM,QAAQ,SAAS,EAAE;AAGzD,YAAI,CAAC,MAAM,SAAS,aAAa;AAC/B,gBAAM,SAAS,mBAAmB;AAAA,QACpC;AAEA,YAAI,MAAM,SAAS,aAAa;AAE9B,gBAAM,YAAY,IAAU,gBAAQ;AACpC,gBAAM,SAAS,YAAY,QAAQ,SAAS;AAC5C,kBAAQ,IAAI,4BAA4B,SAAS;AAGjD,gBAAM,kBAAkB,IAAI;AAC5B,gBAAM,iBAAiB,MAAM,SAAS,YAAY,MAAM,EAAE,aAAa,MAAM,WAAW;AAGxF,gBAAM,kBAAkB,IAAU,gBAAQ;AAC1C,yBAAe,QAAQ,eAAe;AACtC,kBAAQ,IAAI,+BAA+B,eAAe;AAE1D,sBAAY,MAAM,cAAc;AAAA,QAClC,OAAO;AACL,kBAAQ,KAAK,iCAAiC,MAAM,IAAI,EAAE;AAAA,QAC5D;AAAA,MACF;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,mCAA4B,SAAS,EAAE;AAGnD,QAAI,YAAY,QAAQ,GAAG;AACzB,cAAQ,KAAK,6BAAwB,WAAW,IAAI,8BAA8B;AAClF,aAAO,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAAA,IAClC;AAGA,UAAM,OAAO,IAAU,gBAAQ;AAC/B,gBAAY,QAAQ,IAAI;AAExB,YAAQ,IAAI,yCAAkC,WAAW,IAAI,KAAK,IAAI;AACtE,YAAQ,IAAI,+BAAwB,YAAY,GAAG;AACnD,YAAQ,IAAI,+BAAwB,YAAY,GAAG;AAEnD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,YAAkB;AAEvB,QACE,KAAK,WAAW,KAAK,SAAS,SAAS,KACvC,KAAK,WAAW,KAAK,SAAS,QAAQ,KACtC,KAAK,WAAW,KAAK,SAAS,OAAO,GACrC;AAAA,IAEF;AACA,SAAK,WAAW,IAAI;AAAA,EACtB;AAAA,EAEO,YAAwB;AAG7B,UAAM,SAAS,IAAU,aAAK;AAC9B,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,UAAM,QAAQ,KAAK,SAAS;AAC5B,QAAI,MAAM,SAAS,UAAU,QAAQ;AACnC,YAAM,SAAS;AACf,YAAM,cAAc,OAAO;AAG3B,YAAM,SAAS,IAAU,gBAAQ;AAEjC,aAAO,IAAI,IAAI,OAAO,IAAI,YAAY,GAAG,OAAO,IAAI,YAAY,GAAG,OAAO,IAAI,YAAY,CAAC;AAE3F,aAAO,IAAI,IAAI,OAAO,IAAI,YAAY,GAAG,OAAO,IAAI,YAAY,GAAG,OAAO,IAAI,YAAY,CAAC;AAAA,IAC7F;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,aAAmB;AAExB,QACE,KAAK,WAAW,KAAK,SAAS,SAAS,KACvC,KAAK,WAAW,KAAK,SAAS,QAAQ,KACtC,KAAK,WAAW,KAAK,SAAS,OAAO,GACrC;AAAA,IAEF;AACA,SAAK,WAAW,KAAK;AAAA,EACvB;AAAA,EAEU,YAAkB;AAC1B,QAAI,KAAK,QAAQ;AAEf,oBAAc,qBAAqB,KAAK,MAAM;AAG9C,WAAK,yBAAyB;AAC9B,WAAK,wBAAwB;AAG7B,WAAK,0BAA0B;AAE/B,oBAAc,gBAAgB,KAAK,MAAM;AAAA,IAC3C;AAEA,SAAK,YAAY;AACjB,SAAK,WAAW;AAAA,EAClB;AACF;;;ACvsBA,IAAM,wBAAN,MAA4B;AAAA,EAClB,WAAW,oBAAI,IAAwC;AAAA,EAE/D,SAAS,UAAkB,gBAAkD;AAC3E,QAAI,KAAK,SAAS,IAAI,QAAQ,GAAG;AAC/B,cAAQ,KAAK,mBAAmB,QAAQ,uCAAuC;AAAA,IACjF;AACA,SAAK,SAAS,IAAI,UAAU,cAAc;AAAA,EAC5C;AAAA,EAEA,IAAI,UAA0D;AAC5D,WAAO,KAAK,SAAS,IAAI,QAAQ;AAAA,EACnC;AAAA,EAEA,IAAI,UAA2B;AAC7B,WAAO,KAAK,SAAS,IAAI,QAAQ;AAAA,EACnC;AAAA,EAEA,qBAA+B;AAC7B,WAAO,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EACxC;AACF;AAEO,IAAM,oBAAoB,IAAI,sBAAsB;;;AClCpD,SAAS,gBAAgB,UAAkB;AAChD,SAAO,SAAgD,QAAc;AACnE,sBAAkB,SAAS,UAAU,MAAM;AAC3C,WAAO;AAAA,EACT;AACF;;;ACgCO,SAAS,qBAAqB,GAAqD;AACxF,SAAO,EAAE,SAAS;AACpB;;;ACzCA,YAAYK,aAAW;AAIhB,IAAM,aAAN,MAAM,YAAW;AAAA,EACtB,OAAc,eAAe,MAAkC;AAC7D,UAAM,OAAO,KAAK;AAElB,QAAI,YAA2C;AAC/C,UAAM,aAAoC,CAAC;AAE3C,QAAI,KAAK,YAAY;AACnB,iBAAW,aAAa,KAAK,YAAY;AACvC,YAAI,qBAAqB,SAAS,GAAG;AACnC,sBAAY;AAAA,QACd,OAAO;AACL,qBAAW,KAAK,SAAS;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,eAAe,IAAI,oCAAoC;AAAA,IACzE;AAEA,UAAM,WAAyB,CAAC;AAChC,QAAI,KAAK,UAAU;AACjB,iBAAW,aAAa,KAAK,UAAU;AACrC,iBAAS,KAAK,YAAW,eAAe,SAAS,CAAC;AAAA,MACpD;AAAA,IACF;AAEA,WAAO,IAAI,YAAW,MAAM,WAAW,YAAY,QAAQ;AAAA,EAC7D;AAAA,EAEiB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAA8C,oBAAI,IAAI;AAAA,EACtD,oBAA6C,oBAAI,IAAI;AAAA,EAEtE,YACE,MACA,WACA,YACA,UACA;AACA,SAAK,QAAQ;AACb,SAAK,aAAa;AAClB,SAAK,cAAc;AACnB,SAAK,YAAY;AAEjB,eAAW,SAAS,UAAU;AAC5B,WAAK,mBAAmB,IAAI,MAAM,MAAM,KAAK;AAC7C,WAAK,cAAc,OAAO,IAAI,MAAM,IAAI,EAAE;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAW,OAAe;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,KAAa;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,YAAoC;AAC7C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,aAAiD;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,WAAsC;AAC/C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,WAA0B;AACnC,WAAO,IAAU;AAAA,MACf,KAAK,WAAW,SAAS,CAAC;AAAA,MAC1B,KAAK,WAAW,SAAS,CAAC;AAAA,MAC1B,KAAK,WAAW,SAAS,CAAC;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,IAAW,WAAwB;AACjC,WAAO,IAAU;AAAA,MACd,KAAK,WAAW,SAAS,CAAC,IAAI,KAAK,KAAM;AAAA,MACzC,KAAK,WAAW,SAAS,CAAC,IAAI,KAAK,KAAM;AAAA,MACzC,KAAK,WAAW,SAAS,CAAC,IAAI,KAAK,KAAM;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,IAAW,QAAuB;AAChC,WAAO,IAAU;AAAA,MACf,KAAK,WAAW,MAAM,CAAC;AAAA,MACvB,KAAK,WAAW,MAAM,CAAC;AAAA,MACvB,KAAK,WAAW,MAAM,CAAC;AAAA,IACzB;AAAA,EACF;AAAA,EAEO,eAAe,MAAsC;AAC1D,WAAO,KAAK,mBAAmB,IAAI,IAAI;AAAA,EACzC;AAAA,EAEO,cAAc,MAAsC;AACzD,QAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO,IAAI,IAAI;AAC1C,WAAO,KAAK,kBAAkB,IAAI,IAAI;AAAA,EACxC;AAAA,EAEA,IAAW,cAAiD;AAC1D,WAAO,KAAK,kBAAkB,QAAQ;AAAA,EACxC;AAAA,EAEO,wBAAwB,UAA0C;AACvE,eAAW,SAAS,KAAK,WAAW;AAClC,UAAI,MAAM,SAAS,SAAU,QAAO;AACpC,YAAM,QAAQ,MAAM,wBAAwB,QAAQ;AACpD,UAAI,MAAO,QAAO;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA,EAEO,iBAAgD,MAA6B;AAClF,WAAO,KAAK,YAAY,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAAA,EACrD;AAAA,EAEO,iBAAiB,QAA8B;AACpD,WAAO,SAAS,KAAK,KAAK,QAAQ;AAClC,WAAO,SAAS,KAAK,KAAK,QAAQ;AAClC,WAAO,MAAM,KAAK,KAAK,KAAK;AAAA,EAC9B;AAAA,EAEQ,cAAc,MAAkB,MAAoB;AAC1D,SAAK,kBAAkB,IAAI,MAAM,IAAI;AACrC,eAAW,SAAS,KAAK,UAAU;AACjC,WAAK,cAAc,OAAO,GAAG,IAAI,IAAI,MAAM,IAAI,EAAE;AAAA,IACnD;AAAA,EACF;AACF;;;AC1IO,IAAM,SAAN,MAAM,QAAO;AAAA,EAClB,OAAc,eAAe,MAA0B;AACrD,UAAM,OAAO,KAAK,KAAK;AACvB,UAAM,OAAO,WAAW,eAAe,KAAK,IAAI;AAChD,WAAO,IAAI,QAAO,MAAM,MAAM,KAAK,MAAM;AAAA,EAC3C;AAAA,EAEiB;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,MAAc,MAAkB,QAA2C;AACrF,SAAK,QAAQ;AACb,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAW,OAAe;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,OAAmB;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,SAAyD;AAClE,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,cAAc,MAAsC;AACzD,WAAO,KAAK,MAAM,cAAc,IAAI;AAAA,EACtC;AACF;;;AC/BO,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EAC5B,OAAc,eAAe,MAA8C;AACzE,UAAM,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAChE,WAAO,IAAI,kBAAiB,OAAO;AAAA,EACrC;AAAA,EAEiB,iBAAiB,oBAAI,IAAoB;AAAA,EAE1D,YAAY,SAA2B;AACrC,eAAW,UAAU,SAAS;AAC5B,WAAK,eAAe,IAAI,OAAO,MAAM,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,IAAW,UAAoC;AAC7C,WAAO,KAAK,eAAe,OAAO;AAAA,EACpC;AAAA,EAEO,gBAAgB,MAAkC;AACvD,WAAO,KAAK,eAAe,IAAI,IAAI;AAAA,EACrC;AAAA,EAEO,uBAAoC;AACzC,UAAM,QAAQ,oBAAI,IAAY;AAC9B,SAAK,cAAc,CAAC,SAAS;AAC3B,iBAAW,aAAa,KAAK,YAAY;AACvC,cAAM,IAAI,UAAU,IAAI;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YAAoD;AACzD,UAAM,gBAAgB,oBAAI,IAA6C;AAEvE,eAAW,UAAU,KAAK,SAAS;AACjC,iBAAW,SAAS,OAAO,QAAQ;AAEjC,YAAI,CAAC,cAAc,IAAI,MAAM,KAAK,GAAG;AACnC,wBAAc,IAAI,MAAM,OAAO,EAAE,OAAO,MAAM,OAAO,MAAM,MAAM,KAAK,CAAC;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,cAAc,OAAO,CAAC;AAAA,EAC1C;AAAA,EAEQ,cAAc,UAA4C;AAChE,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,OAAO,OAAO;AACpB,eAAS,IAAI;AACb,iBAAW,CAAC,EAAE,UAAU,KAAK,KAAK,aAAa;AAC7C,iBAAS,UAAU;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;;;ACjEA,YAAYC,aAAW;AAehB,IAAM,iBAAN,MAAM,gBAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1B,OAAc,iBAAkD;AAAA,EAEhE,OAAc,YACZ,YACA,SAA4B,MAC5B,SACgB;AAEhB,UAAM,aAAa,gBAAe,mBAAmB;AACrD,QAAI,cAAc,SAAS;AACzB,sBAAe,iBAAiB;AAAA,IAClC;AAEA,UAAM,aAAa,IAAI,WAAW,WAAW,IAAI;AACjD,eAAW,iBAAiB,UAAU;AAEtC,QAAI,QAAQ;AACV,aAAO,IAAI,UAAU;AAAA,IACvB;AAEA,UAAM,aAA0B,CAAC;AAEjC,eAAW,iBAAiB,WAAW,YAAY;AACjD,YAAM,YAAY,gBAAe,gBAAgB,eAAe,UAAU;AAC1E,UAAI,WAAW;AACb,mBAAW,aAAa,SAAS;AACjC,mBAAW,KAAK,SAAS;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,WAA6B,CAAC;AACpC,eAAW,aAAa,WAAW,UAAU;AAC3C,YAAM,gBAAgB,gBAAe,YAAY,WAAW,YAAY,OAAO;AAC/E,eAAS,KAAK,aAAa;AAAA,IAC7B;AAEA,UAAM,WAAW,IAAI,gBAAe,YAAY,YAAY,YAAY,QAAQ;AAOhF,QAAI,YAAY;AACd,sBAAe,iBAAiB;AAAA,IAClC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,WAAW,YAAqB,eAA+B;AACpE,SAAK,YAAY,SAAS,CAAC,UAAU;AACnC,UAAI,iBAAuB,cAAM;AAC/B,cAAM,aAAa;AACnB,YAAI,kBAAkB,QAAW;AAC/B,gBAAM,gBAAgB;AAAA,QACxB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,mBAAmB,SAAyC;AAClE,SAAK,YAAY,SAAS,CAAC,UAAU;AACnC,UAAI,iBAAuB,cAAM;AAC/B,YAAI,QAAQ,eAAe,QAAW;AACpC,gBAAM,aAAa,QAAQ;AAAA,QAC7B;AACA,YAAI,QAAQ,kBAAkB,QAAW;AACvC,gBAAM,gBAAgB,QAAQ;AAAA,QAChC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,gBAAgB,eAA8B,MAAoC;AAC/F,UAAM,UAAU,kBAAkB,IAAI,cAAc,IAAI;AACxD,QAAI,CAAC,SAAS;AACZ,cAAQ,KAAK,4BAA4B,cAAc,IAAI,cAAc;AACzE,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAO,QAAQ,eAAe,eAAe,IAAI;AAAA,IACnD,SAAS,OAAO;AACd,cAAQ,MAAM,+BAA+B,cAAc,IAAI,MAAM,KAAK;AAC1E,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEiB;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAA+C,oBAAI,IAAI;AAAA,EACvD,qBAAkD,oBAAI,IAAI;AAAA,EAE3E,YACE,YACA,YACA,YACA,UACA;AACA,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,cAAc;AAEnB,eAAW,SAAS,UAAU;AAC5B,WAAK,gBAAgB,IAAI,MAAM,MAAM,KAAK;AAC1C,WAAK,mBAAmB,IAAI,IAAI,MAAM,IAAI,IAAI,KAAK;AACnD,iBAAW,CAAC,MAAM,UAAU,KAAK,MAAM,aAAa;AAClD,aAAK,mBAAmB,IAAI,IAAI,MAAM,IAAI,GAAG,IAAI,IAAI,UAAU;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAW,OAAe;AACxB,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEA,IAAW,aAAyB;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,aAAyB;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,aAAuC;AAChD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAW,WAA0C;AACnD,WAAO,MAAM,KAAK,KAAK,gBAAgB,OAAO,CAAC;AAAA,EACjD;AAAA,EAEA,IAAW,cAAqD;AAC9D,WAAO,KAAK,mBAAmB,QAAQ;AAAA,EACzC;AAAA,EAEO,aACL,eACe;AACf,WAAO,KAAK,YAAY,aAAa,aAAa;AAAA,EACpD;AAAA,EAEO,eAAe,MAA0C;AAC9D,WAAO,KAAK,gBAAgB,IAAI,IAAI;AAAA,EACtC;AAAA,EAEO,oBAAoB,MAA0C;AACnE,QAAI,CAAC,KAAK,WAAW,GAAG,EAAG,QAAO,IAAI,IAAI;AAC1C,WAAO,KAAK,mBAAmB,IAAI,IAAI;AAAA,EACzC;AAAA,EAEO,2BAA2B,MAA8B;AAC9D,UAAM,WAAW,KAAK,oBAAoB,IAAI;AAC9C,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,wCAAwC,IAAI,EAAE;AAC7E,WAAO;AAAA,EACT;AAAA,EAEO,UAAgB;AACrB,SAAK,YAAY,QAAQ;AAAA,EAC3B;AACF;;;AClLO,IAAM,eAAN,MAAmB;AAAA,EACxB,OAAc,eAAe,MAA8C;AACzE,WAAO,iBAAiB,eAAe,IAAI;AAAA,EAC7C;AAAA,EAEA,OAAc,YACZ,YACA,SAA4B,MAC5B,SACgB;AAChB,WAAO,eAAe,YAAY,YAAY,QAAQ,OAAO;AAAA,EAC/D;AAAA,EAEA,OAAc,kBACZ,QACA,SAA4B,MAC5B,SACgB;AAChB,WAAO,eAAe,YAAY,OAAO,MAAM,QAAQ,OAAO;AAAA,EAChE;AAAA,EAEA,OAAc,mBAAmB,YAAwC;AACvE,UAAM,eAAyB,CAAC;AAChC,UAAM,WAAW,WAAW,qBAAqB;AAEjD,eAAW,QAAQ,UAAU;AAC3B,UAAI,SAAS,eAAe,CAAC,kBAAkB,IAAI,IAAI,GAAG;AACxD,qBAAa,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAc,8BAAwC;AACpD,WAAO,kBAAkB,mBAAmB;AAAA,EAC9C;AACF;;;AC5CA,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,YAAYC,aAAW;AAgCvB,IAAM,wBAAwB;AAAA,EAC5B,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AACR;AAoBO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACzB,OAAe,YAAkC;AAAA;AAAA,EAGzC;AAAA,EACA,eAAe,EAAE,GAAG,sBAAsB;AAAA,EAC1C;AAAA;AAAA,EAGA,QAAkC,oBAAI,IAAI;AAAA;AAAA,EAG1C,SAAmC,oBAAI,IAAI;AAAA,EAC3C,WAAuC,oBAAI,IAAI;AAAA,EAC/C,aAA+C,oBAAI,IAAI;AAAA,EACvD,aAAuC,oBAAI,IAAI;AAAA;AAAA,EAG/C,oBAA6C;AAAA;AAAA,EAG7C,mBAAsD,oBAAI,IAAI;AAAA,EAC9D,sBAA2D,oBAAI,IAAI;AAAA,EACnE,oBAAuD,oBAAI,IAAI;AAAA,EAC/D,wBAAmE,oBAAI,IAAI;AAAA,EAE3E,cAAc;AAAA,EAAC;AAAA,EAEvB,OAAc,cAA6B;AACzC,QAAI,CAAC,eAAc,WAAW;AAC5B,qBAAc,YAAY,IAAI,eAAc;AAAA,IAC9C;AACA,WAAO,eAAc;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKO,uBAAmF;AACxF,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAa,kBACX,WACA,QAC2B;AAE3B,SAAK,oBAAoB,OAAO;AAChC,SAAK,YAAY,OAAO;AACxB,QAAI,OAAO,cAAc;AACvB,WAAK,eAAe,EAAE,GAAG,uBAAuB,GAAG,OAAO,aAAa;AAAA,IACzE;AAGA,UAAM,mBAAmB,iBAAiB;AAAA,MACxC;AAAA,IACF;AACA,SAAK,oBAAoB;AAGzB,UAAM,SAAS,iBAAiB,UAAU;AAC1C,YAAQ,IAAI,2BAA2B,OAAO,MAAM,uBAAuB;AAE3E,eAAW,QAAQ;AAEnB,eAAW,SAAS,QAAQ;AAC1B,UAAI,KAAK,MAAM,IAAI,MAAM,KAAK,GAAG;AAC/B;AAAA,MACF;AAEA,cAAQ,IAAI,iCAAiC,MAAM,KAAK,UAAU,MAAM,IAAI,EAAE;AAC9E,YAAM,OAAO,MAAM,OAAO,UAAU,MAAM,IAAI;AAC9C,YAAM,cAAc,MAAM,KAAK,YAAY;AAE3C,YAAM,OAAO,MAAM,cAAc,eAAe,aAAa;AAAA,QAC3D,WAAW,KAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,aAAa;AAAA,QAC7B,UAAU,KAAK,aAAa;AAAA,MAC9B,CAAC;AAED,WAAK,MAAM,IAAI,MAAM,OAAO,IAAI;AAAA,IAClC;AAEA,YAAQ,IAAI,kCAAkC;AAC9C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,SAAS,OAAe,MAA6B;AAChE,QAAI,KAAK,MAAM,IAAI,KAAK,GAAG;AACzB,cAAQ,IAAI,yBAAyB,KAAK,4BAA4B;AACtE;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC1F;AAEA,YAAQ,IAAI,iCAAiC,KAAK,UAAU,IAAI,EAAE;AAClE,UAAM,OAAO,MAAM,KAAK,UAAU,IAAI;AACtC,UAAM,cAAc,MAAM,KAAK,YAAY;AAE3C,UAAM,OAAO,MAAM,cAAc,eAAe,aAAa;AAAA,MAC3D,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK,aAAa;AAAA,MAC7B,UAAU,KAAK,aAAa;AAAA,IAC9B,CAAC;AAED,SAAK,MAAM,IAAI,OAAO,IAAI;AAC1B,YAAQ,IAAI,yBAAyB,KAAK,UAAU;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKO,sBAAwC;AAC7C,QAAI,CAAC,KAAK,mBAAmB;AAC3B,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,UAAU,MAA0B;AACzC,UAAM,aAAa,KAAK,oBAAoB;AAC5C,UAAM,mBAAmB,WAAW,gBAAgB,YAAY;AAChE,QAAI,CAAC,kBAAkB;AACrB,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,UAAM,SAAS,iBAAiB,cAAc,IAAI;AAClD,QAAI,UAAU,MAAM;AAClB,YAAM,IAAI,MAAM,oCAAoC,IAAI,EAAE;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,QAAQ,OAAmC;AAChD,WAAO,KAAK,MAAM,IAAI,KAAK,KAAK;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,OAAwB;AAC1C,WAAO,KAAK,MAAM,IAAI,KAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,QAAQ,MAAoC;AAEvD,UAAM,SAAS,KAAK,OAAO,IAAI,IAAI;AACnC,QAAI,OAAQ,QAAO;AAGnB,UAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI;AAC/C,QAAI,SAAU,QAAO;AAGrB,UAAM,UAAU,KAAK,kBAAkB,IAAI;AAC3C,SAAK,iBAAiB,IAAI,MAAM,OAAO;AAEvC,QAAI;AACF,YAAM,OAAO,MAAM;AACnB,WAAK,OAAO,IAAI,MAAM,IAAI;AAC1B,aAAO;AAAA,IACT,UAAE;AACA,WAAK,iBAAiB,OAAO,IAAI;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,MAAkC;AACnD,WAAO,KAAK,OAAO,IAAI,IAAI,KAAK;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,MAAuB;AACzC,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,MAAc,kBAAkB,MAAoC;AAClE,eAAW,CAAC,EAAE,IAAI,KAAK,KAAK,OAAO;AACjC,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,SAAS,IAAI;AACrC,aAAK,mBAAmB,IAAI;AAC5B,eAAO;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,IAAI,MAAM,wBAAwB,IAAI,yBAAyB;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,eAAe,MAAc,QAAgB,GAAyB;AAEjF,UAAM,SAAS,KAAK,OAAO,IAAI,IAAI;AACnC,QAAI,OAAQ,QAAO;AAGnB,UAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI;AAC/C,QAAI,SAAU,QAAO;AAGrB,UAAM,UAAU,KAAK,yBAAyB,MAAM,KAAK;AACzD,SAAK,iBAAiB,IAAI,MAAM,OAAO;AAEvC,QAAI;AACF,YAAM,OAAO,MAAM;AACnB,WAAK,OAAO,IAAI,MAAM,IAAI;AAC1B,aAAO;AAAA,IACT,UAAE;AACA,WAAK,iBAAiB,OAAO,IAAI;AAAA,IACnC;AAAA,EACF;AAAA,EAEA,MAAc,yBAAyB,MAAc,OAAqC;AACxF,eAAW,CAAC,EAAE,IAAI,KAAK,KAAK,OAAO;AACjC,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,gBAAgB,IAAI;AAC5C,YAAI,UAAU,GAAG;AACf,eAAK,MAAM,UAAU,KAAK;AAC1B,eAAK,kBAAkB,IAAI;AAAA,QAC7B;AAEA,aAAK,mBAAmB,IAAI;AAG5B,YAAI,KAAK,mBAAmB;AAC1B,eAAK,SAAS,CAAC,UAAU;AACvB,gBAAK,MAAqB,QAAQ;AAChC,oBAAM,YAAY;AAClB,kBAAI,MAAM,QAAQ,UAAU,QAAQ,GAAG;AACrC,0BAAU,WAAW,UAAU,SAAS,IAAI,CAAC,MAAM,KAAK,kBAAmB,CAAC,CAAC;AAAA,cAC/E,WAAW,UAAU,UAAU;AAC7B,0BAAU,WAAW,KAAK,kBAAmB,UAAU,QAAQ;AAAA,cACjE;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,IAAI,MAAM,gCAAgC,IAAI,yBAAyB;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,UACX,UACA,aAAsB,MACtB,gBAAyB,MACH;AACtB,UAAM,WAAW,MAAM,KAAK,QAAQ,QAAQ;AAC5C,WAAO,KAAK,cAAc,UAAU,YAAY,aAAa;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKO,cACL,UACA,aAAsB,MACtB,gBAAyB,MACZ;AACb,UAAM,SAAS,SAAS,MAAM;AAE9B,WAAO,SAAS,CAAC,UAAU;AACzB,UAAK,MAAqB,QAAQ;AAChC,cAAM,OAAO;AAGb,YAAI,KAAK,mBAAmB;AAC1B,gBAAM,mBAAmB,KAAK;AAC9B,cAAI,kBAAkB;AACpB,iBAAK,WAAW,KAAK,kBAAkB,gBAAgB;AAAA,UACzD;AAAA,QACF;AAEA,aAAK,aAAa;AAClB,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,WAAW,MAAsC;AAE5D,UAAM,SAAS,KAAK,SAAS,IAAI,IAAI;AACrC,QAAI,OAAQ,QAAO;AAGnB,UAAM,WAAW,KAAK,oBAAoB,IAAI,IAAI;AAClD,QAAI,SAAU,QAAO;AAGrB,UAAM,UAAU,KAAK,qBAAqB,IAAI;AAC9C,SAAK,oBAAoB,IAAI,MAAM,OAAO;AAE1C,QAAI;AACF,YAAM,UAAU,MAAM;AACtB,WAAK,SAAS,IAAI,MAAM,OAAO;AAC/B,aAAO;AAAA,IACT,UAAE;AACA,WAAK,oBAAoB,OAAO,IAAI;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,eAAe,MAAoC;AACxD,WAAO,KAAK,SAAS,IAAI,IAAI,KAAK;AAAA,EACpC;AAAA,EAEA,MAAc,qBAAqB,MAAsC;AACvE,eAAW,CAAC,EAAE,IAAI,KAAK,KAAK,OAAO;AACjC,UAAI;AACF,cAAM,MAAM,MAAM,KAAK,YAAY,IAAI;AAEvC,YAAI,aAAa;AACjB,YAAI,QAAc;AAClB,YAAI,QAAc;AAClB,eAAO;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,IAAI,MAAM,2BAA2B,IAAI,yBAAyB;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAa,aAAa,MAAc,UAAiD;AAEvF,UAAM,SAAS,KAAK,WAAW,IAAI,IAAI;AACvC,QAAI,OAAQ,QAAO;AAGnB,UAAM,WAAW,KAAK,sBAAsB,IAAI,IAAI;AACpD,QAAI,SAAU,QAAO;AAErB,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,6BAA6B,IAAI,4CAA4C;AAAA,IAC/F;AAGA,UAAM,UAAU,KAAK,uBAAuB,MAAM,QAAQ;AAC1D,SAAK,sBAAsB,IAAI,MAAM,OAAO;AAE5C,QAAI;AACF,YAAM,OAAO,MAAM;AACnB,WAAK,WAAW,IAAI,MAAM,IAAI;AAC9B,aAAO;AAAA,IACT,UAAE;AACA,WAAK,sBAAsB,OAAO,IAAI;AAAA,IACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,iBAAiB,MAA0C;AAChE,WAAO,KAAK,WAAW,IAAI,IAAI,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKO,mBAAqD;AAC1D,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,uBACZ,MACA,UAC8B;AAC9B,UAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ;AAExC,eAAW,CAAC,EAAE,IAAI,KAAK,KAAK,OAAO;AACjC,UAAI;AACF,cAAM,EAAE,KAAK,IAAI,MAAM,KAAK,cAAc,MAAM,IAAI;AACpD,eAAO;AAAA,MACT,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,IAAI,MAAM,6BAA6B,IAAI,yBAAyB;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,SAAS,MAAoC;AAExD,UAAM,SAAS,KAAK,WAAW,IAAI,IAAI;AACvC,QAAI,OAAQ,QAAO;AAGnB,UAAM,WAAW,KAAK,kBAAkB,IAAI,IAAI;AAChD,QAAI,SAAU,QAAO;AAGrB,UAAM,UAAU,KAAK,mBAAmB,IAAI;AAC5C,SAAK,kBAAkB,IAAI,MAAM,OAAO;AAExC,QAAI;AACF,YAAM,QAAQ,MAAM;AACpB,WAAK,WAAW,IAAI,MAAM,KAAK;AAC/B,aAAO;AAAA,IACT,UAAE;AACA,WAAK,kBAAkB,OAAO,IAAI;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKO,aAAa,MAAkC;AACpD,WAAO,KAAK,WAAW,IAAI,IAAI,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKO,cAAwC;AAC7C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,mBAAmB,MAAoC;AACnE,UAAM,gBAAgB,YAAY;AAClC,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AAEA,eAAW,CAAC,EAAE,IAAI,KAAK,KAAK,OAAO;AACjC,UAAI;AACF,eAAO,MAAM,KAAK,UAAU,MAAM,aAAa;AAAA,MACjD,QAAQ;AAAA,MAER;AAAA,IACF;AACA,UAAM,IAAI,MAAM,yBAAyB,IAAI,yBAAyB;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,0BACX,UACA,UACA,aAAsB,OACtB,gBAAyB,OACzB,kBAA0B,IACR;AAClB,UAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ;AAG7C,UAAM,WAAW,KAAK,gBAAgB,SAAS;AAC/C,QAAI,CAAC,UAAU;AACb,cAAQ,MAAM,mDAAmD,QAAQ,GAAG;AAC5E,aAAO;AAAA,IACT;AAGA,UAAM,WAAW,KAAK,eAAe,SAAS;AAC9C,QAAI,CAAC,UAAU;AACb,cAAQ,MAAM,iDAAiD,QAAQ,GAAG;AAC1E,aAAO;AAAA,IACT;AAGA,UAAM,UAAU,qBAAqB,YAAY;AACjD,UAAM,QAAQ,QAAQ;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,CAAC,OAAO;AACV,cAAQ,MAAM,0CAA0C,QAAQ,GAAG;AACnE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAa,wBACX,YACA,aAAsB,OACtB,gBAAyB,OACzB,kBAA0B,IACR;AAClB,UAAM,mBAAmB,KAAK,oBAAoB;AAClD,UAAM,SAAS,iBAAiB,gBAAgB,UAAU;AAE1D,QAAI,CAAC,QAAQ;AACX,cAAQ,MAAM,2BAA2B,UAAU,aAAa;AAChE,aAAO;AAAA,IACT;AAGA,UAAM,oBAAoB,OAAO,KAAK,WAAW;AAAA,MAC/C,CAAC,MAAwB,EAAE,SAAS;AAAA,IACtC;AAEA,QAAI,CAAC,mBAAmB,MAAM,SAAS;AACrC,cAAQ;AAAA,QACN,2BAA2B,UAAU;AAAA,MACvC;AACA,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,kBAAkB,KAAK;AACxC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,gBAAgB,WAAqD;AAC3E,QAAI,WAAwC;AAE5C,cAAU,SAAS,CAAC,UAAU;AAC5B,UAAI,CAAC,YAAa,MAAqB,QAAQ;AAC7C,cAAM,OAAO;AACb,YAAI,KAAK,UAAU;AACjB,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,WAA+C;AACpE,QAAI,WAAkC;AAEtC,cAAU,SAAS,CAAC,UAAU;AAC5B,UAAI,CAAC,YAAa,MAAqB,QAAQ;AAC7C,cAAM,OAAO;AACb,cAAM,mBAAmB,KAAK;AAE9B,YAAI,kBAAkB;AACpB,cAAI,KAAK,mBAAmB;AAC1B,uBAAW,KAAK,kBAAkB,gBAAgB;AAAA,UACpD,OAAO;AACL,uBAAW,iBAAiB,MAAM;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWQ,mBAAmB,OAA0B;AACnD,UAAM,SAAS,CAAC,UAAU;AACxB,UAAI,CAAE,MAAqB,OAAQ;AACnC,YAAM,OAAO;AACb,YAAM,YAAY,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,WAAW,CAAC,KAAK,QAAQ;AAC/E,iBAAW,OAAO,WAAW;AAC3B,YAAI,CAAC,IAAK;AACV,cAAM,IAAI;AAEV,cAAM,QAAQ,CAAC,OAAO,aAAa,gBAAgB,gBAAgB,SAAS,eAAe,YAAY,WAAW,mBAAmB,UAAU,UAAU;AACzJ,mBAAW,QAAQ,OAAO;AACxB,gBAAM,MAAM,EAAE,IAAI;AAClB,cAAI,KAAK;AACP,gBAAI,QAAc;AAClB,gBAAI,QAAc;AAAA,UACpB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKO,UAAU,WAAuC;AACtD,UAAM,cAAc,IAAU,aAAK;AACnC,QAAI,YAAY;AAEhB,cAAU,SAAS,CAAC,UAAU;AAC5B,UAAI,iBAAuB,gBAAQ,MAAM,UAAU;AACjD,oBAAY;AAEZ,YAAI,CAAC,MAAM,SAAS,aAAa;AAC/B,gBAAM,SAAS,mBAAmB;AAAA,QACpC;AAEA,YAAI,MAAM,SAAS,aAAa;AAC9B,gBAAM,WAAW,MAAM,SAAS,YAAY,MAAM;AAClD,cAAI,MAAM,SAAS,OAAO,IAAI,KAAK,MAAM,MAAM,OAAO,MAAM,KAAK,KAAK,CAAC,GAAG;AACxE,qBAAS,aAAa,MAAM,MAAM;AAAA,UACpC;AACA,sBAAY,MAAM,QAAQ;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,CAAC,aAAa,YAAY,QAAQ,GAAG;AACvC,cAAQ,KAAK,8DAA8D;AAC3E,aAAO,IAAU,gBAAQ,GAAG,GAAG,CAAC;AAAA,IAClC;AAEA,UAAM,OAAO,IAAU,gBAAQ;AAC/B,gBAAY,QAAQ,IAAI;AACxB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKO,UAAgB;AAErB,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC5C,cAAQ,QAAQ;AAAA,IAClB;AACA,SAAK,SAAS,MAAM;AAGpB,eAAW,QAAQ,KAAK,OAAO,OAAO,GAAG;AACvC,WAAK,SAAS,CAAC,UAAU;AACvB,YAAI,iBAAuB,cAAM;AAC/B,gBAAM,UAAU,QAAQ;AACxB,cAAI,MAAM,UAAU;AAClB,gBAAI,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjC,oBAAM,SAAS,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,YAC3C,OAAO;AACL,oBAAM,SAAS,QAAQ;AAAA,YACzB;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AACA,SAAK,OAAO,MAAM;AAGlB,SAAK,WAAW,MAAM;AACtB,SAAK,WAAW,MAAM;AACtB,SAAK,MAAM,MAAM;AAEjB,SAAK,oBAAoB;AACzB,SAAK,eAAe,EAAE,GAAG,sBAAsB;AAC/C,SAAK,oBAAoB;AAAA,EAC3B;AACF;","names":["InputAction","THREE","THREE","THREE","THREE","THREE","THREE","THREE","maxPixelRatio","cappedPixelRatio","THREE","FBXLoader","FBXLoader","THREE","ActiveEvents","ColliderDesc","RigidBodyDesc","RigidBodyType","ColliderShape","THREE","THREE","THREE"]}