@popaya/pgsg-viewer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewers/playcanvas/pgsg-playcanvas-viewer.ts","../src/core/loaders/PGSGLoader.ts","../src/core/loaders/PLYLoader.ts","../src/core/loaders/createLoader.ts","../src/viewers/playcanvas/controls/OrbitCameraController.ts","../src/viewers/playcanvas/utils/fitCameraToBounds.ts","../src/viewers/playcanvas/controls/WalkCameraController.ts"],"sourcesContent":["import * as pc from \"playcanvas\";\n\nimport type { PGSGViewerOptions } from \"../../core/types\";\nimport type { Loader } from \"../../core/loaders/Loader\";\nimport { createLoader } from \"../../core/loaders/createLoader\";\nimport { OrbitCameraController } from \"./controls/OrbitCameraController\";\nimport { fitCameraToBounds } from \"./utils/fitCameraToBounds\";\nimport { WalkCameraController } from \"./controls/WalkCameraController\";\n\ntype CameraPresetId = \"entry\" | \"overview\" | \"close\";\n\ntype Bounds = { min: [number, number, number]; max: [number, number, number] };\n\ntype RoomNode = {\n id: string;\n name: string;\n connections: Array<{\n to: string;\n type: \"doorway\" | \"stairs\";\n }>;\n};\n\nexport class PGSGPlayCanvasViewer {\n private container: HTMLElement;\n private options: PGSGViewerOptions;\n\n private running = false;\n private disposed = false;\n\n // PlayCanvas runtime\n private canvas!: HTMLCanvasElement;\n private app!: pc.Application;\n\n // Scene graph handles\n private root!: pc.Entity;\n private cameraEntity!: pc.Entity;\n\n // Controllers (mutually exclusive)\n private orbit: OrbitCameraController | null = null;\n private walk: WalkCameraController | null = null;\n\n private cameraMode: \"orbit\" | \"walk\" = \"orbit\";\n\n // Loader\n private loader: Loader | null = null;\n\n // Semantic graph\n private roomGraph = new Map<string, RoomNode>();\n private currentRoomId: string | null = null;\n\n // Bounds\n private sceneBounds: Bounds | null = null;\n\n // Observer\n private resizeObserver: ResizeObserver | null = null;\n\n private yaw = 0;\n private pitch = 0;\n\n constructor(options: PGSGViewerOptions) {\n this.container = options.container;\n this.options = options;\n this.assertContainer();\n }\n\n // -----------------------\n // Public API\n // -----------------------\n\n async load(): Promise<void> {\n this.assertNotDisposed();\n\n // Init PlayCanvas once\n this.initRenderer();\n this.initScene();\n this.initCamera();\n\n // Resize\n this.bindResize();\n this.resize();\n\n // Create loader\n this.loader = createLoader(this.options.source, this.options.debug);\n\n // Load scene into this.root\n const result = await this.loader.load({\n rendererType: \"playcanvas\",\n scene: this.root,\n renderer: this.app,\n });\n\n // Build room graph after the scene exists\n this.buildRoomGraph();\n\n // Apply bounds if available\n if (result?.bounds) {\n this.sceneBounds = result.bounds as Bounds;\n this.applyBoundsToCamera(this.sceneBounds);\n\n // Default: start in orbit so zoom works\n this.ensureOrbit();\n // Entry preset means: target inside, camera close enough to go \"inside house\"\n this.setCameraPreset(\"entry\");\n // this.setCameraMode(\"orbit\");\n this.setCameraMode(\"walk\");\n } else {\n // No bounds: still allow orbit (basic)\n this.setCameraMode(\"orbit\");\n }\n }\n\n start(): void {\n this.assertNotDisposed();\n if (this.running) return;\n this.running = true;\n this.app.on(\"update\", this.onUpdate);\n }\n\n pause(): void {\n if (!this.running) return;\n this.running = false;\n this.app.off(\"update\", this.onUpdate);\n }\n\n destroy(): void {\n if (this.disposed) return;\n\n this.pause();\n this.disposed = true;\n\n this.resizeObserver?.disconnect();\n this.resizeObserver = null;\n\n this.walk?.dispose?.();\n this.walk = null;\n\n this.orbit?.dispose();\n this.orbit = null;\n\n this.loader?.dispose();\n this.loader = null;\n\n try {\n this.app?.destroy();\n } catch {\n // ignore\n }\n\n if (this.canvas?.parentElement === this.container) {\n this.container.removeChild(this.canvas);\n } else {\n this.container.innerHTML = \"\";\n }\n }\n\n resize(): void {\n if (!this.app || !this.canvas) return;\n\n const w = Math.max(1, this.container.clientWidth);\n const h = Math.max(1, this.container.clientHeight);\n\n const pixelRatio =\n this.options.renderer?.pixelRatio ??\n Math.min(2, window.devicePixelRatio || 1);\n\n this.canvas.width = Math.floor(w * pixelRatio);\n this.canvas.height = Math.floor(h * pixelRatio);\n\n this.canvas.style.width = `${w}px`;\n this.canvas.style.height = `${h}px`;\n\n this.app.resizeCanvas(this.canvas.width, this.canvas.height);\n\n const cam = this.cameraEntity?.camera;\n if (cam) cam.aspectRatio = w / h;\n }\n\n // Rooms / graph\n listRooms(): Array<{ id: string; name: string }> {\n if (!this.root) return [];\n const out: Array<{ id: string; name: string }> = [];\n\n this.app.root.children.forEach((c: any) => {\n if (c?.name?.startsWith(\"room-\") && c?.pgsg?.id) {\n out.push({ id: c.pgsg.id, name: c.pgsg.name ?? c.pgsg.id });\n }\n });\n\n return out;\n }\n\n showOnlyRoom(roomId: string) {\n if (!this.root) return;\n\n this.root.children.forEach((c) => {\n // if (c.name?.startsWith(\"room-\")) c.enabled = c.name === `room-${roomId}`;\n if (!c.name?.startsWith(\"room-\")) return;\n c.enabled = c.name === `room-${roomId}`;\n });\n\n this.currentRoomId = roomId;\n }\n\n setRoomVisible(roomId: string, visible: boolean) {\n const room = this.getRoomEntity(roomId);\n if (room) room.enabled = visible;\n }\n\n getRoomGraph(): RoomNode[] {\n return Array.from(this.roomGraph.values());\n }\n\n getCurrentRoomId() {\n return this.currentRoomId;\n }\n\n goToRoom(roomId: string, preset: CameraPresetId = \"entry\") {\n const targetRoom = this.getRoomEntity(roomId);\n if (!targetRoom) return;\n\n this.currentRoomId = roomId;\n\n // Prefer room bounds if present; else global bounds; else do nothing\n const bounds = this.getBoundsForRoom(roomId) ?? this.sceneBounds;\n if (!bounds) return;\n\n // Ensure orbit for smooth travel\n this.setCameraMode(\"orbit\");\n\n // Apply preset\n this.setCameraPreset(preset, bounds);\n }\n\n setCameraMode(mode: \"orbit\" | \"walk\") {\n this.assertNotDisposed();\n if (this.cameraMode === mode) return;\n this.cameraMode = mode;\n\n if (mode === \"orbit\") {\n // turn off walk\n this.walk?.dispose?.();\n this.walk = null;\n\n // turn on orbit\n this.app.mouse?.disablePointerLock();\n this.ensureOrbit();\n } else {\n // turn off orbit\n this.orbit?.dispose();\n this.orbit = null;\n\n // turn on walk (requires bounds to feel right)\n this.ensureWalk();\n this.app.mouse?.enablePointerLock();\n }\n }\n\n setCameraPreset(preset: CameraPresetId, bounds?: Bounds) {\n const b = bounds ?? this.sceneBounds;\n if (!b) return;\n\n const fit = fitCameraToBounds(this.cameraEntity, b);\n const eye = this.getFirstPersonStart(b);\n\n let distance = fit.distance;\n if (preset === \"entry\") distance = Math.max(0.5, fit.distance * 0.35);\n if (preset === \"close\") distance = Math.max(0.25, fit.distance * 0.2);\n if (preset === \"overview\") distance = Math.max(1.0, fit.distance * 1.1);\n\n if (this.orbit) {\n // mutate orbit safely\n this.orbit.setTarget(preset === \"overview\" ? fit.center : eye);\n this.orbit.setDistance(distance);\n } else {\n // fallback: just position camera\n const dir = new pc.Vec3(0, 0, 1);\n this.cameraEntity.setPosition(eye.clone().add(dir.mulScalar(distance)));\n this.cameraEntity.lookAt(eye);\n }\n\n console.log(\"[CameraPreset]\", preset, { distance });\n }\n\n // setCameraPreset(preset: CameraPresetId, bounds?: Bounds) {\n // const b = bounds ?? this.sceneBounds;\n // if (!b) return;\n\n // // this.ensureOrbit();\n\n // const entry = this.computeInteriorStart(b);\n\n // // \"fitCameraToBounds\" returns a good distance for overview;\n // // we scale it down for entry/close so you can get inside immediately.\n // const fit = fitCameraToBounds(this.cameraEntity, b);\n // const eye = this.getFirstPersonStart(b)\n // const baseDistance = fit?.distance ?? this.estimateDistanceFromBounds(b);\n\n // let distance = baseDistance;\n // if (preset === \"entry\") distance = Math.max(0.5, baseDistance * 0.35);\n // if (preset === \"close\") distance = Math.max(0.25, baseDistance * 0.2);\n // if (preset === \"overview\") distance = Math.max(1.0, baseDistance * 1.1);\n\n // const center = fit.center.clone();\n\n // // Push orbit target slightly DOWN (important for interiors)\n // center.y = this.sceneBounds!.min[1] + 1.6;\n\n // // Update orbit target and distance\n // // (Assumes OrbitCameraController accepts live updates to target/distance.\n // // If it doesn't, we can re-create orbit here.)\n // this.orbit = new OrbitCameraController(this.app, this.cameraEntity, {\n // target: center,\n // distance: fit.distance * 1.2,\n // minDistance: fit.distance * 0.1,\n // maxDistance: fit.distance * 25,\n // yaw: 180,\n // pitch: -10,\n // });\n\n // console.log(\"[fitCameraToBounds]\", {\n // center: fit.center,\n // radius: fit.radius,\n // distance: fit.distance,\n // });\n // // try {\n // // // @ts-ignore - depending on your controller public fields\n // // this.orbit!.target = preset === \"overview\" ? new pc.Vec3(fit.center.x, fit.center.y, fit.center.z) : entry;\n // // // @ts-ignore\n // // this.orbit!.distance = distance;\n // // // @ts-ignore\n // // this.orbit!.minDistance = Math.max(0.1, distance * 0.15);\n // // // @ts-ignore\n // // this.orbit!.maxDistance = Math.max(distance * 2, distance * 6);\n // // } catch {\n // // // Fallback: recreate orbit if controller doesn't support mutation\n // // this.orbit?.dispose();\n // // this.orbit = new OrbitCameraController(this.app, this.cameraEntity, {\n // // target: preset === \"overview\" ? fit.center : entry,\n // // distance,\n // // minDistance: Math.max(0.1, distance * 0.15),\n // // maxDistance: Math.max(distance * 2, distance * 6),\n // // });\n // // }\n // }\n\n enableWalkMode() {\n // if (!this.sceneBounds || !this.walk) return;\n if (!this.walk) {\n console.warn(\"[PGSGViewer] walk controller missing\");\n return;\n }\n if (!this.sceneBounds) {\n console.warn(\"[PGSGViewer] sceneBounds missing\");\n return;\n }\n\n // 🔥 THIS LINE IS NON-NEGOTIABLE\n this.cameraMode = \"walk\";\n\n const start = this.getWalkStart(this.sceneBounds);\n\n // this.setCameraMode(\"walk\");\n this.walk!.setPosition(start);\n this.walk!.setYawPitch(180, 0);\n this.walk!.setFloorY(this.sceneBounds!.min[1]);\n console.log(\"[PGSGViewer] Walk mode ACTIVE\");\n }\n\n // -----------------------\n // Internals\n // -----------------------\n\n private onUpdate = (dt: number) => {\n if (!this.sceneBounds) return;\n\n // ORBIT MODE\n if (this.cameraMode === \"orbit\") {\n // orbit controller updates internally via mouse events\n return;\n }\n\n // WALK MODE\n if (this.cameraMode === \"walk\" && this.walk) {\n const scale =\n Math.max(\n this.sceneBounds.max[0] - this.sceneBounds.min[0],\n this.sceneBounds.max[2] - this.sceneBounds.min[2]\n ) * 0.05;\n\n this.walk.update(dt, scale);\n }\n };\n\n private initRenderer() {\n if (this.app) return;\n\n this.canvas = document.createElement(\"canvas\");\n this.canvas.addEventListener(\"contextmenu\", (e) => {\n e.preventDefault();\n });\n this.canvas.style.display = \"block\";\n this.canvas.style.width = \"100%\";\n this.canvas.style.height = \"100%\";\n this.container.appendChild(this.canvas);\n\n this.app = new pc.Application(this.canvas, {\n mouse: new pc.Mouse(this.canvas),\n touch: new pc.TouchDevice(this.canvas),\n keyboard: new pc.Keyboard(window),\n elementInput: new pc.ElementInput(this.canvas),\n });\n\n // Set up root scene node\n // this.root = new pc.Entity(\"pgsg-root\");\n // this.app.root.addChild(this.root);\n\n this.root = this.app.root;\n this.app.start();\n }\n\n private initScene() {\n // Basic lighting defaults (adjust if your project uses something else)\n this.app.scene.ambientLight = new pc.Color(0.6, 0.6, 0.6);\n\n // If you use clustered lighting, keep it consistent\n // this.app.scene.clusteredLightingEnabled = true;\n }\n\n private initCamera() {\n // Camera entity\n this.cameraEntity = new pc.Entity(\"camera\");\n this.cameraEntity.addComponent(\"camera\", {\n clearColor: new pc.Color(0, 0, 0),\n nearClip: 0.01,\n farClip: 10000,\n fov: 60,\n layers: [pc.LAYERID_WORLD],\n });\n\n // Start somewhere sensible even before bounds exist\n this.cameraEntity.setLocalPosition(0, 1.6, 5);\n this.cameraEntity.setLocalEulerAngles(0, 180, 0);\n\n this.app.root.addChild(this.cameraEntity);\n console.log(\"Camera layers\", this.cameraEntity.camera!.layers);\n this.cameraEntity.camera!.clearDepthBuffer = true;\n }\n\n private bindResize() {\n this.resizeObserver?.disconnect();\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.container);\n }\n\n private applyBoundsToCamera(bounds: Bounds) {\n // Clip plane tuning based on bounds diagonal\n const dx = bounds.max[0] - bounds.min[0];\n const dy = bounds.max[1] - bounds.min[1];\n const dz = bounds.max[2] - bounds.min[2];\n const radius = Math.sqrt(dx * dx + dy * dy + dz * dz) * 0.5;\n\n const cam = this.cameraEntity.camera!;\n cam.nearClip = Math.max(0.01, radius * 0.001);\n cam.farClip = Math.max(100, radius * 10);\n }\n\n private getFirstPersonStart(bounds: Bounds) {\n const x = (bounds.min[0] + bounds.max[0]) * 0.5;\n const z = (bounds.min[2] + bounds.max[2]) * 0.5;\n const y = bounds.min[1] + 1.6; // eye height\n\n return new pc.Vec3(x, y, z);\n }\n\n private ensureOrbit() {\n if (this.orbit) return;\n if (!this.sceneBounds) return;\n\n const b = this.sceneBounds;\n const fit = fitCameraToBounds(this.cameraEntity, b);\n\n const target = fit.center.clone();\n target.y = b.min[1] + 1.6;\n\n this.orbit = new OrbitCameraController(this.app, this.cameraEntity, {\n target,\n distance: fit.distance * 1.2,\n minDistance: Math.max(0.1, fit.distance * 0.15),\n maxDistance: Math.max(fit.distance * 2, fit.distance * 6),\n yaw: 180,\n pitch: -10,\n });\n\n console.log(\"[ensureOrbit] created\");\n }\n\n // private ensureOrbit() {\n // if (this.orbit) return;\n\n // const bounds = this.sceneBounds;\n // const target = bounds ? this.computeInteriorStart(bounds) : new pc.Vec3(0, 1.6, 0);\n // const distance = bounds ? Math.max(0.5, this.estimateDistanceFromBounds(bounds) * 0.6) : 5;\n\n // this.orbit = new OrbitCameraController(this.app, this.cameraEntity, {\n // target,\n // distance,\n // minDistance: Math.max(0.1, distance * 0.15),\n // maxDistance: Math.max(distance * 2, distance * 6),\n // });\n // }\n\n private ensureWalk() {\n if (this.walk) return;\n\n const bounds = this.sceneBounds;\n const start = bounds\n ? this.computeInteriorStart(bounds)\n : new pc.Vec3(0, 1.6, 0);\n\n this.cameraEntity.setPosition(start);\n this.cameraEntity.setEulerAngles(0, 180, 0);\n\n this.walk = new WalkCameraController(this.app, this.cameraEntity, {\n eyeHeight: 1.6,\n speed: 1.5,\n lookSpeed: 0.0015,\n // enable later if you have colliders:\n // gravity: true,\n // collision: true,\n });\n\n const fwd = this.cameraEntity.forward.clone();\n this.yaw = Math.atan2(fwd.x, fwd.z) * pc.math.RAD_TO_DEG;\n this.pitch = 0;\n }\n\n private computeInteriorStart(bounds: Bounds) {\n const cx = (bounds.min[0] + bounds.max[0]) * 0.5;\n const cz = (bounds.min[2] + bounds.max[2]) * 0.5;\n\n const floorY = bounds.min[1];\n const eyeY = floorY + 1.6;\n\n return new pc.Vec3(cx, eyeY, cz);\n }\n\n private estimateDistanceFromBounds(bounds: Bounds) {\n const dx = bounds.max[0] - bounds.min[0];\n const dy = bounds.max[1] - bounds.min[1];\n const dz = bounds.max[2] - bounds.min[2];\n const radius = Math.sqrt(dx * dx + dy * dy + dz * dz) * 0.5;\n return Math.max(1, radius * 1.2);\n }\n\n private getRoomEntity(roomId: string) {\n if (!this.root) return null;\n // room entities are attached by loader: name = room-<id>\n return this.root.findByName(`room-${roomId}`) as pc.Entity | null;\n }\n\n private getBoundsForRoom(roomId: string): Bounds | null {\n const room = this.getRoomEntity(roomId) as any;\n if (!room) return null;\n\n // If loader attached per-room bounds\n const b = room.pgsg?.bounds;\n if (b?.min && b?.max) return b as Bounds;\n\n return null;\n }\n\n private buildRoomGraph() {\n this.roomGraph.clear();\n\n // Minimal: nodes = rooms. Connections can be extended later from PGSG extras\n const rooms = this.listRooms();\n for (const r of rooms) {\n this.roomGraph.set(r.id, { id: r.id, name: r.name, connections: [] });\n }\n\n // If your loader provides connections in room.pgsg.extras, wire them here later.\n }\n\n private getWalkStart(bounds: Bounds) {\n return new pc.Vec3(\n (bounds.min[0] + bounds.max[0]) * 0.5,\n bounds.min[1] + 1.6, // eye height\n (bounds.min[2] + bounds.max[2]) * 0.5\n );\n }\n\n private assertContainer() {\n if (!this.container) throw new Error(\"[PGSGViewer] container is required\");\n }\n\n private assertNotDisposed() {\n if (this.disposed) throw new Error(\"[PGSGViewer] already destroyed\");\n }\n}\n","import * as pc from \"playcanvas\";\nimport type { Loader, LoaderContext, LoadResult } from \"./Loader\";\n\nexport interface PGSGLoaderOptions {\n url: string;\n debug?: boolean;\n}\n\ntype FieldType =\n | \"float32\"\n | \"uint32\"\n | \"uint16\"\n | \"uint8\"\n | \"int32\"\n | \"int16\"\n | \"int8\";\n\ntype LayoutField = { offset: number; type: FieldType };\n\ntype BufferLayout = {\n stride: number;\n fields?: Record<string, LayoutField>;\n properties?: Record<string, LayoutField>; // alias\n};\n\ntype GaussianSet = {\n id: string;\n file: string;\n count: number;\n bufferLayout: BufferLayout;\n layout?: BufferLayout; // alias\n semanticTags?: string[];\n extras?: any;\n};\n\ntype RoomLayer = {\n id: string;\n type: string;\n gaussianSetIds: string[];\n};\n\ntype Room = {\n id: string;\n name: string;\n label?: string;\n extras?: any;\n layers: RoomLayer[];\n};\n\ntype PGSG = {\n gaussianSets: GaussianSet[];\n rooms?: Room[];\n extras?: {\n globalBounds?: {\n min: [number, number, number];\n max: [number, number, number];\n };\n };\n};\n\ntype NormalizedLayout = {\n stride: number;\n attrs: Record<string, LayoutField>;\n};\n\nexport type RawSplatData = {\n count: number;\n position: Float32Array;\n scale: Float32Array;\n quat: Float32Array;\n color: Float32Array; // linear RGB [0..1]\n opacity: Float32Array; // [0..1]\n bounds: {\n min: [number, number, number];\n max: [number, number, number];\n };\n};\n\nconst REQUIRED_PLY_FIELDS = [\n \"x\",\n \"y\",\n \"z\",\n \"scale_0\",\n \"scale_1\",\n \"scale_2\",\n \"rot_0\",\n \"rot_1\",\n \"rot_2\",\n \"rot_3\",\n \"opacity\",\n \"f_dc_0\",\n \"f_dc_1\",\n \"f_dc_2\",\n // f_rest_0..44 optional (pad zeros if absent)\n] as const;\n\nexport class PGSGLoader implements Loader {\n private opts: PGSGLoaderOptions;\n\n private blobUrls: string[] = [];\n private entities: pc.Entity[] = [];\n private assets: pc.Asset[] = [];\n\n private globalBounds?: {\n min: [number, number, number];\n max: [number, number, number];\n };\n\n constructor(opts: PGSGLoaderOptions) {\n this.opts = opts;\n }\n\n async load(ctx: LoaderContext): Promise<LoadResult> {\n const rawSplats: RawSplatData[] = [];\n\n // hard reset (important for hot reload / repeated loads)\n this.dispose();\n this.globalBounds = undefined;\n\n const { url, debug } = this.opts;\n\n // 1) Resolve pgsgJsonUrl\n const entry = await fetch(url).then((r) => {\n if (!r.ok) {\n throw new Error(\n `[PGSG-Viewer] PGSGLoader: failed to fetch entry JSON ${url} (${r.status})`\n );\n }\n return r.json();\n });\n\n const pgsgJsonUrl: string | undefined =\n entry?.pgsgJsonUrl ?? entry?.pgsg_url ?? entry?.url;\n if (!pgsgJsonUrl) {\n throw new Error(\n `[PGSG-Viewer] PGSGLoader: entry JSON missing \"pgsgJsonUrl\" (url=${url})`\n );\n }\n\n // 2) Fetch PGSG JSON\n const pgsg = await this.fetchJSON<PGSG>(pgsgJsonUrl);\n\n if (!pgsg?.gaussianSets?.length) {\n throw new Error(\"[PGSG-Viewer] PGSGLoader: gaussianSets missing/empty\");\n }\n\n // base URL for bin files (relative set.file)\n const baseUrl = url.substring(0, url.lastIndexOf(\"/\") + 1);\n\n // 3) Pre-load all bin buffers\n const setsData: Array<{\n set: GaussianSet;\n buffer: ArrayBuffer;\n layout: BufferLayout;\n }> = [];\n\n let totalCount = 0;\n\n for (const set of pgsg.gaussianSets) {\n if (!set.file || !set.count) continue;\n\n const layout = set.bufferLayout ?? set.layout;\n if (!layout || !layout.stride) {\n throw new Error(\n `[PGSG-Viewer] PGSGLoader: invalid bufferLayout/stride for ${set.file}`\n );\n }\n\n const fullBinUrl = new URL(set.file, baseUrl).toString();\n const buf = await this.fetchArrayBuffer(fullBinUrl);\n\n totalCount += set.count;\n setsData.push({ set, buffer: buf, layout });\n\n if (debug) {\n console.log(\n \"[PGSG-Viewer] PGSGLoader: loaded bin\",\n fullBinUrl,\n \"bytes=\",\n buf.byteLength\n );\n }\n }\n\n if (totalCount === 0) {\n throw new Error(\"[PGSG-Viewer] PGSGLoader: totalCount=0\");\n }\n\n if (ctx.rendererType === \"three\") {\n for (const { set, buffer, layout } of setsData) {\n const raw = this.extractRawSplatsFromSingleSet(set, buffer, layout);\n rawSplats.push(raw);\n this.expandGlobalBounds(raw.bounds);\n }\n\n const finalBounds = pgsg.extras?.globalBounds ?? this.globalBounds;\n\n return {\n bounds: finalBounds,\n splats: this.mergeRawSplats(rawSplats),\n };\n }\n\n // 4) Build rooms as entities (room-*). Viewer uses these for listRooms/showOnlyRoom.\n const roomIndex = this.buildRoomIndex(pgsg.rooms);\n const roomEntities = new Map<string, pc.Entity>();\n\n if (pgsg.rooms?.length) {\n for (const room of pgsg.rooms) {\n const entity = new pc.Entity(`room-${room.id}`);\n entity.enabled = true;\n\n (entity as any).pgsg = {\n id: room.id,\n name: room.name,\n extras: room.extras,\n };\n\n ctx.renderer?.root.addChild(entity);\n roomEntities.set(room.id, entity);\n }\n }\n\n // 5) Convert each gaussianSet → a gsplat asset + entity\n for (const { set, buffer, layout } of setsData) {\n const { ply, bounds } = this.buildPLYFromSingleSet(set, buffer, layout);\n\n // declared bounds (optional)\n const declared = set.extras?.context?.bounds;\n const setBounds =\n declared?.min && declared?.max\n ? {\n min: declared.min as [number, number, number],\n max: declared.max as [number, number, number],\n }\n : bounds;\n\n // build blob URL and asset\n const blob = new Blob([ply], { type: \"application/octet-stream\" });\n const blobUrl = URL.createObjectURL(blob);\n\n const asset = new pc.Asset(`gsplat-${set.id}`, \"gsplat\", {\n url: blobUrl,\n });\n ctx.renderer?.assets.add(asset);\n await this.loadAssetAsync(ctx.renderer!, asset);\n\n const gsEntity = new pc.Entity(`gs-${set.id}`);\n gsEntity.addComponent(\"gsplat\", { asset });\n\n // IMPORTANT FIX:\n // Do NOT apply arbitrary transforms here (position/rotate/scale flips),\n // because the returned bounds are used by PGSGViewer to place the camera.\n // If you move the entity but return old bounds, the camera starts in the wrong place.\n //\n // If coordinate system conversion is needed, do it inside buildPLYFromSingleSet()\n // (i.e., bake it into the vertex data), not as an entity transform.\n\n (gsEntity as any).pgsg = {\n id: set.id,\n semanticTags: set.semanticTags,\n extras: set.extras,\n bounds: setBounds,\n };\n\n // Attach to room if mapping exists, else attach to root scene\n const roomId = roomIndex.get(set.id);\n // const parent =\n // roomId && roomEntities.get(roomId) ? roomEntities.get(roomId)! : ctx.renderer.root;\n\n // parent.addChild(gsEntity);\n ctx.renderer?.root.addChild(gsEntity);\n\n console.log(\n \"[PGSGLoader] gsplat entity added\",\n gsEntity.name,\n \"parent:\",\n parent.name\n );\n\n this.assets.push(asset);\n this.entities.push(gsEntity);\n this.blobUrls.push(blobUrl);\n\n // Accumulate GLOBAL bounds from *setBounds* (declared override) – not from untrusted local\n this.expandGlobalBounds(bounds);\n }\n\n // if (ctx.rendererType === \"three\") {\n // const merged = this.mergeRawSplats(rawSplats);\n\n // const finalBounds = pgsg.extras?.globalBounds ?? this.globalBounds;\n\n // return {\n // bounds: finalBounds,\n // splats: merged,\n // };\n // }\n\n // 6) If PGSG provides authoritative globalBounds, prefer it\n const finalBounds = pgsg.extras?.globalBounds ?? this.globalBounds;\n\n return finalBounds ? { bounds: finalBounds } : {};\n }\n\n dispose(): void {\n // destroy entities\n try {\n this.entities.forEach((e) => e.destroy());\n } catch {\n // ignore\n }\n this.entities = [];\n\n // unload/destroy assets\n try {\n this.assets.forEach((a) => {\n try {\n a.unload();\n } catch {}\n try {\n a.registry?.remove(a);\n } catch {}\n });\n } catch {\n // ignore\n }\n this.assets = [];\n\n // revoke blob URLs\n try {\n this.blobUrls.forEach((u) => URL.revokeObjectURL(u));\n } catch {\n // ignore\n }\n this.blobUrls = [];\n }\n\n private buildRoomIndex(rooms?: Room[]) {\n const map = new Map<string, string>(); // gsetId -> roomId\n if (!rooms) return map;\n\n for (const room of rooms) {\n for (const layer of room.layers ?? []) {\n for (const gid of layer.gaussianSetIds ?? []) {\n map.set(gid, room.id);\n }\n }\n }\n return map;\n }\n\n private expandGlobalBounds(b: {\n min: [number, number, number];\n max: [number, number, number];\n }) {\n if (!this.globalBounds) {\n this.globalBounds = {\n min: [...b.min],\n max: [...b.max],\n };\n return;\n }\n\n for (let i = 0; i < 3; i++) {\n this.globalBounds.min[i] = Math.min(this.globalBounds.min[i], b.min[i]);\n // ✅ FIX: max should use Math.max (your file had Math.min here)\n this.globalBounds.max[i] = Math.max(this.globalBounds.max[i], b.max[i]);\n }\n }\n\n private async fetchJSON<T>(url: string): Promise<T> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(\n `[PGSG-Viewer] PGSGLoader: failed to fetch JSON: ${url} (${res.status})`\n );\n }\n return (await res.json()) as T;\n }\n\n private async fetchArrayBuffer(url: string): Promise<ArrayBuffer> {\n const res = await fetch(url);\n if (!res.ok) {\n throw new Error(\n `[PGSG-Viewer] PGSGLoader: failed to fetch ArrayBuffer: ${url} (${res.status})`\n );\n }\n return await res.arrayBuffer();\n }\n\n private loadAssetAsync(app: pc.Application, asset: pc.Asset): Promise<void> {\n return new Promise((resolve, reject) => {\n asset.once(\"load\", () => resolve());\n asset.once(\"error\", (error: any) =>\n reject(error ?? new Error(\"gsplat asset failed to load\"))\n );\n app.assets.load(asset);\n });\n }\n\n /**\n * Convert PGSG (bin + layout) to a single binary_little_endian PLY buffer\n * with PlayCanvas's 3DGS property schema. :contentReference[oaicite:2]{index=2}\n */\n private buildPLYFromPGSG(\n setsData: Array<{\n set: GaussianSet;\n buffer: ArrayBuffer;\n layout: BufferLayout;\n }>,\n totalCount: number\n ): {\n ply: ArrayBuffer;\n bounds: { min: [number, number, number]; max: [number, number, number] };\n } {\n // PLY headers for 3DGS\n const headerLines: string[] = [\n \"ply\",\n \"format binary_little_endian 1.0\",\n `element vertex ${totalCount}`,\n \"property float x\",\n \"property float y\",\n \"property float z\",\n \"property float scale_0\",\n \"property float scale_1\",\n \"property float scale_2\",\n \"property float rot_0\",\n \"property float rot_1\",\n \"property float rot_2\",\n \"property float rot_3\",\n \"property float opacity\",\n \"property float f_dc_0\",\n \"property float f_dc_1\",\n \"property float f_dc_2\",\n ];\n\n for (let i = 0; i < 45; i++) headerLines.push(`property float f_rest_${i}`);\n\n headerLines.push(\"end_header\");\n\n const header = headerLines.join(\"\\n\") + \"\\n\";\n const headerBytes = new TextEncoder().encode(header);\n\n // Each vertix = (3 pos + 3 scale + 4 rot + 1 opacity + 3 f_dc + 45 f_rest) float32\n const floatsPerVertex = 3 + 3 + 4 + 1 + 3 + 45; // 59\n const bytesPerVertex = floatsPerVertex * 4;\n\n const out = new ArrayBuffer(\n headerBytes.byteLength + totalCount * bytesPerVertex\n );\n const outU8 = new Uint8Array(out);\n outU8.set(headerBytes, 0);\n\n const dvOut = new DataView(out);\n let writeOffset = headerBytes.byteLength;\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let minZ = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n let maxZ = Number.NEGATIVE_INFINITY;\n\n let written = 0;\n\n for (const { set, buffer, layout } of setsData) {\n const { stride, attrs } = this.normalizeLayout(layout);\n // const stride = layout.stride;\n // const fields = layout.fields ?? layout.properties ?? {};\n let dv = new DataView(buffer);\n\n const expectedBytes = set.count * stride;\n if (buffer.byteLength < expectedBytes) {\n throw new Error(\n `[PGSG-Viewer] bin too small for ${set.file}: have ${buffer.byteLength}, need >= ${expectedBytes}`\n );\n }\n\n const required = [\"position\", \"scale\", \"rotation\", \"opacity\"];\n for (const k of required) {\n if (!attrs[k]) {\n throw new Error(\n `[PGSG-Viewer] PLY build: missing required attribute '${k}' in layout of ${set.file}`\n );\n }\n }\n\n // Color: allow f_dc OR sh\n if (!attrs.f_dc && !attrs.sh) {\n throw new Error(\n `[PGSG-Viewer] PLY build: missing 'f_dc' or 'sh' in ${set.file}`\n );\n }\n\n for (let i = 0; i < set.count; i++) {\n const base = i * stride;\n\n const x = dv.getFloat32(base + attrs.position.offset + 0, true);\n const y = dv.getFloat32(base + attrs.position.offset + 4, true);\n const z = dv.getFloat32(base + attrs.position.offset + 8, true);\n\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n minZ = Math.min(minZ, z);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n maxZ = Math.max(maxZ, z);\n\n // Write in exact PlayCanvas PLY order :contentReference[oaicite:3]{index=3}\n // Translate\n dvOut.setFloat32(writeOffset, x, true);\n writeOffset += 4;\n dvOut.setFloat32(writeOffset, -y, true);\n writeOffset += 4;\n dvOut.setFloat32(writeOffset, -z, true);\n writeOffset += 4;\n\n // Scale\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.scale.offset + 0, true),\n true\n );\n writeOffset += 4;\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.scale.offset + 4, true),\n true\n );\n writeOffset += 4;\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.scale.offset + 8, true),\n true\n );\n writeOffset += 4;\n\n // Quaternion\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.rotation.offset + 0, true),\n true\n );\n writeOffset += 4;\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.rotation.offset + 4, true),\n true\n );\n writeOffset += 4;\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.rotation.offset + 8, true),\n true\n );\n writeOffset += 4;\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.rotation.offset + 12, true),\n true\n );\n writeOffset += 4;\n\n // Opacity\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + attrs.opacity.offset, true),\n true\n );\n writeOffset += 4;\n\n // f_dc SH coefficient (rgb colors)\n const fDcAttr = attrs.f_dc;\n const shAttr = attrs.sh;\n\n if (fDcAttr) {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + fDcAttr.offset + 0, true),\n true\n );\n } else {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + shAttr.offset + 0, true),\n true\n );\n }\n writeOffset += 4;\n\n if (fDcAttr) {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + fDcAttr.offset + 4, true),\n true\n );\n } else {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + shAttr.offset + 4, true),\n true\n );\n }\n writeOffset += 4;\n\n if (fDcAttr) {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + fDcAttr.offset + 8, true),\n true\n );\n } else {\n dvOut.setFloat32(\n writeOffset,\n dv.getFloat32(base + shAttr.offset + 8, true),\n true\n );\n }\n writeOffset += 4;\n\n // f_rest_0..44 SH residual coefficients\n for (let r = 0; r < 45; r++) {\n let v = 0;\n\n if (attrs.f_rest) {\n v = dv.getFloat32(base + attrs.f_rest.offset + r * 4, true);\n } else if (attrs.sh) {\n v = dv.getFloat32(base + attrs.sh.offset + (3 + r) * 4, true);\n }\n dvOut.setFloat32(writeOffset, v, true);\n writeOffset += 4;\n }\n\n written++;\n }\n }\n\n if (written !== totalCount) {\n throw new Error(\n `[PGSG-Viewer] PLY build mismatch: written=${written} total=${totalCount}`\n );\n }\n\n return {\n ply: out,\n bounds: { min: [minX, minY, minZ], max: [maxX, maxY, maxZ] },\n };\n }\n\n private normalizeLayout(layout: BufferLayout): NormalizedLayout {\n if (!layout) {\n throw new Error(\"[PGSG-Viewer] Invalid bufferLayout\");\n }\n\n // 1. Resolve stride\n let stride = layout.stride;\n\n // 2. Resolve attributes from multiple legacy shapes\n let attrs: Record<string, LayoutField> | undefined =\n (layout as any).attributes ?? layout.fields ?? layout.properties;\n\n // 3. Fallback: flat layout (attributes at top level)\n if (!attrs) {\n attrs = {};\n\n for (const [key, value] of Object.entries(layout)) {\n if (key === \"stride\") continue;\n\n if (\n value &&\n typeof value === \"object\" &&\n typeof (value as any).offset === \"number\"\n ) {\n attrs[key] = value as unknown as LayoutField;\n\n // infer stride if missing\n if (stride == null && typeof (value as any).stride === \"number\") {\n stride = (value as any).stride;\n }\n }\n }\n }\n\n if (!attrs || !Object.keys(attrs).length) {\n throw new Error(\"[PGSG-Viewer] bufferLayout has no fields/properties\");\n }\n\n if (typeof stride !== \"number\") {\n throw new Error(\"[PGSG-Viewer] bufferLayout missing stride\");\n }\n\n return { stride, attrs };\n }\n\n private buildPLYFromSingleSet(\n set: GaussianSet,\n buffer: ArrayBuffer,\n layout: BufferLayout\n ) {\n return this.buildPLYFromPGSG([{ set, buffer, layout }], set.count);\n }\n\n private extractRawSplatsFromSingleSet(\n set: GaussianSet,\n buffer: ArrayBuffer,\n layout: BufferLayout\n ): RawSplatData {\n const { stride, attrs } = this.normalizeLayout(layout);\n if (attrs.rotation && !attrs.quat) {\n attrs.quat = attrs.rotation;\n }\n const dv = new DataView(buffer);\n\n console.log(\"attrs\", attrs);\n\n const count = set.count;\n\n const position = new Float32Array(count * 3);\n const scale = new Float32Array(count * 3);\n const quat = new Float32Array(count * 4);\n const color = new Float32Array(count * 3);\n const opacity = new Float32Array(count);\n\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n for (let i = 0; i < count; i++) {\n const base = i * stride;\n\n const x = dv.getFloat32(base + attrs.position.offset + 0, true);\n const y = dv.getFloat32(base + attrs.position.offset + 4, true);\n const z = dv.getFloat32(base + attrs.position.offset + 8, true);\n\n // ⚠️ IMPORTANT: match the SAME coordinate flip you bake into PLY\n // PlayCanvas path does: (x, -y, -z)\n position[i * 3 + 0] = x;\n position[i * 3 + 1] = -y;\n position[i * 3 + 2] = -z;\n\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n minZ = Math.min(minZ, z);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n maxZ = Math.max(maxZ, z);\n\n const sx = dv.getFloat32(base + attrs.scale.offset + 0, true);\n const sy = dv.getFloat32(base + attrs.scale.offset + 4, true);\n const sz = dv.getFloat32(base + attrs.scale.offset + 8, true);\n\n scale[i * 3 + 0] = sx;\n scale[i * 3 + 1] = sy;\n scale[i * 3 + 2] = sz;\n\n const qx = dv.getFloat32(base + attrs.quat.offset + 0, true);\n const qy = dv.getFloat32(base + attrs.quat.offset + 4, true);\n const qz = dv.getFloat32(base + attrs.quat.offset + 8, true);\n const qw = dv.getFloat32(base + attrs.quat.offset + 12, true);\n\n // Apply SAME flip as position: (x, -y, -z)\n quat[i * 4 + 0] = qx;\n quat[i * 4 + 1] = -qy; // ✅ IMPORTANT\n quat[i * 4 + 2] = -qz; // ✅ IMPORTANT\n quat[i * 4 + 3] = qw;\n\n // opacity\n const op = dv.getFloat32(base + attrs.opacity.offset, true);\n opacity[i] = 1 / (1 + Math.exp(-op));\n // opacity[i] = Math.min(1.0, opacity[i] * 1.4);\n // opacity[i] *= 2;\n // opacity[i] = dv.getFloat32(base + attrs.opacity.offset, true);\n\n // color[i * 3 + 0] = 1.0;\n // color[i * 3 + 1] = 0.0;\n // color[i * 3 + 2] = 0.0;\n\n // color: f_dc OR sh\n if (attrs.f_dc) {\n color[i * 3 + 0] = dv.getFloat32(base + attrs.f_dc.offset + 0, true);\n color[i * 3 + 1] = dv.getFloat32(base + attrs.f_dc.offset + 4, true);\n color[i * 3 + 2] = dv.getFloat32(base + attrs.f_dc.offset + 8, true);\n } else if (attrs.sh) {\n // sh[0..2] == DC\n color[i * 3 + 0] = dv.getFloat32(base + attrs.sh.offset + 0, true);\n color[i * 3 + 1] = dv.getFloat32(base + attrs.sh.offset + 4, true);\n color[i * 3 + 2] = dv.getFloat32(base + attrs.sh.offset + 8, true);\n }\n }\n\n console.log({\n pos: position.slice(0, 3),\n scale: scale.slice(0, 3),\n quat: quat.slice(0, 4),\n opacity: opacity[0],\n });\n\n console.log({\n scale: scale.slice(0, 3),\n });\n\n return {\n count,\n position,\n scale,\n quat,\n color,\n opacity,\n bounds: {\n min: [minX, minY, minZ],\n max: [maxX, maxY, maxZ],\n },\n };\n }\n\n private mergeRawSplats(sets: RawSplatData[]) {\n let total = 0;\n for (const s of sets) total += s.count;\n\n const position = new Float32Array(total * 3);\n const scale = new Float32Array(total * 3);\n const quat = new Float32Array(total * 4);\n const color = new Float32Array(total * 3);\n const opacity = new Float32Array(total);\n\n let offset = 0;\n for (const s of sets) {\n position.set(s.position, offset * 3);\n scale.set(s.scale, offset * 3);\n quat.set(s.quat, offset * 4);\n color.set(s.color, offset * 3);\n opacity.set(s.opacity, offset);\n offset += s.count;\n }\n\n return {\n count: total,\n position,\n scale,\n quat,\n color,\n opacity,\n };\n }\n}\n","import type { Loader, LoaderContext, LoadResult } from \"./Loader\";\nimport type { RawSplatData } from \"./PGSGLoader\";\n\ntype PlyProp = {\n name: string;\n type: \"float\";\n offset: number;\n};\n\nexport interface PLYLoaderOptions {\n url: string;\n yUp?: boolean; // default false (we flip to match PGSG)\n}\n\nexport class PLYLoader implements Loader {\n private opts: PLYLoaderOptions;\n\n constructor(opts: PLYLoaderOptions) {\n this.opts = opts;\n }\n\n async load(ctx: LoaderContext): Promise<LoadResult> {\n const buf = await fetch(this.opts.url).then((r) => {\n if (!r.ok) {\n throw new Error(\n `[PLYLoader] Failed to fetch PLY (${r.status}) ${this.opts.url}`\n );\n }\n return r.arrayBuffer();\n });\n\n const raw = this.parseBinaryPLY(buf);\n\n return {\n bounds: raw.bounds,\n splats: raw,\n };\n }\n\n dispose(): void {\n // nothing yet\n }\n\n private parsePlyHeader(text: string): {\n vertexCount: number;\n stride: number;\n props: Record<string, number>;\n } {\n const lines = text.split(/\\r?\\n/);\n\n let vertexCount = 0;\n let readingVertexProps = false;\n let offset = 0;\n\n const props: Record<string, number> = {};\n\n for (const line of lines) {\n const l = line.trim();\n\n if (l.startsWith(\"element vertex\")) {\n vertexCount = parseInt(l.split(/\\s+/)[2], 10);\n readingVertexProps = true;\n continue;\n }\n\n if (readingVertexProps && l.startsWith(\"element\")) {\n readingVertexProps = false;\n }\n\n if (readingVertexProps && l.startsWith(\"property\")) {\n const [, type, name] = l.split(/\\s+/);\n\n if (type !== \"float\") {\n throw new Error(`[PLYLoader] Unsupported PLY type: ${type}`);\n }\n\n props[name] = offset;\n offset += 4;\n }\n\n if (l === \"end_header\") break;\n }\n\n if (!vertexCount || offset === 0) {\n throw new Error(\"[PLYLoader] Invalid PLY header\");\n }\n\n return {\n vertexCount,\n stride: offset,\n props,\n };\n }\n\n // -------------------------------------------------------\n // Binary PLY → RawSplatData (Supersplat / Inria layout)\n // -------------------------------------------------------\n\n private parseBinaryPLY(buffer: ArrayBuffer): RawSplatData {\n const text = new TextDecoder().decode(buffer.slice(0, 8192));\n const match = text.match(/end_header\\s*\\r?\\n/);\n if (!match || match.index == null) {\n throw new Error(\"[PLYLoader] Invalid PLY header\");\n }\n\n const headerEnd = match.index + match[0].length;\n\n // --- Vertex count ---\n let count = 0;\n for (const l of text.slice(0, headerEnd).split(\"\\n\")) {\n if (l.startsWith(\"element vertex\")) {\n count = parseInt(l.split(/\\s+/)[2], 10);\n }\n }\n if (!count) throw new Error(\"Invalid vertex count\");\n\n // Inria GS = 59 floats per vertex\n const FLOATS = 59;\n const STRIDE = FLOATS * 4;\n\n const dv = new DataView(buffer, headerEnd);\n\n const position = new Float32Array(count * 3);\n const scale = new Float32Array(count * 3);\n const quat = new Float32Array(count * 4);\n const color = new Float32Array(count * 3);\n const opacity = new Float32Array(count);\n\n let minX = Infinity,\n minY = Infinity,\n minZ = Infinity;\n let maxX = -Infinity,\n maxY = -Infinity,\n maxZ = -Infinity;\n\n for (let i = 0; i < count; i++) {\n const base = i * STRIDE;\n let o = 0;\n\n // position\n const x = dv.getFloat32(base + o, true);\n const y = dv.getFloat32(base + o + 4, true);\n const z = dv.getFloat32(base + o + 8, true);\n o += 12;\n\n position.set([x, -y, -z], i * 3);\n minX = Math.min(minX, x);\n minY = Math.min(minY, y);\n minZ = Math.min(minZ, z);\n maxX = Math.max(maxX, x);\n maxY = Math.max(maxY, y);\n maxZ = Math.max(maxZ, z);\n\n // skip normals\n o += 12;\n\n // f_dc (RGB)\n color[i * 3 + 0] = dv.getFloat32(base + o, true);\n color[i * 3 + 1] = dv.getFloat32(base + o + 4, true);\n color[i * 3 + 2] = dv.getFloat32(base + o + 8, true);\n o += 12;\n\n // skip f_rest[45]\n o += 45 * 4;\n\n // opacity (sigmoid later)\n const op = dv.getFloat32(base + o, true);\n opacity[i] = 1.0 / (1.0 + Math.exp(-op));\n o += 4;\n\n // ❗ LOG SCALE → EXP REQUIRED\n scale[i * 3 + 0] = Math.exp(dv.getFloat32(base + o, true));\n scale[i * 3 + 1] = Math.exp(dv.getFloat32(base + o + 4, true));\n scale[i * 3 + 2] = Math.exp(dv.getFloat32(base + o + 8, true));\n o += 12;\n\n // quaternion\n quat[i * 4 + 0] = dv.getFloat32(base + o, true);\n quat[i * 4 + 1] = -dv.getFloat32(base + o + 4, true);\n quat[i * 4 + 2] = -dv.getFloat32(base + o + 8, true);\n quat[i * 4 + 3] = dv.getFloat32(base + o + 12, true);\n }\n\n return {\n count,\n position,\n scale,\n quat,\n color,\n opacity,\n bounds: {\n min: [minX, minY, minZ],\n max: [maxX, maxY, maxZ],\n },\n };\n }\n}\n","import type { ViewerSource } from \"../types\";\nimport type { Loader } from \"./Loader\";\nimport { PGSGLoader } from \"./PGSGLoader\";\nimport { PLYLoader } from \"./PLYLoader\";\n\nexport function createLoader(source: ViewerSource, debug?: boolean): Loader {\n switch (source.type) {\n case \"pgsg\":\n return new PGSGLoader({ url: source.url, debug });\n case \"ply\":\n return new PLYLoader({ url: source.url });\n default:\n throw new Error(`[PGSG-Viewer] Unsupported source type`);\n }\n}\n","import * as pc from \"playcanvas\";\n\nexport interface OrbitOptions {\n target: pc.Vec3;\n distance: number;\n minDistance?: number;\n maxDistance?: number;\n yaw?: number;\n pitch?: number;\n rotateSpeed?: number;\n zoomSpeed?: number;\n}\n\nexport class OrbitCameraController {\n private app: pc.Application;\n private camera: pc.Entity;\n\n private target: pc.Vec3;\n\n private distance: number;\n private minDistance: number;\n private maxDistance: number;\n\n private yaw: number;\n private pitch: number;\n\n private rotateSpeed: number;\n private zoomSpeed: number;\n\n private mouse: pc.Mouse;\n\n private dragging = false;\n private lastX = 0;\n private lastY = 0;\n\n private panning = false;\n\n constructor(app: pc.Application, camera: pc.Entity, opts: OrbitOptions) {\n this.app = app;\n this.camera = camera;\n\n this.target = opts.target.clone();\n\n this.distance = opts.distance;\n this.minDistance = opts.minDistance ?? 0.1;\n this.maxDistance = opts.maxDistance ?? 1000;\n\n this.yaw = opts.yaw ?? 180;\n this.pitch = opts.pitch ?? -10;\n\n this.rotateSpeed = opts.rotateSpeed ?? 0.3;\n this.zoomSpeed = opts.zoomSpeed ?? 1.1; // exponential factor\n\n this.mouse = app.mouse!;\n\n this.bind();\n this.updateCamera();\n }\n\n dispose() {\n this.unbind();\n }\n\n // -----------------------------\n // Input handling\n // -----------------------------\n\n private bind() {\n this.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown);\n this.mouse.on(pc.EVENT_MOUSEUP, this.onMouseUp);\n this.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove);\n this.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel);\n }\n\n private unbind() {\n this.mouse.off(pc.EVENT_MOUSEDOWN, this.onMouseDown);\n this.mouse.off(pc.EVENT_MOUSEUP, this.onMouseUp);\n this.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove);\n this.mouse.off(pc.EVENT_MOUSEWHEEL, this.onMouseWheel);\n }\n\n private onMouseDown = (e: pc.MouseEvent) => {\n if (e.button === pc.MOUSEBUTTON_LEFT) {\n this.dragging = true;\n }\n if (e.button === pc.MOUSEBUTTON_RIGHT) {\n this.panning = true;\n }\n this.lastX = e.x;\n this.lastY = e.y;\n };\n\n\n private onMouseUp = () => {\n this.dragging = false;\n this.panning = false;\n };\n\n\n private onMouseMove = (e: pc.MouseEvent) => {\n const dx = e.x - this.lastX;\n const dy = e.y - this.lastY;\n\n this.lastX = e.x;\n this.lastY = e.y;\n\n // LEFT = orbit rotate\n if (this.dragging) {\n this.yaw -= dx * this.rotateSpeed;\n this.pitch -= dy * this.rotateSpeed;\n this.pitch = pc.math.clamp(this.pitch, -89, 89);\n this.updateCamera();\n }\n\n // RIGHT = pan\n if (this.panning) {\n const panSpeed = this.distance * 0.002;\n\n const right = this.camera.right.clone().mulScalar(-dx * panSpeed);\n const up = this.camera.up.clone().mulScalar(dy * panSpeed);\n\n this.target.add(right).add(up);\n this.updateCamera();\n }\n };\n\n\n private onMouseWheel = (e: pc.MouseEvent) => {\n // Exponential zoom (GS-friendly)\n const zoomFactor = Math.pow(this.zoomSpeed, e.wheelDelta / 10);\n\n this.distance *= zoomFactor;\n\n // Clamp AFTER zoom\n this.distance = pc.math.clamp(\n this.distance,\n this.minDistance,\n this.maxDistance\n );\n\n this.updateCamera();\n };\n\n // -----------------------------\n // Camera math\n // -----------------------------\n\n private updateCamera() {\n const yawRad = (this.yaw * Math.PI) / 180;\n const pitchRad = (this.pitch * Math.PI) / 180;\n\n const x =\n this.target.x +\n this.distance * Math.cos(pitchRad) * Math.sin(yawRad);\n const y = this.target.y + this.distance * Math.sin(pitchRad);\n const z =\n this.target.z +\n this.distance * Math.cos(pitchRad) * Math.cos(yawRad);\n\n this.camera.setPosition(x, y, z);\n this.camera.lookAt(this.target, pc.Vec3.UP);\n }\n\n // -----------------------------\n // Public API (used by viewer)\n // -----------------------------\n\n setTarget(target: pc.Vec3) {\n this.target.copy(target);\n this.updateCamera();\n }\n\n setDistance(distance: number) {\n this.distance = pc.math.clamp(\n distance,\n this.minDistance,\n this.maxDistance\n );\n this.updateCamera();\n }\n\n setLimits(minDistance: number, maxDistance: number) {\n this.minDistance = minDistance;\n this.maxDistance = maxDistance;\n this.distance = pc.math.clamp(\n this.distance,\n this.minDistance,\n this.maxDistance\n );\n this.updateCamera();\n }\n}\n","import * as pc from \"playcanvas\";\n\nexport type Bounds = {\n min: [number, number, number];\n max: [number, number, number];\n};\n\nexport function fitCameraToBounds(\n cameraEntity: pc.Entity,\n bounds: Bounds,\n padding: number = 1.15\n) {\n const cam = cameraEntity.camera!;\n if (!cam) throw new Error(\"Camera component missing\");\n\n // Bounds center\n const cx = (bounds.min[0] + bounds.max[0]) * 0.5;\n const cy = (bounds.min[1] + bounds.max[1]) * 0.5;\n const cz = (bounds.min[2] + bounds.max[2]) * 0.5;\n const center = new pc.Vec3(cx, cy, cz);\n\n // Half extents\n const ex = (bounds.max[0] - bounds.min[0]) * 0.5;\n const ey = (bounds.max[1] - bounds.min[1]) * 0.5;\n const ez = (bounds.max[2] - bounds.min[2]) * 0.5;\n\n // Use the largest dimension (GS clouds are irregular)\n const radius = Math.max(ex, ey, ez);\n\n // Convert FOV to radians\n const fovRad = (cam.fov * Math.PI) / 180;\n\n // Account for aspect ratio (horizontal fit matters!)\n const aspect = cam.aspectRatio || 1;\n const verticalDist = radius / Math.tan(fovRad * 0.5);\n const horizontalDist = radius / Math.tan(Math.atan(Math.tan(fovRad * 0.5) * aspect));\n\n // Choose the larger distance\n let distance = Math.max(verticalDist, horizontalDist);\n\n // Safety padding\n distance *= padding;\n\n // Final safety clamp (prevents NaNs / extreme zoom)\n distance = Math.max(distance, 0.1);\n\n return {\n center,\n radius,\n distance,\n };\n}\n","import * as pc from \"playcanvas\";\n\nexport interface WalkOptions {\n eyeHeight?: number;\n speed?: number; // base speed (will be scaled)\n lookSpeed?: number;\n}\n\nexport class WalkCameraController {\n private app: pc.Application;\n private camera: pc.Entity;\n\n private eyeHeight: number;\n private baseSpeed: number;\n private lookSpeed: number;\n\n private yaw = 0;\n private pitch = 0;\n private mouseDX = 0;\n private mouseDY = 0;\n\n private keys: Record<number, boolean> = {};\n\n private mouse: pc.Mouse;\n private keyboard: pc.Keyboard;\n\n private floorY = 0\n private skipLookFrame = false;\n private suppressLookUntil = 0;\n\n constructor(app: pc.Application, camera: pc.Entity, opts: WalkOptions = {}) {\n this.app = app;\n this.camera = camera;\n\n this.eyeHeight = opts.eyeHeight ?? 1.6;\n this.baseSpeed = opts.speed ?? 1.0;\n this.lookSpeed = opts.lookSpeed ?? 0.15;\n\n this.mouse = app.mouse!;\n this.keyboard = app.keyboard!;\n\n // Pointer lock changes (VERY important)\n document.addEventListener(\"pointerlockchange\", () => {\n this.syncFromCamera();\n });\n\n // Window loses focus\n window.addEventListener(\"blur\", () => {\n this.mouse?.disablePointerLock();\n this.syncFromCamera();\n });\n\n // Tab visibility\n document.addEventListener(\"visibilitychange\", () => {\n if (document.hidden) {\n this.mouse?.disablePointerLock();\n this.syncFromCamera();\n }\n });\n\n this.mouse?.on('mousedown', (e) => {\n if (e.button === pc.MOUSEBUTTON_LEFT) {\n this.app.mouse?.enablePointerLock();\n }\n })\n\n // this.mouse?.on('mouseup', (e) => {\n // this.app.mouse?.disablePointerLock();\n // })\n\n // Optional: unlock on ESC\n document.addEventListener(\"keydown\", (e) => {\n if (e.key === \"Escape\") {\n this.mouse?.disablePointerLock();\n }\n });\n\n this.mouse?.on('mousemove', (e) => {\n if (!pc.Mouse.isPointerLocked()) return;\n if (document.hidden) return;\n if (performance.now() < this.suppressLookUntil) return;\n\n this.mouseDX += e.dx;\n this.mouseDY += e.dy;\n })\n\n const euler = this.camera.getEulerAngles();\n this.pitch = euler.x;\n this.yaw = euler.y;\n\n this.bind();\n }\n\n dispose() {\n this.unbind();\n }\n\n // -----------------------------\n // Input handling\n // -----------------------------\n\n private bind() {\n this.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove);\n this.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown);\n this.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp);\n }\n\n private unbind() {\n this.mouse.off(pc.EVENT_MOUSEMOVE, this.onMouseMove);\n this.keyboard.off(pc.EVENT_KEYDOWN, this.onKeyDown);\n this.keyboard.off(pc.EVENT_KEYUP, this.onKeyUp);\n }\n\n private onKeyDown = (e: pc.KeyboardEvent) => {\n this.keys[e.key as number] = true;\n };\n\n private onKeyUp = (e: pc.KeyboardEvent) => {\n this.keys[e.key as number] = false;\n };\n\n private onMouseMove = (e: pc.MouseEvent) => {\n // if (!e.buttons) return;\n\n this.yaw -= e.dx * this.lookSpeed;\n this.pitch -= e.dy * this.lookSpeed;\n\n this.pitch = pc.math.clamp(this.pitch, -89, 89);\n\n this.camera.setEulerAngles(this.pitch, this.yaw, 0);\n };\n\n private syncFromCamera() {\n const euler = this.camera.getLocalEulerAngles();\n\n this.pitch = euler.x;\n this.yaw = euler.y;\n\n this.mouseDX = 0;\n this.mouseDY = 0;\n\n // 🔒 Suppress look for ~2 frames\n this.suppressLookUntil = performance.now() + 50;\n }\n\n\n // -----------------------------\n // Update loop\n // -----------------------------\n\n update(dt: number, sceneScale: number = 1.0) {\n // if (this.skipLookFrame) {\n // this.skipLookFrame = false;\n // this.mouseDX = 0;\n // this.mouseDY = 0;\n // return;\n // }\n\n if (pc.Mouse.isPointerLocked()) {\n const maxDelta = 50;\n\n const dx = pc.math.clamp(this.mouseDX, -maxDelta, maxDelta);\n const dy = pc.math.clamp(this.mouseDY, -maxDelta, maxDelta);\n\n // if (performance.now() < this.suppressLookUntil) {\n // this.mouseDX = 0;\n // this.mouseDY = 0;\n // return;\n // }\n\n\n this.yaw -= dx * this.lookSpeed;\n this.pitch -= dy * this.lookSpeed;\n\n // this.yaw -= this.mouseDX * this.lookSpeed;\n // this.pitch -= this.mouseDY * this.lookSpeed;\n\n // Clamp pitch (no neck-breaking)\n this.pitch = pc.math.clamp(this.pitch, -89, 89);\n\n this.camera.setLocalEulerAngles(this.pitch, this.yaw, 0);\n\n // Reset deltas after applying\n this.mouseDX = 0;\n this.mouseDY = 0;\n }\n\n\n // Scene-scaled speed (THIS IS IMPORTANT)\n const speed = this.baseSpeed * sceneScale;\n\n const forward = this.camera.forward.clone();\n forward.y = 0;\n forward.normalize();\n\n const right = this.camera.right.clone()\n right.y = 0;\n right.normalize();\n\n\n\n const move = new pc.Vec3();\n\n if (this.keys[pc.KEY_W]) move.add(forward);\n if (this.keys[pc.KEY_S]) move.sub(forward);\n // if (this.keys[pc.KEY_A]) move.sub(right);\n // if (this.keys[pc.KEY_D]) move.add(right);\n\n const turnSpeed = 90; // degrees per second (tune: 60–120)\n\n if (this.keys[pc.KEY_A]) {\n this.yaw += turnSpeed * dt;\n }\n\n if (this.keys[pc.KEY_D]) {\n this.yaw -= turnSpeed * dt;\n }\n\n this.camera.setLocalEulerAngles(this.pitch, this.yaw, 0);\n\n if (move.lengthSq() > 0) {\n move.normalize().addScalar(speed * dt);\n this.camera.translate(move);\n }\n\n\n // Yaw-only forward/right vectors\n const yawRad = pc.math.DEG_TO_RAD * this.yaw //(this.yaw * Math.PI) / 180;\n // new pc.Vec3(\n // -Math.sin(yawRad),\n // 0,\n // -Math.cos(yawRad)\n // );\n\n // new pc.Vec3(\n // Math.cos(yawRad),\n // 0,\n // -Math.sin(yawRad)\n // );\n\n const velocity = new pc.Vec3();\n velocity.add(forward.mulScalar(move.z));\n velocity.add(right.mulScalar(move.x));\n velocity.normalize().mulScalar(speed * dt);\n\n this.camera.translate(velocity);\n\n const pos = this.camera.getPosition()\n pos.y = pc.math.lerp(pos.y, this.floorY + this.eyeHeight, 0.25)\n this.camera.setPosition(pos)\n }\n\n // -----------------------------\n // Public helpers\n // -----------------------------\n\n setPosition(pos: pc.Vec3) {\n this.camera.setPosition(pos.x, pos.y + this.eyeHeight, pos.z);\n }\n\n setYawPitch(yaw: number, pitch: number) {\n this.yaw = yaw;\n this.pitch = pc.math.clamp(pitch, -89, 89);\n this.camera.setEulerAngles(this.pitch, this.yaw, 0);\n }\n\n setFloorY(y: number) {\n this.floorY = y;\n }\n}\n"],"mappings":";AAAA,YAAYA,SAAQ;;;ACApB,YAAY,QAAQ;AAgGb,IAAM,aAAN,MAAmC;AAAA,EAChC;AAAA,EAEA,WAAqB,CAAC;AAAA,EACtB,WAAwB,CAAC;AAAA,EACzB,SAAqB,CAAC;AAAA,EAEtB;AAAA,EAKR,YAAY,MAAyB;AACnC,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,KAAyC;AAClD,UAAM,YAA4B,CAAC;AAGnC,SAAK,QAAQ;AACb,SAAK,eAAe;AAEpB,UAAM,EAAE,KAAK,MAAM,IAAI,KAAK;AAG5B,UAAM,QAAQ,MAAM,MAAM,GAAG,EAAE,KAAK,CAAC,MAAM;AACzC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI;AAAA,UACR,wDAAwD,GAAG,KAAK,EAAE,MAAM;AAAA,QAC1E;AAAA,MACF;AACA,aAAO,EAAE,KAAK;AAAA,IAChB,CAAC;AAED,UAAM,cACJ,OAAO,eAAe,OAAO,YAAY,OAAO;AAClD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR,mEAAmE,GAAG;AAAA,MACxE;AAAA,IACF;AAGA,UAAM,OAAO,MAAM,KAAK,UAAgB,WAAW;AAEnD,QAAI,CAAC,MAAM,cAAc,QAAQ;AAC/B,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAGA,UAAM,UAAU,IAAI,UAAU,GAAG,IAAI,YAAY,GAAG,IAAI,CAAC;AAGzD,UAAM,WAID,CAAC;AAEN,QAAI,aAAa;AAEjB,eAAW,OAAO,KAAK,cAAc;AACnC,UAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,MAAO;AAE7B,YAAM,SAAS,IAAI,gBAAgB,IAAI;AACvC,UAAI,CAAC,UAAU,CAAC,OAAO,QAAQ;AAC7B,cAAM,IAAI;AAAA,UACR,6DAA6D,IAAI,IAAI;AAAA,QACvE;AAAA,MACF;AAEA,YAAM,aAAa,IAAI,IAAI,IAAI,MAAM,OAAO,EAAE,SAAS;AACvD,YAAM,MAAM,MAAM,KAAK,iBAAiB,UAAU;AAElD,oBAAc,IAAI;AAClB,eAAS,KAAK,EAAE,KAAK,QAAQ,KAAK,OAAO,CAAC;AAE1C,UAAI,OAAO;AACT,gBAAQ;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,IAAI;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI,MAAM,wCAAwC;AAAA,IAC1D;AAEA,QAAI,IAAI,iBAAiB,SAAS;AAChC,iBAAW,EAAE,KAAK,QAAQ,OAAO,KAAK,UAAU;AAC9C,cAAM,MAAM,KAAK,8BAA8B,KAAK,QAAQ,MAAM;AAClE,kBAAU,KAAK,GAAG;AAClB,aAAK,mBAAmB,IAAI,MAAM;AAAA,MACpC;AAEA,YAAMC,eAAc,KAAK,QAAQ,gBAAgB,KAAK;AAEtD,aAAO;AAAA,QACL,QAAQA;AAAA,QACR,QAAQ,KAAK,eAAe,SAAS;AAAA,MACvC;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,eAAe,KAAK,KAAK;AAChD,UAAM,eAAe,oBAAI,IAAuB;AAEhD,QAAI,KAAK,OAAO,QAAQ;AACtB,iBAAW,QAAQ,KAAK,OAAO;AAC7B,cAAM,SAAS,IAAO,UAAO,QAAQ,KAAK,EAAE,EAAE;AAC9C,eAAO,UAAU;AAEjB,QAAC,OAAe,OAAO;AAAA,UACrB,IAAI,KAAK;AAAA,UACT,MAAM,KAAK;AAAA,UACX,QAAQ,KAAK;AAAA,QACf;AAEA,YAAI,UAAU,KAAK,SAAS,MAAM;AAClC,qBAAa,IAAI,KAAK,IAAI,MAAM;AAAA,MAClC;AAAA,IACF;AAGA,eAAW,EAAE,KAAK,QAAQ,OAAO,KAAK,UAAU;AAC9C,YAAM,EAAE,KAAK,OAAO,IAAI,KAAK,sBAAsB,KAAK,QAAQ,MAAM;AAGtE,YAAM,WAAW,IAAI,QAAQ,SAAS;AACtC,YAAM,YACJ,UAAU,OAAO,UAAU,MACvB;AAAA,QACE,KAAK,SAAS;AAAA,QACd,KAAK,SAAS;AAAA,MAChB,IACA;AAGN,YAAM,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,EAAE,MAAM,2BAA2B,CAAC;AACjE,YAAM,UAAU,IAAI,gBAAgB,IAAI;AAExC,YAAM,QAAQ,IAAO,SAAM,UAAU,IAAI,EAAE,IAAI,UAAU;AAAA,QACvD,KAAK;AAAA,MACP,CAAC;AACD,UAAI,UAAU,OAAO,IAAI,KAAK;AAC9B,YAAM,KAAK,eAAe,IAAI,UAAW,KAAK;AAE9C,YAAM,WAAW,IAAO,UAAO,MAAM,IAAI,EAAE,EAAE;AAC7C,eAAS,aAAa,UAAU,EAAE,MAAM,CAAC;AAUzC,MAAC,SAAiB,OAAO;AAAA,QACvB,IAAI,IAAI;AAAA,QACR,cAAc,IAAI;AAAA,QAClB,QAAQ,IAAI;AAAA,QACZ,QAAQ;AAAA,MACV;AAGA,YAAM,SAAS,UAAU,IAAI,IAAI,EAAE;AAKnC,UAAI,UAAU,KAAK,SAAS,QAAQ;AAEpC,cAAQ;AAAA,QACN;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,OAAO;AAAA,MACT;AAEA,WAAK,OAAO,KAAK,KAAK;AACtB,WAAK,SAAS,KAAK,QAAQ;AAC3B,WAAK,SAAS,KAAK,OAAO;AAG1B,WAAK,mBAAmB,MAAM;AAAA,IAChC;AAcA,UAAM,cAAc,KAAK,QAAQ,gBAAgB,KAAK;AAEtD,WAAO,cAAc,EAAE,QAAQ,YAAY,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,UAAgB;AAEd,QAAI;AACF,WAAK,SAAS,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,IAC1C,QAAQ;AAAA,IAER;AACA,SAAK,WAAW,CAAC;AAGjB,QAAI;AACF,WAAK,OAAO,QAAQ,CAAC,MAAM;AACzB,YAAI;AACF,YAAE,OAAO;AAAA,QACX,QAAQ;AAAA,QAAC;AACT,YAAI;AACF,YAAE,UAAU,OAAO,CAAC;AAAA,QACtB,QAAQ;AAAA,QAAC;AAAA,MACX,CAAC;AAAA,IACH,QAAQ;AAAA,IAER;AACA,SAAK,SAAS,CAAC;AAGf,QAAI;AACF,WAAK,SAAS,QAAQ,CAAC,MAAM,IAAI,gBAAgB,CAAC,CAAC;AAAA,IACrD,QAAQ;AAAA,IAER;AACA,SAAK,WAAW,CAAC;AAAA,EACnB;AAAA,EAEQ,eAAe,OAAgB;AACrC,UAAM,MAAM,oBAAI,IAAoB;AACpC,QAAI,CAAC,MAAO,QAAO;AAEnB,eAAW,QAAQ,OAAO;AACxB,iBAAW,SAAS,KAAK,UAAU,CAAC,GAAG;AACrC,mBAAW,OAAO,MAAM,kBAAkB,CAAC,GAAG;AAC5C,cAAI,IAAI,KAAK,KAAK,EAAE;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,GAGxB;AACD,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe;AAAA,QAClB,KAAK,CAAC,GAAG,EAAE,GAAG;AAAA,QACd,KAAK,CAAC,GAAG,EAAE,GAAG;AAAA,MAChB;AACA;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,WAAK,aAAa,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,aAAa,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAEtE,WAAK,aAAa,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,aAAa,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAc,UAAa,KAAyB;AAClD,UAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR,mDAAmD,GAAG,KAAK,IAAI,MAAM;AAAA,MACvE;AAAA,IACF;AACA,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAAA,EAEA,MAAc,iBAAiB,KAAmC;AAChE,UAAM,MAAM,MAAM,MAAM,GAAG;AAC3B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR,0DAA0D,GAAG,KAAK,IAAI,MAAM;AAAA,MAC9E;AAAA,IACF;AACA,WAAO,MAAM,IAAI,YAAY;AAAA,EAC/B;AAAA,EAEQ,eAAe,KAAqB,OAAgC;AAC1E,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,KAAK,QAAQ,MAAM,QAAQ,CAAC;AAClC,YAAM;AAAA,QAAK;AAAA,QAAS,CAAC,UACnB,OAAO,SAAS,IAAI,MAAM,6BAA6B,CAAC;AAAA,MAC1D;AACA,UAAI,OAAO,KAAK,KAAK;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBACN,UAKA,YAIA;AAEA,UAAM,cAAwB;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,kBAAkB,UAAU;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,IAAI,IAAK,aAAY,KAAK,yBAAyB,CAAC,EAAE;AAE1E,gBAAY,KAAK,YAAY;AAE7B,UAAM,SAAS,YAAY,KAAK,IAAI,IAAI;AACxC,UAAM,cAAc,IAAI,YAAY,EAAE,OAAO,MAAM;AAGnD,UAAM,kBAAkB,IAAI,IAAI,IAAI,IAAI,IAAI;AAC5C,UAAM,iBAAiB,kBAAkB;AAEzC,UAAM,MAAM,IAAI;AAAA,MACd,YAAY,aAAa,aAAa;AAAA,IACxC;AACA,UAAM,QAAQ,IAAI,WAAW,GAAG;AAChC,UAAM,IAAI,aAAa,CAAC;AAExB,UAAM,QAAQ,IAAI,SAAS,GAAG;AAC9B,QAAI,cAAc,YAAY;AAE9B,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,OAAO;AAClB,QAAI,OAAO,OAAO;AAElB,QAAI,UAAU;AAEd,eAAW,EAAE,KAAK,QAAQ,OAAO,KAAK,UAAU;AAC9C,YAAM,EAAE,QAAQ,MAAM,IAAI,KAAK,gBAAgB,MAAM;AAGrD,UAAI,KAAK,IAAI,SAAS,MAAM;AAE5B,YAAM,gBAAgB,IAAI,QAAQ;AAClC,UAAI,OAAO,aAAa,eAAe;AACrC,cAAM,IAAI;AAAA,UACR,mCAAmC,IAAI,IAAI,UAAU,OAAO,UAAU,aAAa,aAAa;AAAA,QAClG;AAAA,MACF;AAEA,YAAM,WAAW,CAAC,YAAY,SAAS,YAAY,SAAS;AAC5D,iBAAW,KAAK,UAAU;AACxB,YAAI,CAAC,MAAM,CAAC,GAAG;AACb,gBAAM,IAAI;AAAA,YACR,wDAAwD,CAAC,kBAAkB,IAAI,IAAI;AAAA,UACrF;AAAA,QACF;AAAA,MACF;AAGA,UAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,IAAI;AAC5B,cAAM,IAAI;AAAA,UACR,sDAAsD,IAAI,IAAI;AAAA,QAChE;AAAA,MACF;AAEA,eAAS,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AAClC,cAAM,OAAO,IAAI;AAEjB,cAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAC9D,cAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAC9D,cAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAE9D,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AACvB,eAAO,KAAK,IAAI,MAAM,CAAC;AAIvB,cAAM,WAAW,aAAa,GAAG,IAAI;AACrC,uBAAe;AACf,cAAM,WAAW,aAAa,CAAC,GAAG,IAAI;AACtC,uBAAe;AACf,cAAM,WAAW,aAAa,CAAC,GAAG,IAAI;AACtC,uBAAe;AAGf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAAA,UACjD;AAAA,QACF;AACA,uBAAe;AACf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAAA,UACjD;AAAA,QACF;AACA,uBAAe;AACf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAAA,UACjD;AAAA,QACF;AACA,uBAAe;AAGf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAAA,UACpD;AAAA,QACF;AACA,uBAAe;AACf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAAA,UACpD;AAAA,QACF;AACA,uBAAe;AACf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAAA,UACpD;AAAA,QACF;AACA,uBAAe;AACf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,IAAI,IAAI;AAAA,UACrD;AAAA,QACF;AACA,uBAAe;AAGf,cAAM;AAAA,UACJ;AAAA,UACA,GAAG,WAAW,OAAO,MAAM,QAAQ,QAAQ,IAAI;AAAA,UAC/C;AAAA,QACF;AACA,uBAAe;AAGf,cAAM,UAAU,MAAM;AACtB,cAAM,SAAS,MAAM;AAErB,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,QAAQ,SAAS,GAAG,IAAI;AAAA,YAC7C;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,OAAO,SAAS,GAAG,IAAI;AAAA,YAC5C;AAAA,UACF;AAAA,QACF;AACA,uBAAe;AAEf,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,QAAQ,SAAS,GAAG,IAAI;AAAA,YAC7C;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,OAAO,SAAS,GAAG,IAAI;AAAA,YAC5C;AAAA,UACF;AAAA,QACF;AACA,uBAAe;AAEf,YAAI,SAAS;AACX,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,QAAQ,SAAS,GAAG,IAAI;AAAA,YAC7C;AAAA,UACF;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,YACJ;AAAA,YACA,GAAG,WAAW,OAAO,OAAO,SAAS,GAAG,IAAI;AAAA,YAC5C;AAAA,UACF;AAAA,QACF;AACA,uBAAe;AAGf,iBAAS,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,cAAI,IAAI;AAER,cAAI,MAAM,QAAQ;AAChB,gBAAI,GAAG,WAAW,OAAO,MAAM,OAAO,SAAS,IAAI,GAAG,IAAI;AAAA,UAC5D,WAAW,MAAM,IAAI;AACnB,gBAAI,GAAG,WAAW,OAAO,MAAM,GAAG,UAAU,IAAI,KAAK,GAAG,IAAI;AAAA,UAC9D;AACA,gBAAM,WAAW,aAAa,GAAG,IAAI;AACrC,yBAAe;AAAA,QACjB;AAEA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,YAAY,YAAY;AAC1B,YAAM,IAAI;AAAA,QACR,6CAA6C,OAAO,UAAU,UAAU;AAAA,MAC1E;AAAA,IACF;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,QAAQ,EAAE,KAAK,CAAC,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,MAAM,IAAI,EAAE;AAAA,IAC7D;AAAA,EACF;AAAA,EAEQ,gBAAgB,QAAwC;AAC9D,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAGA,QAAI,SAAS,OAAO;AAGpB,QAAI,QACD,OAAe,cAAc,OAAO,UAAU,OAAO;AAGxD,QAAI,CAAC,OAAO;AACV,cAAQ,CAAC;AAET,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAI,QAAQ,SAAU;AAEtB,YACE,SACA,OAAO,UAAU,YACjB,OAAQ,MAAc,WAAW,UACjC;AACA,gBAAM,GAAG,IAAI;AAGb,cAAI,UAAU,QAAQ,OAAQ,MAAc,WAAW,UAAU;AAC/D,qBAAU,MAAc;AAAA,UAC1B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,SAAS,CAAC,OAAO,KAAK,KAAK,EAAE,QAAQ;AACxC,YAAM,IAAI,MAAM,qDAAqD;AAAA,IACvE;AAEA,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,WAAO,EAAE,QAAQ,MAAM;AAAA,EACzB;AAAA,EAEQ,sBACN,KACA,QACA,QACA;AACA,WAAO,KAAK,iBAAiB,CAAC,EAAE,KAAK,QAAQ,OAAO,CAAC,GAAG,IAAI,KAAK;AAAA,EACnE;AAAA,EAEQ,8BACN,KACA,QACA,QACc;AACd,UAAM,EAAE,QAAQ,MAAM,IAAI,KAAK,gBAAgB,MAAM;AACrD,QAAI,MAAM,YAAY,CAAC,MAAM,MAAM;AACjC,YAAM,OAAO,MAAM;AAAA,IACrB;AACA,UAAM,KAAK,IAAI,SAAS,MAAM;AAE9B,YAAQ,IAAI,SAAS,KAAK;AAE1B,UAAM,QAAQ,IAAI;AAElB,UAAM,WAAW,IAAI,aAAa,QAAQ,CAAC;AAC3C,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,OAAO,IAAI,aAAa,QAAQ,CAAC;AACvC,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,UAAU,IAAI,aAAa,KAAK;AAEtC,QAAI,OAAO,UACT,OAAO,UACP,OAAO;AACT,QAAI,OAAO,WACT,OAAO,WACP,OAAO;AAET,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAO,IAAI;AAEjB,YAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAC9D,YAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAC9D,YAAM,IAAI,GAAG,WAAW,OAAO,MAAM,SAAS,SAAS,GAAG,IAAI;AAI9D,eAAS,IAAI,IAAI,CAAC,IAAI;AACtB,eAAS,IAAI,IAAI,CAAC,IAAI,CAAC;AACvB,eAAS,IAAI,IAAI,CAAC,IAAI,CAAC;AAEvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AAEvB,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAC5D,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAC5D,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,MAAM,SAAS,GAAG,IAAI;AAE5D,YAAM,IAAI,IAAI,CAAC,IAAI;AACnB,YAAM,IAAI,IAAI,CAAC,IAAI;AACnB,YAAM,IAAI,IAAI,CAAC,IAAI;AAEnB,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AAC3D,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AAC3D,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AAC3D,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,IAAI,IAAI;AAG5D,WAAK,IAAI,IAAI,CAAC,IAAI;AAClB,WAAK,IAAI,IAAI,CAAC,IAAI,CAAC;AACnB,WAAK,IAAI,IAAI,CAAC,IAAI,CAAC;AACnB,WAAK,IAAI,IAAI,CAAC,IAAI;AAGlB,YAAM,KAAK,GAAG,WAAW,OAAO,MAAM,QAAQ,QAAQ,IAAI;AAC1D,cAAQ,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC,EAAE;AAUlC,UAAI,MAAM,MAAM;AACd,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AACnE,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AACnE,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,KAAK,SAAS,GAAG,IAAI;AAAA,MACrE,WAAW,MAAM,IAAI;AAEnB,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI;AACjE,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI;AACjE,cAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,MAAM,GAAG,SAAS,GAAG,IAAI;AAAA,MACnE;AAAA,IACF;AAEA,YAAQ,IAAI;AAAA,MACV,KAAK,SAAS,MAAM,GAAG,CAAC;AAAA,MACxB,OAAO,MAAM,MAAM,GAAG,CAAC;AAAA,MACvB,MAAM,KAAK,MAAM,GAAG,CAAC;AAAA,MACrB,SAAS,QAAQ,CAAC;AAAA,IACpB,CAAC;AAED,YAAQ,IAAI;AAAA,MACV,OAAO,MAAM,MAAM,GAAG,CAAC;AAAA,IACzB,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN,KAAK,CAAC,MAAM,MAAM,IAAI;AAAA,QACtB,KAAK,CAAC,MAAM,MAAM,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,MAAsB;AAC3C,QAAI,QAAQ;AACZ,eAAW,KAAK,KAAM,UAAS,EAAE;AAEjC,UAAM,WAAW,IAAI,aAAa,QAAQ,CAAC;AAC3C,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,OAAO,IAAI,aAAa,QAAQ,CAAC;AACvC,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,UAAU,IAAI,aAAa,KAAK;AAEtC,QAAI,SAAS;AACb,eAAW,KAAK,MAAM;AACpB,eAAS,IAAI,EAAE,UAAU,SAAS,CAAC;AACnC,YAAM,IAAI,EAAE,OAAO,SAAS,CAAC;AAC7B,WAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC3B,YAAM,IAAI,EAAE,OAAO,SAAS,CAAC;AAC7B,cAAQ,IAAI,EAAE,SAAS,MAAM;AAC7B,gBAAU,EAAE;AAAA,IACd;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACl0BO,IAAM,YAAN,MAAkC;AAAA,EAC/B;AAAA,EAER,YAAY,MAAwB;AAClC,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,KAAyC;AAClD,UAAM,MAAM,MAAM,MAAM,KAAK,KAAK,GAAG,EAAE,KAAK,CAAC,MAAM;AACjD,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI;AAAA,UACR,oCAAoC,EAAE,MAAM,KAAK,KAAK,KAAK,GAAG;AAAA,QAChE;AAAA,MACF;AACA,aAAO,EAAE,YAAY;AAAA,IACvB,CAAC;AAED,UAAM,MAAM,KAAK,eAAe,GAAG;AAEnC,WAAO;AAAA,MACL,QAAQ,IAAI;AAAA,MACZ,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,UAAgB;AAAA,EAEhB;AAAA,EAEQ,eAAe,MAIrB;AACA,UAAM,QAAQ,KAAK,MAAM,OAAO;AAEhC,QAAI,cAAc;AAClB,QAAI,qBAAqB;AACzB,QAAI,SAAS;AAEb,UAAM,QAAgC,CAAC;AAEvC,eAAW,QAAQ,OAAO;AACxB,YAAM,IAAI,KAAK,KAAK;AAEpB,UAAI,EAAE,WAAW,gBAAgB,GAAG;AAClC,sBAAc,SAAS,EAAE,MAAM,KAAK,EAAE,CAAC,GAAG,EAAE;AAC5C,6BAAqB;AACrB;AAAA,MACF;AAEA,UAAI,sBAAsB,EAAE,WAAW,SAAS,GAAG;AACjD,6BAAqB;AAAA,MACvB;AAEA,UAAI,sBAAsB,EAAE,WAAW,UAAU,GAAG;AAClD,cAAM,CAAC,EAAE,MAAM,IAAI,IAAI,EAAE,MAAM,KAAK;AAEpC,YAAI,SAAS,SAAS;AACpB,gBAAM,IAAI,MAAM,qCAAqC,IAAI,EAAE;AAAA,QAC7D;AAEA,cAAM,IAAI,IAAI;AACd,kBAAU;AAAA,MACZ;AAEA,UAAI,MAAM,aAAc;AAAA,IAC1B;AAEA,QAAI,CAAC,eAAe,WAAW,GAAG;AAChC,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,QAAmC;AACxD,UAAM,OAAO,IAAI,YAAY,EAAE,OAAO,OAAO,MAAM,GAAG,IAAI,CAAC;AAC3D,UAAM,QAAQ,KAAK,MAAM,oBAAoB;AAC7C,QAAI,CAAC,SAAS,MAAM,SAAS,MAAM;AACjC,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,UAAM,YAAY,MAAM,QAAQ,MAAM,CAAC,EAAE;AAGzC,QAAI,QAAQ;AACZ,eAAW,KAAK,KAAK,MAAM,GAAG,SAAS,EAAE,MAAM,IAAI,GAAG;AACpD,UAAI,EAAE,WAAW,gBAAgB,GAAG;AAClC,gBAAQ,SAAS,EAAE,MAAM,KAAK,EAAE,CAAC,GAAG,EAAE;AAAA,MACxC;AAAA,IACF;AACA,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,sBAAsB;AAGlD,UAAM,SAAS;AACf,UAAM,SAAS,SAAS;AAExB,UAAM,KAAK,IAAI,SAAS,QAAQ,SAAS;AAEzC,UAAM,WAAW,IAAI,aAAa,QAAQ,CAAC;AAC3C,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,OAAO,IAAI,aAAa,QAAQ,CAAC;AACvC,UAAM,QAAQ,IAAI,aAAa,QAAQ,CAAC;AACxC,UAAM,UAAU,IAAI,aAAa,KAAK;AAEtC,QAAI,OAAO,UACT,OAAO,UACP,OAAO;AACT,QAAI,OAAO,WACT,OAAO,WACP,OAAO;AAET,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,YAAM,OAAO,IAAI;AACjB,UAAI,IAAI;AAGR,YAAM,IAAI,GAAG,WAAW,OAAO,GAAG,IAAI;AACtC,YAAM,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AAC1C,YAAM,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AAC1C,WAAK;AAEL,eAAS,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;AAC/B,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AACvB,aAAO,KAAK,IAAI,MAAM,CAAC;AAGvB,WAAK;AAGL,YAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,GAAG,IAAI;AAC/C,YAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AACnD,YAAM,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AACnD,WAAK;AAGL,WAAK,KAAK;AAGV,YAAM,KAAK,GAAG,WAAW,OAAO,GAAG,IAAI;AACvC,cAAQ,CAAC,IAAI,KAAO,IAAM,KAAK,IAAI,CAAC,EAAE;AACtC,WAAK;AAGL,YAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,WAAW,OAAO,GAAG,IAAI,CAAC;AACzD,YAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI,CAAC;AAC7D,YAAM,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI,CAAC;AAC7D,WAAK;AAGL,WAAK,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,GAAG,IAAI;AAC9C,WAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AACnD,WAAK,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,OAAO,IAAI,GAAG,IAAI;AACnD,WAAK,IAAI,IAAI,CAAC,IAAI,GAAG,WAAW,OAAO,IAAI,IAAI,IAAI;AAAA,IACrD;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN,KAAK,CAAC,MAAM,MAAM,IAAI;AAAA,QACtB,KAAK,CAAC,MAAM,MAAM,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACF;;;AC/LO,SAAS,aAAa,QAAsB,OAAyB;AAC1E,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,IAAI,WAAW,EAAE,KAAK,OAAO,KAAK,MAAM,CAAC;AAAA,IAClD,KAAK;AACH,aAAO,IAAI,UAAU,EAAE,KAAK,OAAO,IAAI,CAAC;AAAA,IAC1C;AACE,YAAM,IAAI,MAAM,uCAAuC;AAAA,EAC3D;AACF;;;ACdA,YAAYC,SAAQ;AAab,IAAM,wBAAN,MAA4B;AAAA,EACzB;AAAA,EACA;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAEA;AAAA,EAEA,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,QAAQ;AAAA,EAER,UAAU;AAAA,EAElB,YAAY,KAAqB,QAAmB,MAAoB;AACtE,SAAK,MAAM;AACX,SAAK,SAAS;AAEd,SAAK,SAAS,KAAK,OAAO,MAAM;AAEhC,SAAK,WAAW,KAAK;AACrB,SAAK,cAAc,KAAK,eAAe;AACvC,SAAK,cAAc,KAAK,eAAe;AAEvC,SAAK,MAAM,KAAK,OAAO;AACvB,SAAK,QAAQ,KAAK,SAAS;AAE3B,SAAK,cAAc,KAAK,eAAe;AACvC,SAAK,YAAY,KAAK,aAAa;AAEnC,SAAK,QAAQ,IAAI;AAEjB,SAAK,KAAK;AACV,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,UAAU;AACR,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO;AACb,SAAK,MAAM,GAAM,qBAAiB,KAAK,WAAW;AAClD,SAAK,MAAM,GAAM,mBAAe,KAAK,SAAS;AAC9C,SAAK,MAAM,GAAM,qBAAiB,KAAK,WAAW;AAClD,SAAK,MAAM,GAAM,sBAAkB,KAAK,YAAY;AAAA,EACtD;AAAA,EAEQ,SAAS;AACf,SAAK,MAAM,IAAO,qBAAiB,KAAK,WAAW;AACnD,SAAK,MAAM,IAAO,mBAAe,KAAK,SAAS;AAC/C,SAAK,MAAM,IAAO,qBAAiB,KAAK,WAAW;AACnD,SAAK,MAAM,IAAO,sBAAkB,KAAK,YAAY;AAAA,EACvD;AAAA,EAEQ,cAAc,CAAC,MAAqB;AAC1C,QAAI,EAAE,WAAc,sBAAkB;AACpC,WAAK,WAAW;AAAA,IAClB;AACA,QAAI,EAAE,WAAc,uBAAmB;AACrC,WAAK,UAAU;AAAA,IACjB;AACA,SAAK,QAAQ,EAAE;AACf,SAAK,QAAQ,EAAE;AAAA,EACjB;AAAA,EAGQ,YAAY,MAAM;AACxB,SAAK,WAAW;AAChB,SAAK,UAAU;AAAA,EACjB;AAAA,EAGQ,cAAc,CAAC,MAAqB;AAC1C,UAAM,KAAK,EAAE,IAAI,KAAK;AACtB,UAAM,KAAK,EAAE,IAAI,KAAK;AAEtB,SAAK,QAAQ,EAAE;AACf,SAAK,QAAQ,EAAE;AAGf,QAAI,KAAK,UAAU;AACjB,WAAK,OAAO,KAAK,KAAK;AACtB,WAAK,SAAS,KAAK,KAAK;AACxB,WAAK,QAAW,SAAK,MAAM,KAAK,OAAO,KAAK,EAAE;AAC9C,WAAK,aAAa;AAAA,IACpB;AAGA,QAAI,KAAK,SAAS;AAChB,YAAM,WAAW,KAAK,WAAW;AAEjC,YAAM,QAAQ,KAAK,OAAO,MAAM,MAAM,EAAE,UAAU,CAAC,KAAK,QAAQ;AAChE,YAAM,KAAK,KAAK,OAAO,GAAG,MAAM,EAAE,UAAU,KAAK,QAAQ;AAEzD,WAAK,OAAO,IAAI,KAAK,EAAE,IAAI,EAAE;AAC7B,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA,EAGQ,eAAe,CAAC,MAAqB;AAE3C,UAAM,aAAa,KAAK,IAAI,KAAK,WAAW,EAAE,aAAa,EAAE;AAE7D,SAAK,YAAY;AAGjB,SAAK,WAAc,SAAK;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe;AACrB,UAAM,SAAU,KAAK,MAAM,KAAK,KAAM;AACtC,UAAM,WAAY,KAAK,QAAQ,KAAK,KAAM;AAE1C,UAAM,IACJ,KAAK,OAAO,IACZ,KAAK,WAAW,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,MAAM;AACtD,UAAM,IAAI,KAAK,OAAO,IAAI,KAAK,WAAW,KAAK,IAAI,QAAQ;AAC3D,UAAM,IACJ,KAAK,OAAO,IACZ,KAAK,WAAW,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,MAAM;AAEtD,SAAK,OAAO,YAAY,GAAG,GAAG,CAAC;AAC/B,SAAK,OAAO,OAAO,KAAK,QAAW,SAAK,EAAE;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,QAAiB;AACzB,SAAK,OAAO,KAAK,MAAM;AACvB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,YAAY,UAAkB;AAC5B,SAAK,WAAc,SAAK;AAAA,MACtB;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,UAAU,aAAqB,aAAqB;AAClD,SAAK,cAAc;AACnB,SAAK,cAAc;AACnB,SAAK,WAAc,SAAK;AAAA,MACtB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,aAAa;AAAA,EACpB;AACF;;;AC/LA,YAAYC,SAAQ;AAOb,SAAS,kBACd,cACA,QACA,UAAkB,MAClB;AACA,QAAM,MAAM,aAAa;AACzB,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,0BAA0B;AAGpD,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,QAAM,SAAS,IAAO,SAAK,IAAI,IAAI,EAAE;AAGrC,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,QAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAG7C,QAAM,SAAS,KAAK,IAAI,IAAI,IAAI,EAAE;AAGlC,QAAM,SAAU,IAAI,MAAM,KAAK,KAAM;AAGrC,QAAM,SAAS,IAAI,eAAe;AAClC,QAAM,eAAe,SAAS,KAAK,IAAI,SAAS,GAAG;AACnD,QAAM,iBAAiB,SAAS,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,SAAS,GAAG,IAAI,MAAM,CAAC;AAGnF,MAAI,WAAW,KAAK,IAAI,cAAc,cAAc;AAGpD,cAAY;AAGZ,aAAW,KAAK,IAAI,UAAU,GAAG;AAEjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACnDA,YAAYC,SAAQ;AAQb,IAAM,uBAAN,MAA2B;AAAA,EACxB;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EAEV,OAAgC,CAAC;AAAA,EAEjC;AAAA,EACA;AAAA,EAEA,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EAE5B,YAAY,KAAqB,QAAmB,OAAoB,CAAC,GAAG;AAC1E,SAAK,MAAM;AACX,SAAK,SAAS;AAEd,SAAK,YAAY,KAAK,aAAa;AACnC,SAAK,YAAY,KAAK,SAAS;AAC/B,SAAK,YAAY,KAAK,aAAa;AAEnC,SAAK,QAAQ,IAAI;AACjB,SAAK,WAAW,IAAI;AAGpB,aAAS,iBAAiB,qBAAqB,MAAM;AACnD,WAAK,eAAe;AAAA,IACtB,CAAC;AAGD,WAAO,iBAAiB,QAAQ,MAAM;AACpC,WAAK,OAAO,mBAAmB;AAC/B,WAAK,eAAe;AAAA,IACtB,CAAC;AAGD,aAAS,iBAAiB,oBAAoB,MAAM;AAClD,UAAI,SAAS,QAAQ;AACnB,aAAK,OAAO,mBAAmB;AAC/B,aAAK,eAAe;AAAA,MACtB;AAAA,IACF,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,CAAC,MAAM;AACjC,UAAI,EAAE,WAAc,sBAAkB;AACpC,aAAK,IAAI,OAAO,kBAAkB;AAAA,MACpC;AAAA,IACF,CAAC;AAOD,aAAS,iBAAiB,WAAW,CAAC,MAAM;AAC1C,UAAI,EAAE,QAAQ,UAAU;AACtB,aAAK,OAAO,mBAAmB;AAAA,MACjC;AAAA,IACF,CAAC;AAED,SAAK,OAAO,GAAG,aAAa,CAAC,MAAM;AACjC,UAAI,CAAI,UAAM,gBAAgB,EAAG;AACjC,UAAI,SAAS,OAAQ;AACrB,UAAI,YAAY,IAAI,IAAI,KAAK,kBAAmB;AAEhD,WAAK,WAAW,EAAE;AAClB,WAAK,WAAW,EAAE;AAAA,IACpB,CAAC;AAED,UAAM,QAAQ,KAAK,OAAO,eAAe;AACzC,SAAK,QAAQ,MAAM;AACnB,SAAK,MAAM,MAAM;AAEjB,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,UAAU;AACR,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO;AACb,SAAK,MAAM,GAAM,qBAAiB,KAAK,WAAW;AAClD,SAAK,SAAS,GAAM,mBAAe,KAAK,SAAS;AACjD,SAAK,SAAS,GAAM,iBAAa,KAAK,OAAO;AAAA,EAC/C;AAAA,EAEQ,SAAS;AACf,SAAK,MAAM,IAAO,qBAAiB,KAAK,WAAW;AACnD,SAAK,SAAS,IAAO,mBAAe,KAAK,SAAS;AAClD,SAAK,SAAS,IAAO,iBAAa,KAAK,OAAO;AAAA,EAChD;AAAA,EAEQ,YAAY,CAAC,MAAwB;AAC3C,SAAK,KAAK,EAAE,GAAa,IAAI;AAAA,EAC/B;AAAA,EAEQ,UAAU,CAAC,MAAwB;AACzC,SAAK,KAAK,EAAE,GAAa,IAAI;AAAA,EAC/B;AAAA,EAEQ,cAAc,CAAC,MAAqB;AAG1C,SAAK,OAAO,EAAE,KAAK,KAAK;AACxB,SAAK,SAAS,EAAE,KAAK,KAAK;AAE1B,SAAK,QAAW,SAAK,MAAM,KAAK,OAAO,KAAK,EAAE;AAE9C,SAAK,OAAO,eAAe,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,EACpD;AAAA,EAEQ,iBAAiB;AACvB,UAAM,QAAQ,KAAK,OAAO,oBAAoB;AAE9C,SAAK,QAAQ,MAAM;AACnB,SAAK,MAAM,MAAM;AAEjB,SAAK,UAAU;AACf,SAAK,UAAU;AAGf,SAAK,oBAAoB,YAAY,IAAI,IAAI;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,IAAY,aAAqB,GAAK;AAQ3C,QAAO,UAAM,gBAAgB,GAAG;AAC9B,YAAM,WAAW;AAEjB,YAAM,KAAQ,SAAK,MAAM,KAAK,SAAS,CAAC,UAAU,QAAQ;AAC1D,YAAM,KAAQ,SAAK,MAAM,KAAK,SAAS,CAAC,UAAU,QAAQ;AAS1D,WAAK,OAAO,KAAK,KAAK;AACtB,WAAK,SAAS,KAAK,KAAK;AAMxB,WAAK,QAAW,SAAK,MAAM,KAAK,OAAO,KAAK,EAAE;AAE9C,WAAK,OAAO,oBAAoB,KAAK,OAAO,KAAK,KAAK,CAAC;AAGvD,WAAK,UAAU;AACf,WAAK,UAAU;AAAA,IACjB;AAIA,UAAM,QAAQ,KAAK,YAAY;AAE/B,UAAM,UAAU,KAAK,OAAO,QAAQ,MAAM;AAC1C,YAAQ,IAAI;AACZ,YAAQ,UAAU;AAElB,UAAM,QAAQ,KAAK,OAAO,MAAM,MAAM;AACtC,UAAM,IAAI;AACV,UAAM,UAAU;AAIhB,UAAM,OAAO,IAAO,SAAK;AAEzB,QAAI,KAAK,KAAQ,SAAK,EAAG,MAAK,IAAI,OAAO;AACzC,QAAI,KAAK,KAAQ,SAAK,EAAG,MAAK,IAAI,OAAO;AAIzC,UAAM,YAAY;AAElB,QAAI,KAAK,KAAQ,SAAK,GAAG;AACvB,WAAK,OAAO,YAAY;AAAA,IAC1B;AAEA,QAAI,KAAK,KAAQ,SAAK,GAAG;AACvB,WAAK,OAAO,YAAY;AAAA,IAC1B;AAEA,SAAK,OAAO,oBAAoB,KAAK,OAAO,KAAK,KAAK,CAAC;AAEvD,QAAI,KAAK,SAAS,IAAI,GAAG;AACvB,WAAK,UAAU,EAAE,UAAU,QAAQ,EAAE;AACrC,WAAK,OAAO,UAAU,IAAI;AAAA,IAC5B;AAIA,UAAM,SAAY,SAAK,aAAa,KAAK;AAazC,UAAM,WAAW,IAAO,SAAK;AAC7B,aAAS,IAAI,QAAQ,UAAU,KAAK,CAAC,CAAC;AACtC,aAAS,IAAI,MAAM,UAAU,KAAK,CAAC,CAAC;AACpC,aAAS,UAAU,EAAE,UAAU,QAAQ,EAAE;AAEzC,SAAK,OAAO,UAAU,QAAQ;AAE9B,UAAM,MAAM,KAAK,OAAO,YAAY;AACpC,QAAI,IAAO,SAAK,KAAK,IAAI,GAAG,KAAK,SAAS,KAAK,WAAW,IAAI;AAC9D,SAAK,OAAO,YAAY,GAAG;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAc;AACxB,SAAK,OAAO,YAAY,IAAI,GAAG,IAAI,IAAI,KAAK,WAAW,IAAI,CAAC;AAAA,EAC9D;AAAA,EAEA,YAAY,KAAa,OAAe;AACtC,SAAK,MAAM;AACX,SAAK,QAAW,SAAK,MAAM,OAAO,KAAK,EAAE;AACzC,SAAK,OAAO,eAAe,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,EACpD;AAAA,EAEA,UAAU,GAAW;AACnB,SAAK,SAAS;AAAA,EAChB;AACF;;;ANvPO,IAAM,uBAAN,MAA2B;AAAA,EACxB;AAAA,EACA;AAAA,EAEA,UAAU;AAAA,EACV,WAAW;AAAA;AAAA,EAGX;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA,QAAsC;AAAA,EACtC,OAAoC;AAAA,EAEpC,aAA+B;AAAA;AAAA,EAG/B,SAAwB;AAAA;AAAA,EAGxB,YAAY,oBAAI,IAAsB;AAAA,EACtC,gBAA+B;AAAA;AAAA,EAG/B,cAA6B;AAAA;AAAA,EAG7B,iBAAwC;AAAA,EAExC,MAAM;AAAA,EACN,QAAQ;AAAA,EAEhB,YAAY,SAA4B;AACtC,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU;AACf,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAsB;AAC1B,SAAK,kBAAkB;AAGvB,SAAK,aAAa;AAClB,SAAK,UAAU;AACf,SAAK,WAAW;AAGhB,SAAK,WAAW;AAChB,SAAK,OAAO;AAGZ,SAAK,SAAS,aAAa,KAAK,QAAQ,QAAQ,KAAK,QAAQ,KAAK;AAGlE,UAAM,SAAS,MAAM,KAAK,OAAO,KAAK;AAAA,MACpC,cAAc;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,IACjB,CAAC;AAGD,SAAK,eAAe;AAGpB,QAAI,QAAQ,QAAQ;AAClB,WAAK,cAAc,OAAO;AAC1B,WAAK,oBAAoB,KAAK,WAAW;AAGzC,WAAK,YAAY;AAEjB,WAAK,gBAAgB,OAAO;AAE5B,WAAK,cAAc,MAAM;AAAA,IAC3B,OAAO;AAEL,WAAK,cAAc,OAAO;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,kBAAkB;AACvB,QAAI,KAAK,QAAS;AAClB,SAAK,UAAU;AACf,SAAK,IAAI,GAAG,UAAU,KAAK,QAAQ;AAAA,EACrC;AAAA,EAEA,QAAc;AACZ,QAAI,CAAC,KAAK,QAAS;AACnB,SAAK,UAAU;AACf,SAAK,IAAI,IAAI,UAAU,KAAK,QAAQ;AAAA,EACtC;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,SAAU;AAEnB,SAAK,MAAM;AACX,SAAK,WAAW;AAEhB,SAAK,gBAAgB,WAAW;AAChC,SAAK,iBAAiB;AAEtB,SAAK,MAAM,UAAU;AACrB,SAAK,OAAO;AAEZ,SAAK,OAAO,QAAQ;AACpB,SAAK,QAAQ;AAEb,SAAK,QAAQ,QAAQ;AACrB,SAAK,SAAS;AAEd,QAAI;AACF,WAAK,KAAK,QAAQ;AAAA,IACpB,QAAQ;AAAA,IAER;AAEA,QAAI,KAAK,QAAQ,kBAAkB,KAAK,WAAW;AACjD,WAAK,UAAU,YAAY,KAAK,MAAM;AAAA,IACxC,OAAO;AACL,WAAK,UAAU,YAAY;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,SAAe;AACb,QAAI,CAAC,KAAK,OAAO,CAAC,KAAK,OAAQ;AAE/B,UAAM,IAAI,KAAK,IAAI,GAAG,KAAK,UAAU,WAAW;AAChD,UAAM,IAAI,KAAK,IAAI,GAAG,KAAK,UAAU,YAAY;AAEjD,UAAM,aACJ,KAAK,QAAQ,UAAU,cACvB,KAAK,IAAI,GAAG,OAAO,oBAAoB,CAAC;AAE1C,SAAK,OAAO,QAAQ,KAAK,MAAM,IAAI,UAAU;AAC7C,SAAK,OAAO,SAAS,KAAK,MAAM,IAAI,UAAU;AAE9C,SAAK,OAAO,MAAM,QAAQ,GAAG,CAAC;AAC9B,SAAK,OAAO,MAAM,SAAS,GAAG,CAAC;AAE/B,SAAK,IAAI,aAAa,KAAK,OAAO,OAAO,KAAK,OAAO,MAAM;AAE3D,UAAM,MAAM,KAAK,cAAc;AAC/B,QAAI,IAAK,KAAI,cAAc,IAAI;AAAA,EACjC;AAAA;AAAA,EAGA,YAAiD;AAC/C,QAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,UAAM,MAA2C,CAAC;AAElD,SAAK,IAAI,KAAK,SAAS,QAAQ,CAAC,MAAW;AACzC,UAAI,GAAG,MAAM,WAAW,OAAO,KAAK,GAAG,MAAM,IAAI;AAC/C,YAAI,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,MAAM,EAAE,KAAK,QAAQ,EAAE,KAAK,GAAG,CAAC;AAAA,MAC5D;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,QAAgB;AAC3B,QAAI,CAAC,KAAK,KAAM;AAEhB,SAAK,KAAK,SAAS,QAAQ,CAAC,MAAM;AAEhC,UAAI,CAAC,EAAE,MAAM,WAAW,OAAO,EAAG;AAClC,QAAE,UAAU,EAAE,SAAS,QAAQ,MAAM;AAAA,IACvC,CAAC;AAED,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,eAAe,QAAgB,SAAkB;AAC/C,UAAM,OAAO,KAAK,cAAc,MAAM;AACtC,QAAI,KAAM,MAAK,UAAU;AAAA,EAC3B;AAAA,EAEA,eAA2B;AACzB,WAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC;AAAA,EAC3C;AAAA,EAEA,mBAAmB;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,SAAS,QAAgB,SAAyB,SAAS;AACzD,UAAM,aAAa,KAAK,cAAc,MAAM;AAC5C,QAAI,CAAC,WAAY;AAEjB,SAAK,gBAAgB;AAGrB,UAAM,SAAS,KAAK,iBAAiB,MAAM,KAAK,KAAK;AACrD,QAAI,CAAC,OAAQ;AAGb,SAAK,cAAc,OAAO;AAG1B,SAAK,gBAAgB,QAAQ,MAAM;AAAA,EACrC;AAAA,EAEA,cAAc,MAAwB;AACpC,SAAK,kBAAkB;AACvB,QAAI,KAAK,eAAe,KAAM;AAC9B,SAAK,aAAa;AAElB,QAAI,SAAS,SAAS;AAEpB,WAAK,MAAM,UAAU;AACrB,WAAK,OAAO;AAGZ,WAAK,IAAI,OAAO,mBAAmB;AACnC,WAAK,YAAY;AAAA,IACnB,OAAO;AAEL,WAAK,OAAO,QAAQ;AACpB,WAAK,QAAQ;AAGb,WAAK,WAAW;AAChB,WAAK,IAAI,OAAO,kBAAkB;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,gBAAgB,QAAwB,QAAiB;AACvD,UAAM,IAAI,UAAU,KAAK;AACzB,QAAI,CAAC,EAAG;AAER,UAAM,MAAM,kBAAkB,KAAK,cAAc,CAAC;AAClD,UAAM,MAAM,KAAK,oBAAoB,CAAC;AAEtC,QAAI,WAAW,IAAI;AACnB,QAAI,WAAW,QAAS,YAAW,KAAK,IAAI,KAAK,IAAI,WAAW,IAAI;AACpE,QAAI,WAAW,QAAS,YAAW,KAAK,IAAI,MAAM,IAAI,WAAW,GAAG;AACpE,QAAI,WAAW,WAAY,YAAW,KAAK,IAAI,GAAK,IAAI,WAAW,GAAG;AAEtE,QAAI,KAAK,OAAO;AAEd,WAAK,MAAM,UAAU,WAAW,aAAa,IAAI,SAAS,GAAG;AAC7D,WAAK,MAAM,YAAY,QAAQ;AAAA,IACjC,OAAO;AAEL,YAAM,MAAM,IAAO,SAAK,GAAG,GAAG,CAAC;AAC/B,WAAK,aAAa,YAAY,IAAI,MAAM,EAAE,IAAI,IAAI,UAAU,QAAQ,CAAC,CAAC;AACtE,WAAK,aAAa,OAAO,GAAG;AAAA,IAC9B;AAEA,YAAQ,IAAI,kBAAkB,QAAQ,EAAE,SAAS,CAAC;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgEA,iBAAiB;AAEf,QAAI,CAAC,KAAK,MAAM;AACd,cAAQ,KAAK,sCAAsC;AACnD;AAAA,IACF;AACA,QAAI,CAAC,KAAK,aAAa;AACrB,cAAQ,KAAK,kCAAkC;AAC/C;AAAA,IACF;AAGA,SAAK,aAAa;AAElB,UAAM,QAAQ,KAAK,aAAa,KAAK,WAAW;AAGhD,SAAK,KAAM,YAAY,KAAK;AAC5B,SAAK,KAAM,YAAY,KAAK,CAAC;AAC7B,SAAK,KAAM,UAAU,KAAK,YAAa,IAAI,CAAC,CAAC;AAC7C,YAAQ,IAAI,+BAA+B;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,CAAC,OAAe;AACjC,QAAI,CAAC,KAAK,YAAa;AAGvB,QAAI,KAAK,eAAe,SAAS;AAE/B;AAAA,IACF;AAGA,QAAI,KAAK,eAAe,UAAU,KAAK,MAAM;AAC3C,YAAM,QACJ,KAAK;AAAA,QACH,KAAK,YAAY,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC;AAAA,QAChD,KAAK,YAAY,IAAI,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC;AAAA,MAClD,IAAI;AAEN,WAAK,KAAK,OAAO,IAAI,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEQ,eAAe;AACrB,QAAI,KAAK,IAAK;AAEd,SAAK,SAAS,SAAS,cAAc,QAAQ;AAC7C,SAAK,OAAO,iBAAiB,eAAe,CAAC,MAAM;AACjD,QAAE,eAAe;AAAA,IACnB,CAAC;AACD,SAAK,OAAO,MAAM,UAAU;AAC5B,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,OAAO,MAAM,SAAS;AAC3B,SAAK,UAAU,YAAY,KAAK,MAAM;AAEtC,SAAK,MAAM,IAAO,gBAAY,KAAK,QAAQ;AAAA,MACzC,OAAO,IAAO,UAAM,KAAK,MAAM;AAAA,MAC/B,OAAO,IAAO,gBAAY,KAAK,MAAM;AAAA,MACrC,UAAU,IAAO,aAAS,MAAM;AAAA,MAChC,cAAc,IAAO,iBAAa,KAAK,MAAM;AAAA,IAC/C,CAAC;AAMD,SAAK,OAAO,KAAK,IAAI;AACrB,SAAK,IAAI,MAAM;AAAA,EACjB;AAAA,EAEQ,YAAY;AAElB,SAAK,IAAI,MAAM,eAAe,IAAO,UAAM,KAAK,KAAK,GAAG;AAAA,EAI1D;AAAA,EAEQ,aAAa;AAEnB,SAAK,eAAe,IAAO,WAAO,QAAQ;AAC1C,SAAK,aAAa,aAAa,UAAU;AAAA,MACvC,YAAY,IAAO,UAAM,GAAG,GAAG,CAAC;AAAA,MAChC,UAAU;AAAA,MACV,SAAS;AAAA,MACT,KAAK;AAAA,MACL,QAAQ,CAAI,iBAAa;AAAA,IAC3B,CAAC;AAGD,SAAK,aAAa,iBAAiB,GAAG,KAAK,CAAC;AAC5C,SAAK,aAAa,oBAAoB,GAAG,KAAK,CAAC;AAE/C,SAAK,IAAI,KAAK,SAAS,KAAK,YAAY;AACxC,YAAQ,IAAI,iBAAiB,KAAK,aAAa,OAAQ,MAAM;AAC7D,SAAK,aAAa,OAAQ,mBAAmB;AAAA,EAC/C;AAAA,EAEQ,aAAa;AACnB,SAAK,gBAAgB,WAAW;AAChC,SAAK,iBAAiB,IAAI,eAAe,MAAM,KAAK,OAAO,CAAC;AAC5D,SAAK,eAAe,QAAQ,KAAK,SAAS;AAAA,EAC5C;AAAA,EAEQ,oBAAoB,QAAgB;AAE1C,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI;AAExD,UAAM,MAAM,KAAK,aAAa;AAC9B,QAAI,WAAW,KAAK,IAAI,MAAM,SAAS,IAAK;AAC5C,QAAI,UAAU,KAAK,IAAI,KAAK,SAAS,EAAE;AAAA,EACzC;AAAA,EAEQ,oBAAoB,QAAgB;AAC1C,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC5C,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC5C,UAAM,IAAI,OAAO,IAAI,CAAC,IAAI;AAE1B,WAAO,IAAO,SAAK,GAAG,GAAG,CAAC;AAAA,EAC5B;AAAA,EAEQ,cAAc;AACpB,QAAI,KAAK,MAAO;AAChB,QAAI,CAAC,KAAK,YAAa;AAEvB,UAAM,IAAI,KAAK;AACf,UAAM,MAAM,kBAAkB,KAAK,cAAc,CAAC;AAElD,UAAM,SAAS,IAAI,OAAO,MAAM;AAChC,WAAO,IAAI,EAAE,IAAI,CAAC,IAAI;AAEtB,SAAK,QAAQ,IAAI,sBAAsB,KAAK,KAAK,KAAK,cAAc;AAAA,MAClE;AAAA,MACA,UAAU,IAAI,WAAW;AAAA,MACzB,aAAa,KAAK,IAAI,KAAK,IAAI,WAAW,IAAI;AAAA,MAC9C,aAAa,KAAK,IAAI,IAAI,WAAW,GAAG,IAAI,WAAW,CAAC;AAAA,MACxD,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AAED,YAAQ,IAAI,uBAAuB;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBQ,aAAa;AACnB,QAAI,KAAK,KAAM;AAEf,UAAM,SAAS,KAAK;AACpB,UAAM,QAAQ,SACV,KAAK,qBAAqB,MAAM,IAChC,IAAO,SAAK,GAAG,KAAK,CAAC;AAEzB,SAAK,aAAa,YAAY,KAAK;AACnC,SAAK,aAAa,eAAe,GAAG,KAAK,CAAC;AAE1C,SAAK,OAAO,IAAI,qBAAqB,KAAK,KAAK,KAAK,cAAc;AAAA,MAChE,WAAW;AAAA,MACX,OAAO;AAAA,MACP,WAAW;AAAA;AAAA;AAAA;AAAA,IAIb,CAAC;AAED,UAAM,MAAM,KAAK,aAAa,QAAQ,MAAM;AAC5C,SAAK,MAAM,KAAK,MAAM,IAAI,GAAG,IAAI,CAAC,IAAO,SAAK;AAC9C,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,qBAAqB,QAAgB;AAC3C,UAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAC7C,UAAM,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAE7C,UAAM,SAAS,OAAO,IAAI,CAAC;AAC3B,UAAM,OAAO,SAAS;AAEtB,WAAO,IAAO,SAAK,IAAI,MAAM,EAAE;AAAA,EACjC;AAAA,EAEQ,2BAA2B,QAAgB;AACjD,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,KAAK,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC;AACvC,UAAM,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE,IAAI;AACxD,WAAO,KAAK,IAAI,GAAG,SAAS,GAAG;AAAA,EACjC;AAAA,EAEQ,cAAc,QAAgB;AACpC,QAAI,CAAC,KAAK,KAAM,QAAO;AAEvB,WAAO,KAAK,KAAK,WAAW,QAAQ,MAAM,EAAE;AAAA,EAC9C;AAAA,EAEQ,iBAAiB,QAA+B;AACtD,UAAM,OAAO,KAAK,cAAc,MAAM;AACtC,QAAI,CAAC,KAAM,QAAO;AAGlB,UAAM,IAAI,KAAK,MAAM;AACrB,QAAI,GAAG,OAAO,GAAG,IAAK,QAAO;AAE7B,WAAO;AAAA,EACT;AAAA,EAEQ,iBAAiB;AACvB,SAAK,UAAU,MAAM;AAGrB,UAAM,QAAQ,KAAK,UAAU;AAC7B,eAAW,KAAK,OAAO;AACrB,WAAK,UAAU,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC,EAAE,CAAC;AAAA,IACtE;AAAA,EAGF;AAAA,EAEQ,aAAa,QAAgB;AACnC,WAAO,IAAO;AAAA,OACX,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAAA,MAClC,OAAO,IAAI,CAAC,IAAI;AAAA;AAAA,OACf,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,KAAK;AAAA,IACpC;AAAA,EACF;AAAA,EAEQ,kBAAkB;AACxB,QAAI,CAAC,KAAK,UAAW,OAAM,IAAI,MAAM,oCAAoC;AAAA,EAC3E;AAAA,EAEQ,oBAAoB;AAC1B,QAAI,KAAK,SAAU,OAAM,IAAI,MAAM,gCAAgC;AAAA,EACrE;AACF;","names":["pc","finalBounds","pc","pc","pc"]}