[
  {
    "path": ".agents/skills/canvasengine/SKILL.md",
    "content": "---\nname: canvasengine\ndescription: Work on CanvasEngine projects and .ce components using the official documentation. Use when Codex needs to explain, create, review, or modify CanvasEngine code, especially files ending in .ce, CanvasEngine reactivity with signals, computed, and effect, template directives such as @if and @for, component script/template/style structure, or CanvasEngine-specific syntax that mixes ideas from React, Vue, and Angular.\n---\n\n# CanvasEngine Project\n\n## Documentation First\n\nBefore answering or editing CanvasEngine code, fetch and read the current documentation index:\n\n```bash\ncurl -L https://canvasengine.net/llms.txt\n```\n\nIf `curl` is unavailable, use an equivalent command or tool (`wget`, browser/web fetch, or another HTTP client). If network access is blocked, say that the current documentation could not be fetched and proceed only from local code plus any already available docs.\n\nUse `llms.txt` as a table of contents:\n\n1. Read the summary and section list.\n2. Identify the Markdown documentation URLs relevant to the user request.\n3. Fetch the relevant `.md` pages with `curl -L <url>` or an equivalent tool.\n4. Base implementation and explanations on those pages, not on assumptions from React, Vue, Angular, or PixiJS.\n5. Mention the specific docs or examples consulted when the answer depends on them.\n\n## Project Model\n\nTreat CanvasEngine components as `.ce` files with:\n\n- a script block for state, imports, functions, signals, `computed`, and `effect`\n- component content/template markup\n- an optional CSS style block\n\nPrefer existing project conventions for file layout, imports, naming, and component composition. Inspect nearby `.ce` files before adding new patterns.\n\n## Reactivity\n\nCanvasEngine reactivity is centered on signals plus `computed` and `effect`.\n\nUse the documentation to confirm exact APIs before writing code. Do not assume that signal usage is identical to Solid, Angular, Vue, React, or another framework.\n\nImportant template rules:\n\n- In a template, `<Rect x />` means bind the `x` variable from the script scope. `x` may be a signal or a plain value. Do not interpret this as a boolean-only JSX prop.\n- For reactive conditions, pass the signal/reference to the directive: use `@if (show)`, not `@if (show())`.\n- For reactive loops, pass the signal/reference to the directive in the same spirit: use `@for` with the reactive source itself rather than eagerly calling or unwrapping it, unless the official docs for the exact case say otherwise.\n- Keep signal reads/writes consistent with the documented CanvasEngine syntax for the context: script code and template code may differ.\n\n## Implementation Checklist\n\nWhen modifying a CanvasEngine project:\n\n1. Fetch `llms.txt` and the relevant Markdown docs.\n2. Inspect local examples with `rg --files -g '*.ce'` and read nearby components.\n3. Preserve `.ce` component structure: script, content/template, optional style.\n4. Use CanvasEngine primitives and directives instead of importing framework habits from React/Vue/Angular.\n5. Verify shorthand bindings, reactive `@if`, and reactive `@for` syntax before finishing.\n6. Run the project’s relevant checks or at least a focused syntax/type check when available.\n"
  },
  {
    "path": ".agents/skills/canvasengine/agents/openai.yaml",
    "content": "interface:\n  display_name: \"CanvasEngine\"\n  short_description: \"Guide projets CanvasEngine et fichiers .ce\"\n  default_prompt: \"Use $canvasengine to implement or explain a CanvasEngine .ce component with the official docs.\"\n"
  },
  {
    "path": ".agents/skills/pixijs/SKILL.md",
    "content": "---\nname: pixijs\ndescription: \"Use this skill first for ANY PixiJS v8 task; it routes to the right specialized skill for the job. Covers the full PixiJS surface: Application setup, the scene graph (Container, Sprite, Graphics, Text, Mesh, ParticleContainer, DOMContainer, GifSprite), rendering (WebGL/WebGPU/Canvas, render loop, custom shaders, filters, blend modes), assets, events, color, math, ticker, accessibility, performance, environments, migration from v7, and project scaffolding. Triggers on: pixi, pixi.js, pixijs, PixiJS, v8, Application, app.init, Sprite, Container, Graphics, Text, Mesh, ParticleContainer, DOMContainer, GifSprite, Assets, Ticker, renderer, WebGL, WebGPU, scene graph, filter, shader, blend mode, texture, BitmapText, create-pixi, how do I draw, how do I render, how do I animate in pixi.\"\nlicense: MIT\n---\n\nEntry point for the PixiJS v8 skill collection. PixiJS is the fastest library available for the web, working across all devices and allowing you to create rich, interactive graphics and cross-platform applications using WebGL, WebGPU, and Canvas as a fallback.\n\n## How to use this skill\n\n1. Find the specialized skill in the router below that best matches the task.\n2. Load that skill's `SKILL.md` and follow its guidance.\n3. If no sub-skill fits (the task references a specific class, function, option, or API surface not listed below), **WebFetch `https://pixijs.download/release/docs/llms.txt`**. That file is the auto-generated, always-current index of the full PixiJS API and guides. Each entry links to a `.html.md` page you can WebFetch for the detailed content.\n\nFor the long-form description and trigger keywords of every skill, see [references/index.md](references/index.md).\n\n## Skill router\n\n### Foundations\n\n| Skill | Load when... |\n|---|---|\n| [pixijs-application](../pixijs-application/SKILL.md) | Creating or configuring a PixiJS `Application`, calling `app.init()`, accessing `app.stage`/`renderer`/`canvas`/`screen`, resize/ticker plugins, `app.destroy()`. |\n| [pixijs-core-concepts](../pixijs-core-concepts/SKILL.md) | Understanding the renderer pipeline, choosing WebGL/WebGPU/Canvas, render loop internals, systems and pipes. |\n| [pixijs-create](../pixijs-create/SKILL.md) | Scaffolding a new project with the `create-pixi` CLI (bundler-vite, creation-web, framework-react templates). |\n| [pixijs-environments](../pixijs-environments/SKILL.md) | Running PixiJS in Web Workers, Node/SSR, or strict-CSP contexts (`DOMAdapter`, `WebWorkerAdapter`, `pixi.js/unsafe-eval`). |\n| [pixijs-migration-v8](../pixijs-migration-v8/SKILL.md) | Upgrading from v7 to v8 or fixing v7 patterns (`beginFill`/`endFill`, `@pixi/*` packages, `BaseTexture`, `DisplayObject`). |\n| [pixijs-scene-core-concepts](../pixijs-scene-core-concepts/SKILL.md) | Understanding the scene graph as a whole: containers vs leaves, transforms, render order, masking, `RenderLayer`. |\n\n### Scene Objects\n\n| Skill | Load when... |\n|---|---|\n| [pixijs-scene-container](../pixijs-scene-container/SKILL.md) | Working with `Container`: `addChild`/`removeChild`, transforms, `zIndex`, bounds, `toGlobal`/`toLocal`, `destroy`. |\n| [pixijs-scene-sprite](../pixijs-scene-sprite/SKILL.md) | Drawing images: `Sprite`, `AnimatedSprite`, `NineSliceSprite`, `TilingSprite`. |\n| [pixijs-scene-graphics](../pixijs-scene-graphics/SKILL.md) | Drawing vector shapes or paths: `Graphics`, `GraphicsContext`, `fill`/`stroke`, `FillGradient`, SVG. |\n| [pixijs-scene-text](../pixijs-scene-text/SKILL.md) | Rendering text: `Text`, `BitmapText`, `HTMLText`, `SplitText`, `TextStyle`. |\n| [pixijs-scene-mesh](../pixijs-scene-mesh/SKILL.md) | Custom geometry: `Mesh`, `MeshSimple`, `MeshPlane`, `MeshRope`, `PerspectiveMesh`. |\n| [pixijs-scene-particle-container](../pixijs-scene-particle-container/SKILL.md) | Rendering thousands of lightweight sprites: `ParticleContainer`, `Particle`, `dynamicProperties`. |\n| [pixijs-scene-dom-container](../pixijs-scene-dom-container/SKILL.md) | Overlaying HTML elements on the canvas: `DOMContainer`, `pixi.js/dom`. |\n| [pixijs-scene-gif](../pixijs-scene-gif/SKILL.md) | Displaying animated GIFs: `GifSprite`, `GifSource`, `pixi.js/gif`. |\n\n### Utilities\n\n| Skill | Load when... |\n|---|---|\n| [pixijs-assets](../pixijs-assets/SKILL.md) | Loading resources: `Assets.init`, `Assets.load`, bundles, manifests, spritesheets, caching. |\n| [pixijs-color](../pixijs-color/SKILL.md) | Creating or converting colors: `Color` class, hex/rgb/hsl, `tint`, `premultiply`. |\n| [pixijs-events](../pixijs-events/SKILL.md) | Handling pointer/mouse/touch/wheel input: `eventMode`, `FederatedEvent`, `hitArea`, `cursor`, drag. |\n| [pixijs-math](../pixijs-math/SKILL.md) | Points, vectors, matrices, shapes, hit testing: `Point`, `Matrix`, `Rectangle`, `toGlobal`/`toLocal`. |\n| [pixijs-ticker](../pixijs-ticker/SKILL.md) | Per-frame logic or controlling the render loop: `Ticker`, `deltaTime`, `UPDATE_PRIORITY`, `maxFPS`. |\n\n### Advanced\n\n| Skill | Load when... |\n|---|---|\n| [pixijs-accessibility](../pixijs-accessibility/SKILL.md) | Screen reader or keyboard navigation: `AccessibilitySystem`, `accessibleTitle`, `tabIndex`. |\n| [pixijs-blend-modes](../pixijs-blend-modes/SKILL.md) | Compositing with blend modes: `add`, `multiply`, `screen`, `overlay`, `pixi.js/advanced-blend-modes`. |\n| [pixijs-custom-rendering](../pixijs-custom-rendering/SKILL.md) | Writing custom shaders, uniforms, or batchers: `Shader.from`, `GlProgram`/`GpuProgram`, `UniformGroup`, custom `Filter`. |\n| [pixijs-filters](../pixijs-filters/SKILL.md) | Applying visual effects: `BlurFilter`, `ColorMatrixFilter`, `DisplacementFilter`, `Filter.from`, `pixi-filters`. |\n| [pixijs-performance](../pixijs-performance/SKILL.md) | Profiling or optimizing FPS, draw calls, GPU memory: culling, `GCSystem`, `cacheAsTexture`, object pooling. |\n\n## Fallback: canonical PixiJS docs\n\nIf the task references a class, function, option, or API surface not covered by any sub-skill above, **WebFetch `https://pixijs.download/release/docs/llms.txt`**. It's the auto-generated index of the full PixiJS API and guides, regenerated on every release. Each entry links to a `.html.md` page you can WebFetch for the detailed content. Use this fallback whenever the router table doesn't point at an obvious match.\n"
  },
  {
    "path": ".agents/skills/pixijs/references/index.md",
    "content": "# PixiJS Skills: Full Index\n\nDetailed routing table for the PixiJS v8 skill collection. Each entry lists the skill's full description and the trigger keywords that should match it. For a scannable short-form table, see the parent `SKILL.md`.\n\n## Foundations\n\n### pixijs-application\nCreate and configure a PixiJS v8 `Application`. Covers `new Application()` + async `app.init()` options (width, height, background, antialias, resolution, autoDensity, preference, resizeTo, autoStart, sharedTicker, canvas), `app.stage`/`renderer`/`canvas`/`screen` access, `ResizePlugin`, `TickerPlugin`, and `app.destroy()`.\n\n**Triggers:** Application, app.init, app.stage, app.renderer, app.canvas, app.screen, ApplicationOptions, resizeTo, preference, autoStart, sharedTicker, app.destroy.\n\n### pixijs-core-concepts\nHow PixiJS v8 renders frames: the systems-and-pipes renderer, the render loop, and how the library adapts to different environments. Covers `WebGLRenderer`/`WebGPURenderer`/`CanvasRenderer` selection, `renderer.render()` pipeline, environment detection, and pointers to per-topic deep dives.\n\n**Triggers:** renderer, WebGL, WebGPU, Canvas, render loop, render pipeline, systems, environments, autoDetectRenderer.\n\n### pixijs-create\nScaffold a new PixiJS v8 project with the `create-pixi` CLI. Covers npm/yarn/pnpm/bun create commands, interactive vs non-interactive flows, available template presets (bundler-vite, bundler-webpack, bundler-esbuild, bundler-import-map, creation-web, framework-react, extension-default), Node version requirements, and post-scaffold dev flow.\n\n**Triggers:** create pixi.js, npm create, scaffold, template, bundler-vite, bundler-webpack, creation-web, framework-react, new project, getting started.\n\n### pixijs-environments\nRun PixiJS v8 outside a standard browser: Web Workers, `OffscreenCanvas`, Node/SSR, or CSP-restricted contexts. Covers `DOMAdapter.set`, `BrowserAdapter`, `WebWorkerAdapter`, custom `Adapter` interface, `pixi.js/unsafe-eval` for strict CSP.\n\n**Triggers:** DOMAdapter, BrowserAdapter, WebWorkerAdapter, Web Worker, OffscreenCanvas, Node, headless, SSR, CSP, unsafe-eval, Adapter.\n\n### pixijs-migration-v8\nUpgrade a PixiJS project from v7 to v8 or diagnose broken v7 code after an upgrade. Covers async `app.init`, single `pixi.js` package (deprecated `@pixi/*` sub-packages), `Graphics` shape-then-fill, `BaseTexture` -> `TextureSource`, shader/uniform rework, `ParticleContainer`+`Particle`, constructor options objects, `DisplayObject` removal, `settings`/`utils` removal, `Ticker` signature, events rewrite.\n\n**Triggers:** migrate v7, v8 breaking changes, @pixi/ import, DisplayObject, beginFill, endFill, cacheAsBitmap, BaseTexture, deprecated.\n\n### pixijs-scene-core-concepts\nThe PixiJS v8 scene graph as a whole: how containers, leaves, transforms, and render order fit together. Covers leaf vs container distinction, local/world coordinates, culling, render groups, sortable children, masking, `RenderLayer`, and which leaf skill covers which display object.\n\n**Triggers:** scene graph, display list, Container, Sprite, Graphics, Text, Mesh, ParticleContainer, DOMContainer, GifSprite, masking, render group, RenderLayer, world transform.\n\n## Scene Objects\n\n### pixijs-scene-container\nGroup, position, or transform display objects. Covers `Container` constructor options (`isRenderGroup`, `sortableChildren`, `boundsArea`), `addChild`/`removeChild`/`addChildAt`/`swapChildren`/`setChildIndex`, `position`/`scale`/`rotation`/`pivot`/`skew`/`alpha`/`tint`, `getBounds`/`getGlobalPosition`/`toLocal`/`toGlobal`, `zIndex` sorting, `cullable`, `destroy`.\n\n**Triggers:** Container, addChild, removeChild, addChildAt, swapChildren, sortableChildren, zIndex, position, scale, rotation, pivot, getBounds, toGlobal, toLocal, destroy.\n\n### pixijs-scene-dom-container\nOverlay HTML elements on the PixiJS v8 canvas. Covers `DOMContainer` with `element`, `anchor`, and scene-graph-driven CSS transforms, the `pixi.js/dom` side-effect import, `DOMPipe` registration, visibility sync, pointer-events handling.\n\n**Triggers:** DOMContainer, pixi.js/dom, DOMPipe, HTML overlay, input on canvas, iframe overlay, DOMContainerOptions, element, anchor.\n\n### pixijs-scene-gif\nDisplay animated GIFs. Covers the `pixi.js/gif` side-effect import, `Assets.load` returning a `GifSource`, `GifSprite` playback (`play`/`stop`/`currentFrame`/`animationSpeed`), `autoPlay`/`loop` options, `onComplete`/`onLoop`/`onFrameChange` callbacks, `GifSource` sharing, `clone`, `destroy`.\n\n**Triggers:** GifSprite, GifSource, pixi.js/gif, animationSpeed, currentFrame, autoPlay, onComplete, onFrameChange.\n\n### pixijs-scene-graphics\nDraw vector shapes and paths. Covers the `Graphics` shape-then-fill API (`rect`/`circle`/`ellipse`/`poly`/`roundRect`/`star`), path methods (`moveTo`/`lineTo`/`bezierCurveTo`/`arc`), `fill`/`stroke`/`cut`, `FillGradient`, `FillPattern`, `GraphicsContext` sharing, SVG markup.\n\n**Triggers:** Graphics, GraphicsContext, rect, circle, poly, roundRect, fill, stroke, cut, FillGradient, FillPattern, moveTo, bezierCurveTo, svg.\n\n### pixijs-scene-mesh\nRender custom geometry. Covers `Mesh` with `MeshGeometry` (positions, uvs, indices, topology), `MeshSimple` for per-frame vertex animation, `MeshPlane` for subdivided deformation, `MeshRope` for path-following textures, `PerspectiveMesh` for 2.5D corners.\n\n**Triggers:** Mesh, MeshGeometry, MeshSimple, MeshPlane, MeshRope, PerspectiveMesh, positions, uvs, indices, topology, setCorners.\n\n### pixijs-scene-particle-container\nRender thousands of lightweight sprites. Covers `ParticleContainer` with `Particle` instances, `addParticle`/`removeParticle`, `particleChildren` array, `dynamicProperties` (vertex, position, rotation, uvs, color), `boundsArea`, `roundPixels`, `update`.\n\n**Triggers:** ParticleContainer, Particle, IParticle, addParticle, particleChildren, dynamicProperties, boundsArea, particle effects.\n\n### pixijs-scene-sprite\nDraw images. Covers `Sprite` with `anchor`/`tint`/`texture`, `AnimatedSprite` for frame animation, `NineSliceSprite` for resizable UI panels, `TilingSprite` for scrolling/repeating backgrounds.\n\n**Triggers:** Sprite, AnimatedSprite, NineSliceSprite, TilingSprite, Sprite.from, anchor, tint, tilePosition, animationSpeed, gotoAndPlay, leftWidth, topHeight.\n\n### pixijs-scene-text\nRender text. Covers `Text` for canvas-quality styled labels, `BitmapText` for cheap per-frame updates via glyph atlas, `HTMLText` for HTML/CSS markup via SVG, `SplitText` and `SplitBitmapText` for per-character animation, `TextStyle`, `tagStyles`.\n\n**Triggers:** Text, BitmapText, HTMLText, SplitText, SplitBitmapText, TextStyle, HTMLTextStyle, BitmapFont.install, tagStyles, fontFamily, wordWrap.\n\n## Utilities\n\n### pixijs-assets\nLoad and manage resources. Covers `Assets.init`, `Assets.load`/`add`/`unload`, bundles, manifests, background loading, `onProgress`, caching, spritesheets, compressed textures, SVG as texture or Graphics, resolution detection.\n\n**Triggers:** Assets, Assets.load, Assets.init, loadBundle, manifest, backgroundLoad, Spritesheet, Cache, LoadOptions, unload.\n\n### pixijs-color\nCreate, convert, or manipulate colors. Covers `Color` class input formats (hex, CSS names, RGB/HSL objects, arrays, `Uint8Array`), conversion methods (`toHex`, `toNumber`, `toArray`, `toRgba`), component access, `setAlpha`/`multiply`/`premultiply`, `Color.shared` singleton.\n\n**Triggers:** Color, ColorSource, hex, rgb, hsl, tint, premultiply, Color.shared, color conversion.\n\n### pixijs-events\nHandle pointer, mouse, touch, or wheel input. Covers `eventMode` (none, passive, auto, static, dynamic), `FederatedEvent` types, propagation and capture phase, `hitArea`, `interactiveChildren`, `cursor` and `cursorStyles`, global move events for drag, `eventFeatures` config.\n\n**Triggers:** eventMode, FederatedPointerEvent, pointerdown, click, tap, globalpointermove, drag, hitArea, cursor, stopPropagation.\n\n### pixijs-math\nCoordinates, vectors, matrices, shapes, and hit testing. Covers `Point`/`ObservablePoint`, `Matrix` (2D affine, decompose, apply), shapes (`Rectangle`, `Circle`, `Ellipse`, `Polygon`, `RoundedRectangle`, `Triangle`), `toGlobal`/`toLocal`, `PointData` types, `DEG_TO_RAD`, and `pixi.js/math-extras` vector helpers.\n\n**Triggers:** Point, ObservablePoint, Matrix, Rectangle, Circle, Polygon, toGlobal, toLocal, hitArea, math-extras, DEG_TO_RAD, PointData.\n\n### pixijs-ticker\nRun per-frame logic or control the render loop. Covers `Ticker.add`/`addOnce`/`remove`, `deltaTime` vs `deltaMS` vs `elapsedMS`, `UPDATE_PRIORITY` ordering, `maxFPS`/`minFPS` capping, speed scaling, `Ticker.shared` vs new instances, per-object `onRender` hook, manual rendering.\n\n**Triggers:** Ticker, UPDATE_PRIORITY, deltaTime, deltaMS, elapsedMS, onRender, app.ticker, maxFPS, minFPS, Ticker.shared.\n\n## Advanced\n\n### pixijs-accessibility\nAdd screen reader and keyboard navigation to PixiJS v8 apps. Covers `AccessibilitySystem` options (`enabledByDefault`, `debug`, `activateOnTab`, `deactivateOnMouseMove`), per-container accessibility properties, shadow DOM overlay, mobile touch-hook activation.\n\n**Triggers:** accessibility, a11y, screen reader, ARIA, keyboard navigation, tab order, AccessibilitySystem, accessibleTitle, accessibleHint, tabIndex, accessibleChildren.\n\n### pixijs-blend-modes\nComposite display objects with blend modes. Covers standard modes (`normal`, `add`, `multiply`, `screen`, `erase`, `min`, `max`), advanced modes via `pixi.js/advanced-blend-modes` (`color-burn`, `overlay`, `hard-light`, etc.), batch-friendly ordering.\n\n**Triggers:** blendMode, additive, multiply, screen, overlay, color-burn, color-dodge, advanced-blend-modes, glow, erase.\n\n### pixijs-custom-rendering\nWrite custom shaders, uniforms, or batchers. Covers `Shader.from({gl, gpu, resources})`, `GlProgram`/`GpuProgram`, `UniformGroup` with typed uniforms (`f32`, `vec2`, `mat4x4`), UBO mode, textures as resources, custom `Filter`, custom `Batcher` via extensions.\n\n**Triggers:** Shader, GlProgram, GpuProgram, UniformGroup, Batcher, Filter, GLSL, WGSL, UBO, uniform, custom shader.\n\n### pixijs-filters\nApply visual effects to containers via the filter pipeline. Covers built-in filters (`AlphaFilter`, `BlurFilter`, `ColorMatrixFilter`, `DisplacementFilter`, `NoiseFilter`), custom `Filter.from()` with GLSL/WGSL, options (`resolution`, `padding`, `antialias`, `blendRequired`), `filterArea` optimization, `pixi-filters` community package.\n\n**Triggers:** filters, BlurFilter, ColorMatrixFilter, DisplacementFilter, NoiseFilter, Filter.from, GLSL filter, pixi-filters, filterArea.\n\n### pixijs-performance\nProfile or optimize a PixiJS v8 app for FPS, draw calls, or GPU memory. Covers destroy patterns (`cacheAsTexture(false)`, `releaseGlobalResources`), `GCSystem` and `TextureGCSystem`, `PrepareSystem`, object pooling, batching rules, `BitmapText` for dynamic text, culling (`Culler`, `CullerPlugin`, `cullable`, `cullArea`), resolution/antialias tradeoffs.\n\n**Triggers:** FPS, jank, draw calls, batching, object pool, GCSystem, PrepareSystem, Culler, cacheAsTexture, memory leak, destroy patterns.\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n    \"$schema\": \"https://unpkg.com/@changesets/config@3.0.1/schema.json\",\n    \"changelog\": \"@changesets/cli/changelog\",\n    \"commit\": false,\n    \"fixed\": [],\n    \"linked\": [],\n    \"access\": \"restricted\",\n    \"baseBranch\": \"v2\",\n    \"updateInternalDependencies\": \"patch\",\n    \"ignore\": []\n  }"
  },
  {
    "path": ".codex",
    "content": ""
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - \"*\"\n    paths-ignore:\n      - \"docs/**\"\n  pull_request:\n    branches:\n      - \"*\"\n    paths-ignore:\n      - \"docs/**\"\n\njobs:\n  tests:\n    runs-on: ubuntu-22.04\n    strategy:\n      matrix:\n        node-version: [20]\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n          cache: \"pnpm\"\n      - name: Install dependencies\n        run: pnpm install --no-frozen-lockfile\n      - name: Build\n        run: pnpm build\n      - name: Run Tests\n        run: pnpm test\n\n  deploy:\n    needs: tests\n    runs-on: ubuntu-22.04\n    if: github.ref == 'refs/heads/v2'\n    steps:\n      - uses: actions/checkout@v4\n      - name: Install pnpm\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n      - name: Use Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: \"pnpm\"\n      - name: Install dependencies\n        run: pnpm install --no-frozen-lockfile\n      - name: Build\n        run: pnpm build\n      - name: 📣 Create Release Pull Request or Publish to npm\n        id: changesets\n        uses: changesets/action@v1\n        with:\n          title: \"chore(release): version packages 🦋\"\n          publish: pnpm publish:packages\n          version: pnpm version:packages\n          commit: \"chore(release): version packages 🦋 [skip ci]\"\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}\n      - name: Update Starter Package Versions\n        run: |\n          CORE_VERSION=$(jq -r '.version' packages/core/package.json)\n          jq --arg version \"$CORE_VERSION\" '.dependencies.canvasengine = $version | .devDependencies[\"@canvasengine/compiler\"] = $version' starter/package.json > starter/package.tmp.json\n          mv starter/package.tmp.json starter/package.json\n        shell: bash\n      - name: Commit Changes\n        run: |\n          git add starter/package.json\n          git commit -m \"chore(release): update starter package version to $CORE_VERSION\"\n          git push\n        shell: bash\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\nlib\ncache\n.vitepress/dist\n.vitepress/cache\ncoverage\nsample/public"
  },
  {
    "path": ".npmignore",
    "content": "tests\ntemplate\nsample\npublic\ndocs\n.vitepress\nnode_modules\nstarter\n.github\n.cursorrules\nlogo.png\ncompiler"
  },
  {
    "path": "README.md",
    "content": "# CanvasEngine - A reactive HTML5 Canvas management library built on top of PixiJS and Vite\n\n![CanvasEngine](docs/public/logo.png)\n\nCanvasEngine is a reactive HTML5 Canvas management library built on top of PixiJS and Vite. It provides a component-oriented approach to canvas rendering, similar to modern frontend frameworks.\n\nFeatures:\n- Reactive components\n- Use flex in Canvas !\n- Easy Animation system \n- Keyboard, Gamepad et Virtual Joystick\n- Tiled Map Editor integration\n- Particle Emitter\n- Audio System\n\n## Installation\n\n```bash\nnpx degit RSamaium/CanvasEngine/starter my-project\ncd my-project\nnpm install\nnpm run dev # and go to localhost:5173\n```\n\n## Documentation\n\nhttps://canvasengine.net\n\n## Example:\n\n```html\n<Container flexDirection=\"row\" width={500}>\n    <Sprite \n        image=\"/assets/logo.png\" \n        anchor={0.5}\n        rotation\n        scale\n        pointerenter={onEnter} \n        pointerleave={onLeave}\n    />\n    <Text text size={70} fontFamily=\"Helvetica\" x={90} y={-30} />\n</Container>\n\n<script>\nimport { signal, tick, animatedSignal, Easing } from \"canvasengine\";\n\nconst { text } = defineProps();\nconst rotation = signal(0);\nconst scale = animatedSignal(1, {\n    duration: 300,\n    ease: Easing.easeInOut,\n});\n\ntick(() => {\n    rotation.update(rotation => rotation + 0.01);\n});\n\nconst onEnter = () => {\n    scale.set(1.5);\n};\n\nconst onLeave = () => {\n    scale.set(1);\n};\n</script>\n```\n\n## Contributing\n\nBefore, install `pnpm` and run the following command:\n\n```bash\ngit clone https://github.com/RSamaium/CanvasEngine.git\ncd CanvasEngine\npnpm install\npnpm run dev # to build the libraries\n```\n\nTo run the sample project:\n\n```bash\npnpm run dev:sample\n```\n\n### Build Documentation/Website\n\n```\ncd docs\npnpm install\npnpm run dev\n```\n\n### Release\n\n```bash\npnpm run release\n```\n\n> Choose the version you want to release\n\nPush the release branch to the remote repository\n\n```bash\ngit push origin v2\n```\n\n"
  },
  {
    "path": "__mocks__/pixi-viewport.ts",
    "content": "import { vi } from \"vitest\";\nimport { Viewport as PixiViewport } from 'pixi-viewport';\n\nexport class Viewport extends PixiViewport {\n    drag = vi.fn().mockReturnThis();\n    wheel = vi.fn().mockReturnThis();\n    clamp = vi.fn().mockReturnThis();\n    decelerate = vi.fn().mockReturnThis();\n    pinch = vi.fn().mockReturnThis();\n    on = vi.fn().mockReturnThis();\n    update = vi.fn().mockReturnThis();\n\n    screenWidth = 0;\n    screenHeight = 0;\n    worldWidth = 0;\n    worldHeight = 0;\n    options: any = { events: {} }; // Initialize options\n    input: any = { wheelFunction: vi.fn() }; // Mock input property\n}\n"
  },
  {
    "path": "docs/.vitepress/config.ts",
    "content": "import { defineConfig } from 'vitepress';\nimport llmstxt from 'vitepress-plugin-llms'\n\nconst guideMenu = [\n  {\n    text: \"Quick Start\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Installation\",\n        link: \"/get_started/installation\",\n      },\n      {\n        text: \"Start\",\n        link: \"/get_started/start\",\n      }\n    ],\n  },\n  {\n    text: \"Concepts\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Template Syntax\",\n        link: \"/concepts/template-syntax\",\n      },\n      {\n        text: \"Reactivity\",\n        link: \"/concepts/reactive\",\n      },\n      {\n        text: \"Child Component\",\n        link: \"/concepts/child-component\",\n      },\n      {\n        text: \"Trigger\",\n        link: \"/concepts/trigger\",\n      },\n      {\n        text: \"Lifecycle\",\n        link: \"/concepts/lifecycle\",\n      },\n      {\n        text: \"Dependencies\",\n        link: \"/concepts/dependencies\",\n      },\n      {\n        text: \"Slot\",\n        link: \"/concepts/slot\",\n      },\n      {\n        text: \"Dynamic Components\",\n        link: \"/concepts/dynamic-components\",\n      },\n      {\n        text: \"Primitive Animation\",\n        link: \"/concepts/animation\",\n      },\n      {\n        text: \"Styling\",\n        link: \"/concepts/styling\",\n      }\n    ],\n  },\n  {\n    text: \"Components\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Canvas\",\n        link: \"/components/canvas\",\n      },\n      {\n        text: \"Container\",\n        link: \"/components/container\",\n      },\n      {\n        text: \"Graphics\",\n        link: \"/components/graphic\",\n      },\n      {\n        text: \"Svg\",\n        link: \"/components/svg\",\n      },\n      {\n        text: \"Text\",\n        link: \"/components/text\",\n      },\n      {\n        text: \"Button\",\n        link: \"/components/button\",\n      },\n      {\n        text: \"Sprite\",\n        link: \"/components/sprite\",\n      },\n      {\n        text: \"NineSliceSprite\",\n        link: \"/components/nine-slice-sprite\",\n      },\n      {\n        text: \"Viewport\",\n        link: \"/components/viewport\",\n      },\n      {\n        text: \"TilingSprite\",\n        link: \"/components/tiling-sprite\",\n      },\n      {\n        text: \"Video\",\n        link: \"/components/video\",\n      },\n      {\n        text: \"Mesh\",\n        link: \"/components/mesh\",\n      },\n      {\n        text: \"DOMContainer\",\n        link: \"/components/dom-container\",\n      },\n      {\n        text: \"Navigation\",\n        link: \"/components/navigation\",\n      },\n      {\n        text: \"Joystick\",\n        link: \"/components/joystick\",\n      }\n    ],\n  },\n  {\n    text: \"Directives\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Controls\",\n        link: \"/directives/controls\",\n      },\n      {\n        text: \"Drag\",\n        link: \"/directives/drag\",\n      },\n      {\n        text: \"Sound\",\n        link: \"/directives/sound\",\n      },\n      {\n        text: \"Flash\",\n        link: \"/directives/flash\",\n      },\n      {\n        text: \"Shake\",\n        link: \"/directives/shake\",\n      }\n    ],\n  },\n  {\n    text: \"Presets Components\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Bar\",\n        link: \"/presets/bar\",\n      },\n      {\n        text: \"Loading\",\n        link: \"/presets/loading\",\n      },\n      {\n        text: \"Tilemap\",\n        link: \"/presets/tilemap\",\n      },\n      {\n        text: \"Weather\",\n        link: \"/presets/weather\",\n      },\n      {\n        text: \"NightAmbiant\",\n        link: \"/presets/night-ambiant\",\n      },\n      {\n        text: \"Footprints\",\n        link: \"/presets/footprints\",\n      },\n      {\n        text: \"Fx\",\n        link: \"/presets/fx\",\n      }\n    ],\n  },\n  {\n    text: \"API\",\n    collapsed: false,\n    items: [\n      {\n        text: \"Element Object\",\n        link: \"/api/element\",\n      },\n      {\n        text: \"Context\",\n        link: \"/api/context\",\n      },\n      {\n        text: \"Testing\",\n        link: \"/api/testing\",\n      },\n      {\n        text: \"Use without Compiler\",\n        link: \"/advanced/without-compiler\",\n      }\n    ],\n  },\n];\n\nexport default defineConfig({\n  title: \"Canvas Engine Documentation\",\n  description: \"Reactive Canvas Framework\",\n  ignoreDeadLinks: true,\n  themeConfig: {\n    search: {\n      provider: \"local\",\n    },\n    repo: \"https://github.com/RSamaium/CanvasEngine\",\n    nav: [\n      {\n        text: \"Home\",\n        link: \"https://canvasengine.net\",\n      },\n      {\n        text: \"Guide\",\n        link: \"/guide/get-started\",\n      },\n    ],\n    sidebar: {\n      \"/\": guideMenu,\n      \"/guide/\": guideMenu,\n      \"/components/\": guideMenu,\n      \"/directives/\": guideMenu,\n    },\n  },\n  vite: {\n    plugins: [llmstxt()]\n  },\n})\n"
  },
  {
    "path": "docs/.vitepress/theme/Layout.vue",
    "content": "<template>\n  <Layout v-if=\"!isHome\" />\n  <CustomHome v-else />\n</template>\n\n<script setup>\nimport { computed } from 'vue'\nimport { useData } from 'vitepress'\nimport DefaultTheme from 'vitepress/theme'\nimport CustomHome from './components/CustomHome.vue'\n\nconst { Layout } = DefaultTheme\nconst { page } = useData()\n\nconst isHome = computed(() => page.value.relativePath === 'index.md')\n</script> "
  },
  {
    "path": "docs/.vitepress/theme/components/CustomHome.vue",
    "content": "<template>\n  <div class=\"custom-home\">\n    <!-- Custom Navbar -->\n    <nav class=\"custom-navbar\">\n      <div class=\"navbar-container\">\n        <div class=\"navbar-brand\">\n          \n        </div>\n        <div class=\"navbar-links\">\n          <a href=\"/get_started/installation\" class=\"nav-link\">Documentation</a>\n          <a href=\"https://github.com/RSamaium/CanvasEngine\" target=\"_blank\" class=\"nav-link\">Github</a>\n          <a href=\"https://discord.gg/W38yDyGfwC\" class=\"nav-link\">Discord</a>\n        </div>\n      </div>\n    </nav>\n\n    <!-- Hero Section -->\n    <section class=\"hero\">\n      <div class=\"hero-content\">\n        <div class=\"hero-text\">\n          <h1 class=\"hero-title\">\n            <img src=\"/logo.png\" alt=\"Canvas Engine\" class=\"logo\" />\n          </h1>\n          <p class=\"hero-subtitle\">\n            A reactive HTML5 Canvas management library built on top of PixiJS\n          </p>\n          <p class=\"hero-description\">\n            Component-oriented approach to canvas rendering, similar to modern frontend frameworks.\n            Build interactive games and applications with ease.\n          </p>\n          <div class=\"hero-actions\">\n            <a href=\"/get_started/installation\" class=\"btn btn-primary\">\n              Get Started\n            </a>\n            <a href=\"https://github.com/RSamaium/CanvasEngine\" class=\"btn btn-secondary\" target=\"_blank\">\n              <svg class=\"github-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z\"/>\n              </svg>\n              GitHub\n            </a>\n          </div>\n        </div>\n        <div class=\"hero-visual\">\n          <div class=\"canvas-preview\">\n            <div class=\"canvas-mock\">\n              <div class=\"canvas-element sprite\"></div>\n              <div class=\"canvas-element container\">\n                <div class=\"canvas-element text\">Canvas Engine</div>\n                <div class=\"canvas-element graphic\"></div>\n              </div>\n              <div class=\"canvas-element particle\"></div>\n              <div class=\"canvas-element particle\"></div>\n              <div class=\"canvas-element particle\"></div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n\n    <!-- Features Section -->\n    <section class=\"features\">\n      <div class=\"features-container\">\n        <h2 class=\"section-title\">Why Canvas Engine?</h2>\n        <div class=\"features-grid\">\n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\"/>\n              </svg>\n            </div>\n            <h3>Reactive Components</h3>\n            <p>Build interactive canvas applications with reactive components that automatically update when data changes.</p>\n          </div>\n          \n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <rect x=\"2\" y=\"3\" width=\"20\" height=\"14\" rx=\"2\" ry=\"2\"/>\n                <line x1=\"8\" y1=\"21\" x2=\"16\" y2=\"21\"/>\n                <line x1=\"12\" y1=\"17\" x2=\"12\" y2=\"21\"/>\n              </svg>\n            </div>\n            <h3>Flexbox in Canvas</h3>\n            <p>Use familiar CSS Flexbox layout system directly in your canvas applications for responsive designs.</p>\n          </div>\n          \n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z\"/>\n              </svg>\n            </div>\n            <h3>Easy Animations</h3>\n            <p>Create smooth animations with a simple and intuitive animation system built for performance.</p>\n          </div>\n          \n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <rect x=\"3\" y=\"8\" width=\"18\" height=\"4\" rx=\"1\"/>\n                <path d=\"M12 8v13\"/>\n                <path d=\"M19 12v7a2 2 0 01-2 2H7a2 2 0 01-2-2v-7\"/>\n                <path d=\"M7.5 8a2.5 2.5 0 010-5A4.8 8 0 0112 8a4.8 8 0 014.5-5 2.5 2.5 0 010 5\"/>\n              </svg>\n            </div>\n            <h3>Input Controls</h3>\n            <p>Support for keyboard, gamepad (ready when connected), and virtual joystick controls out of the box.</p>\n          </div>\n          \n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z\"/>\n                <polyline points=\"3.27,6.96 12,12.01 20.73,6.96\"/>\n                <line x1=\"12\" y1=\"22.08\" x2=\"12\" y2=\"12\"/>\n              </svg>\n            </div>\n            <h3>Tiled Map Support</h3>\n            <p>Seamless integration with Tiled Map Editor for creating complex game worlds and levels.</p>\n          </div>\n          \n          <div class=\"feature-card\">\n            <div class=\"feature-icon\">\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M9 18V5l12-2v13\"/>\n                <circle cx=\"6\" cy=\"18\" r=\"3\"/>\n                <circle cx=\"18\" cy=\"16\" r=\"3\"/>\n              </svg>\n            </div>\n            <h3>Audio System</h3>\n            <p>Built-in audio system with particle emitters for creating immersive gaming experiences.</p>\n          </div>\n        </div>\n      </div>\n    </section>\n\n    <!-- Examples Section -->\n    <section class=\"examples\">\n      <div class=\"examples-container\">\n        <h2 class=\"section-title\">Interactive Examples</h2>\n        <p class=\"section-description\">Try these examples directly in your browser</p>\n        \n        <div class=\"examples-grid\">\n          <div v-for=\"example in examples\" :key=\"example.title\" class=\"example-item\">\n            <Playground \n              :title=\"example.title\"\n              :description=\"example.description\"\n              :files=\"example.files\" \n            />\n          </div>\n        </div>\n      </div>\n    </section>\n\n  </div>\n</template>\n\n<script setup>\nimport Playground from './Playground.vue'\nimport examples from './example'\n</script>\n\n<style scoped>\n.custom-home {\n  --primary-color: #646cff;\n  --primary-color-light: #747bff;\n  --secondary-color: #42b883;\n  --text-color: #213547;\n  --text-color-light: #64748b;\n  --bg-color: #ffffff;\n  --border-color: #e2e8f0;\n  --card-bg: #f8fafc;\n}\n\n.dark .custom-home {\n  --text-color: #f1f5f9;\n  --text-color-light: #94a3b8;\n  --bg-color: #0f172a;\n  --border-color: #334155;\n  --card-bg: #1e293b;\n}\n\n/* Custom Navbar */\n.custom-navbar {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  z-index: 1000;\n  background: rgba(255, 255, 255, 0.95);\n  backdrop-filter: blur(10px);\n  border-bottom: 1px solid var(--border-color);\n  padding: 1rem 0;\n}\n\n.dark .custom-navbar {\n  background: rgba(15, 23, 42, 0.95);\n}\n\n.navbar-container {\n  max-width: 1200px;\n  margin: 0 auto;\n  padding: 0 2rem;\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n}\n\n.brand-text {\n  font-size: 1.5rem;\n  font-weight: 700;\n  background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n  background-clip: text;\n}\n\n.navbar-links {\n  display: flex;\n  gap: 2rem;\n}\n\n.nav-link {\n  color: var(--text-color);\n  text-decoration: none;\n  font-weight: 500;\n  transition: color 0.2s;\n  position: relative;\n}\n\n.nav-link:hover {\n  color: var(--primary-color);\n}\n\n.nav-link::after {\n  content: '';\n  position: absolute;\n  bottom: -4px;\n  left: 0;\n  width: 0;\n  height: 2px;\n  background: var(--primary-color);\n  transition: width 0.2s;\n}\n\n.nav-link:hover::after {\n  width: 100%;\n}\n\n/* Hero Section */\n.hero {\n  background: linear-gradient(135deg, var(--bg-color) 0%, #f1f5f9 100%);\n  padding: 8rem 2rem 4rem;\n  min-height: 70vh;\n  display: flex;\n  align-items: center;\n}\n\n.dark .hero {\n  background: linear-gradient(135deg, var(--bg-color) 0%, #1e293b 100%);\n}\n\n.hero-content {\n  max-width: 1200px;\n  margin: 0 auto;\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 4rem;\n  align-items: center;\n}\n\n.hero-title {\n  font-size: 3.5rem;\n  font-weight: 800;\n  line-height: 1.1;\n  margin-bottom: 1.5rem;\n}\n\n.gradient-text {\n  background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n  background-clip: text;\n}\n\n.hero-subtitle {\n  font-size: 1.5rem;\n  color: var(--text-color);\n  margin-bottom: 1rem;\n  font-weight: 600;\n}\n\n.hero-description {\n  font-size: 1.1rem;\n  color: var(--text-color-light);\n  line-height: 1.6;\n  margin-bottom: 2rem;\n}\n\n.hero-actions {\n  display: flex;\n  gap: 1rem;\n  flex-wrap: wrap;\n}\n\n.btn {\n  display: inline-flex;\n  align-items: center;\n  gap: 0.5rem;\n  padding: 0.75rem 1.5rem;\n  border-radius: 0.5rem;\n  font-weight: 600;\n  text-decoration: none;\n  transition: all 0.2s;\n  border: 2px solid transparent;\n}\n\n.btn-primary {\n  background: var(--primary-color);\n  color: white;\n}\n\n.btn-primary:hover {\n  background: var(--primary-color-light);\n  transform: translateY(-2px);\n  box-shadow: 0 8px 25px rgba(100, 108, 255, 0.3);\n}\n\n.btn-secondary {\n  background: var(--card-bg);\n  color: var(--text-color);\n  border-color: var(--border-color);\n}\n\n.btn-secondary:hover {\n  border-color: var(--primary-color);\n  transform: translateY(-2px);\n  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);\n}\n\n.btn-outline {\n  background: transparent;\n  color: var(--primary-color);\n  border-color: var(--primary-color);\n}\n\n.btn-outline:hover {\n  background: var(--primary-color);\n  color: white;\n  transform: translateY(-2px);\n}\n\n.btn-large {\n  padding: 1rem 2rem;\n  font-size: 1.1rem;\n}\n\n.github-icon {\n  width: 1.2rem;\n  height: 1.2rem;\n}\n\n/* Canvas Preview */\n.canvas-preview {\n  perspective: 1000px;\n}\n\n.canvas-mock {\n  width: 400px;\n  height: 300px;\n  background: #1a1a1a;\n  border-radius: 1rem;\n  position: relative;\n  overflow: hidden;\n  transform: rotateY(-15deg) rotateX(5deg);\n  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n  animation: float 6s ease-in-out infinite;\n}\n\n.canvas-element {\n  position: absolute;\n  border-radius: 0.5rem;\n}\n\n.sprite {\n  width: 60px;\n  height: 60px;\n  background: linear-gradient(45deg, #ff6b6b, #feca57);\n  top: 50px;\n  left: 50px;\n  animation: bounce 2s ease-in-out infinite;\n}\n\n.container {\n  width: 200px;\n  height: 100px;\n  border: 2px dashed #646cff;\n  top: 100px;\n  left: 150px;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n.text {\n  color: white;\n  font-size: 14px;\n  font-weight: bold;\n  position: static;\n  margin-bottom: 10px;\n}\n\n.graphic {\n  width: 40px;\n  height: 40px;\n  background: #42b883;\n  position: static;\n  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);\n}\n\n.particle {\n  width: 6px;\n  height: 6px;\n  background: #feca57;\n  border-radius: 50%;\n  animation: particle 3s linear infinite;\n}\n\n.particle:nth-child(4) {\n  top: 200px;\n  left: 100px;\n  animation-delay: 0s;\n}\n\n.particle:nth-child(5) {\n  top: 180px;\n  left: 120px;\n  animation-delay: 1s;\n}\n\n.particle:nth-child(6) {\n  top: 220px;\n  left: 80px;\n  animation-delay: 2s;\n}\n\n@keyframes float {\n  0%, 100% { transform: rotateY(-15deg) rotateX(5deg) translateY(0px); }\n  50% { transform: rotateY(-15deg) rotateX(5deg) translateY(-20px); }\n}\n\n@keyframes bounce {\n  0%, 100% { transform: translateY(0px); }\n  50% { transform: translateY(-10px); }\n}\n\n@keyframes particle {\n  0% { opacity: 1; transform: translateY(0px) scale(1); }\n  100% { opacity: 0; transform: translateY(-50px) scale(0.5); }\n}\n\n/* Features Section */\n.features {\n  padding: 6rem 2rem;\n  background: var(--card-bg);\n}\n\n.features-container {\n  max-width: 1400px;\n  margin: 0 auto;\n}\n\n.section-title {\n  text-align: center;\n  font-size: 2.5rem;\n  font-weight: 700;\n  color: var(--text-color);\n  margin-bottom: 4rem;\n}\n\n.features-grid {\n  display: grid;\n  grid-template-columns: repeat(3, 1fr);\n  gap: 2.5rem;\n  align-items: start;\n}\n\n.feature-card {\n  background: var(--bg-color);\n  padding: 2.5rem;\n  border-radius: 1rem;\n  border: 1px solid var(--border-color);\n  transition: all 0.3s ease;\n  height: 100%;\n  display: flex;\n  flex-direction: column;\n}\n\n.feature-card:hover {\n  transform: translateY(-8px);\n  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);\n  border-color: var(--primary-color);\n}\n\n.dark .feature-card:hover {\n  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);\n}\n\n.feature-icon {\n  width: 4rem;\n  height: 4rem;\n  background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n  border-radius: 1rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  margin-bottom: 1.5rem;\n  flex-shrink: 0;\n}\n\n.feature-icon svg {\n  width: 2rem;\n  height: 2rem;\n  color: white;\n}\n\n.feature-card h3 {\n  font-size: 1.4rem;\n  font-weight: 600;\n  color: var(--text-color);\n  margin-bottom: 1rem;\n  line-height: 1.3;\n}\n\n.feature-card p {\n  color: var(--text-color-light);\n  line-height: 1.6;\n  font-size: 1rem;\n  flex-grow: 1;\n}\n\n/* Examples Section */\n.examples {\n  padding: 6rem 2rem;\n  background: var(--bg-color);\n}\n\n.examples-container {\n  max-width: 1400px;\n  margin: 0 auto;\n}\n\n.section-description {\n  text-align: center;\n  font-size: 1.2rem;\n  color: var(--text-color-light);\n  margin-bottom: 4rem;\n  max-width: 600px;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n.examples-grid {\n  display: flex;\n  flex-direction: column;\n  gap: 4rem;\n}\n\n.example-item {\n  width: 100%;\n}\n\n/* Code Example Section */\n.code-example {\n  padding: 6rem 2rem;\n  background: var(--bg-color);\n}\n\n.code-showcase {\n  display: grid;\n  grid-template-columns: 1fr 1fr;\n  gap: 4rem;\n  align-items: center;\n  max-width: 1000px;\n  margin: 0 auto;\n}\n\n.code-block {\n  background: #1e293b;\n  border-radius: 1rem;\n  padding: 2rem;\n  overflow-x: auto;\n  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);\n}\n\n.code-block pre {\n  margin: 0;\n  color: #e2e8f0;\n  font-family: 'Fira Code', monospace;\n  font-size: 0.9rem;\n  line-height: 1.6;\n}\n\n.code-description h3 {\n  font-size: 1.5rem;\n  font-weight: 600;\n  color: var(--text-color);\n  margin-bottom: 1rem;\n}\n\n.code-description p {\n  color: var(--text-color-light);\n  line-height: 1.6;\n  font-size: 1.1rem;\n}\n\n/* CTA Section */\n.cta {\n  padding: 6rem 2rem;\n  background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));\n  text-align: center;\n}\n\n.cta-content h2 {\n  font-size: 2.5rem;\n  font-weight: 700;\n  color: white;\n  margin-bottom: 1rem;\n}\n\n.cta-content p {\n  font-size: 1.2rem;\n  color: rgba(255, 255, 255, 0.9);\n  margin-bottom: 2rem;\n  max-width: 600px;\n  margin-left: auto;\n  margin-right: auto;\n}\n\n.cta-actions {\n  display: flex;\n  gap: 1rem;\n  justify-content: center;\n  flex-wrap: wrap;\n}\n\n.cta .btn-primary {\n  background: white;\n  color: var(--primary-color);\n}\n\n.cta .btn-primary:hover {\n  background: #f1f5f9;\n  transform: translateY(-2px);\n  box-shadow: 0 8px 25px rgba(255, 255, 255, 0.3);\n}\n\n.cta .btn-outline {\n  background: transparent;\n  color: white;\n  border-color: white;\n}\n\n.cta .btn-outline:hover {\n  background: white;\n  color: var(--primary-color);\n  transform: translateY(-2px);\n}\n\n/* Responsive Design */\n@media (max-width: 1024px) {\n  .features-grid {\n    grid-template-columns: repeat(2, 1fr);\n    gap: 2rem;\n  }\n}\n\n@media (max-width: 768px) {\n  .navbar-container {\n    padding: 0 1rem;\n  }\n  \n  .navbar-links {\n    gap: 1rem;\n  }\n  \n  .hero {\n    padding: 6rem 1rem 4rem;\n  }\n  \n  .hero-content {\n    grid-template-columns: 1fr;\n    text-align: center;\n    gap: 3rem;\n  }\n  \n  .hero-title {\n    font-size: 2.5rem;\n  }\n  \n  .canvas-mock {\n    width: 300px;\n    height: 225px;\n    transform: none;\n  }\n  \n  .code-showcase {\n    grid-template-columns: 1fr;\n  }\n  \n  .features-grid {\n    grid-template-columns: 1fr;\n    gap: 1.5rem;\n  }\n  \n  .feature-card {\n    padding: 2rem;\n  }\n  \n  .section-title {\n    font-size: 2rem;\n  }\n  \n  .cta-content h2 {\n    font-size: 2rem;\n  }\n  \n  .cta-actions {\n    flex-direction: column;\n    align-items: center;\n  }\n  \n  .btn-large {\n    width: 100%;\n    max-width: 300px;\n  }\n}\n\n@media (max-width: 480px) {\n  .navbar-links {\n    gap: 0.5rem;\n  }\n  \n  .nav-link {\n    font-size: 0.9rem;\n  }\n  \n  .hero {\n    padding: 5rem 1rem 3rem;\n  }\n  \n  .hero-title {\n    font-size: 2rem;\n  }\n  \n  .hero-subtitle {\n    font-size: 1.2rem;\n  }\n  \n  .features {\n    padding: 4rem 1rem;\n  }\n  \n  .code-example {\n    padding: 4rem 1rem;\n  }\n  \n  .cta {\n    padding: 4rem 1rem;\n  }\n}\n</style> "
  },
  {
    "path": "docs/.vitepress/theme/components/Playground.vue",
    "content": "<template>\n  <div class=\"playground-container\" ref=\"playgroundContainer\" :class=\"{ 'fullscreen': isFullscreen }\">\n    <div class=\"playground-header\" v-if=\"title || description\">\n      <div class=\"header-content\">\n        <h3 v-if=\"title\">{{ title }}</h3>\n        <p v-if=\"description\" class=\"playground-description\">{{ description }}</p>\n      </div>\n      <div class=\"header-controls\">\n        <!-- View Mode Buttons -->\n        <div class=\"view-mode-controls\">\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'code' }]\"\n            @click=\"setViewMode('code')\"\n            title=\"Show code only\"\n          >\n            <span class=\"icon\">📝</span>\n            Code\n          </button>\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'preview' }]\"\n            @click=\"setViewMode('preview')\"\n            title=\"Show preview only\"\n          >\n            <span class=\"icon\">👁️</span>\n            Preview\n          </button>\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'both' }]\"\n            @click=\"setViewMode('both')\"\n            title=\"Show both code and preview\"\n          >\n            <span class=\"icon\">⚡</span>\n            Both\n          </button>\n        </div>\n        \n        <!-- Fullscreen Button -->\n        <button \n          class=\"fullscreen-btn\"\n          @click=\"toggleFullscreen\"\n          :title=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n        >\n          <span class=\"icon\">{{ isFullscreen ? '🗗' : '⛶' }}</span>\n        </button>\n      </div>\n    </div>\n    \n    <!-- Simplified header when no title/description but need controls -->\n    <div class=\"playground-controls-only\" v-else>\n      <div class=\"header-controls\">\n        <!-- View Mode Buttons -->\n        <div class=\"view-mode-controls\">\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'code' }]\"\n            @click=\"setViewMode('code')\"\n            title=\"Show code only\"\n          >\n            <span class=\"icon\">📝</span>\n            Code\n          </button>\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'preview' }]\"\n            @click=\"setViewMode('preview')\"\n            title=\"Show preview only\"\n          >\n            <span class=\"icon\">👁️</span>\n            Preview\n          </button>\n          <button \n            :class=\"['view-mode-btn', { active: viewMode === 'both' }]\"\n            @click=\"setViewMode('both')\"\n            title=\"Show both code and preview\"\n          >\n            <span class=\"icon\">⚡</span>\n            Both\n          </button>\n        </div>\n        \n        <!-- Fullscreen Button -->\n        <button \n          class=\"fullscreen-btn\"\n          @click=\"toggleFullscreen\"\n          :title=\"isFullscreen ? 'Exit fullscreen' : 'Enter fullscreen'\"\n        >\n          <span class=\"icon\">{{ isFullscreen ? '🗗' : '⛶' }}</span>\n        </button>\n      </div>\n    </div>\n    \n    <div class=\"playground-content\" :class=\"`view-mode-${viewMode}`\">\n      <!-- Code Editor with CodeMirror -->\n      <div class=\"code-editor\" v-show=\"viewMode === 'code' || viewMode === 'both'\">\n        <div class=\"editor-header\">\n          <div class=\"tabs\">\n            <button \n              v-for=\"file in fileList\" \n              :key=\"file.name\"\n              :class=\"['tab', { active: activeFile === file.name }]\"\n              @click=\"setActiveFile(file.name)\"\n            >\n              {{ file.name }}\n            </button>\n          </div>\n        </div>\n        \n        <div class=\"editor-content\">\n          <div ref=\"editorContainer\" class=\"codemirror-container\"></div>\n        </div>\n      </div>\n      \n      <!-- Preview Panel -->\n      <div class=\"preview-panel\" v-show=\"viewMode === 'preview' || viewMode === 'both'\">\n        <div class=\"preview-header\">\n          <span>Preview</span>\n        </div>\n        \n        <div class=\"preview-content\">\n          <div v-if=\"error\" class=\"error-display\">\n            <div class=\"error-header\">\n              <i class=\"error-icon\">⚠️</i>\n              <strong>Error</strong>\n            </div>\n            <pre class=\"error-message\">{{ error }}</pre>\n          </div>\n          \n          <div v-else ref=\"canvasContainer\" class=\"canvas-container\"></div>\n        </div>\n        \n        <!-- Console Accordion -->\n        <div class=\"console-accordion\">\n          <button \n            class=\"console-toggle\" \n            @click=\"consoleOpen = !consoleOpen\"\n            :class=\"{ active: consoleOpen }\"\n          >\n            <span>Console</span>\n            <span class=\"console-badge\" v-if=\"logs.length > 0\">{{ logs.length }}</span>\n            <span class=\"toggle-icon\" :class=\"{ rotated: consoleOpen }\">▼</span>\n          </button>\n          \n          <div ref=\"consoleContent\" class=\"console-content\" v-show=\"consoleOpen\">\n            <div v-if=\"logs.length === 0\" class=\"console-empty\">\n              No console output\n            </div>\n            <div v-else>\n              <div v-for=\"(log, index) in logs\" :key=\"index\" class=\"console-line\">\n                <span class=\"console-timestamp\">{{ log.timestamp }}</span>\n                <span class=\"console-message\" :class=\"log.type\">{{ log.message }}</span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n    \n    <!-- Fullscreen overlay backdrop -->\n    <div v-if=\"isFullscreen\" class=\"fullscreen-backdrop\" @click=\"exitFullscreen\"></div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, nextTick, watch, onUnmounted } from 'vue'\nimport { EditorView, basicSetup } from 'codemirror'\nimport { html } from '@codemirror/lang-html'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { EditorState, Compartment } from '@codemirror/state'\nimport pkg from \"peggy\"\nimport { dependencyConfig, CORE_FUNCTIONS, PRIMITIVE_COMPONENTS } from './config'\n\nconst { generate } = pkg\n\n/**\n * Enhanced Playground component for CanvasEngine with CodeMirror\n * \n * Features:\n * - CodeMirror editor with syntax highlighting\n * - View mode controls (Code, Preview, Both)\n * - Fullscreen mode\n * - Accordion console\n * - Auto-reload on code changes\n * - Error display in preview\n * - Automatic WebGL context management (destroys when out of viewport)\n * \n * The component automatically monitors its visibility using Intersection Observer\n * and destroys the WebGL context when the playground is not visible to prevent\n * the \"Too many active WebGL contexts\" warning. It recreates the context when\n * the playground becomes visible again.\n * \n * @example\n * ```vue\n * <Playground\n *   title=\"Basic Canvas Example\"\n *   description=\"A simple canvas with a red rectangle\"\n *   :files=\"{\n *     'app.ce': '<Canvas><Rect color=\"red\" width={100} height={100} /></Canvas>'\n *   }\"\n *   defaultViewMode=\"both\"\n * />\n * ```\n */\n\ninterface PlaygroundProps {\n  /** Title of the playground example */\n  title?: string\n  /** Description of what the example demonstrates */\n  description?: string\n  /** Custom files to include in the editor */\n  files?: Record<string, string>\n  /** Height of the playground */\n  height?: number\n  /** Default view mode: 'code', 'preview', or 'both' */\n  defaultViewMode?: 'code' | 'preview' | 'both'\n}\n\ninterface PlaygroundFile {\n  name: string\n  content: string\n  language: string\n}\n\ninterface ConsoleLog {\n  timestamp: string\n  message: string\n  type: 'log' | 'error' | 'warn' | 'info'\n}\n\nconst props = withDefaults(defineProps<PlaygroundProps>(), {\n  height: 600,\n  files: () => ({}),\n  defaultViewMode: 'both'\n})\n\n// Reactive state\nconst editorContainer = ref<HTMLDivElement>()\nconst canvasContainer = ref<HTMLDivElement>()\nconst consoleContent = ref<HTMLDivElement>()\nconst activeFile = ref('app.ce')\nconst error = ref('')\nconst logs = ref<ConsoleLog[]>([])\nconst consoleOpen = ref(false)\nconst viewMode = ref<'code' | 'preview' | 'both'>(props.defaultViewMode)\nconst isFullscreen = ref(false)\nlet currentApp: any = null\nlet editorView: EditorView | null = null\nlet parser: any = null\nlet isConsoleScrollAtBottom = ref(true)\nlet consoleScrollContainer: HTMLElement | null = null\nlet messageListener: ((event: MessageEvent) => void) | null = null\n// Unique identifier for this playground instance\nconst playgroundId = ref(`playground-${Math.random().toString(36).substr(2, 9)}-${Date.now()}`)\n\n// Intersection Observer for viewport detection\nlet intersectionObserver: IntersectionObserver | null = null\nconst isInViewport = ref(true)\nconst playgroundContainer = ref<HTMLDivElement>()\n\n/**\n * Set view mode and update layout\n */\nconst setViewMode = (mode: 'code' | 'preview' | 'both') => {\n  viewMode.value = mode\n  \n  // Trigger editor resize after view mode change\n  nextTick(() => {\n    if (editorView) {\n      editorView.requestMeasure()\n    }\n  })\n}\n\n/**\n * Toggle fullscreen mode\n */\nconst toggleFullscreen = () => {\n  isFullscreen.value = !isFullscreen.value\n  \n  if (isFullscreen.value) {\n    // Add fullscreen class to body to prevent scrolling\n    document.body.classList.add('playground-fullscreen-active')\n    \n    // Add escape key listener\n    document.addEventListener('keydown', handleEscapeKey)\n  } else {\n    exitFullscreen()\n  }\n  \n  // Trigger editor resize after fullscreen change\n  nextTick(() => {\n    if (editorView) {\n      editorView.requestMeasure()\n    }\n  })\n}\n\n/**\n * Exit fullscreen mode\n */\nconst exitFullscreen = () => {\n  isFullscreen.value = false\n  document.body.classList.remove('playground-fullscreen-active')\n  document.removeEventListener('keydown', handleEscapeKey)\n  \n  // Trigger editor resize after exiting fullscreen\n  nextTick(() => {\n    if (editorView) {\n      editorView.requestMeasure()\n    }\n  })\n}\n\n/**\n * Handle escape key to exit fullscreen\n */\nconst handleEscapeKey = (event: KeyboardEvent) => {\n  if (event.key === 'Escape' && isFullscreen.value) {\n    exitFullscreen()\n  }\n}\n\n/**\n * Initialize viewport intersection observer to destroy playground when not visible\n * This prevents accumulation of WebGL contexts that cause the \"Too many active WebGL contexts\" warning\n */\nconst initViewportObserver = () => {\n  if (!playgroundContainer.value) return\n  \n  intersectionObserver = new IntersectionObserver(\n    (entries) => {\n      entries.forEach((entry) => {\n        const wasInViewport = isInViewport.value\n        isInViewport.value = entry.isIntersecting\n        \n        // If playground was visible and is now not visible, destroy it\n        if (wasInViewport && !isInViewport.value) {\n          addLog('Playground moved out of viewport, destroying to free WebGL context', 'info')\n          clearPreview()\n        }\n        // If playground becomes visible again, recreate it\n        else if (!wasInViewport && isInViewport.value) {\n          addLog('Playground back in viewport, recreating', 'info')\n          // Small delay to ensure DOM is ready\n          setTimeout(() => {\n            runCode()\n          }, 100)\n        }\n      })\n    },\n    {\n      // Trigger when 10% of the playground is visible/hidden\n      threshold: 0.1,\n      // Add some margin to trigger slightly before/after entering viewport\n      rootMargin: '50px'\n    }\n  )\n  \n  intersectionObserver.observe(playgroundContainer.value)\n}\n\n/**\n * Cleanup viewport observer\n */\nconst cleanupViewportObserver = () => {\n  if (intersectionObserver) {\n    intersectionObserver.disconnect()\n    intersectionObserver = null\n  }\n}\n\n/**\n * Check if console scroll is at bottom\n */\nconst checkConsoleScrollPosition = () => {\n  if (consoleScrollContainer) {\n    const threshold = 5 // pixels threshold\n    const isAtBottom = (consoleScrollContainer as HTMLElement).scrollTop + (consoleScrollContainer as HTMLElement).clientHeight >= (consoleScrollContainer as HTMLElement).scrollHeight - threshold\n    isConsoleScrollAtBottom.value = isAtBottom\n  }\n}\n\n/**\n * Scroll console to bottom if needed\n */\nconst scrollConsoleToBottomIfNeeded = () => {\n  if (isConsoleScrollAtBottom.value && consoleScrollContainer) {\n    nextTick(() => {\n      (consoleScrollContainer as HTMLElement).scrollTop = (consoleScrollContainer as HTMLElement).scrollHeight\n    })\n  }\n}\n\n/**\n * Initialize console scroll tracking\n */\nconst initConsoleScroll = () => {\n  nextTick(() => {\n    if (consoleContent.value) {\n      consoleScrollContainer = consoleContent.value\n      \n      // Add scroll event listener\n      consoleScrollContainer.addEventListener('scroll', checkConsoleScrollPosition)\n      \n      // Initial scroll position check\n      checkConsoleScrollPosition()\n    }\n  })\n}\n\n/**\n * Add log to console\n */\nconst addLog = (message: string, type: ConsoleLog['type'] = 'log') => {\n  const timestamp = new Date().toLocaleTimeString()\n  logs.value.push({ timestamp, message, type })\n  scrollConsoleToBottomIfNeeded()\n}\n\n/**\n * Initialize the PEG.js parser with CanvasEngine grammar\n */\nconst initParser = async () => {\n  try {\n    // Load the grammar from the compiler package\n    const response = await fetch('/grammar.pegjs')\n    const grammar = await response.text()\n    parser = generate(grammar)\n    addLog('Parser initialized successfully', 'info')\n  } catch (err: any) {\n    addLog(`Failed to initialize parser: ${err.message}`, 'error')\n    console.error('Parser initialization error:', err)\n  }\n}\n\n/**\n * Format a syntax error message with visual pointer to the error location\n * Similar to the function in packages/compiler/index.ts\n */\nconst showErrorMessage = (template: string, error: any): string => {\n  if (!error.location) {\n    return `Syntax error: ${error.message}`;\n  }\n\n  const lines = template.split('\\n');\n  const { line, column } = error.location.start;\n  const errorLine = lines[line - 1] || '';\n  \n  // Create a visual pointer with an arrow\n  const pointer = ' '.repeat(column - 1) + '^';\n  \n  return `Syntax error at line ${line}, column ${column}: ${error.message}\\n\\n` +\n         `${errorLine}\\n${pointer}\\n`;\n}\n\n/**\n * Default files for the playground\n */\nconst defaultFiles: Record<string, PlaygroundFile> = {\n  'app.ce': {\n    name: 'app.ce',\n    content: ``,\n    language: 'html'\n  }\n}\n\n/**\n * Merge default files with user-provided files\n */\nconst allFiles = computed(() => {\n  const result: Record<string, PlaygroundFile> = { ...defaultFiles }\n  \n  if (props.files) {\n    Object.entries(props.files).forEach(([fileName, content]) => {\n      result[fileName] = {\n        name: fileName,\n        content,\n        language: fileName.endsWith('.ce') ? 'html' : fileName.endsWith('.ts') ? 'typescript' : 'javascript'\n      }\n    })\n  }\n  \n  return result\n})\n\n/**\n * List of files for the tab interface\n */\nconst fileList = computed(() => Object.values(allFiles.value))\n\n/**\n * Set the active file and update editor\n */\nconst setActiveFile = (fileName: string) => {\n  if (activeFile.value === fileName) return\n  \n  // Save current file content\n  if (editorView && allFiles.value[activeFile.value]) {\n    allFiles.value[activeFile.value].content = editorView.state.doc.toString()\n  }\n  \n  activeFile.value = fileName\n  updateEditor()\n}\n\n/**\n * Update CodeMirror editor content and language\n */\nconst updateEditor = () => {\n  if (!editorView || !editorContainer.value) return\n  \n  const currentFile = allFiles.value[activeFile.value]\n  if (!currentFile) return\n  \n  // Destroy current editor and recreate with new language\n  editorView.destroy()\n  \n  const extensions = [\n    basicSetup,\n    getLanguageExtension(activeFile.value),\n    oneDark,\n    EditorView.updateListener.of((update) => {\n      if (update.docChanged) {\n        // Update file content\n        allFiles.value[activeFile.value].content = update.state.doc.toString()\n        \n        // Auto-reload preview with debounce\n        clearTimeout(autoReloadTimeout)\n        autoReloadTimeout = setTimeout(() => {\n          runCode()\n        }, 500)\n      }\n    }),\n    EditorView.theme({\n      '&': {\n        fontSize: '14px',\n        height: '100%',\n      },\n      '.cm-content': {\n        padding: '16px',\n        minHeight: '100%'\n      },\n      '.cm-editor': {\n        height: '100%',\n      },\n      '.cm-scroller': {\n        fontFamily: \"'Monaco', 'Menlo', 'Ubuntu Mono', monospace\"\n      }\n    })\n  ]\n  \n  const state = EditorState.create({\n    doc: currentFile.content,\n    extensions\n  })\n  \n  editorView = new EditorView({\n    state,\n    parent: editorContainer.value\n  })\n}\n\n/**\n * Get language extension based on file type\n */\nconst getLanguageExtension = (fileName: string) => {\n  if (fileName.endsWith('.js')) {\n    return javascript()\n  } else if (fileName.endsWith('.ts')) {\n    return javascript({ typescript: true })\n  } else if (fileName.endsWith('.ce')) {\n    return html()\n  } else {\n    return html() // Default fallback\n  }\n}\n\n/**\n * Initialize CodeMirror editor\n */\nconst initEditor = () => {\n  if (!editorContainer.value) return\n  \n  const currentFile = allFiles.value[activeFile.value]\n  if (!currentFile) return\n  \n  const extensions = [\n    basicSetup,\n    getLanguageExtension(activeFile.value),\n    oneDark,\n    EditorView.updateListener.of((update) => {\n      if (update.docChanged) {\n        // Update file content\n        allFiles.value[activeFile.value].content = update.state.doc.toString()\n        \n        // Auto-reload preview with debounce\n        clearTimeout(autoReloadTimeout)\n        autoReloadTimeout = setTimeout(() => {\n          runCode()\n        }, 500)\n      }\n    }),\n    EditorView.theme({\n      '&': {\n        fontSize: '14px',\n        height: '100%',\n      },\n      '.cm-content': {\n        padding: '16px',\n        minHeight: '100%'\n      },\n      '.cm-editor': {\n        height: '100%',\n      },\n      '.cm-scroller': {\n        fontFamily: \"'Monaco', 'Menlo', 'Ubuntu Mono', monospace\"\n      }\n    })\n  ]\n  \n  const state = EditorState.create({\n    doc: currentFile.content,\n    extensions\n  })\n  \n  editorView = new EditorView({\n    state,\n    parent: editorContainer.value\n  })\n}\n\n/**\n * Clear the preview and reset state\n */\nconst clearPreview = () => {\n  error.value = ''\n  logs.value = []\n  \n  // Clean up message listener\n  if (messageListener) {\n    window.removeEventListener('message', messageListener)\n    messageListener = null\n  }\n  \n  if (currentApp) {\n    try {\n      // Destroy PIXI application properly to free WebGL context\n      if (currentApp.destroy) {\n        currentApp.destroy(true, { children: true, texture: true, baseTexture: true })\n      }\n    } catch (e) {\n      console.warn('Error destroying app:', e)\n    }\n    currentApp = null\n  }\n  \n  if (canvasContainer.value) {\n    // Remove all child elements including iframes\n    while (canvasContainer.value.firstChild) {\n      const child = canvasContainer.value.firstChild\n      // If it's an iframe, ensure proper cleanup\n      if (child instanceof HTMLIFrameElement) {\n        try {\n          // Try to destroy any PIXI apps in the iframe\n          const iframeWindow = child.contentWindow\n          if (iframeWindow && (iframeWindow as any).PIXI) {\n            const pixiApps = (iframeWindow as any).PIXI.Application?.instances || []\n            pixiApps.forEach((app: any) => {\n              try {\n                app.destroy(true, { children: true, texture: true, baseTexture: true })\n              } catch (e) {\n                console.warn('Error destroying iframe PIXI app:', e)\n              }\n            })\n          }\n        } catch (e) {\n          // Cross-origin or other access issues, ignore\n        }\n      }\n      canvasContainer.value.removeChild(child)\n    }\n  }\n}\n\n\n/**\n * Generate HTML content for the iframe sandbox\n * Creates a complete HTML page with CanvasEngine imports and bootstrap code\n */\nconst generateIframeContent = (componentFunction: string, dependencies: Set<string> = new Set(), scopedStyle: string = ''): string => {\n\n  // Generate script tags for dependencies\n  const dependencyScripts = Array.from(dependencies)\n    .map(dep => dependencyConfig[dep])\n    .filter(config => config && config.url)\n    .map(config => `<script src=\"${config.url}\"><\\/script>`)\n    .join('\\n    ')\n\n  // Generate core functions extraction code\n  const coreExtractionCode = CORE_FUNCTIONS.map(func => \n    `if (!CanvasEngine.${func}) throw new Error(\"${func} function not found in CanvasEngine\");\n                coreExports.${func} = CanvasEngine.${func};`\n  ).join('\\n                ')\n\n  // Generate component extraction code\n  const componentExtractionCode = PRIMITIVE_COMPONENTS.map(comp => \n    `if (CanvasEngine.${comp}) componentExports.${comp} = CanvasEngine.${comp};`\n  ).join('\\n                ')\n\n  return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>CanvasEngine Playground</title>\n    <script src=\"https://cdn.jsdelivr.net/npm/pixi.js@latest/dist/pixi.min.js\"><\\/script>\n    <style>\n        body { overflow: hidden; margin: 0; padding: 0; font-family: Arial, sans-serif; background: #f5f5f5; display: flex; justify-content: center; align-items: center; min-height: 100vh; }\n        #root { width: 100%; height: 100%; min-height: 400px; }\n        .error { \n            color: #dc2626; \n            background: #fef2f2; \n            border: 1px solid #fecaca; \n            border-radius: 8px; \n            padding: 16px; \n            margin: 16px; \n            font-family: monospace; \n            white-space: pre-wrap; \n            line-height: 1.4;\n            max-height: 80vh;\n            overflow-y: auto;\n        }\n        .error strong { \n            color: #b91c1c; \n            font-weight: 600; \n        }\n        .error details { \n            margin-top: 12px; \n            cursor: pointer; \n        }\n        .error summary { \n            color: #b91c1c; \n            font-weight: 500; \n            padding: 4px 0;\n            user-select: none;\n        }\n        .error summary:hover { \n            background: rgba(220, 38, 38, 0.1); \n            border-radius: 4px;\n            padding: 4px 8px;\n        }\n        .error pre { \n            background: #fff; \n            border: 1px solid #fecaca; \n            border-radius: 4px; \n            padding: 8px; \n            margin: 8px 0; \n            font-size: 11px; \n            white-space: pre-wrap; \n            overflow-x: auto;\n            max-height: 200px;\n            overflow-y: auto;\n        }\n        .loading { text-align: center; padding: 20px; color: #666; }\n    </style>\n    <style id=\"playground-scoped-style\">${scopedStyle}</style>\n</head>\n<body>\n    <div id=\"root\"></div>\n\n    ${dependencyScripts}\n\n    <script type=\"module\">\n        // Set up console interception FIRST, before anything else\n        const originalConsole = window.console;\n        window.console = {\n            ...originalConsole,\n            log: (...args) => {\n                try {\n                    const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)).join(' ');\n                    window.parent.postMessage({\n                        type: 'playground-console',\n                        playgroundId: '${playgroundId.value}',\n                        logType: 'log',\n                        message: message,\n                        timestamp: new Date().toISOString()\n                    }, '*');\n                } catch (e) {\n                    // Fallback to original console if message posting fails\n                }\n                originalConsole.log(...args);\n            },\n            error: (...args) => {\n                const errorMsg = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)).join(' ');\n                window.parent.postMessage({\n                    type: 'playground-console',\n                    playgroundId: '${playgroundId.value}',\n                    logType: 'error',\n                    message: errorMsg,\n                    timestamp: new Date().toISOString(),\n                    isSignificantError: errorMsg.toLowerCase().includes('error') || errorMsg.toLowerCase().includes('failed')\n                }, '*');\n                originalConsole.error(...args);\n            },\n            warn: (...args) => {\n                const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)).join(' ');\n                window.parent.postMessage({\n                    type: 'playground-console',\n                    playgroundId: '${playgroundId.value}',\n                    logType: 'warn',\n                    message: message,\n                    timestamp: new Date().toISOString()\n                }, '*');\n                originalConsole.warn(...args);\n            },\n            info: (...args) => {\n                const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)).join(' ');\n                window.parent.postMessage({\n                    type: 'playground-console',\n                    playgroundId: '${playgroundId.value}',\n                    logType: 'info',\n                    message: message,\n                    timestamp: new Date().toISOString()\n                }, '*');\n                originalConsole.info(...args);\n            }\n        };\n        \n        console.log(\"Starting CanvasEngine playground...\");\n        \n        // Enhanced error handling function\n        function handleError(error, context = 'Unknown') {\n            console.error(\\`\\${context} error:\\`, error);\n            \n            // Send error to parent window for console logging with unique playground ID\n            try {\n                window.parent.postMessage({\n                    type: 'playground-error',\n                    playgroundId: '${playgroundId.value}',\n                    context: context,\n                    message: error.message || error.toString(),\n                    stack: error.stack || '',\n                    timestamp: new Date().toISOString()\n                }, '*');\n            } catch (postError) {\n                console.warn('Could not send error to parent:', postError);\n            }\n            \n            const rootElement = document.getElementById(\"root\");\n            if (rootElement && !rootElement.querySelector('.error')) {\n                let errorMessage = error.message || error.toString();\n                \n                if (errorMessage.includes(\"already has a handler\")) {\n                    errorMessage = \"PixiJS extension conflict detected. Try refreshing the page.\";\n                }\n                \n                // Include stack trace if available\n                let stackTrace = '';\n                if (error.stack) {\n                    stackTrace = '<br/><br/><details><summary>Stack Trace</summary><pre style=\"font-size: 11px; margin: 8px 0; white-space: pre-wrap;\">' + \n                        error.stack + '</pre></details>';\n                }\n                \n                rootElement.innerHTML = '<div class=\"error\"><strong>' + context + ' Error:</strong><br/>' + \n                    errorMessage + stackTrace + \n                    '<br/><br/><small>If this persists, try refreshing the page.</small></div>';\n            }\n        }\n\n        // Global error handler for uncaught exceptions\n        window.addEventListener('error', (event) => {\n            console.error('Global JavaScript Error:', event.error || event.message);\n            const error = event.error || new Error(event.message);\n            handleError(error, 'Global JavaScript');\n            \n            // Prevent default browser error handling\n            event.preventDefault();\n        });\n        \n        // Global promise rejection handler\n        window.addEventListener('unhandledrejection', (event) => {\n            console.error('Unhandled Promise Rejection:', event.reason);\n            const error = event.reason instanceof Error ? event.reason : new Error(event.reason);\n            handleError(error, 'Unhandled Promise');\n            \n            // Prevent default browser rejection handling\n            event.preventDefault();\n        });\n\n        async function initializeCanvas() {\n            try {\n                const rootElement = document.getElementById(\"root\");\n                if (!rootElement) throw new Error(\"Root element not found\");\n\n                // Extract all core functions and primitive components from CanvasEngine\n                const coreExports = {};\n                const componentExports = {};\n                \n                // Get core functions\n                ${coreExtractionCode}\n                \n                // Get primitive components  \n                ${componentExtractionCode}\n                \n                // Destructure for easy access\n                const { ${CORE_FUNCTIONS.join(', ')} } = coreExports;\n                const { ${PRIMITIVE_COMPONENTS.join(', ')} } = componentExports;\n                \n                let comp = null\n                \n                // Wrap component function execution in try-catch to catch syntax errors\n                try {\n                    comp = ${componentFunction}\n                } catch (syntaxError) {\n                    throw new Error(\"Syntax error in component code: \" + syntaxError.message);\n                }\n\n                if (typeof comp !== \"function\") {\n                    throw new Error(\"Component is not a function: \" + typeof comp);\n                }\n\n                // Wrap the component function to catch async errors during execution\n                const wrappedComp = function(...args) {\n                    try {\n                        const result = comp(...args);\n                        // If the result is a promise, catch any rejections\n                        if (result && typeof result.then === 'function') {\n                            return result.catch(asyncError => {\n                                handleError(asyncError, 'Component Async');\n                                throw asyncError;\n                            });\n                        }\n                        return result;\n                    } catch (syncError) {\n                        handleError(syncError, 'Component Sync');\n                        throw syncError;\n                    }\n                };\n \n                // Wrap bootstrapCanvas call with additional error handling\n                const result = await Promise.resolve(bootstrapCanvas(rootElement, wrappedComp))\n                    .catch(bootstrapError => {\n                        handleError(bootstrapError, 'Bootstrap');\n                        throw bootstrapError;\n                    });\n                    \n                console.log(\"CanvasEngine initialized successfully\");\n                \n            } catch (error) {\n                handleError(error, 'Initialization');\n            }\n        }\n        \n        // Initialize with additional promise rejection handling\n        initializeCanvas().catch(error => {\n            handleError(error, 'Main Initialization');\n        });\n    <\\/script>\n</body>\n</html>`\n}\n\n\n/**\n * Process all imports and resolve local files\n * \n * @param {string} scriptContent - The script content to transform\n * @returns {Promise<{transformedContent: string, dependencies: Set<string>}>} - The transformed script content with resolved imports and dependencies\n */\nconst processImports = async (scriptContent: string): Promise<{transformedContent: string, dependencies: Set<string>}> => {\n  let transformedContent = scriptContent\n  let resolvedModules = ''\n  const dependencies = new Set<string>()\n  \n  // Transform external library imports\n  for (const [packageName, config] of Object.entries(dependencyConfig)) {\n    const regex = new RegExp(`import\\\\s*\\\\{\\\\s*([^}]+)\\\\s*\\\\}\\\\s*from\\\\s*['\"]${packageName.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}['\"];?`, 'g')\n    transformedContent = transformedContent.replace(regex, (match, imports) => {\n      const cleanImports = imports.trim()\n      dependencies.add(packageName)\n      return `const { ${cleanImports} } = ${config.globalName};`\n    })\n  }\n  \n  // Process local file imports\n  const importRegex = /import\\s+(.+?)\\s+from\\s+['\"](.+?)['\"];?/g\n  let importMatch\n  \n  while ((importMatch = importRegex.exec(scriptContent)) !== null) {\n    const [fullMatch, importClause, filePath] = importMatch\n    \n    // Skip CanvasEngine imports (already processed)\n    if (filePath[0] != '.') continue\n    \n    // Resolve local file path (remove ./ and normalize)\n    const normalizedPath = filePath.replace(/^\\.\\//, '').replace(/^\\//, '')\n    \n    // Check if file exists in allFiles\n    const targetFile = allFiles.value[normalizedPath]\n    if (!targetFile) {\n      addLog(`Warning: File not found: ${filePath}`, 'warn')\n      continue\n    }\n    \n    // Process the file based on its extension\n    let processedContent = ''\n    \n    if (normalizedPath.endsWith('.ce')) {\n      // Parse .ce file like a component\n      const ceScriptMatch = targetFile.content.match(/<script>([\\s\\S]*?)<\\/script>/)\n      const ceScriptContent = ceScriptMatch ? ceScriptMatch[1].trim() : \"\"\n\n      // Extract all style tags\n      const styleRegex = /<style[^>]*>([\\s\\S]*?)<\\/style>/g\n      let ceStyle = \"\"\n      let styleMatch\n      while ((styleMatch = styleRegex.exec(targetFile.content)) !== null) {\n        ceStyle += styleMatch[1].trim() + \"\\n\"\n      }\n\n      // Recursively process imports in the .ce file\n      const processedCeScript = await processImports(ceScriptContent)\n\n      // Merge dependencies from nested imports\n      processedCeScript.dependencies.forEach(dep => dependencies.add(dep))\n\n      const ceTemplate = targetFile.content.replace(/<script>[\\s\\S]*?<\\/script>/, \"\")\n        .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/g, \"\")\n        .replace(/^\\s+|\\s+$/g, '')\n\n      let parsedCeTemplate\n      try {\n        parsedCeTemplate = parser.parse(ceTemplate)\n      } catch (parseError: any) {\n        const errorMsg = showErrorMessage(ceTemplate, parseError)\n        throw new Error(`Error parsing template in ${normalizedPath}:\\n${errorMsg}`)\n      }\n\n      // Generate component function for .ce file with style\n      processedContent = `\n        function ${getModuleName(normalizedPath)}($$props = {}) {\n          const $props = useProps($$props);\n          const defineProps = useDefineProps($$props);\n          ${processedCeScript.transformedContent}\n          const __style = ${JSON.stringify(ceStyle)};\n          if (__style) {\n            const styleEl = document.createElement('style');\n            styleEl.textContent = __style;\n            document.head.appendChild(styleEl);\n          }\n          return ${parsedCeTemplate};\n        }\n      `\n         } else if (normalizedPath.endsWith('.js') || normalizedPath.endsWith('.ts')) {\n       // Process .js/.ts files\n       const result = await processImports(targetFile.content)\n       \n       // Transform ES6 exports to object assignments\n       const moduleName = getModuleName(normalizedPath)\n       const transformedJsContent = transformExports(result.transformedContent, moduleName)\n\n       // Wrap in a function that creates and returns the module object\n       processedContent = `\n         const ${moduleName} = (function() {\n           ${transformedJsContent}\n         })();\n       `\n       \n       // Merge dependencies from nested imports\n       result.dependencies.forEach(dep => dependencies.add(dep))\n     }\n     \n     // Add the processed content to resolved modules\n     resolvedModules += processedContent + '\\n'\n     \n     // Replace the import statement with variable assignment\n     const moduleName = getModuleName(normalizedPath)\n     if (importClause.includes('{')) {\n       // Named imports: import { func1, func2 } from './utils.js'\n       transformedContent = transformedContent.replace(fullMatch, `const ${importClause} = ${moduleName};`)\n     } else {\n       // Default import: import HelloWorld from './hello.ce'\n       const varName = importClause.trim()\n       transformedContent = transformedContent.replace(fullMatch, `const ${varName} = ${moduleName};`)\n     }\n   }\n   \n   return {\n     transformedContent: resolvedModules + transformedContent,\n     dependencies\n   }\n}\n\n/**\n * Transform ES6 exports to return statement with object for sandbox compatibility\n */\nconst transformExports = (jsContent: string, moduleName: string): string => {\n  let transformedContent = jsContent\n  const exportedNames: string[] = []\n  let hasDefaultExport = false\n  let defaultExportValue = ''\n  \n  // Transform named exports: export const foo = ... → const foo = ...;\n  transformedContent = transformedContent.replace(/export\\s+const\\s+(\\w+)\\s*=\\s*([^;]+);?/g, (match, name, value) => {\n    exportedNames.push(name)\n    return `const ${name} = ${value};`\n  })\n  \n  // Transform named exports: export function foo() {} → function foo() {}\n  transformedContent = transformedContent.replace(/export\\s+function\\s+(\\w+)\\s*\\([^)]*\\)\\s*\\{[^}]*\\}/g, (match, name) => {\n    exportedNames.push(name)\n    const funcDeclaration = match.replace(/^export\\s+/, '')\n    return funcDeclaration\n  })\n  \n  // Transform default export: export default ... → store the value\n  transformedContent = transformedContent.replace(/export\\s+default\\s+([^;]+);?/g, (match, value) => {\n    hasDefaultExport = true\n    defaultExportValue = value\n    return '' // Remove the export default line\n  })\n  \n  // Transform export { ... } syntax\n  transformedContent = transformedContent.replace(/export\\s*\\{\\s*([^}]+)\\s*\\}/g, (match, exports) => {\n    const exportList = exports.split(',').map(exp => exp.trim())\n    exportList.forEach(exp => {\n      const [localName, exportedName] = exp.includes(' as ') ? exp.split(' as ').map(s => s.trim()) : [exp, exp]\n      if (!exportedNames.includes(exportedName)) {\n        exportedNames.push(exportedName)\n      }\n    })\n    return '' // Remove the export statement\n  })\n  \n  // Build the return object\n  const returnObject: string[] = []\n  \n  // Add named exports\n  exportedNames.forEach(name => {\n    returnObject.push(`${name}: ${name}`)\n  })\n  \n  // Add default export if present\n  if (hasDefaultExport) {\n    returnObject.push(`default: ${defaultExportValue}`)\n  }\n  \n  // Add return statement with the module object\n  if (returnObject.length > 0) {\n    transformedContent += `\\n\\nreturn {\\n  ${returnObject.join(',\\n  ')}\\n};`\n  } else {\n    transformedContent += `\\n\\nreturn {};`\n  }\n\n  return transformedContent\n}\n\n/**\n * Generate a module name from file path\n */\nconst getModuleName = (filePath: string): string => {\n  return filePath\n    .replace(/[^a-zA-Z0-9]/g, '_')\n    .replace(/^_+|_+$/g, '')\n    .replace(/_+/g, '_') + '_module'\n}\n\n/**\n * Parse and run the CanvasEngine code using the PEG.js parser\n */\nconst runCode = async () => {\n  try {\n    // Don't run if not in viewport to save resources\n    if (!isInViewport.value) {\n      addLog('Playground not in viewport, skipping execution', 'info')\n      return\n    }\n    \n    clearPreview()\n    \n    // Ensure parser is initialized\n    if (!parser) {\n      await initParser()\n      if (!parser) {\n        throw new Error('Parser initialization failed')\n      }\n    }\n    \n    // Get the main component file content\n    const mainFile = allFiles.value['app.ce']\n    if (!mainFile) {\n      throw new Error('app.ce file is required')\n    }\n    \n    // Extract the script, style, and template content like in the compiler\n    const scriptMatch = mainFile.content.match(/<script>([\\s\\S]*?)<\\/script>/)\n    let scriptContent = scriptMatch ? scriptMatch[1].trim() : \"\"\n\n    // Extract all style tags\n    const styleRegex = /<style[^>]*>([\\s\\S]*?)<\\/style>/g\n    let scopedStyle = \"\"\n    let styleMatch\n    while ((styleMatch = styleRegex.exec(mainFile.content)) !== null) {\n      scopedStyle += styleMatch[1].trim() + \"\\n\"\n    }\n\n    // Process all imports and resolve local files\n    const importResult = await processImports(scriptContent)\n    scriptContent = importResult.transformedContent\n    const dependencies = importResult.dependencies\n    \n    // Always ensure CanvasEngine is available and is the first dependency\n    const orderedDependencies = new Set(['canvasengine'])\n    dependencies.forEach(dep => {\n      if (dep !== 'canvasengine') {\n        orderedDependencies.add(dep)\n      }\n    })\n \n    // Extract template (everything except script and style)\n    const template = mainFile.content.replace(/<script>[\\s\\S]*?<\\/script>/, \"\")\n      .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/g, \"\")\n      .replace(/^\\s+|\\s+$/g, '')\n    \n    let parsedTemplate\n    try {\n      // Parse the template using the PEG.js parser\n      parsedTemplate = parser.parse(template)\n      addLog(`Template parsed successfully: ${parsedTemplate}`, 'info')\n    } catch (parseError: any) {\n      const errorMsg = showErrorMessage(template, parseError)\n      throw new Error(`Error parsing template:\\n${errorMsg}`)\n    }\n    \n    // Generate the complete component function like in the compiler\n    // Make sure the component function returns the correct structure\n    const componentFunction = `\n            function component($$props = {}) {\n                const $props = useProps($$props);\n                const defineProps = useDefineProps($$props);\n                ${scriptContent}\n                return ${parsedTemplate};\n            }`\n    \n    // Create sandbox iframe with CanvasEngine\n    if (canvasContainer.value) {\n      const iframe = document.createElement('iframe')\n      iframe.style.cssText = `\n        width: 100%;\n        height: 100%;\n        border: none;\n        background: white;\n      `\n      \n      // Generate the complete HTML for the iframe\n      const iframeContent = generateIframeContent(componentFunction, orderedDependencies, scopedStyle)\n\n      // Set up message listener for iframe communication\n      messageListener = (event: MessageEvent) => {\n        if (event.data && event.data.playgroundId === playgroundId.value) {\n          if (event.data.type === 'playground-error') {\n            const { context, message, stack } = event.data\n            const fullErrorMsg = stack ? `${message}\\n\\nStack trace:\\n${stack}` : message\n            error.value = fullErrorMsg\n            addLog(`${context}: ${message}`, 'error')\n          } else if (event.data.type === 'playground-console') {\n            const { logType, message, isSignificantError } = event.data\n            addLog(message, logType as ConsoleLog['type'])\n            \n            // Set error in preview if it's a significant console error\n            if (isSignificantError) {\n              error.value = message\n            }\n          }\n        }\n      }\n      \n      window.addEventListener('message', messageListener)\n\n      iframe.onload = () => {\n        try {\n          iframe.contentDocument?.open()\n          iframe.contentDocument?.write(iframeContent)\n          iframe.contentDocument?.close()\n        } catch (writeError) {\n          console.error('Error writing to iframe:', writeError)\n          addLog(`Error writing to iframe: ${writeError.message}`, 'error')\n        }\n      }\n      \n      canvasContainer.value.appendChild(iframe)\n    }\n    \n  } catch (err: any) {\n    error.value = err.message || 'Unknown error occurred'\n    addLog(`Error: ${err.message}`, 'error')\n    console.error('Playground error:', err)\n  }\n}\n\nlet autoReloadTimeout: ReturnType<typeof setTimeout>\n\n// Watch for console open/close to initialize scroll tracking\nwatch(consoleOpen, (isOpen) => {\n  if (isOpen) {\n    initConsoleScroll()\n  }\n})\n\n// Lifecycle\nonMounted(() => {\n  nextTick(async () => {\n    await initParser()\n    initEditor()\n    initViewportObserver()\n    runCode()\n  })\n})\n\nonUnmounted(() => {\n  if (editorView) {\n    editorView.destroy()\n  }\n  \n  // Clean up console scroll event listener\n  if (consoleScrollContainer) {\n    (consoleScrollContainer as HTMLElement).removeEventListener('scroll', checkConsoleScrollPosition)\n  }\n  \n  // Clean up message listener\n  if (messageListener) {\n    window.removeEventListener('message', messageListener)\n    messageListener = null\n  }\n  \n  // Clean up viewport observer\n  cleanupViewportObserver()\n  \n  // Clean up preview resources\n  clearPreview()\n  \n  // Clean up fullscreen\n  if (isFullscreen.value) {\n    exitFullscreen()\n  }\n  \n  clearTimeout(autoReloadTimeout)\n})\n</script>\n\n<style scoped>\n.playground-container {\n  margin: 20px 0;\n  border: 1px solid var(--vp-c-border);\n  border-radius: 12px;\n  overflow: hidden;\n  background: var(--vp-c-bg);\n  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n  position: relative;\n}\n\n/* Fullscreen styles */\n.playground-container.fullscreen {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  width: 100vw;\n  height: 100vh;\n  margin: 0;\n  border-radius: 0;\n  z-index: 9999;\n  box-shadow: none;\n}\n\n.fullscreen-backdrop {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background: rgba(0, 0, 0, 0.8);\n  z-index: -1;\n}\n\n:global(.playground-fullscreen-active) {\n  overflow: hidden;\n}\n\n.playground-header {\n  padding: 20px 24px;\n  background: var(--vp-c-bg-soft);\n  border-bottom: 1px solid var(--vp-c-border);\n  display: flex;\n  justify-content: space-between;\n  align-items: flex-start;\n  gap: 20px;\n}\n\n.playground-controls-only {\n  padding: 12px 24px;\n  background: var(--vp-c-bg-soft);\n  border-bottom: 1px solid var(--vp-c-border);\n  display: flex;\n  justify-content: flex-end;\n}\n\n.header-content {\n  flex: 1;\n}\n\n.header-controls {\n  display: flex;\n  align-items: center;\n  gap: 12px;\n  flex-shrink: 0;\n}\n\n.playground-header h3 {\n  margin: 0 0 8px 0;\n  font-size: 20px;\n  font-weight: 600;\n  color: var(--vp-c-text-1);\n}\n\n.playground-description {\n  margin: 0;\n  font-size: 14px;\n  color: var(--vp-c-text-2);\n  line-height: 1.6;\n}\n\n.playground-content {\n  display: flex;\n  height: v-bind('props.height + \"px\"');\n}\n\n/* Fullscreen content adjustments */\n.playground-container.fullscreen .playground-content {\n  height: calc(100vh - 60px); /* Adjust for header */\n}\n\n/* View mode layouts */\n.playground-content.view-mode-code {\n  display: block;\n}\n\n.playground-content.view-mode-code .code-editor {\n  width: 100%;\n  height: 100%;\n  border-right: none;\n}\n\n.playground-content.view-mode-preview {\n  display: block;\n}\n\n.playground-content.view-mode-preview .preview-panel {\n  width: 100%;\n  height: 100%;\n}\n\n.playground-content.view-mode-both {\n  display: flex;\n}\n\n.playground-content.view-mode-both .code-editor {\n  width: 40%;\n  border-right: 1px solid var(--vp-c-border);\n}\n\n.playground-content.view-mode-both .preview-panel {\n  flex: 1;\n}\n\n/* View Mode Controls */\n.view-mode-controls {\n  display: flex;\n  gap: 4px;\n  background: var(--vp-c-bg-elv);\n  border-radius: 8px;\n  padding: 4px;\n}\n\n.view-mode-btn {\n  display: flex;\n  align-items: center;\n  gap: 6px;\n  padding: 8px 12px;\n  border: none;\n  background: transparent;\n  color: var(--vp-c-text-2);\n  cursor: pointer;\n  border-radius: 6px;\n  font-size: 13px;\n  font-weight: 500;\n  transition: all 0.2s;\n  white-space: nowrap;\n}\n\n.view-mode-btn:hover {\n  background: var(--vp-c-bg);\n  color: var(--vp-c-text-1);\n}\n\n.view-mode-btn.active {\n  background: var(--vp-c-brand);\n  color: white;\n}\n\n.view-mode-btn .icon {\n  font-size: 14px;\n}\n\n/* Fullscreen Button */\n.fullscreen-btn {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 40px;\n  height: 40px;\n  border: 1px solid var(--vp-c-border);\n  background: var(--vp-c-bg);\n  color: var(--vp-c-text-2);\n  cursor: pointer;\n  border-radius: 8px;\n  transition: all 0.2s;\n  font-size: 16px;\n}\n\n.fullscreen-btn:hover {\n  background: var(--vp-c-bg-elv);\n  color: var(--vp-c-text-1);\n  border-color: var(--vp-c-brand);\n}\n\n.fullscreen-btn .icon {\n  font-size: 18px;\n}\n\n/* Code Editor */\n.code-editor {\n  width: 40%;\n  display: flex;\n  flex-direction: column;\n  border-right: 1px solid var(--vp-c-border);\n  background: var(--vp-c-bg-soft);\n}\n\n.editor-header {\n  padding: 12px 16px;\n  background: var(--vp-c-bg-soft);\n  border-bottom: 1px solid var(--vp-c-border);\n}\n\n.tabs {\n  display: flex;\n  gap: 4px;\n}\n\n.tab {\n  padding: 8px 16px;\n  border: none;\n  background: transparent;\n  color: var(--vp-c-text-2);\n  cursor: pointer;\n  border-radius: 6px;\n  font-size: 13px;\n  font-weight: 500;\n  transition: all 0.2s;\n}\n\n.tab:hover {\n  background: var(--vp-c-bg-elv);\n  color: var(--vp-c-text-1);\n}\n\n.tab.active {\n  background: var(--vp-c-brand);\n  color: white;\n}\n\n.editor-content {\n  flex: 1;\n  position: relative;\n  overflow: auto;\n  min-height: 0;\n}\n\n.codemirror-container {\n  height: 100%;\n  overflow: auto;\n}\n\n/* Preview Panel */\n.preview-panel {\n  flex: 1;\n  display: flex;\n  flex-direction: column;\n  background: var(--vp-c-bg);\n}\n\n.preview-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 12px 16px;\n  background: var(--vp-c-bg-soft);\n  border-bottom: 1px solid var(--vp-c-border);\n  font-size: 13px;\n  font-weight: 600;\n  color: var(--vp-c-text-1);\n}\n\n.clear-button {\n  padding: 6px 12px;\n  background: transparent;\n  color: var(--vp-c-text-2);\n  border: 1px solid var(--vp-c-border);\n  border-radius: 6px;\n  cursor: pointer;\n  font-size: 12px;\n  font-weight: 500;\n  transition: all 0.2s;\n}\n\n.clear-button:hover {\n  background: var(--vp-c-bg-elv);\n  color: var(--vp-c-text-1);\n}\n\n.preview-content {\n  flex: 1;\n  overflow: hidden;\n  display: flex;\n  background: #f8f9fa;\n  height: 100%;\n  position: relative;\n}\n\n.canvas-container {\n  width: 100%;\n  height: 100%;\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n}\n\n/* Error Display */\n.error-display {\n  width: 100%;\n  height: 100%;\n  background: #fef2f2;\n  border: 1px solid #fecaca;\n  border-radius: 8px;\n  padding: 20px;\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n}\n\n.error-header {\n  display: flex;\n  align-items: center;\n  gap: 8px;\n  margin-bottom: 12px;\n  color: #dc2626;\n  font-weight: 600;\n}\n\n.error-icon {\n  font-size: 18px;\n}\n\n.error-message {\n  margin: 0;\n  padding: 12px;\n  background: #fff;\n  border: 1px solid #fecaca;\n  border-radius: 6px;\n  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n  font-size: 13px;\n  color: #dc2626;\n  white-space: pre-wrap;\n  overflow-x: auto;\n}\n\n/* Console Accordion */\n.console-accordion {\n  border-top: 1px solid var(--vp-c-border);\n  background: var(--vp-c-bg-soft);\n}\n\n.console-toggle {\n  width: 100%;\n  padding: 12px 16px;\n  background: transparent;\n  border: none;\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n  cursor: pointer;\n  font-size: 13px;\n  font-weight: 600;\n  color: var(--vp-c-text-1);\n  transition: all 0.2s;\n}\n\n.console-toggle:hover {\n  background: var(--vp-c-bg-elv);\n}\n\n.console-toggle.active {\n  background: var(--vp-c-bg-elv);\n}\n\n.console-badge {\n  background: var(--vp-c-brand);\n  color: white;\n  padding: 2px 6px;\n  border-radius: 10px;\n  font-size: 11px;\n  font-weight: 600;\n  min-width: 18px;\n  text-align: center;\n}\n\n.toggle-icon {\n  transition: transform 0.2s;\n  font-size: 12px;\n}\n\n.toggle-icon.rotated {\n  transform: rotate(180deg);\n}\n\n.console-content {\n  max-height: 200px;\n  overflow-y: auto;\n  border-top: 1px solid var(--vp-c-border);\n  background: var(--vp-c-bg);\n}\n\n.console-empty {\n  padding: 16px;\n  text-align: center;\n  color: var(--vp-c-text-2);\n  font-size: 13px;\n  font-style: italic;\n}\n\n.console-line {\n  padding: 8px 16px;\n  border-bottom: 1px solid var(--vp-c-divider);\n  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n  font-size: 12px;\n  display: flex;\n  gap: 12px;\n}\n\n.console-line:last-child {\n  border-bottom: none;\n}\n\n.console-timestamp {\n  color: var(--vp-c-text-3);\n  font-size: 11px;\n  flex-shrink: 0;\n}\n\n.console-message {\n  color: var(--vp-c-text-1);\n  flex: 1;\n}\n\n.console-message.error {\n  color: #dc2626;\n}\n\n.console-message.warn {\n  color: #d97706;\n}\n\n.console-message.info {\n  color: #2563eb;\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n  .playground-header {\n    flex-direction: column;\n    align-items: stretch;\n    gap: 16px;\n  }\n  \n  .header-controls {\n    justify-content: center;\n  }\n  \n  .playground-controls-only {\n    justify-content: center;\n  }\n  \n  .playground-content.view-mode-both {\n    flex-direction: column;\n    height: auto;\n    min-height: 600px;\n  }\n  \n  .playground-content.view-mode-both .code-editor {\n    width: 100%;\n    height: 250px;\n    border-right: none;\n    border-bottom: 1px solid var(--vp-c-border);\n  }\n  \n  .playground-content.view-mode-code .code-editor {\n    height: 100%;\n  }\n  \n  .playground-content.view-mode-preview .preview-panel {\n    height: 100%;\n  }\n  \n  .editor-content {\n    overflow: auto;\n  }\n  \n  .preview-panel {\n    flex: 1;\n    min-height: 350px;\n  }\n  \n  /* View mode controls responsive */\n  .view-mode-controls {\n    flex-wrap: wrap;\n    justify-content: center;\n  }\n  \n  .view-mode-btn {\n    font-size: 12px;\n    padding: 6px 10px;\n  }\n  \n  .fullscreen-btn {\n    width: 36px;\n    height: 36px;\n  }\n}\n\n@media (max-width: 768px) {\n  .playground-header {\n    padding: 16px 20px;\n  }\n  \n  .playground-controls-only {\n    padding: 8px 20px;\n  }\n  \n  .playground-content.view-mode-both {\n    min-height: 700px;\n  }\n  \n  .playground-content.view-mode-both .code-editor {\n    height: 280px;\n  }\n  \n  .playground-content.view-mode-code .code-editor {\n    height: 100%;\n  }\n  \n  .playground-content.view-mode-preview .preview-panel {\n    height: 100%;\n  }\n  \n  .editor-content {\n    overflow: auto;\n  }\n  \n  .preview-panel {\n    min-height: 420px;\n  }\n  \n  .tabs {\n    flex-wrap: wrap;\n    gap: 2px;\n  }\n  \n  .tab {\n    padding: 6px 12px;\n    font-size: 12px;\n  }\n  \n  .console-content {\n    max-height: 150px;\n  }\n  \n  /* Mobile view controls */\n  .view-mode-btn {\n    font-size: 11px;\n    padding: 6px 8px;\n    gap: 4px;\n  }\n  \n  .view-mode-btn .icon {\n    font-size: 12px;\n  }\n  \n  .fullscreen-btn {\n    width: 32px;\n    height: 32px;\n  }\n  \n  .fullscreen-btn .icon {\n    font-size: 16px;\n  }\n}\n\n@media (max-width: 480px) {\n  .playground-header {\n    padding: 12px 16px;\n    gap: 12px;\n  }\n  \n  .playground-controls-only {\n    padding: 8px 16px;\n  }\n  \n  .playground-header h3 {\n    font-size: 18px;\n  }\n  \n  .playground-description {\n    font-size: 13px;\n  }\n  \n  .playground-content.view-mode-both {\n    min-height: 650px;\n  }\n  \n  .playground-content.view-mode-both .code-editor {\n    height: 250px;\n  }\n  \n  .playground-content.view-mode-code .code-editor {\n    height: 100%;\n  }\n  \n  .playground-content.view-mode-preview .preview-panel {\n    height: 100%;\n  }\n  \n  .editor-content {\n    overflow: auto;\n  }\n  \n  .preview-panel {\n    min-height: 400px;\n  }\n  \n  .preview-header,\n  .editor-header {\n    padding: 8px 12px;\n  }\n  \n  .console-toggle {\n    padding: 8px 12px;\n    font-size: 12px;\n  }\n  \n  .console-content {\n    max-height: 120px;\n  }\n  \n  .console-line {\n    padding: 6px 12px;\n    font-size: 11px;\n  }\n  \n  /* Extra small mobile adjustments */\n  .view-mode-controls {\n    padding: 2px;\n    gap: 2px;\n  }\n  \n  .view-mode-btn {\n    font-size: 10px;\n    padding: 4px 6px;\n    gap: 2px;\n  }\n  \n  .view-mode-btn .icon {\n    font-size: 11px;\n  }\n  \n  .fullscreen-btn {\n    width: 28px;\n    height: 28px;\n  }\n  \n  .fullscreen-btn .icon {\n    font-size: 14px;\n  }\n  \n  .header-controls {\n    gap: 8px;\n  }\n}\n</style> "
  },
  {
    "path": "docs/.vitepress/theme/components/config.ts",
    "content": "const isDev = typeof window !== 'undefined' && window.location.hostname === 'localhost'\n\n/**\n * Configuration map for external dependencies\n * Ensures all CanvasEngine exports from the compiler are always available\n */\nexport const dependencyConfig = {\n    'canvasengine': {\n      globalName: 'CanvasEngine',\n      url: isDev ? 'http://localhost:3000/packages/core/dist/index.global.js' : 'https://cdn.jsdelivr.net/npm/canvasengine@latest/dist/index.global.js'\n    },\n    '@canvasengine/presets': {\n      globalName: 'CanvasEnginePresets',\n      url: isDev ? 'http://localhost:3000/packages/presets/dist/index.global.js' : 'https://cdn.jsdelivr.net/npm/@canvasengine/presets@latest/dist/index.global.js'\n    },\n    'pixi.js': {\n      globalName: 'PIXI',\n      url: 'https://cdn.jsdelivr.net/npm/pixi.js@latest/dist/pixi.min.js'\n    }\n  }\n  \n  /**\n   * List of primitive components that should always be available\n   * Matches the PRIMITIVE_COMPONENTS from the compiler\n   */\n  export const PRIMITIVE_COMPONENTS = [\n    \"Canvas\",\n    \"Sprite\", \n    \"Text\",\n    \"Viewport\",\n    \"Graphics\",\n    \"Container\",\n    \"ImageMap\",\n    \"NineSliceSprite\",\n    \"Rect\",\n    \"Circle\",\n    \"Ellipse\",\n    \"Triangle\",\n    \"TilingSprite\",\n    \"svg\",\n    \"Video\",\n    \"Mesh\",\n    \"Svg\",\n    \"DOMContainer\",\n    \"DOMElement\",\n    \"Button\",\n    \"Joystick\",\n    \"FocusContainer\"\n  ]\n  \n  /**\n   * Core functions that should always be available\n   * Matches the required imports from the compiler\n   */\n  export const CORE_FUNCTIONS = [\n    \"h\",\n    \"computed\", \n    \"cond\",\n    \"loop\",\n    \"useProps\",\n    \"useDefineProps\",\n    \"bootstrapCanvas\"\n  ]\n  "
  },
  {
    "path": "docs/.vitepress/theme/components/example.ts",
    "content": "interface Example {\n    title: string;\n    description: string;\n    files: Record<string, string>;\n}\n\nconst examples: Example[] = [{\n    title: 'Hello World',\n    description: 'A simple example of how to use CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas \n    backgroundColor=\"#fff\" \n    width=\"100%\" \n    height=\"100%\" \n    antialias=\"true\"\n    >\n    <Container\n        width=\"100%\" \n        height=\"100%\" \n        justifyContent=\"center\"\n        alignItems=\"center\">\n        <HelloWorld text=\"CanvasEngine\" color=\"black\" />\n    </Container>\n</Canvas>\n\n<script>\n    import HelloWorld from \"./hello.ce\";\n</script>\n        `,\n        \"hello.ce\": `<Text text=\"Hello World\" size={70} fontFamily=\"Helvetica\" x={50} y={40} />`,\n    },\n}, \n{\n    title: 'Reactivity',\n    description: 'Example of using reactivity in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <Container flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" width=\"100%\" height=\"100%\">\n        <Text text=\"Click Me\" color=\"white\" size={50} click />\n        <Text text={counter} color=\"white\" size={70} />\n        <Text text={double} color=\"white\" size={70} />\n    </Container>\n</Canvas>\n\n<script>\nimport { signal, computed, effect } from 'canvasengine'\n\nconst counter = signal(0)\nconst double = computed(() => counter() * 2)\n\neffect(() => {\n    console.log(counter())\n})\n\nconst click = () => {\n    counter.update(c => c + 1)\n}\n</script>\n\n        `,\n    },\n},\n{\n    title: 'With loop and condition syntax',\n    description: 'Example of using loop and condition syntax in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <Container>\n        @if (show) {\n            <Container>\n                @for ((color,index) of colors) {\n                    <!-- we use @ in \"@index\" because index is not a signal -->\n                    <Rect width={100} height={100} color={color} x={@index * 100} />\n                }\n            </Container>\n        }\n        <Container x={100} y={100} click>\n            <Rect width={100} height={100} color=\"red\" />\n            <Text text=\"Click me\" />\n        </Container>\n    </Container>\n</Canvas>\n\n<script>\nimport { signal, computed, effect } from 'canvasengine'\n\nconst colors = signal(['red', 'green', 'blue'])\nconst show = signal(true)\n\nconst click = () => {\n    show.update(show => !show)\n}\n</script>\n\n        `,\n    },\n},\n {\n    title: 'Drag and Drop',\n    description: 'Example of using drag and drop in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <Container>\n        <Rect width={100} height={100} color=\"red\" drag />\n    </Container>\n</Canvas>\n\n<script>\nconst drag = {\n  direction: 'all', // 'all', 'x', or 'y'\n  start() {\n    console.log(\"Drag started\");\n  },\n  move(event) {\n    console.log(\"Dragging\", event.global.x, event.global.y);\n  },\n  end() {\n    console.log(\"Drag ended\");\n  }\n};\n</script>\n\n        `,\n    },\n},\n{\n    title: 'Sprite Animation',\n    description: 'Example of using sprite animation in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <Container>\n        <Sprite \n            sheet={{\n                definition,\n                playing: \"default\"\n            }}\n        />\n    </Container>\n</Canvas>\n\n<script>\nconst definition = {\n    id: \"explosion\",\n    image: \"./exp.png\",\n    width: 1024,\n    height: 1024,\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n        default: {\n             animations: () => [\n                [ \n                    { time: 0, frameX: 0, frameY: 0 },\n                    { time: 10, frameX: 1, frameY: 0 },\n                    { time: 20, frameX: 2, frameY: 0 },\n                    { time: 30, frameX: 3, frameY: 0 },\n                    { time: 40, frameX: 0, frameY: 1 },\n                    { time: 50, frameX: 1, frameY: 1 },\n                    { time: 60, frameX: 2, frameY: 1 },     \n                    { time: 70, frameX: 3, frameY: 1 },\n                    { time: 80, frameX: 0, frameY: 2 },\n                    { time: 90, frameX: 1, frameY: 2 },\n                    { time: 100, frameX: 2, frameY: 2 },\n                    { time: 110, frameX: 3, frameY: 2 },\n                    { time: 120, frameX: 0, frameY: 3 },\n                    { time: 130, frameX: 1, frameY: 3 },\n                    { time: 140, frameX: 2, frameY: 3 },\n                    { time: 150, frameX: 3, frameY: 3 },\n                ]\n             ]\n        }\n    }\n}\n\n</script>\n\n        `,\n    },\n},\n\n// {\n//     title: 'Joystick',\n//     description: 'Example of using joystick in CanvasEngine',\n//     files: {\n//         \"app.ce\": `\n// <Canvas>\n//     <Container>\n//         <Joystick />\n//     </Container>\n// </Canvas>\n\n// <script>\n// import { Joystick } from '@canvasengine/presets'\n// </script>\n//         `,\n//     },\n// },\n{\n    title: 'Sprite Animation and controls',\n    description: 'Example of using sprite animation and controls in CanvasEngine. Use the arrow keys to move the sprite.',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <Container>\n        <Sprite \n            x\n            y\n            sheet={{\n                definition,\n                playing: animationPlaying,\n                params: {\n                    direction\n                }\n            }}\n            controls\n        />\n    </Container>\n</Canvas>\n\n<script>\nimport { spritesheet } from \"./spritesheet.js\"\nimport { signal } from 'canvasengine'\n\nconst x = signal(0)\nconst y = signal(0)\nconst direction = signal(\"down\")\nconst speed = signal(3)\nconst animationPlaying = signal(\"stand\")\n\nconst keyUp = () => {\n    animationPlaying.set(\"stand\")\n}\n\nconst controls = signal({\n    down: {\n      repeat: true,\n      bind: \"down\",\n      keyDown() {\n        y.update(y => y + speed());\n        direction.set(\"down\");\n        animationPlaying.set(\"walk\")\n      },\n      keyUp\n    },\n    up: {\n      repeat: true,\n      bind: 'up',\n      keyDown() {\n        y.update(y => y - speed());\n        direction.set(\"up\");\n        animationPlaying.set(\"walk\")\n      },\n      keyUp\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        x.update(x => x - speed());\n        direction.set(\"left\");\n        animationPlaying.set(\"walk\")\n      },\n      keyUp\n    },\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown() {\n        x.update(x => x + speed());\n        direction.set(\"right\");\n        animationPlaying.set(\"walk\")\n      },\n      keyUp\n    }\n});\n\nconst definition = {\n    id: \"hero\",\n    image: \"./hero.png\",\n    width: 96,\n    height: 128,\n    ...spritesheet(3, 4)\n}\n\n</script>\n\n        `,\n        \"spritesheet.js\": `\nexport const spritesheet = (framesWidth, framesHeight, frameStand = 1) => {\n\n    if (framesWidth <= frameStand) {\n        frameStand = framesWidth - 1\n    }\n\n    const frameY = direction => {\n        const gap = Math.max(4 - framesHeight, 0)\n        return {\n            'down': 0,\n            'left': Math.max(0, 1 - gap),\n            'right': Math.max(0, 2 - gap),\n            'up': Math.max(0, 3 - gap)\n        }[direction]\n    }\n\n    const stand = (direction) => [{ time: 0, frameX: frameStand, frameY: frameY(direction) }]\n    const walk = direction => {\n        const array = []\n        const durationFrame = 10\n        for (let i = 0; i < framesWidth; i++) {\n            array.push({ time: i * durationFrame, frameX: i, frameY: frameY(direction) })\n        }\n        array.push({ time: array[array.length - 1].time + durationFrame })\n        return array\n    }\n\n    return {\n        textures: {\n            'stand': {\n                animations: ({direction}) => [stand(direction)]\n            },\n            'walk': {\n                animations: ({direction}) => [walk(direction)]\n            }\n        },\n        framesHeight,\n        framesWidth\n    }\n}\n        `\n    },\n},\n{\n    title: 'Tiled Map',\n    description: 'Example of using a Tiled map in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas>\n    <TiledMap \n        map={map} \n        createLayersPerTilesZ={true} \n        basePath=\"/\" \n        objectLayer={(layer) => <Rect width={32} height={32} color=\"red\" />} \n    />\n</Canvas>\n\n<script>\n    import { TiledMap } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n    \n    let map = signal(null)\n    \n    fetch('/simplemap.tmx')\n        .then((res) => res.text())\n        .then((text) => {\n            map.set(text)\n        })\n</script>\n        `,\n    },\n},\n{\n    title: 'DOM with form',\n    description: 'Example of using a Tiled map in CanvasEngine',\n    files: {\n        \"app.ce\": `\n<Canvas backgroundColor=\"white\">\n  <DOMContainer x={100} y={100}>\n      <form submit={click}>\n        <input name=\"username\" type=\"text\" value={text} />\n        <button>Submit</button>\n        <p>{text}</p>\n      </form>\n  </DOMContainer>\n</Canvas>\n\n<script>\nimport { signal } from \"canvasengine\";\n\nconst text = signal(\"Hello\");\nconst click = (event, formData) => {\n  console.log(formData)\n}\n</script>\n\n\n        `,\n    },\n},\n{\n    title: 'Animated signal',\n    description: 'Example of using an animated signal in CanvasEngine. Click the rect to move it.',\n    files: {\n        \"app.ce\": `\n<Canvas backgroundColor=\"white\">\n  <Container>\n    <Rect width={100} height={100} color=\"red\" x click />\n  </Container>\n</Canvas>\n\n<script>\nimport { animatedSignal, Easing } from \"canvasengine\";\n\nlet direction = \"left\"\n\nconst x = animatedSignal(0, {\n    duration: 1000\n})\n\nconst click = () => {\n    if (direction === \"left\") {\n        x.update(x => x + 500)\n        direction = \"right\"\n    } else {\n        x.update(x => x - 500)\n        direction = \"left\"\n    }\n}\n</script>\n\n\n        `,\n    },\n},\n{\n    title: 'Joystick',\n    description: 'Example of using a joystick in CanvasEngine. Use the joystick to move the rect.',\n    files: {\n        \"app.ce\": `\n<Canvas backgroundColor=\"white\">\n  <Container>\n    <Joystick x={100} y={100} onChange={onChange} />\n    <Container x={300} flexDirection=\"column\" top={50} gap={10}>\n        <Text text={angleStr} />\n        <Text text={directionStr} />\n        <Text text={powerStr} />\n    </Container>\n  </Container>\n</Canvas>\n\n<script>\nimport { signal, computed } from 'canvasengine'\n\nconst angle = signal(0)\nconst direction = signal(\"up\")\nconst power = signal(0)\nconst angleStr = computed(() => \\`Angle: \\${angle()}\\`)\nconst directionStr = computed(() => \\`Direction: \\${direction()}\\`)\nconst powerStr = computed(() => \\`Power: \\${power()}\\`)\n\nconst onChange = (event) => {\n    angle.set(event.angle)\n    direction.set(event.direction)\n    power.set(event.power)\n}\n</script>\n\n\n        `,\n    },\n},\n{\n    title: 'Flash Effect',\n    description: 'Example of using flash effects in CanvasEngine. Click the rectangles to see different flash types.',\n    files: {\n        \"app.ce\": `\n<Canvas backgroundColor=\"#2c3e50\">\n    <Container flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" width=\"100%\" height=\"100%\" gap={30}>\n        <Text text=\"Click the rectangles to flash them!\" color=\"white\" size={24} />\n        \n        <Container flexDirection=\"row\" gap={30}>\n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n                <Text text=\"Alpha Flash\" color=\"#ecf0f1\" size={14} />\n                <Rect \n                    color=\"#e74c3c\" \n                    width={80} \n                    height={80} \n                    borderRadius={8} \n                    flash={alphaFlashConfig}\n                    click={() => alphaFlashTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n                <Text text=\"Tint Flash\" color=\"#ecf0f1\" size={14} />\n                <Rect \n                    color=\"#3498db\" \n                    width={80} \n                    height={80} \n                    borderRadius={8} \n                    flash={tintFlashConfig}\n                    click={() => tintFlashTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n                <Text text=\"Both Flash\" color=\"#ecf0f1\" size={14} />\n                <Rect \n                    color=\"#2ecc71\" \n                    width={80} \n                    height={80} \n                    borderRadius={8} \n                    flash={bothFlashConfig}\n                    click={() => bothFlashTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n                <Text text=\"Multi Cycle\" color=\"#ecf0f1\" size={14} />\n                <Rect \n                    color=\"#f39c12\" \n                    width={80} \n                    height={80} \n                    borderRadius={8} \n                    flash={multiCycleFlashConfig}\n                    click={() => multiCycleFlashTrigger.start()}\n                />\n            </Container>\n        </Container>\n    </Container>\n</Canvas>\n\n<script>\nimport { trigger } from 'canvasengine';\n\n// Alpha flash - changes opacity\nconst alphaFlashTrigger = trigger();\nconst alphaFlashConfig = {\n    trigger: alphaFlashTrigger,\n    type: 'alpha',\n    alpha: 0.2,\n    duration: 300\n};\n\n// Tint flash - changes color\nconst tintFlashTrigger = trigger();\nconst tintFlashConfig = {\n    trigger: tintFlashTrigger,\n    type: 'tint',\n    tint: 0xff0000,  // Red flash\n    duration: 300\n};\n\n// Both flash - changes opacity and color\nconst bothFlashTrigger = trigger();\nconst bothFlashConfig = {\n    trigger: bothFlashTrigger,\n    type: 'both',\n    alpha: 0.5,\n    tint: 0x00ff00,  // Green flash\n    duration: 400\n};\n\n// Multi-cycle flash - flashes multiple times\nconst multiCycleFlashTrigger = trigger();\nconst multiCycleFlashConfig = {\n    trigger: multiCycleFlashTrigger,\n    type: 'alpha',\n    cycles: 3,\n    duration: 600\n};\n</script>\n\n        `,\n    },\n},\n{\n    title: 'Shake Effect',\n    description: 'Example of using shake effects in CanvasEngine. Click the rectangles to see different shake configurations.',\n    files: {\n        \"app.ce\": `\n<Canvas backgroundColor=\"#2c3e50\">\n    <Container flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" width=\"100%\" height=\"100%\" gap={30}>\n        <Text text=\"Click the rectangles to shake them!\" color=\"white\" size={24} />\n        \n        <Container flexDirection=\"row\" gap={30}>\n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n               \n                <Rect \n                    color=\"#e74c3c\" \n                    width={100} \n                    height={100} \n                    borderRadius={8} \n                    shake={basicShakeConfig}\n                    click={() => basicShakeTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n               \n                <Rect \n                    color=\"#3498db\" \n                    width={100} \n                    height={100} \n                    borderRadius={8} \n                    shake={horizontalShakeConfig}\n                    click={() => horizontalShakeTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n               \n                <Rect \n                    color=\"#2ecc71\" \n                    width={100} \n                    height={100} \n                    borderRadius={8} \n                    shake={verticalShakeConfig}\n                    click={() => verticalShakeTrigger.start()}\n                />\n            </Container>\n            \n            <Container flexDirection=\"column\" alignItems=\"center\" gap={10}>\n              \n                <Rect \n                    color=\"#f39c12\" \n                    width={100} \n                    height={100} \n                    borderRadius={8} \n                    shake={intenseShakeConfig}\n                    click={() => intenseShakeTrigger.start()}\n                />\n            </Container>\n        </Container>\n    </Container>\n</Canvas>\n\n<script>\nimport { trigger } from 'canvasengine';\n\n// Basic shake - shakes in both directions\nconst basicShakeTrigger = trigger();\nconst basicShakeConfig = {\n    trigger: basicShakeTrigger,\n    intensity: 15,\n    duration: 500,\n    frequency: 10,\n    direction: 'both'\n};\n\n// Horizontal shake - only shakes on X axis\nconst horizontalShakeTrigger = trigger();\nconst horizontalShakeConfig = {\n    trigger: horizontalShakeTrigger,\n    intensity: 15,\n    duration: 500,\n    frequency: 10,\n    direction: 'x'\n};\n\n// Vertical shake - only shakes on Y axis\nconst verticalShakeTrigger = trigger();\nconst verticalShakeConfig = {\n    trigger: verticalShakeTrigger,\n    intensity: 15,\n    duration: 500,\n    frequency: 10,\n    direction: 'y'\n};\n\n// Intense shake - higher intensity and frequency\nconst intenseShakeTrigger = trigger();\nconst intenseShakeConfig = {\n    trigger: intenseShakeTrigger,\n    intensity: 25,\n    duration: 400,\n    frequency: 15,\n    direction: 'both'\n};\n</script>\n\n        `,\n    },\n},\n];\n\nexport default examples;"
  },
  {
    "path": "docs/.vitepress/theme/index.ts",
    "content": "import DefaultTheme from \"vitepress/theme\";\nimport CustomHome from \"./components/CustomHome.vue\";\nimport Playground from \"./components/Playground.vue\";\nimport Layout from \"./Layout.vue\";\nimport \"./style.css\";\n\nexport default {\n  ...DefaultTheme,\n  Layout,\n  enhanceApp(ctx) {\n    DefaultTheme.enhanceApp(ctx);\n    ctx.app.component('CustomHome', CustomHome);\n    ctx.app.component('Playground', Playground);\n  },\n};\n"
  },
  {
    "path": "docs/.vitepress/theme/style.css",
    "content": "/* Custom theme styles */\n:root {\n  --vp-c-brand: #646cff;\n  --vp-c-brand-light: #747bff;\n  --vp-c-brand-lighter: #9499ff;\n  --vp-c-brand-lightest: #bcc0ff;\n  --vp-c-brand-dark: #535bf2;\n  --vp-c-brand-darker: #454ce1;\n  --vp-c-brand-dimm: rgba(100, 108, 255, 0.08);\n}\n\n/* Hide default layout for custom home */\n.custom-layout .VPContent {\n  padding: 0 !important;\n}\n\n/* Smooth scrolling */\nhtml {\n  scroll-behavior: smooth;\n}\n\n/* Custom scrollbar */\n::-webkit-scrollbar {\n  width: 8px;\n}\n\n::-webkit-scrollbar-track {\n  background: var(--vp-c-bg-soft);\n}\n\n::-webkit-scrollbar-thumb {\n  background: var(--vp-c-brand);\n  border-radius: 4px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n  background: var(--vp-c-brand-dark);\n} "
  },
  {
    "path": "docs/advanced/conditional-rendering.md",
    "content": "# Conditional Rendering\n\nThe `cond()` function allows you to conditionally render elements based on reactive signals or static boolean values. It supports if/else if/else patterns for complex conditional logic.\n\n## Basic Usage\n\n### Simple Condition\n\n```typescript\nimport { cond, signal, h, Text } from 'canvasengine';\n\nconst isVisible = signal(true);\n\nconst conditionalText = cond(\n  isVisible,\n  () => h(Text, { text: 'I am visible!' })\n);\n```\n\n### With Else\n\n```typescript\nconst conditionalText = cond(\n  isVisible,\n  () => h(Text, { text: 'Visible' }),\n  () => h(Text, { text: 'Hidden' }) // else case\n);\n```\n\n## Advanced Usage\n\n### Multiple Conditions (else if)\n\n```typescript\nconst status = signal('loading');\n\nconst statusDisplay = cond(\n  () => status() === 'loading',\n  () => h(Text, { text: 'Loading...', color: 'yellow' }),\n  [() => status() === 'error', () => h(Text, { text: 'Error!', color: 'red' })], // else if\n  [() => status() === 'success', () => h(Text, { text: 'Success!', color: 'green' })], // else if\n  () => h(Text, { text: 'Unknown status', color: 'gray' }) // else\n);\n```\n\n### Grade System Example\n\n```typescript\nconst score = signal(85);\n\nconst gradeDisplay = cond(\n  () => score() >= 90,\n  () => h(Text, { text: 'A+', color: 'gold' }),\n  [() => score() >= 80, () => h(Text, { text: 'A', color: 'green' })],\n  [() => score() >= 70, () => h(Text, { text: 'B', color: 'blue' })],\n  [() => score() >= 60, () => h(Text, { text: 'C', color: 'orange' })],\n  () => h(Text, { text: 'F', color: 'red' }) // else\n);\n```\n\n## Condition Types\n\nThe `cond()` function accepts three types of conditions:\n\n1. **Signals**: Reactive values that trigger re-evaluation when changed\n2. **Static booleans**: Simple true/false values\n3. **Functions**: Functions that return boolean values (automatically converted to computed signals)\n\n### Examples\n\n```typescript\n// Signal condition\nconst showElement = signal(true);\ncond(showElement, () => h(Text, { text: 'Signal condition' }));\n\n// Static boolean condition\ncond(true, () => h(Text, { text: 'Static condition' }));\n\n// Function condition (reactive)\nconst user = signal({ role: 'admin' });\ncond(\n  () => user().role === 'admin',\n  () => h(Text, { text: 'Admin panel' })\n);\n```\n\n## Reactivity\n\nAll conditions are reactive. When any signal used in the conditions changes, the `cond()` function automatically re-evaluates and updates the rendered element:\n\n```typescript\nconst userRole = signal('guest');\n\nconst navigation = cond(\n  () => userRole() === 'admin',\n  () => h(Container, { children: [\n    h(Text, { text: 'Admin Dashboard' }),\n    h(Text, { text: 'User Management' }),\n    h(Text, { text: 'Settings' })\n  ]}),\n  [() => userRole() === 'user', () => h(Container, { children: [\n    h(Text, { text: 'Dashboard' }),\n    h(Text, { text: 'Profile' })\n  ]})],\n  () => h(Text, { text: 'Please log in' }) // guest\n);\n\n// Changing the role will automatically update the UI\nuserRole.set('admin'); // Shows admin navigation\nuserRole.set('user');  // Shows user navigation\nuserRole.set('guest'); // Shows login message\n```\n\n## Performance\n\n- **Lazy evaluation**: Only the matching condition's element is created\n- **Automatic cleanup**: Previous elements are properly destroyed when conditions change\n- **Optimized updates**: Elements are only updated when the matching condition actually changes\n\n## Best Practices\n\n1. **Order matters**: Conditions are evaluated in order, the first `true` condition wins\n2. **Use functions for complex logic**: Convert complex boolean expressions to functions for better reactivity\n3. **Provide fallbacks**: Always consider adding an `else` case for unexpected states\n4. **Keep conditions simple**: Complex logic should be extracted to computed signals or functions\n\n```typescript\n// Good: Simple, readable conditions\nconst theme = signal('dark');\ncond(\n  () => theme() === 'dark',\n  () => h(Text, { text: 'Dark mode', color: 'white' }),\n  () => h(Text, { text: 'Light mode', color: 'black' })\n);\n\n// Better: Extract complex logic\nconst isDarkMode = computed(() => {\n  const currentTheme = theme();\n  const userPreference = getUserPreference();\n  const systemPreference = getSystemPreference();\n  \n  return currentTheme === 'dark' || \n         (currentTheme === 'auto' && (userPreference === 'dark' || systemPreference === 'dark'));\n});\n\ncond(\n  isDarkMode,\n  () => h(Text, { text: 'Dark mode', color: 'white' }),\n  () => h(Text, { text: 'Light mode', color: 'black' })\n);\n``` "
  },
  {
    "path": "docs/advanced/performance.md",
    "content": "# Performance Optimization Guide\n\nWhen building games or visualizations with many elements (1000+), performance becomes critical. This guide covers best practices for optimizing CanvasEngine applications.\n\n## Understanding the Reactive System Cost\n\nCanvasEngine uses a reactive system based on signals. Each signal creates:\n- An RxJS subscription\n- Change detection overhead\n- Component update callbacks\n\n**Rule of thumb**: Minimize the number of signals, especially for properties that change frequently.\n\n### Signal Count Impact\n\n| Elements | Signals/Element | Total Signals | Estimated Cost |\n|----------|-----------------|---------------|----------------|\n| 100 | 5 | 500 | Low |\n| 1000 | 5 | 5,000 | Medium |\n| 5000 | 5 | 25,000 | High |\n| 5000 | 2 | 10,000 | Medium |\n\n## Optimization Strategies\n\n### 1. Reduce Signal Granularity\n\nInstead of creating signals for every property, only use signals for properties that need reactive updates from external sources.\n\n**Before (expensive)**:\n```javascript\n// 5 signals per element = 25,000 signals for 5000 elements\nfunction generateItems(count) {\n  return Array.from({ length: count }, (_, i) => ({\n    x: signal(i * 10),\n    y: signal(i * 10),\n    rotation: signal(0),      // Animated - DON'T use signal!\n    alpha: signal(1),         // Animated - DON'T use signal!\n    scale: signal(1),         // Animated - DON'T use signal!\n  }));\n}\n```\n\n**After (optimized)**:\n```javascript\n// 2 signals per element = 10,000 signals for 5000 elements\nfunction generateItems(count) {\n  return Array.from({ length: count }, (_, i) => ({\n    x: signal(i * 10),        // Position needs signals for loop\n    y: signal(i * 10),\n    rotationSpeed: Math.random() * 0.1,  // Plain value\n    alphaBase: 0.5 + Math.random() * 0.5, // Plain value\n    scaleBase: 0.8 + Math.random() * 0.4, // Plain value\n  }));\n}\n```\n\n### 2. Imperative Animation in tick()\n\nFor animations, update Pixi objects directly instead of going through signals:\n\n```html\n<script>\n  import { tick } from 'canvasengine';\n  \n  tick((tickValue, element) => {\n    // Get the container with sprites\n    const container = element.componentInstance.children[0];\n    const sprites = container.children;\n    const items = itemsSignal();\n    \n    sprites.forEach((sprite, i) => {\n      const item = items[i];\n      // Direct Pixi manipulation - no signal overhead!\n      sprite.rotation = item.rotationSpeed * tickValue.frame;\n      sprite.alpha = item.alphaBase + Math.sin(tickValue.frame * 0.05) * 0.2;\n    });\n  });\n</script>\n```\n\n### 3. Incremental Collection Updates\n\nWhen adding/removing elements, avoid resetting the entire collection:\n\n**Before (expensive)**:\n```javascript\n// This triggers a full reset - destroys and recreates ALL elements\nitems.set(generateItems(newCount));\n```\n\n**After (optimized)**:\n```javascript\neffect(() => {\n  const targetCount = elementCount();\n  const currentItems = items();\n  const currentCount = currentItems.length;\n  \n  if (targetCount > currentCount) {\n    // Add only new elements\n    const newItems = [...currentItems];\n    for (let i = currentCount; i < targetCount; i++) {\n      newItems.push(createItem(i));\n    }\n    items.set(newItems);\n  } else if (targetCount < currentCount) {\n    // Remove from end - avoids full recreation\n    items.set(currentItems.slice(0, targetCount));\n  }\n});\n```\n\n### 4. Frame Throttling\n\nFor non-critical updates, skip frames:\n\n```javascript\ntick((tickValue) => {\n  // Update every 2nd frame (30 FPS effective)\n  if (tickValue.frame % 2 !== 0) return;\n  \n  // Or every 3rd frame (20 FPS effective)\n  if (tickValue.frame % 3 !== 0) return;\n  \n  // Animation logic\n});\n```\n\n### 5. Level of Detail (LOD)\n\nReduce visual complexity based on element count:\n\n```javascript\ntick((tickValue, element) => {\n  const count = items().length;\n  const sprites = getSprites(element);\n  \n  sprites.forEach((sprite, i) => {\n    // Always animate rotation (cheap)\n    sprite.rotation += items()[i].rotationSpeed;\n    \n    // Animate alpha only below 5000 elements\n    if (count < 5000) {\n      sprite.alpha = 0.5 + Math.sin(tickValue.frame * 0.02) * 0.5;\n    }\n    \n    // Animate scale only below 2000 elements\n    if (count < 2000) {\n      const scale = 1 + Math.sin(tickValue.frame * 0.01) * 0.2;\n      sprite.scale.set(scale);\n    }\n  });\n});\n```\n\n### 6. Viewport Culling\n\nUse the `viewportCull` directive to hide off-screen elements:\n\n```html\n<Viewport worldWidth=\"5000\" worldHeight=\"5000\">\n  <Container viewportCull={true}>\n    @for (item of items) {\n      <Sprite x={item().x} y={item().y} />\n    }\n  </Container>\n</Viewport>\n```\n\n## Complete Optimized Example\n\n```html\n<Canvas>\n  <Viewport worldWidth={worldWidth} worldHeight={worldHeight} drag={true}>\n    <Container>\n      @for (item of items) {\n        <Sprite \n          image=\"sprite.png\"\n          x={item().x}\n          y={item().y}\n        />\n      }\n    </Container>\n  </Viewport>\n</Canvas>\n\n<script>\n  import { signal, computed, effect, tick } from 'canvasengine';\n  \n  const elementCount = signal(1000);\n  let spriteRefs = [];\n  \n  // Optimized: Only position signals\n  function createItem(index, cols) {\n    const col = index % cols;\n    const row = Math.floor(index / cols);\n    return {\n      x: signal(col * 50),\n      y: signal(row * 50),\n      rotationSpeed: (Math.random() - 0.5) * 0.1,\n      alphaBase: 0.5 + Math.random() * 0.5,\n    };\n  }\n  \n  const items = signal([]);\n  \n  // Incremental updates\n  effect(() => {\n    const target = elementCount();\n    const current = items();\n    const cols = Math.ceil(Math.sqrt(target));\n    \n    if (target > current.length) {\n      const newItems = [...current];\n      for (let i = current.length; i < target; i++) {\n        newItems.push(createItem(i, cols));\n      }\n      items.set(newItems);\n      spriteRefs = []; // Reset cache\n    } else if (target < current.length) {\n      items.set(current.slice(0, target));\n      spriteRefs = [];\n    }\n  });\n  \n  // Imperative animation\n  tick((tickValue, element) => {\n    const viewport = element.componentInstance?.children?.[0];\n    const container = viewport?.children?.[0];\n    \n    if (spriteRefs.length === 0 && container) {\n      spriteRefs = container.children;\n    }\n    \n    const data = items();\n    const count = data.length;\n    \n    spriteRefs.forEach((sprite, i) => {\n      if (!sprite || !data[i]) return;\n      \n      sprite.rotation += data[i].rotationSpeed;\n      \n      // LOD: alpha only below 3000\n      if (count < 3000) {\n        sprite.alpha = data[i].alphaBase + \n          Math.sin(tickValue.frame * 0.02) * 0.3;\n      }\n    });\n  });\n  \n  const worldWidth = computed(() => Math.ceil(Math.sqrt(elementCount())) * 50);\n  const worldHeight = worldWidth;\n</script>\n```\n\n## Performance Checklist\n\n- [ ] Minimize signals per element (2-3 max for large collections)\n- [ ] Use imperative updates in `tick()` for animations\n- [ ] Implement incremental add/remove for collections\n- [ ] Add frame throttling for non-critical updates\n- [ ] Implement LOD for very large element counts\n- [ ] Enable viewport culling for scrollable worlds\n- [ ] Profile with browser DevTools to identify bottlenecks\n\n## Benchmark\n\nRun the benchmark in `sample/src/benchmark.ce` to test different optimization modes:\n\n```bash\ncd sample\nnpm run dev\n```\n\nPress `1-4` to switch between optimization modes and observe FPS differences.\n"
  },
  {
    "path": "docs/advanced/without-compiler.md",
    "content": "# Using CanvasEngine Without the Compiler\n\nCanvasEngine provides a powerful template syntax that gets compiled to JavaScript functions. However, you can also use CanvasEngine directly without the compiler by using the core functions: `h`, `loop`, and `cond` from the `canvasengine` package.\n\nThis approach gives you more control and can be useful for:\n- Dynamic template generation\n- Integration with existing build systems\n- Learning how the compiler works under the hood\n- Performance-critical applications where you want to avoid compilation overhead\n\n## Core Functions\n\n### `h(component, props?, children?)`\nCreates a component instance. This is the equivalent of JSX elements.\n\n### `loop(iterable, callback)`\nRenders a list of items. This is the equivalent of `@for` loops.\n\n### `cond(condition, callback)`\nConditionally renders content. This is the equivalent of `@if` statements.\n\n## Components\n\n### Basic Component\nInstead of writing:\n```html\n<Canvas />\n```\n\nUse:\n```javascript\nh('Canvas')\n```\n\n### Component with Properties\nInstead of writing:\n```html\n<Canvas width=\"800\" height=\"600\" />\n```\n\nUse:\n```javascript\nh('Canvas', { width: '800', height: '600' })\n```\n\n### Dynamic Properties\nInstead of writing:\n```html\n<Canvas width={screenWidth} height={screenHeight} />\n```\n\nUse:\n```javascript\nh('Canvas', { width: screenWidth, height: screenHeight })\n```\n\n### Computed Properties\nFor reactive expressions, instead of writing:\n```html\n<Canvas width={x * 2} />\n```\n\nUse:\n```javascript\nh('Canvas', { width: computed(() => x() * 2) })\n```\n\n### Complex Computed Properties\nFor multiple reactive variables:\n```html\n<Canvas width={x * 2 * y} />\n```\n\nUse:\n```javascript\nh('Canvas', { width: computed(() => x() * 2 * y()) })\n```\n\n### Object Properties\nInstead of writing:\n```html\n<Sprite sheet={{\n    definition,\n    playing: \"stand\",\n    params: {\n        direction: \"right\"\n    },\n    onFinish\n}} />\n```\n\nUse:\n```javascript\nh('Sprite', { \n  sheet: { \n    definition, \n    playing: \"stand\", \n    params: { \n      direction: \"right\" \n    }, \n    onFinish \n  } \n})\n```\n\n### Array Properties\nInstead of writing:\n```html\n<Canvas positions={[x, 20]} />\n```\n\nUse:\n```javascript\nh('Canvas', { positions: computed(() => [x(), 20]) })\n```\n\n### Event Handlers\nInstead of writing:\n```html\n<Sprite click={handleClick} />\n```\n\nUse:\n```javascript\nh('Sprite', { click: handleClick })\n```\n\n### Inline Event Handlers\nInstead of writing:\n```html\n<Sprite click={() => console.log('clicked')} />\n```\n\nUse:\n```javascript\nh('Sprite', { click: () => console.log('clicked') })\n```\n\n### Spread Operator\nInstead of writing:\n```html\n<Canvas ...props />\n```\n\nUse:\n```javascript\nh('Canvas', props)\n```\n\n### Component as Property\nInstead of writing:\n```html\n<Canvas child={<Sprite />} />\n```\n\nUse:\n```javascript\nh('Canvas', { child: h('Sprite') })\n```\n\n### Function Returning Component\nInstead of writing:\n```html\n<Canvas child={() => <Sprite />} />\n```\n\nUse:\n```javascript\nh('Canvas', { child: () => h('Sprite') })\n```\n\n## Children\n\n### Single Child\nInstead of writing:\n```html\n<Canvas>\n    <Sprite />\n</Canvas>\n```\n\nUse:\n```javascript\nh('Canvas', null, h('Sprite'))\n```\n\n### Multiple Children\nInstead of writing:\n```html\n<Canvas>\n    <Sprite />\n    <Text />\n</Canvas>\n```\n\nUse:\n```javascript\nh('Canvas', null, [\n    h('Sprite'),\n    h('Text')\n])\n```\n\n## Loops\n\n### Basic Loop\nInstead of writing:\n```html\n@for (sprite of sprites) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\nloop(sprites, sprite => h('Sprite'))\n```\n\n### Loop with Properties\nInstead of writing:\n```html\n@for (sprite of sprites) {\n    <Sprite x={sprite.x} y={sprite.y} />\n}\n```\n\nUse:\n```javascript\nloop(sprites, sprite => h('Sprite', { x: sprite.x, y: sprite.y }))\n```\n\n### Loop with Index\nInstead of writing:\n```html\n@for ((sprite, index) of sprites) {\n    <Sprite key={index} />\n}\n```\n\nUse:\n```javascript\nloop(sprites, (sprite, index) => h('Sprite', { key: index }))\n```\n\n### Loop with Object Property\nInstead of writing:\n```html\n@for (sprite of sprites.items) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\nloop(sprites.items, sprite => h('Sprite'))\n```\n\n### Loop with Function Call\nInstead of writing:\n```html\n@for (sprite of getSprites()) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\nloop(getSprites(), sprite => h('Sprite'))\n```\n\n### Nested Loops\nInstead of writing:\n```html\n@for (sprite of sprites) {\n    @for (other of others) {\n        <Sprite />\n    }\n}\n```\n\nUse:\n```javascript\nloop(sprites, sprite => \n    loop(others, other => h('Sprite'))\n)\n```\n\n### Loop in Component\nInstead of writing:\n```html\n<Canvas>\n    @for (sprite of sprites) {\n        <Sprite />\n    }\n</Canvas>\n```\n\nUse:\n```javascript\nh('Canvas', null, loop(sprites, sprite => h('Sprite')))\n```\n\n## Conditions\n\n### Basic Condition\nInstead of writing:\n```html\n@if (sprite) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\ncond(sprite, () => h('Sprite'))\n```\n\n### Property-based Condition\nInstead of writing:\n```html\n@if (sprite.visible) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\ncond(sprite.visible, () => h('Sprite'))\n```\n\n### Function-based Condition\nInstead of writing:\n```html\n@if (isVisible()) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\ncond(isVisible(), () => h('Sprite'))\n```\n\n### Complex Conditions\nInstead of writing:\n```html\n@if (!sprite && other) {\n    <Sprite />\n}\n```\n\nUse:\n```javascript\ncond(computed(() => !sprite() && other()), () => h('Sprite'))\n```\n\n### Multiple Conditions\nInstead of writing:\n```html\n@if (sprite) {\n    <Sprite />\n}\n@if (other) {\n    <Text />\n}\n```\n\nUse:\n```javascript\n[\n    cond(sprite, () => h('Sprite')),\n    cond(other, () => h('Text'))\n]\n```\n\n### Nested Conditions\nInstead of writing:\n```html\n@if (sprite.visible) {\n    @if (deep) {\n        <Sprite />\n    }\n}\n```\n\nUse:\n```javascript\ncond(sprite.visible, () => \n    cond(deep, () => h('Sprite'))\n)\n```\n\n### Condition with Multiple Elements\nInstead of writing:\n```html\n@if (sprite.visible) {\n    <Sprite />\n    <Text />\n}\n```\n\nUse:\n```javascript\ncond(sprite.visible, () => [\n    h('Sprite'),\n    h('Text')\n])\n```\n\n## Combining Loops and Conditions\n\n### Condition in Loop\nInstead of writing:\n```html\n<Canvas>\n    @for (sprite of sprites) {\n        @if (sprite.visible) {\n            <Sprite />\n        }\n    }\n</Canvas>\n```\n\nUse:\n```javascript\nh('Canvas', null, \n    loop(sprites, sprite => \n        cond(sprite.visible, () => h('Sprite'))\n    )\n)\n```\n\n### Multiple Loops\nInstead of writing:\n```html\n<Canvas>\n    @for (sprite of sprites) {\n        <Sprite />\n    }\n    @for (other of others) {\n        <Text />\n    }\n</Canvas>\n```\n\nUse:\n```javascript\nh('Canvas', null, [\n    loop(sprites, sprite => h('Sprite')),\n    loop(others, other => h('Text'))\n])\n```\n\n## Complete Example\n\nHere's a complete example showing how to build a complex component without the compiler:\n\n```javascript\nimport { h, loop, cond, computed } from 'canvasengine';\n\nfunction GameScene({ sprites, enemies, showUI }) {\n    return h('Canvas', { width: 800, height: 600 }, [\n        // Background\n        h('Sprite', { texture: 'background' }),\n        \n        // Player sprites\n        loop(sprites, sprite => \n            cond(sprite.visible, () => \n                h('Sprite', {\n                    x: sprite.x,\n                    y: sprite.y,\n                    texture: sprite.texture,\n                    click: () => sprite.onClick()\n                })\n            )\n        ),\n        \n        // Enemies\n        loop(enemies, (enemy, index) => \n            h('Sprite', {\n                key: index,\n                x: computed(() => enemy.x() + 10),\n                y: computed(() => enemy.y() + 10),\n                texture: enemy.texture,\n                tint: enemy.isHit ? 0xff0000 : 0xffffff\n            })\n        ),\n        \n        // UI overlay\n        cond(showUI, () => \n            h('Container', null, [\n                h('Text', { text: 'Score: 100', x: 10, y: 10 }),\n                h('Text', { text: 'Lives: 3', x: 10, y: 30 })\n            ])\n        )\n    ]);\n}\n```\n\nThis approach gives you the full power of CanvasEngine while maintaining complete control over your component structure and logic."
  },
  {
    "path": "docs/api/context.md",
    "content": "# Context\n\nThe context is an object that is automatically provided to all components in the component tree. It contains shared resources and utilities that are available throughout your application.\n\n## Available Properties\n\nThe context object contains the following properties:\n\n| Name | Type | Description |\n|------|------|-------------|\n| `app` | `() => Application \\| null` | Function that returns the PixiJS Application instance. Returns `null` until the canvas is rendered. |\n| `canvasSize` | `Signal<{ width: number, height: number }>` | Signal containing the current width and height of the canvas. Updates automatically when the canvas is resized. |\n| `globalLoader` | `GlobalAssetLoader` | Global asset loader instance that tracks loading progress of all assets across the component tree. See [GlobalAssetLoader documentation](/components/sprite.html#global-asset-loader) for more details. |\n| `tick` | `Signal<Tick>` | Signal containing the ticker information. Updates on each frame with timing and frame data. See [Tick interface](#tick-interface) below. |\n| `rootElement` | `Element` | The root Canvas element. See [Element documentation](./element.md) for more details. |\n\n## Tick Interface\n\nThe `tick` signal contains the following properties:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `timestamp` | `number` | Current timestamp in milliseconds |\n| `deltaTime` | `number` | Time elapsed since the last frame in milliseconds |\n| `frame` | `number` | Current frame number |\n| `deltaRatio` | `number` | Ratio of deltaTime to the target frame time (useful for frame-independent animations) |\n\n## Accessing Context\n\nYou can access the context through the `element.props.context` property in any component:\n\n```html\n<script>\n  import { mount, effect } from 'canvasengine';\n\n  mount((element) => {\n    const context = element.props.context;\n    \n    // Access PixiJS Application\n    const app = context.app();\n    if (app) {\n      console.log('PixiJS Application:', app);\n    }\n    \n    // Access canvas size signal\n    const canvasSize = context.canvasSize();\n    console.log('Canvas size:', canvasSize.width, canvasSize.height);\n    \n    // Subscribe to canvas size changes using effect\n    effect(() => {\n      const size = context.canvasSize();\n      console.log('Canvas resized:', size.width, size.height);\n    });\n    \n    // Access global loader\n    context.globalLoader.onProgress((progress) => {\n      console.log('Loading progress:', progress * 100 + '%');\n    });\n    \n    context.globalLoader.onComplete(() => {\n      console.log('All assets loaded!');\n    });\n    \n    // Access tick signal\n    const tick = context.tick();\n    console.log('Current frame:', tick.frame);\n    console.log('Delta time:', tick.deltaTime);\n    \n    // Subscribe to tick updates using effect\n    effect(() => {\n      const tick = context.tick();\n      console.log('Frame:', tick.frame, 'Delta:', tick.deltaTime);\n    });\n    \n    // Access root element\n    console.log('Root element:', context.rootElement);\n  });\n</script>\n```\n\n## Examples\n\n### Using Canvas Size for Responsive Layouts\n\n```html\n<Container>\n  <Sprite image=\"background.png\" />\n</Container>\n\n<script>\n  import { mount, effect } from 'canvasengine';\n\n  mount((element) => {\n    const context = element.props.context;\n    \n    // Center sprite based on canvas size\n    effect(() => {\n      const size = context.canvasSize();\n      const sprite = element.componentInstance;\n      sprite.x = size.width / 2;\n      sprite.y = size.height / 2;\n      sprite.anchor.set(0.5);\n    });\n  });\n</script>\n```\n\n### Tracking Asset Loading Progress\n\n```html\n<Container>\n  <Sprite image=\"image1.png\" />\n  <Sprite image=\"image2.png\" />\n  <Sprite image=\"image3.png\" />\n</Container>\n\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    const context = element.props.context;\n    \n    // Show loading progress\n    context.globalLoader.onProgress((progress) => {\n      const percentage = Math.round(progress * 100);\n      console.log(`Loading: ${percentage}%`);\n    });\n    \n    // Hide loading screen when complete\n    context.globalLoader.onComplete(() => {\n      console.log('All assets loaded!');\n      // Hide your loading screen here\n    });\n  });\n</script>\n```\n\n### Using Tick for Frame-Independent Animations\n\n```html\n<Sprite image=\"sprite.png\" />\n\n<script>\n  import { mount, effect } from 'canvasengine';\n\n  mount((element) => {\n    const context = element.props.context;\n    const sprite = element.componentInstance;\n    \n    // Move sprite at constant speed regardless of FPS\n    effect(() => {\n      const tick = context.tick();\n      // deltaRatio ensures consistent movement speed\n      sprite.x += 100 * tick.deltaRatio; // 100 pixels per second\n      \n      if (sprite.x > 800) {\n        sprite.x = 0; // Reset when off screen\n      }\n    });\n  });\n</script>\n```\n\n### Accessing PixiJS Application\n\n```html\n<Container>\n  <Sprite image=\"sprite.png\" />\n</Container>\n\n<script>\n  import { mount, effect } from 'canvasengine';\n\n  mount((element) => {\n    const context = element.props.context;\n    \n    // Wait for app to be initialized\n    effect(() => {\n      const app = context.app();\n      if (app) {\n        console.log('PixiJS Application:', app);\n        console.log('Renderer:', app.renderer);\n        console.log('Stage:', app.stage);\n        \n        // You can now use any PixiJS API\n        app.ticker.add(() => {\n          // Custom ticker logic\n        });\n      }\n    });\n  });\n</script>\n```\n"
  },
  {
    "path": "docs/api/element.md",
    "content": "# Element Interface\n\nThe Element interface represents a component in the framework. It contains all the necessary properties and methods to manage a component's lifecycle, props, effects, and relationships.\n\n## Properties and Methods\n\n| Name | Type | Description |\n|------|------|-------------|\n| `tag` | `string` | The HTML tag name or component name |\n| `props` | `Props` | The component's properties/attributes |\n| `componentInstance` | `T` | The instance of the component. It is the PixiJS instance |\n| `propObservables` | `NestedSignalObjects \\| undefined` | Observable objects for reactive properties |\n| `parent` | `Element \\| null` | Reference to the parent element. Null if it's a root element |\n| `context` | `{ [key: string]: any }` | Optional context object for sharing data between components |\n| `directives` | `{ [key: string]: Directive }` | Map of directives applied to the element |\n| `destroy` | `() => void` | Cleanup method called when the element is being destroyed |\n| `isFrozen` | `boolean` | Indicates whether the element is currently frozen (read-only)\n\n## Examples\n\n### Get the tag name\n\n```html\n<Container x={5} y={5} />\n\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    console.log(element.tag)\n    console.log(element.parent)\n    console.log(element.props)\n  });\n</script>\n```\n\n### Get the children components:\n\n```html\n<Container x={5} y={5}>\n  <Rect x={5} y={5} width={10} height={10} color=\"red\" />\n</Container>\n\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    console.log(element.props.children)\n  });\n</script>\n```\n\n### Get context\n```html\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    console.log(element.props.context)\n  });\n</script>\n```\n\n### Get the reactive props\n\n```html\n<Container x y />\n\n<script>\n    import { mount, signal } from 'canvasengine'\n\n    const x = signal(5)\n    const y = signal(5)\n\n    mount((element) => {\n        const x = element.propObservables.x\n\n        // Get signal value\n        console.log(x())\n\n        // Subscribe to the RxJS observable\n        x.observable.subscribe((value) => {\n            console.log(value)\n        })\n    })\n</script>\n\n```\n\n### Get directives\n\nYou can access directive instances through the `directives` property. Each directive is stored with its attribute name as the key.\n\n```html\n<Sprite image=\"path/to/image.png\" controls drag />\n\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    // Access the controls directive instance\n    const controlsInstance = element.directives.controls;\n    \n    if (controlsInstance) {\n      // Use methods from the directive instance\n      // For example, with controls directive:\n      // controlsInstance.stopInputs()\n      // controlsInstance.getControls()\n    }\n    \n    // Access the drag directive instance\n    const dragInstance = element.directives.drag;\n    \n    // Check all available directives\n    console.log(Object.keys(element.directives));\n  });\n</script>\n```\n\n## Freeze System\n\nThe `freeze` prop allows you to completely freeze an element, preventing all updates, controls, and events. When an element is frozen:\n\n- **Reactive updates are blocked**: No `onUpdate` calls are made when signal values change\n- **Controls are blocked**: All input controls (keyboard, gamepad, joystick) are stopped\n- **Events are blocked**: Event handlers (click, mousedown, etc.) are not executed\n\nThe `freeze` prop accepts either a `boolean` or `Signal<boolean>`, allowing you to toggle the freeze state dynamically.\n\n### Basic Usage\n\n```html\n<!-- Freeze with boolean -->\n<Sprite image=\"path/to/image.png\" freeze={true} />\n\n<!-- Freeze with signal (dynamic) -->\n<Sprite image=\"path/to/image.png\" freeze={freezeSignal} />\n```\n\n### Example: Dynamic Freeze\n\n```html\n<Canvas>\n    <Container>\n        <Text text=\"Click to toggle freeze\" x={10} y={10} />\n        <Sprite \n            image=\"hero.png\"\n            x={x}\n            y={y}\n            freeze={isFrozen}\n            controls={{\n                up: {\n                    bind: 'ArrowUp',\n                    keyDown: () => y.set(y() - 10)\n                }\n            }}\n            click={() => {\n                console.log('Sprite clicked!')\n            }}\n        />\n    </Container>\n</Canvas>\n\n<script>\n    import { signal } from 'canvasengine';\n    \n    const isFrozen = signal(false);\n    const x = signal(100);\n    const y = signal(100);\n    \n    // Toggle freeze state\n    function toggleFreeze() {\n        isFrozen.set(!isFrozen());\n    }\n</script>\n```\n\n### Example: Blocking Updates\n\nWhen frozen, reactive property updates are completely blocked:\n\n```html\n<Sprite \n    image=\"hero.png\"\n    x={xSignal}\n    y={ySignal}\n    freeze={freezeSignal}\n/>\n\n<script>\n    import { signal } from 'canvasengine';\n    \n    const freezeSignal = signal(false);\n    const xSignal = signal(0);\n    const ySignal = signal(0);\n    \n    // When freezeSignal is true, these updates won't trigger onUpdate\n    xSignal.set(100);\n    ySignal.set(200);\n</script>\n```\n\n### Example: Blocking Controls\n\nWhen frozen, all controls are automatically stopped:\n\n```html\n<Sprite \n    image=\"hero.png\"\n    freeze={freezeSignal}\n    controls={{\n        move: {\n            bind: 'ArrowUp',\n            keyDown: () => {\n                console.log('Moving...'); // Won't execute when frozen\n            }\n        }\n    }}\n/>\n```\n\n### Example: Blocking Events\n\nWhen frozen, event handlers are not executed:\n\n```html\n<Sprite \n    image=\"hero.png\"\n    freeze={freezeSignal}\n    click={() => {\n        console.log('Clicked!'); // Won't execute when frozen\n    }}\n    mousedown={() => {\n        console.log('Mouse down!'); // Won't execute when frozen\n    }}\n/>\n```\n\n### Checking Freeze State\n\nYou can check if an element is frozen using the `isElementFrozen` helper function:\n\n```html\n<script>\n    import { isElementFrozen } from 'canvasengine';\n    \n    mount((element) => {\n        if (isElementFrozen(element)) {\n            console.log('Element is frozen');\n        }\n    });\n</script>\n```\n\nOr access the `isFrozen` property directly:\n\n```html\n<script>\n    mount((element) => {\n        console.log('Is frozen:', element.isFrozen);\n    });\n</script>\n```"
  },
  {
    "path": "docs/api/testing.md",
    "content": "# Testing Package\n\nThe `@canvasengine/testing` package provides comprehensive testing utilities and mocks for CanvasEngine. It allows you to test your CanvasEngine components without requiring a full PixiJS environment or jsdom setup.\n\n## Installation\n\n```bash\nnpm install @canvasengine/testing --save-dev\n```\n\nor with pnpm:\n\n```bash\npnpm add @canvasengine/testing --save-dev\n```\n\n## Overview\n\nThe testing package includes:\n\n- **PixiJS Mocks**: Complete mocks for all PixiJS classes used in CanvasEngine (Container, Sprite, Text, Application, etc.)\n- **Element Helpers**: Utilities to create mock elements with spyable `componentInstance`\n- **Spy Utilities**: Helpers to easily spy on element properties and methods\n\n## PixiJS Mocks\n\nThe package provides mocks for all major PixiJS classes:\n\n- `MockContainer` - Mock for PixiJS Container\n- `MockSprite` - Mock for PixiJS Sprite\n- `MockText` - Mock for PixiJS Text\n- `MockGraphics` - Mock for PixiJS Graphics\n- `MockMesh` - Mock for PixiJS Mesh\n- `MockTilingSprite` - Mock for PixiJS TilingSprite\n- `MockNineSlicePlane` - Mock for PixiJS NineSlicePlane\n- `MockDOMElement` - Mock for PixiJS DOMElement\n- `MockDOMContainer` - Mock for PixiJS DOMContainer\n- `MockApplication` - Mock for PixiJS Application\n- `MockTexture` - Mock for PixiJS Texture\n- `MockRectangle` - Mock for PixiJS Rectangle\n- `MockObservablePoint` - Mock for PixiJS ObservablePoint\n- `MockVideoResource` - Mock for PixiJS VideoResource\n\nAll mocks include:\n- Essential properties (x, y, width, height, alpha, visible, rotation, etc.)\n- Methods mocked with `vi.fn()` for easy spying\n- Event support (on, off, emit)\n- Child management for Container-based mocks\n\n### Using PixiJS Mocks\n\n```typescript\nimport { MockContainer, MockSprite } from '@canvasengine/testing';\n\n// Create a mock container\nconst container = new MockContainer();\ncontainer.x = 100;\ncontainer.y = 50;\ncontainer.width = 200;\ncontainer.height = 150;\n\n// Create a mock sprite\nconst sprite = new MockSprite();\nsprite.x = 10;\nsprite.y = 10;\n\n// Add sprite to container\ncontainer.addChild(sprite);\n\n// Spy on methods\nimport { vi } from 'vitest';\nconst addChildSpy = vi.spyOn(container, 'addChild');\ncontainer.addChild(new MockContainer());\nexpect(addChildSpy).toHaveBeenCalled();\n```\n\n## Creating Mock Elements\n\nThe `createMockElement` helper creates a complete mock Element with all required properties.\n\n### Basic Usage\n\n```typescript\nimport { createMockElement } from '@canvasengine/testing';\n\n// Create a basic element with default mock\nconst element = createMockElement('Container', { x: 100, y: 50 });\n\nexpect(element.tag).toBe('Container');\nexpect(element.props.x).toBe(100);\nexpect(element.componentInstance.x).toBe(100);\n```\n\n### With Custom ComponentInstance\n\n```typescript\nimport { createMockElement, MockSprite } from '@canvasengine/testing';\n\n// Create an element with custom componentInstance\nconst customInstance = new MockSprite();\nconst spriteElement = createMockElement('Sprite', { \n  image: 'hero.png',\n  x: 200,\n  y: 100\n}, customInstance);\n\nexpect(spriteElement.componentInstance).toBe(customInstance);\nexpect(spriteElement.componentInstance.x).toBe(200);\n```\n\n### Accessing componentInstance\n\nThe `componentInstance` property contains the mock PixiJS instance, which you can spy upon:\n\n```typescript\nimport { createMockElement } from '@canvasengine/testing';\nimport { vi } from 'vitest';\n\nconst element = createMockElement('Container', { x: 100 });\n\n// Access the componentInstance\nconst instance = element.componentInstance;\nexpect(instance.x).toBe(100);\n\n// Spy on properties or methods\nconst xSpy = vi.spyOn(instance, 'x', 'get');\nconst addChildSpy = vi.spyOn(instance, 'addChild');\n```\n\n## Spying on Elements\n\nThe `spyOnElement` helper makes it easy to spy on element properties and methods.\n\n### Spying on a Single Property\n\n```typescript\nimport { createMockElement, spyOnElement } from '@canvasengine/testing';\n\nconst element = createMockElement('Container', { x: 100 });\n\n// Spy on a property\nconst spy = spyOnElement(element, 'x');\nelement.componentInstance.x = 200;\n\n// Note: For property setters, you may need to use vi.spyOn directly\n// depending on your testing needs\n```\n\n### Spying on Methods\n\n```typescript\nimport { createMockElement, spyOnElement } from '@canvasengine/testing';\n\nconst element = createMockElement('Container');\n\n// Spy on a method\nconst addChildSpy = spyOnElement(element, 'addChild');\n\nelement.componentInstance.addChild(new MockContainer());\n\nexpect(addChildSpy).toHaveBeenCalled();\n```\n\n### Spying on Multiple Properties\n\n```typescript\nimport { createMockElement, spyOnElementMultiple } from '@canvasengine/testing';\n\nconst element = createMockElement('Container');\n\n// Spy on multiple methods at once\nconst spies = spyOnElementMultiple(element, ['addChild', 'removeChild', 'destroy']);\n\nelement.componentInstance.addChild(new MockContainer());\nelement.componentInstance.removeChild(element.componentInstance.children[0]);\nelement.componentInstance.destroy();\n\nexpect(spies.addChild).toHaveBeenCalled();\nexpect(spies.removeChild).toHaveBeenCalled();\nexpect(spies.destroy).toHaveBeenCalled();\n```\n\n## Creating Mock Component Instances\n\nThe `createMockComponentInstance` helper creates appropriate mock instances based on component type:\n\n```typescript\nimport { createMockComponentInstance } from '@canvasengine/testing';\n\nconst containerInstance = createMockComponentInstance('Container');\nconst spriteInstance = createMockComponentInstance('Sprite');\nconst textInstance = createMockComponentInstance('Text');\n```\n\n## Common Use Cases\n\n### Testing Component Logic\n\n```typescript\nimport { describe, test, expect, vi } from 'vitest';\nimport { createMockElement, spyOnElement } from '@canvasengine/testing';\n\ndescribe('MyComponent', () => {\n  test('should update position', () => {\n    const element = createMockElement('Container', { x: 0, y: 0 });\n    \n    // Your component logic that updates position\n    element.componentInstance.x = 100;\n    element.componentInstance.y = 50;\n    \n    expect(element.componentInstance.x).toBe(100);\n    expect(element.componentInstance.y).toBe(50);\n  });\n\n  test('should add children', () => {\n    const parent = createMockElement('Container');\n    const child = createMockElement('Sprite');\n    \n    const addChildSpy = spyOnElement(parent, 'addChild');\n    parent.componentInstance.addChild(child.componentInstance);\n    \n    expect(addChildSpy).toHaveBeenCalledWith(child.componentInstance);\n    expect(parent.componentInstance.children).toContain(child.componentInstance);\n  });\n});\n```\n\n### Testing Directives\n\n```typescript\nimport { describe, test, expect } from 'vitest';\nimport { createMockElement } from '@canvasengine/testing';\n\ndescribe('MyDirective', () => {\n  test('should apply directive to element', () => {\n    const element = createMockElement('Sprite', { x: 100, y: 100 });\n    \n    // Apply your directive\n    // directive.onInit(element);\n    \n    // Test directive behavior\n    // expect(element.directives.myDirective).toBeDefined();\n  });\n});\n```\n\n### Testing Event Handlers\n\n```typescript\nimport { describe, test, expect } from 'vitest';\nimport { createMockElement } from '@canvasengine/testing';\n\ndescribe('Event Handling', () => {\n  test('should handle click events', () => {\n    const element = createMockElement('Sprite');\n    const clickHandler = vi.fn();\n    \n    element.componentInstance.on('click', clickHandler);\n    element.componentInstance.emit('click', { x: 100, y: 100 });\n    \n    expect(clickHandler).toHaveBeenCalledWith({ x: 100, y: 100 });\n  });\n});\n```\n\n## Migration from Manual Mocks\n\nIf you're currently creating manual mocks in your tests, you can migrate to use `@canvasengine/testing`:\n\n### Before\n\n```typescript\n// Manual mock\nclass MockContainer {\n  x = 0;\n  y = 0;\n  children = [];\n  addChild() {}\n}\n\nconst element = {\n  tag: 'Container',\n  props: { x: 100 },\n  componentInstance: new MockContainer(),\n  // ... other properties\n};\n```\n\n### After\n\n```typescript\nimport { createMockElement } from '@canvasengine/testing';\n\nconst element = createMockElement('Container', { x: 100 });\n// All properties are automatically set up\n```\n\n## Best Practices\n\n1. **Use createMockElement for Elements**: Always use `createMockElement` when you need an Element in tests. It ensures all required properties are present.\n\n2. **Spy on componentInstance**: Use `spyOnElement` to spy on the PixiJS instance methods and properties.\n\n3. **Use Appropriate Mocks**: Use the specific mock class (MockSprite, MockText, etc.) when you need a particular PixiJS class.\n\n4. **Test Behavior, Not Implementation**: Focus on testing the behavior of your components rather than internal PixiJS implementation details.\n\n5. **Clean Up**: The mocks are lightweight and don't require cleanup, but if you're using spies, remember to clear them between tests if needed.\n\n## TypeScript Support\n\nThe package is fully typed and provides TypeScript definitions for all mocks and helpers. You'll get full autocomplete and type checking in your tests.\n\n```typescript\nimport { createMockElement, Element, ComponentInstance } from '@canvasengine/testing';\n\nconst element: Element<ComponentInstance> = createMockElement('Container');\n```\n\n## Using Mocks with bootstrapCanvas\n\nThe `bootstrapCanvas` function supports component registration configuration, allowing you to use mocks for testing.\n\n### mockComponents\n\nThe `mockComponents` object provides a mapping of all CanvasEngine component names to their corresponding mock classes. You can import it from `@canvasengine/testing`:\n\n```typescript\nimport { mockComponents } from '@canvasengine/testing';\n```\n\n### Registering All Mocks\n\nTo register all components as mocks:\n\n```typescript\nimport { bootstrapCanvas } from 'canvasengine';\nimport { mockComponents } from '@canvasengine/testing';\n\nawait bootstrapCanvas(rootElement, MyComponent, {\n  components: mockComponents,\n  autoRegister: false // Only register the specified (mocked) components\n});\n```\n\n### Registering Specific Mocks\n\nTo register only specific components as mocks while keeping others as real components:\n\n```typescript\nimport { bootstrapCanvas } from 'canvasengine';\nimport { MockSprite, MockContainer, mockComponents } from '@canvasengine/testing';\n\nawait bootstrapCanvas(rootElement, MyComponent, {\n  components: {\n    Sprite: MockSprite,\n    Container: MockContainer,\n    // Other components will be registered normally\n  },\n  autoRegister: true // Register all default components, then override with mocks\n});\n```\n\n### Overriding Specific Components\n\nTo register all default components but override specific ones with mocks:\n\n```typescript\nimport { bootstrapCanvas } from 'canvasengine';\nimport { MockSprite } from '@canvasengine/testing';\n\nawait bootstrapCanvas(rootElement, MyComponent, {\n  components: {\n    Sprite: MockSprite // Replace Sprite with mock, keep others as real\n  },\n  autoRegister: true // Register all default components first\n});\n```\n\n### Available Mock Components\n\nThe `mockComponents` object includes mappings for:\n\n- `Canvas` → `MockContainer`\n- `Container` → `MockContainer`\n- `Sprite` → `MockSprite`\n- `Text` → `MockText`\n- `Graphics`, `Rect`, `Circle`, `Ellipse`, `Triangle`, `Svg` → `MockGraphics`\n- `Mesh` → `MockMesh`\n- `TilingSprite` → `MockTilingSprite`\n- `NineSliceSprite` → `MockNineSlicePlane`\n- `DOMContainer` → `MockDOMContainer`\n- `DOMElement` → `MockDOMElement`\n- `Viewport` → `MockContainer`\n- `ParticlesEmitter` → `MockContainer`\n\nYou can access individual mocks directly:\n\n```typescript\nimport {\n  MockContainer,\n  MockSprite,\n  MockText,\n  MockGraphics,\n  MockMesh,\n  MockTilingSprite,\n  MockNineSlicePlane,\n  MockDOMElement,\n  MockDOMContainer,\n  mockComponents\n} from '@canvasengine/testing';\n```\n\n## API Reference\n\n### mockComponents\n\n```typescript\nconst mockComponents: {\n  readonly Canvas: typeof MockContainer;\n  readonly Container: typeof MockContainer;\n  readonly Sprite: typeof MockSprite;\n  readonly Text: typeof MockText;\n  readonly Graphics: typeof MockGraphics;\n  readonly Rect: typeof MockGraphics;\n  readonly Circle: typeof MockGraphics;\n  readonly Ellipse: typeof MockGraphics;\n  readonly Triangle: typeof MockGraphics;\n  readonly Svg: typeof MockGraphics;\n  readonly Mesh: typeof MockMesh;\n  readonly TilingSprite: typeof MockTilingSprite;\n  readonly NineSliceSprite: typeof MockNineSlicePlane;\n  readonly DOMContainer: typeof MockDOMContainer;\n  readonly DOMElement: typeof MockDOMElement;\n  readonly Viewport: typeof MockContainer;\n  readonly ParticlesEmitter: typeof MockContainer;\n}\n```\n\nMapping of CanvasEngine component names to their corresponding mock classes. Can be used directly with `bootstrapCanvas()`.\n\n### createMockElement\n\n```typescript\nfunction createMockElement<T extends ComponentInstance = ComponentInstance>(\n  tag: string,\n  props?: Props,\n  componentInstance?: T\n): Element<T>\n```\n\nCreates a mock Element with all required properties.\n\n### createMockComponentInstance\n\n```typescript\nfunction createMockComponentInstance(componentType: string): ComponentInstance\n```\n\nCreates a mock ComponentInstance based on the component type.\n\n### spyOnElement\n\n```typescript\nfunction spyOnElement<T extends ComponentInstance>(\n  element: Element<T>,\n  property: keyof T | string\n): ReturnType<typeof vi.spyOn>\n```\n\nCreates a spy on a property or method of an element's componentInstance.\n\n### spyOnElementMultiple\n\n```typescript\nfunction spyOnElementMultiple<T extends ComponentInstance>(\n  element: Element<T>,\n  properties: (keyof T | string)[]\n): Record<string, ReturnType<typeof vi.spyOn>>\n```\n\nCreates spies on multiple properties or methods at once.\n"
  },
  {
    "path": "docs/components/_display-object.md",
    "content": "## Common Properties\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| x              | number              | X-coordinate position of the display object.                                |\n| y              | number              | Y-coordinate position of the display object.                                |\n| width          | number              | Width of the display object.                                                |\n| height         | number              | Height of the display object.                                               |\n| scale          | object              | Scale of the display object.                                                |\n| anchor         | object              | Anchor point of the display object.                                         |\n| skew           | object              | Skew of the display object.                                                 |\n| tint           | number              | Tint color of the display object.                                           |\n| rotation       | number              | Rotation of the display object in radians.                                  |\n| angle          | number              | Rotation of the display object in degrees.                                  |\n| zIndex         | number              | Z-index of the display object.                                              |\n| roundPixels    | boolean             | Whether to round pixel values.                                              |\n| cursor         | string              | Cursor style when hovering over the display object.                         |\n| visible        | boolean             | Visibility of the display object.                                           |\n| alpha          | number              | Alpha transparency of the display object.                                   |\n| pivot          | object              | Pivot point of the display object.                                          |\n| filters        | array               | Filters applied to the display object.                                      |\n| maskOf         | Element             | Element that this display object masks.                                     |\n| blendMode      | string              | Blend mode for rendering.                                                   |\n| filterArea     | object              | Filter area for rendering.                                                  |\n\n## Layout Properties\n\nPour obtenir la documentation complète et détaillée sur toutes les propriétés de mise en page, consultez la documentation officielle de [PixiJS Layout](https://layout.pixijs.io/).\n\n### Sizing and Dimensions\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| width          | number/string       | Width of the display object. Accepts pixels or percentage (e.g. '50%').     |\n| height         | number/string       | Height of the display object. Accepts pixels or percentage (e.g. '50%').    |\n| minWidth       | number/string       | Minimum width the object can shrink to.                                     |\n| minHeight      | number/string       | Minimum height the object can shrink to.                                    |\n| maxWidth       | number/string       | Maximum width the object can expand to.                                     |\n| maxHeight      | number/string       | Maximum height the object can expand to.                                    |\n| aspectRatio    | number              | Ratio between width and height (e.g. 1.5 for 3:2 ratio).                    |\n\n### Flex Layout\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| flexDirection  | string              | Direction of flex items. Values: 'row', 'column', 'row-reverse', 'column-reverse'. |\n| flexWrap       | string              | Whether items wrap. Values: 'wrap', 'nowrap', 'wrap-reverse'.               |\n| justifyContent | string              | Alignment along main axis. Values: 'flex-start', 'flex-end', 'center', 'space-between', 'space-around'. |\n| alignItems     | string              | Alignment along cross axis. Values: 'flex-start', 'flex-end', 'center', 'stretch', 'baseline'. |\n| alignContent   | string              | Alignment of lines with multiple items. Values: 'flex-start', 'flex-end', 'center', 'stretch', 'space-between', 'space-around'. |\n| alignSelf      | string              | Override of parent's alignItems for specific item.                          |\n| flexGrow       | number              | Grow factor of item relative to other items.                                |\n| flexShrink     | number              | Shrink factor of item relative to other items.                              |\n| flexBasis      | number/string       | Initial size of item before flex growing/shrinking.                         |\n| gap            | number/object       | Gap between items.                                                          |\n| rowGap         | number              | Gap between rows.                                                           |\n| columnGap      | number              | Gap between columns.                                                        |\n\n### Positioning\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| positionType   | string              | Type of positioning. Values: 'relative', 'absolute', 'static'.              |\n| top            | number/string       | Distance from the top edge.                                                 |\n| right          | number/string       | Distance from the right edge.                                               |\n| bottom         | number/string       | Distance from the bottom edge.                                              |\n| left           | number/string       | Distance from the left edge.                                                |\n\n### Spacing, Margins and Borders\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| margin         | number/array        | Space outside border box. Can be single value or array for different sides. |\n| padding        | number/array        | Space inside border box. Can be single value or array for different sides.  |\n| border         | number/array        | Border width. Can be single value or array for different sides.             |\n\n### Object Fitting and Alignment\n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| objectFit      | string              | How object is resized to fit layout box. Values: 'contain', 'cover', 'fill', 'none', 'scale-down'. |\n| objectPosition | string              | Anchor point of object inside layout box. E.g. 'center', 'top left'.        |\n| transformOrigin| string              | Pivot point for rotation and scaling of layout box.                         |\n\n## Shadow \n\n| Property       | Type                | Description                                                                 |\n|----------------|---------------------|-----------------------------------------------------------------------------|\n| blur           | number              | Blur strength.                                                              |\n| color          | number              | Color of the shadow.                                                        |\n| offset         | object              | Offset of the shadow.                                                       |\n| quality        | number              | Quality of the shadow.                                                      |\n\n\n# Hook before destroy\n\n\n```html\n<script>\n  import {\n    signal,\n    animatedSignal,\n    effect,\n    animatedSequence,\n  } from \"canvasengine\";\n  import MyViewport from \"./viewport.ce\";\n  \n  let bool = signal(true)\n  const opacity = animatedSignal(1, { duration: 500 });\n\n  const click = async () => {\n    bool.set(!bool())\n  }\n\n  const beforeDestroy = async () => {\n    await animatedSequence([\n      () => opacity.set(0),\n    ])\n    console.log(\"before destroy\")\n  }\n</script>\n\n\n<Canvas antialias={true}>\n     <Container onBeforeDestroy={beforeDestroy}>\n        @if (bool) {\n            <Rect width={300} height={300} color=\"red\" alpha={opacity} click />\n        }\n    </Container>\n</Canvas>\n```"
  },
  {
    "path": "docs/components/button.md",
    "content": "# Button\n\nThe Button component provides an interactive button with visual feedback for different states (normal, hover, pressed, disabled). It supports both sprite-based and graphics-based rendering approaches.\n\n## Basic Usage\n\n```html\n<Button \n  text=\"Click Me\" \n  width={150} \n  height={50}\n  click={() => console.log(\"Button clicked!\")} \n/>\n```\n\n## Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `text` | `string` | `\"\"` | Button text content |\n| `disabled` | `boolean` | `false` | Whether the button is disabled |\n| `width` | `number` | `120` | Button width in pixels |\n| `height` | `number` | `40` | Button height in pixels |\n| `x` | `number` | `0` | Button X position |\n| `y` | `number` | `0` | Button Y position |\n| `alpha` | `number` | `1` | Button opacity (0-1) |\n| `visible` | `boolean` | `true` | Button visibility |\n| `style` | `ButtonStyle` | `{}` | Visual styling configuration |\n| `cursor` | `string` | `\"pointer\"` | Button cursor |\n| `controls` | `ControlsDirective \\| JoystickControls` | - | Controls instance to automatically apply button events to. Can be accessed via `element.directives.controls` |\n| `controlName` | `string` | - | Name of the control to trigger with `applyControl` when button is clicked |\n| `shape` | `'rect' \\| 'circle' \\| 'ellipse'` | `'rect'` | Shape of the button background |\n| `background` | `Element \\| ComponentFunction` | - | Custom background component or element (replaces default background if provided) |\n| `children` | `Element[]` | - | Custom children components for button content (takes priority over `text` if provided) |\n\n## Events\n\n| Event | Type | Description |\n|-------|------|-------------|\n| `click` | `(event: FederatedPointerEvent) => void` | Fired when button is clicked |\n| `hoverEnter` | `(event: FederatedPointerEvent) => void` | Fired when mouse enters button |\n| `hoverLeave` | `(event: FederatedPointerEvent) => void` | Fired when mouse leaves button |\n| `pressDown` | `(event: FederatedPointerEvent) => void` | Fired when button is pressed down |\n| `pressUp` | `(event: FederatedPointerEvent) => void` | Fired when button is released |\n\n## Button States\n\nThe button automatically manages four visual states:\n\n- **Normal**: Default appearance\n- **Hover**: When mouse is over the button\n- **Pressed**: When button is being clicked\n- **Disabled**: When button is not interactive\n\n## Styling\n\n### Background Colors\n\n```html\n<Button \n  text=\"Styled Button\"\n  style={{\n    backgroundColor: {\n      normal: \"#28a745\",\n      hover: \"#218838\",\n      pressed: \"#1e7e34\",\n      disabled: \"#6c757d\"\n    }\n  }}\n/>\n```\n\n### Text Styling\n\n```html\n<Button \n  text=\"Custom Text\"\n  style={{\n    text: {\n      fontSize: 18,\n      fontFamily: \"Arial\",\n      color: \"#ffffff\"\n    }\n  }}\n/>\n```\n\n### Border Styling\n\n```html\n<Button \n  text=\"Bordered Button\"\n  style={{\n    border: {\n      radius: 8,\n      width: 2,\n      color: \"#ffffff\"\n    }\n  }}\n/>\n```\n\n### Sprite-based Button\n\nFor more advanced styling, you can use different sprite textures for each state:\n\n```html\n<Button \n  text=\"Play Game\"\n  style={{\n    textures: {\n      normal: \"/assets/button-normal.png\",\n      hover: \"/assets/button-hover.png\",\n      pressed: \"/assets/button-pressed.png\",\n      disabled: \"/assets/button-disabled.png\"\n    }\n  }}\n/>\n```\n\n## Controls Integration\n\nThe Button can be automatically integrated with the controls system, similar to joystick controls:\n\n```html\n<Canvas>\n  <Button \n    text=\"Jump\" \n    controls={element.directives.controls}\n    controlName=\"jump\"\n    width={120}\n    height={40}\n  />\n</Canvas>\n\n<script>\n  import { signal, mount } from \"canvasengine\";\n  import { Button } from \"@canvasengine/core\";\n\n  const controls = signal({\n    jump: {\n      bind: \"space\",\n      keyDown() {\n        console.log(\"Jump!\");\n        // Jump logic here\n      },\n    },\n  });\n\n  mount((element) => {\n    // The button will automatically trigger the \"jump\" control when clicked\n  });\n</script>\n```\n\n## Button Shapes\n\nYou can customize the button shape using the `shape` property:\n\n### Rectangular Button (default)\n\n```html\n<Button \n  text=\"Rectangular\"\n  shape=\"rect\"\n  width={150}\n  height={50}\n/>\n```\n\n### Circular Button\n\n```html\n<Button \n  text=\"Circular\"\n  shape=\"circle\"\n  width={100}\n  height={100}\n/>\n```\n\n### Elliptical Button\n\n```html\n<Button \n  text=\"Elliptical\"\n  shape=\"ellipse\"\n  width={150}\n  height={80}\n/>\n```\n\n## Custom Content\n\nYou can provide custom content using children components instead of text:\n\n### Button with Icon\n\n```html\n<Button shape=\"circle\" width={80} height={80}>\n  <Sprite image=\"icon.png\" width={50} height={50} />\n</Button>\n```\n\n### Button with Multiple Elements\n\n```html\n<Button shape=\"rect\" width={200} height={60}>\n  <Sprite image=\"icon.png\" x={20} y={30} width={30} height={30} />\n  <Text text=\"Custom\" x={60} y={30} />\n</Button>\n```\n\nWhen `children` are provided, they take priority over the `text` property.\n\n## Custom Background\n\nYou can provide a custom background component:\n\n```html\n<Button \n  text=\"Custom Background\"\n  background={<Sprite image=\"custom-bg.png\" />}\n  width={150}\n  height={50}\n/>\n```\n\n## Complete Example\n\n```html\n<Canvas width={800} height={600}>\n  <Button \n    text=\"Start Game\"\n    x={350}\n    y={250}\n    width={200}\n    height={80}\n    style={{\n      backgroundColor: {\n        normal: \"#007bff\",\n        hover: \"#0056b3\",\n        pressed: \"#004085\",\n        disabled: \"#6c757d\"\n      },\n      border: {\n        radius: 10\n      },\n      text: {\n        fontSize: 20,\n        fontFamily: \"Arial Bold\",\n        color: \"#ffffff\"\n      }\n    }}\n    click={() => {\n      console.log(\"Starting game...\");\n      // Game start logic here\n    }}\n  />\n  \n  <Button \n    text=\"Settings\"\n    x={350}\n    y={350}\n    width={200}\n    height={60}\n    style={{\n      backgroundColor: {\n        normal: \"#6c757d\",\n        hover: \"#5a6268\",\n        pressed: \"#545b62\"\n      },\n      text: {\n        fontSize: 16,\n        color: \"#ffffff\"\n      }\n    }}\n    click={() => {\n      console.log(\"Opening settings...\");\n    }}\n  />\n  \n  <!-- Circular button with controls -->\n  <Button \n    text=\"Jump\"\n    shape=\"circle\"\n    x={100}\n    y={100}\n    width={80}\n    height={80}\n    controls={element.directives.controls}\n    controlName=\"jump\"\n    style={{\n      backgroundColor: {\n        normal: \"#28a745\",\n        hover: \"#218838\",\n        pressed: \"#1e7e34\"\n      }\n    }}\n  />\n  \n  <!-- Button with custom content -->\n  <Button \n    shape=\"circle\"\n    x={200}\n    y={100}\n    width={80}\n    height={80}\n    style={{\n      backgroundColor: {\n        normal: \"#ffc107\",\n        hover: \"#e0a800\",\n        pressed: \"#d39e00\"\n      }\n    }}\n  >\n    <Sprite image=\"power-icon.png\" width={50} height={50} />\n  </Button>\n</Canvas>\n\n<script>\n  import { signal, mount } from \"canvasengine\";\n  import { Button } from \"@canvasengine/core\";\n\n  const controls = signal({\n    jump: {\n      bind: \"space\",\n      keyDown() {\n        console.log(\"Jump action!\");\n      },\n    },\n  });\n\n  mount((element) => {\n    // Controls are automatically applied when buttons are clicked\n  });\n</script>\n```\n\n<script>\n  // You can also create buttons programmatically\n  const createButton = (text, onClick) => {\n    return Button({\n      text,\n      click,\n      style: {\n        backgroundColor: {\n          normal: \"#28a745\",\n          hover: \"#218838\",\n          pressed: \"#1e7e34\"\n        }\n      }\n    });\n  };\n</script>\n```\n\n## TypeScript Types\n\n```typescript\ninterface ButtonStyle {\n  backgroundColor?: {\n    normal?: string;\n    hover?: string;\n    pressed?: string;\n    disabled?: string;\n  };\n  border?: {\n    color?: string;\n    width?: number;\n    radius?: number;\n  };\n  text?: {\n    color?: string;\n    fontSize?: number;\n    fontFamily?: string;\n  };\n  textures?: {\n    normal?: string;\n    hover?: string;\n    pressed?: string;\n    disabled?: string;\n  };\n}\n\ninterface ButtonProps {\n  text?: string;\n  disabled?: boolean;\n  click?: (event: FederatedPointerEvent) => void;\n  hoverEnter?: (event: FederatedPointerEvent) => void;\n  hoverLeave?: (event: FederatedPointerEvent) => void;\n  pressDown?: (event: FederatedPointerEvent) => void;\n  pressUp?: (event: FederatedPointerEvent) => void;\n  style?: ButtonStyle;\n  width?: number;\n  height?: number;\n  x?: number;\n  y?: number;\n  alpha?: number;\n  visible?: boolean;\n  cursor?: string;\n  controls?: ControlsDirective | JoystickControls;\n  controlName?: string;\n  shape?: 'rect' | 'circle' | 'ellipse';\n  background?: Element | ComponentFunction;\n  children?: Element[];\n}\n``` "
  },
  {
    "path": "docs/components/canvas.md",
    "content": "# Use Canvas component\n\nIt's the starting point for all the other components.\n\nCommon example:\n\n```html\n<Canvas antialias=\"true\">\n    \n</Canvas>\n```\n\n### options\n\nYou can use all properties from [PixiJS Canvas Renderer](https://pixijs.download/release/docs/rendering.html#autoDetectRenderer)"
  },
  {
    "path": "docs/components/container.md",
    "content": "# Use Container component\n\nCommon example:\n\n```html\n<Container />\n```\n\nExample with x and y:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst x = signal(10)\nconst y = signal(10)\n\nconst click = () => {\n    x.update(x => x + 10)\n    y.update(y => y + 10)\n}\n</script>\n\n<Container x y @click />\n```\n\n<!-- @include: ./_display-object.md -->"
  },
  {
    "path": "docs/components/dom-container.md",
    "content": "# DOMContainer Component\n\nThe `DOMContainer` component provides a bridge between the canvas rendering system and traditional DOM manipulation. It allows you to render standard DOM elements within your canvas application while maintaining proper transform hierarchy and visibility.\n\nThis component is especially useful for rendering form elements like `<input>`, `<textarea>`, or `<select>` that handle user input, as this is often simpler and more flexible than implementing text input directly in PixiJS.\n\n## Basic Usage\n\n```html\n<DOMContainer x={100} y={50}>\n  <input type=\"text\" placeholder=\"Enter text...\" />\n</DOMContainer>\n```\n\n## Sprite in DOMContainer\n\nYou can use the standard `Sprite` component inside a `DOMContainer`. It will automatically render as a `DOMSprite` when placed anywhere under a `DOMContainer` (even if the parent is distant).\n\nUse the same props as `Sprite`:\n\n- See `docs/components/sprite.md`\n\n## Form Elements with Reactive Signals\n\nFor form elements (`input`, `textarea`, `select`), the component supports reactive two-way data binding using signals:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst inputValue = signal('initial value')\n</script>\n\n<DOMContainer>\n  <input type=\"text\" value={inputValue} />\n</DOMContainer>\n```\n\nThe component automatically:\n- Sets the initial value from the signal\n- Listens for `input` events and updates the signal with the new value\n- Updates the DOM element when the signal value changes programmatically\n\n## Form Submission with Automatic Data Collection\n\nWhen a `form` element has a `submit` event handler, the component automatically:\n- Prevents the default form submission behavior (stops propagation)\n- Collects all form data from input elements within the form\n- Passes both the event and the collected form data as parameters to the submit handler\n- Handles multiple values for the same field name (e.g., checkboxes with same name)\n\n```html\n<script>\nconst handleSubmit = (event, formData) => {\n  console.log('Form submitted with data:', formData)\n  // Example formData: { username: 'john', password: 'secret', remember: 'on' }\n}\n</script>\n\n<DOMContainer>\n  <form submit={handleSubmit}>\n    <input name=\"username\" type=\"text\" placeholder=\"Username\" />\n    <input name=\"password\" type=\"password\" placeholder=\"Password\" />\n    <input name=\"remember\" type=\"checkbox\" value=\"on\" />\n    <button type=\"submit\">Login</button>\n  </form>\n</DOMContainer>\n```\n\n## Styling DOM Elements\n\n### CSS Classes\n\nYou can apply CSS classes using different formats:\n\n```html\n<!-- String format: space-separated classes -->\n<DOMContainer>\n  <div class=\"container primary-theme\">Content</div>\n</DOMContainer>\n\n<!-- You can also declare multiple class attributes; they are merged -->\n<DOMContainer>\n  <div class=\"container\" class={['primary-theme', { active: isActive } ]}>Content</div>\n</DOMContainer>\n\n<!-- Array format: array of class names -->\n<DOMContainer>\n  <div class={['container', 'primary-theme', 'active']}>Content</div>\n</DOMContainer>\n\n<!-- Mixed array format: combine static and reactive classes -->\n<DOMContainer>\n  <div class={['container', { active: isActive } ]}>Content</div>\n</DOMContainer>\n\n<!-- Object format: conditional classes -->\n<script>\nconst isActive = signal(false)\nconst theme = signal('light')\n</script>\n\n<DOMContainer>\n  <div class={{\n    'container': true,\n    'active': isActive(),\n    'theme-light': theme() === 'light',\n    'theme-dark': theme() === 'dark'\n  }}>Content</div>\n</DOMContainer>\n```\n\n### Inline Styles\n\nYou can apply styles using different formats:\n\n```html\n<!-- String format: CSS style string -->\n<DOMContainer>\n  <div style=\"background-color: red; padding: 10px;\">Content</div>\n</DOMContainer>\n\n<!-- Object format: style properties -->\n<DOMContainer>\n  <div style={{\n    backgroundColor: 'blue',\n    padding: '20px',\n    fontSize: '16px'\n  }}>Content</div>\n</DOMContainer>\n```\n\n## Event Handling\n\nYou can attach event handlers to DOM elements:\n\n```html\n<script>\nconst handleClick = (event) => {\n  console.log('Button clicked!', event)\n}\n\nconst handleFocus = (event) => {\n  console.log('Input focused!', event)\n}\n</script>\n\n<DOMContainer>\n  <button click={handleClick}>Click me</button>\n  <input type=\"text\" focus={handleFocus} placeholder=\"Focus me\" />\n</DOMContainer>\n```\n\n## Nested DOM Elements\n\nYou can create complex DOM structures with nested elements:\n\n```html\n<DOMContainer>\n  <div class=\"outer-container\">\n    <div class=\"inner-container\">\n      <h2>Nested Content</h2>\n      <p>This is nested inside multiple divs</p>\n    </div>\n  </div>\n</DOMContainer>\n```\n\n## Complete Form Example\n\nHere's a comprehensive example showing a login form with reactive inputs:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst username = signal('')\nconst password = signal('')\nconst rememberMe = signal(false)\n\nconst handleSubmit = (event, formData) => {\n  console.log('Login attempt:', formData)\n  // Handle login logic here\n}\n\nconst handleReset = () => {\n  username.set('')\n  password.set('')\n  rememberMe.set(false)\n}\n</script>\n\n<DOMContainer x={100} y={100}>\n  <form submit={handleSubmit} class=\"login-form\">\n    <div class=\"form-group\">\n      <label for=\"username\">Username:</label>\n      <input \n        id=\"username\"\n        name=\"username\" \n        type=\"text\" \n        placeholder=\"Enter username\"\n        value={username}\n        required\n      />\n    </div>\n    \n    <div class=\"form-group\">\n      <label for=\"password\">Password:</label>\n      <input \n        id=\"password\"\n        name=\"password\" \n        type=\"password\" \n        placeholder=\"Enter password\"\n        value={password}\n        required\n      />\n    </div>\n    \n    <div class=\"form-group\">\n      <label>\n        <input \n          name=\"remember\" \n          type=\"checkbox\" \n          checked={rememberMe()}\n        />\n        Remember me\n      </label>\n    </div>\n    \n    <div class=\"form-actions\">\n      <button type=\"submit\">Login</button>\n      <button type=\"button\" click={handleReset}>Reset</button>\n    </div>\n  </form>\n</DOMContainer>\n```\n\n## Supported HTML Elements\n\nThe DOMContainer supports all standard HTML elements, including:\n\n- **Form elements**: `input`, `textarea`, `select`, `button`, `form`\n- **Text elements**: `p`, `span`, `div`, `h1`-`h6`, `label`\n- **List elements**: `ul`, `ol`, `li`\n- **Media elements**: `img`, `video`, `audio`\n- **Interactive elements**: `a`, `button`\n- **Semantic elements**: `section`, `article`, `header`, `footer`, `nav`\n\n## Supported Events\n\nThe component supports all standard DOM events:\n\n- **Mouse events**: `click`, `mouseover`, `mouseout`, `mouseenter`, `mouseleave`, `mousemove`, `mouseup`, `mousedown`\n- **Touch events**: `touchstart`, `touchend`, `touchmove`, `touchcancel`\n- **Keyboard events**: `keydown`, `keyup`, `keypress`\n- **Form events**: `submit`, `reset`, `change`, `input`, `focus`, `blur`\n- **Drag events**: `drag`, `dragend`, `dragenter`, `dragleave`, `dragover`, `drop`, `dragstart`\n- **Other events**: `wheel`, `scroll`, `resize`, `contextmenu`, `select`\n"
  },
  {
    "path": "docs/components/examples/focus-navigation-dom.js",
    "content": "export default {\n  title: \"Focus Navigation with DOM\",\n  description: \"Navigate through a scrollable list of DOM buttons using keyboard controls (arrow keys or gamepad)\",\n  defaultViewMode: \"both\",\n  files: {\n    \"app.ce\": `\n    <Canvas>\n    <Container>\n  <Text\n    text=\"Focus Navigation DOM Example\"\n    x={0}\n    y={-250}\n    style={{ fontSize: 32, fill: \"#ecf0f1\" }}\n  />\n\n  <Navigation\n    tabindex={tabindex}\n    controls={controls}\n  >\n    <DOMContainer>\n      <div class=\"button-container\">\n        <div>\n          <div>\n            @for (item of items) {\n              <button tabindex={@item.@id}>{@item.@label}</button>\n            }\n          </div>\n        </div>\n      </div>\n    </DOMContainer>\n  </Navigation>\n</Container>\n</Canvas>\n\n<style scoped>\n  .button-container {\n    display: flex;\n    flex-direction: column;\n    gap: 10px;\n    padding: 20px;\n    background: rgba(255, 255, 255, 0.1);\n    border-radius: 8px;\n    overflow: hidden;\n    height: 300px;\n  }\n  button {\n    padding: 10px 20px;\n    font-size: 18px;\n    cursor: pointer;\n    background: #34495e;\n    color: white;\n    border: 2px solid transparent;\n    border-radius: 4px;\n    transition: all 0.2s;\n  }\n  button:focus {\n    background: #3498db;\n    border-color: white;\n    outline: none;\n    transform: scale(1.05);\n  }\n</style>\n\n<script>\n  import { signal, effect } from \"canvasengine\";\n\n  const tabindex = signal(0);\n\n  effect(() => {\n    console.log(\"Selected index:\", tabindex());\n  });\n\n  const items100 = new Array(20).fill(0).map((_, index) => ({ id: index, label: \\`Item \\${index + 1}\\` }));\n  const items = signal(items100);\n\n  const controls = signal({\n    up: {\n      repeat: true,\n      bind: \"up\"\n    },\n    down: {\n      repeat: true,\n      bind: \"down\"\n    },\n    action: {\n      bind: [\"space\", \"enter\"]\n    },\n    gamepad: {\n      enabled: true\n    }\n  });\n</script>`\n  }\n};\n"
  },
  {
    "path": "docs/components/examples/polygon-example.js",
    "content": "export default {\n  title: \"Polygon Example\",\n  description: \"Multiple polygons with different shapes, colors and styles to demonstrate polygon drawing capabilities\",\n  files: {\n    'app.ce': `<Canvas width=\"100%\" height=\"100%\">\n  <Container>\n    <Graphics draw />\n  </Container>\n</Canvas>\n\n<script>\n/**\n * Draw various polygon shapes to demonstrate polygon functionality\n * @param {Graphics} g - The PIXI Graphics object\n * @example\n * // Creates multiple polygons with different shapes and styles\n * draw(graphicsObject);\n */\nconst draw = (g) => {\n    // Triangle - Simple 3-sided polygon\n    const triangle = [100, 50, 200, 50, 150, 150];\n    g.poly(triangle).fill(0xff6b6b);\n    \n    // Rectangle using polygon coordinates\n    const rectangle = [250, 50, 350, 50, 350, 150, 250, 150];\n    g.poly(rectangle).fill(0x4ecdc4);\n    \n    // Pentagon - 5-sided polygon\n    const pentagon = [\n        450, 80,   // top\n        480, 120,  // top right\n        465, 170,  // bottom right\n        435, 170,  // bottom left\n        420, 120   // top left\n    ];\n    g.poly(pentagon).fill(0xffe66d);\n    \n    // Hexagon - 6-sided polygon\n    const hexagon = [\n        550, 80,   // top\n        580, 100,  // top right\n        580, 140,  // bottom right\n        550, 160,  // bottom\n        520, 140,  // bottom left\n        520, 100   // top left\n    ];\n    g.poly(hexagon).fill(0xa8e6cf);\n    \n    // Star shape - more complex polygon\n    const star = [\n        400, 220,  // top point\n        410, 250,  // inner right\n        440, 250,  // outer right\n        420, 270,  // inner bottom right\n        430, 300,  // bottom right point\n        400, 280,  // inner bottom\n        370, 300,  // bottom left point\n        380, 270,  // inner bottom left\n        360, 250,  // outer left\n        390, 250   // inner left\n    ];\n    g.poly(star).fill(0xff8b94);\n    \n    // Arrow shape\n    const arrow = [\n        100, 220,  // left point\n        150, 200,  // top left\n        150, 210,  // inner top left\n        200, 210,  // inner top right\n        200, 200,  // top right\n        250, 220,  // right point\n        200, 240,  // bottom right\n        200, 230,  // inner bottom right\n        150, 230,  // inner bottom left\n        150, 240   // bottom left\n    ];\n    g.poly(arrow).fill(0xdda0dd);\n    \n    // Diamond shape\n    const diamond = [\n        350, 350,  // top\n        400, 400,  // right\n        350, 450,  // bottom\n        300, 400   // left\n    ];\n    g.poly(diamond).fill(0x98d8c8);\n    \n    // Complex polygon with stroke\n    const complexShape = [\n        500, 350,\n        550, 320,\n        600, 350,\n        580, 400,\n        550, 430,\n        520, 400\n    ];\n    g.poly(complexShape)\n     .fill(0x06d6a0)\n     .stroke({ width: 3, color: 0x118ab2 });\n}\n</script>`\n  }\n} "
  },
  {
    "path": "docs/components/graphic.md",
    "content": "# Use Graphics component\n\n<script setup>\nimport polygonExample from './examples/polygon-example.js'\n</script>\n\nCommon example:\n\n```html\n<script>\n    \nconst draw = (g) => {\n    g.rect(0, 0, 100, 100).fill('red')\n}\n</script>\n\n<Graphics draw />\n```\n\nExample with width and height:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst width = signal(100)\nconst height = signal(100)\n\nconst draw = (g, width, height) => {\n    g.rect(0, 0, width, height).fill('red')\n}\n\nconst click = () => {\n    width.update(w => w + 10)\n    height.update(h => h + 10)\n}\n</script>\n\n<Graphics draw click width height />\n```\n\nthe drawing is redrawn if width and height change\n\n## Polygon Example\n\n<Playground v-bind=\"polygonExample\" />\n\n## Rectangle\n\n```html\n<Rect x={0} y={0} width={100} height={100} color=\"red\" />\n```\n\n## Circle\n\n```html\n<Circle x={0} y={0} radius={50} color=\"red\" />\n```\n\n## Triangle\n\n```html\n<Triangle x={0} y={0} width={100} height={100} color=\"red\" />\n```\n\n## Ellipse\n\n```html\n<Ellipse x={0} y={0} width={100} height={100} color=\"red\" />\n```\n\n### draw\n\nFunction that draws on the canvas. It receives the `Graphics` object as argument. It uses [PixiJS Graphics](https://pixijs.download/release/docs/scene.Graphics.html) to draw.\n\n<!-- @include: ./_display-object.md -->\n\n"
  },
  {
    "path": "docs/components/joystick.md",
    "content": "# Joystick\n\n<!-- @include: ./_before.md -->\n\n## Usage\n\n### Basic Usage\n\n```html\n<Canvas>\n    <Joystick />\n</Canvas>\n```\n\n### With Controls Integration\n\nThe Joystick can be automatically integrated with the controls system, similar to gamepad controls:\n\n```html\n<Canvas>\n    <Rect controls={controlsConfig} x={x} y={y} />\n    \n    <Joystick \n        controls={element.directives.controls}\n        outerColor=\"#34495e\"\n        innerColor=\"#3498db\"\n    />\n</Canvas>\n\n<script>\n    import { signal, mount } from \"canvasengine\";\n\n    const x = signal(200);\n    const y = signal(200);\n    const speed = 10;\n\n    const controls = signal({\n        up: {\n            repeat: true,\n            bind: \"up\",\n            keyDown() {\n                y.update((y) => Math.max(0, y - speed));\n            },\n        },\n        down: {\n            repeat: true,\n            bind: \"down\",\n            keyDown() {\n                y.update((y) => y + speed);\n            },\n        },\n        left: {\n            repeat: true,\n            bind: \"left\",\n            keyDown() {\n                x.update((x) => Math.max(0, x - speed));\n            },\n        },\n        right: {\n            repeat: true,\n            bind: \"right\",\n            keyDown() {\n                x.update((x) => x + speed);\n            },\n        },\n        joystick: {\n            enabled: true,\n            directionMapping: {\n                'top': 'up',\n                'bottom': 'down',\n                'left': 'left',\n                'right': 'right',\n                'top_left': ['up', 'left'],\n                'top_right': ['up', 'right'],\n                'bottom_left': ['down', 'left'],\n                'bottom_right': ['down', 'right']\n            },\n            moveInterval: 50,\n            threshold: 0.1\n        }\n    });\n\n    mount((element) => {\n        // The joystick will automatically use the controls from the Rect element\n    });\n</script>\n```\n\n## Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| outer | string | - | Path to the outer joystick image |\n| inner | string | - | Path to the inner joystick image |\n| outerColor | string | - | Color of the outer joystick element |\n| innerColor | string | - | Color of the inner joystick element |\n| outerScale | `{ x: number; y: number }`| Scale of the outer joystick element |\n| innerScale | `{ x: number; y: number }` | Scale of the inner joystick element |\n| onChange | (data: JoystickChangeEvent) => void | - | Callback function triggered when joystick position changes |\n| onStart | () => void | - | Callback function triggered when joystick interaction starts |\n| onEnd | () => void | - | Callback function triggered when joystick interaction ends |\n| controls | ControlsDirective \\| JoystickControls | - | Controls instance to automatically apply joystick events to. Can be accessed via `element.directives.controls` |\n\nAnd use all the properties of the `Container` component.\n\n### JoystickChangeEvent\n\nThe `onChange` callback receives a `JoystickChangeEvent` object with the following properties:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| angle | number | Angle in degrees (0-360) |\n| direction | Direction | Direction enum value (LEFT, RIGHT, TOP, BOTTOM, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT) |\n| power | number | Power/distance from center (0-1) |\n\n### Joystick Configuration\n\nWhen using the joystick with the controls system, you can configure it in the controls configuration:\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| enabled | boolean | true | Whether joystick controls are enabled |\n| directionMapping | object | See below | Mapping of joystick directions to control names |\n| moveInterval | number | 50 | Interval in milliseconds for repeating movement actions |\n| threshold | number | 0.1 | Minimum power value (0-1) required to trigger movement |\n\n#### Default Direction Mapping\n\n```typescript\n{\n    'top': 'up',\n    'bottom': 'down',\n    'left': 'left',\n    'right': 'right',\n    'top_left': ['up', 'left'],\n    'top_right': ['up', 'right'],\n    'bottom_left': ['down', 'left'],\n    'bottom_right': ['down', 'right']\n}\n```\n\nYou can override this mapping in your controls configuration. Diagonal directions can map to multiple controls (array) or a single control (string)."
  },
  {
    "path": "docs/components/mesh.md",
    "content": "# Mesh\n\nThe `Mesh` component allows you to render custom 3D meshes with shaders and textures in your canvas application. It provides advanced rendering capabilities for complex geometries and custom visual effects.\n\n## Basic Usage\n\n```html\n<Mesh \n  geometry={triangleGeometry} \n  texture=\"assets/texture.png\"\n  x={100}\n  y={100}\n/>\n```\n\n## Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `geometry` | `Geometry` | The geometry defining the mesh structure (vertices, indices, UVs, etc.) |\n| `shader` | `Shader` | The shader to render the mesh with |\n| `texture` | `Texture \\| string` | The texture to apply to the mesh |\n| `image` | `string` | The image URL to load as texture |\n| `tint` | `number` | The tint color to apply to the mesh |\n| `roundPixels` | `boolean` | Whether to round pixels for sharper rendering |\n\n## Examples\n\n### Basic Textured Mesh\n\n```html\n<Canvas>\n  <Mesh \n    geometry={triangleGeometry} \n    texture=\"assets/triangle-texture.png\"\n    x={200}\n    y={150}\n    tint={0xff0000}\n  />\n</Canvas>\n\n<script>\n  import { Geometry } from 'pixi.js';\n\n  // Create a simple triangle geometry\n  const triangleGeometry = new Geometry()\n    .addAttribute('aPosition', [\n      0, 0,     // vertex 1\n      100, 0,   // vertex 2\n      50, 100   // vertex 3\n    ], 2)\n    .addIndex([0, 1, 2]);\n</script>\n```\n\n### Mesh with Custom Shader\n\n```html\n<Canvas>\n  <Mesh \n    geometry={planeGeometry}\n    shader={customShader}\n    x={100}\n    y={100}\n  />\n</Canvas>\n\n<script>\n  import { Geometry, Shader } from 'pixi.js';\n\n  // Create plane geometry\n  const planeGeometry = new Geometry()\n    .addAttribute('aPosition', [\n      -50, -50,  // bottom-left\n      50, -50,   // bottom-right\n      50, 50,    // top-right\n      -50, 50    // top-left\n    ], 2)\n    .addAttribute('aUV', [\n      0, 1,      // bottom-left UV\n      1, 1,      // bottom-right UV\n      1, 0,      // top-right UV\n      0, 0       // top-left UV\n    ], 2)\n    .addIndex([0, 1, 2, 0, 2, 3]);\n\n  // Custom vertex shader\n  const vertexShader = `\n    attribute vec2 aPosition;\n    attribute vec2 aUV;\n    \n    uniform mat3 translationMatrix;\n    uniform mat3 projectionMatrix;\n    \n    varying vec2 vUV;\n    \n    void main() {\n      vUV = aUV;\n      gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n    }\n  `;\n\n  // Custom fragment shader\n  const fragmentShader = `\n    precision mediump float;\n    \n    varying vec2 vUV;\n    uniform float time;\n    \n    void main() {\n      vec3 color = vec3(sin(vUV.x + time), cos(vUV.y + time), sin(time));\n      gl_FragColor = vec4(color, 1.0);\n    }\n  `;\n\n  const customShader = Shader.from(vertexShader, fragmentShader, {\n    time: 0.0\n  });\n</script>\n```\n\n### Animated Mesh\n\n```html\n<Canvas>\n  <Mesh \n    geometry={quadGeometry}\n    texture=\"assets/animated-texture.png\"\n    x={centerX}\n    y={centerY}\n    tint={animatedTint}\n    rotation={rotation}\n    draw={animateMesh}\n  />\n</Canvas>\n\n<script>\n  import { signal } from 'canvasengine';\n  import { Geometry } from 'pixi.js';\n\n  const centerX = signal(400);\n  const centerY = signal(300);\n  const animatedTint = signal(0xffffff);\n  const rotation = signal(0);\n\n  // Create quad geometry\n  const quadGeometry = new Geometry()\n    .addAttribute('aPosition', [\n      -25, -25,  // bottom-left\n      25, -25,   // bottom-right\n      25, 25,    // top-right\n      -25, 25    // top-left\n    ], 2)\n    .addAttribute('aUV', [\n      0, 1, 1, 1, 1, 0, 0, 0\n    ], 2)\n    .addIndex([0, 1, 2, 0, 2, 3]);\n\n  const animateMesh = (mesh, delta) => {\n    // Rotate the mesh\n    rotation.set(rotation() + 0.02 * delta);\n    \n    // Animate tint color\n    const time = Date.now() * 0.001;\n    const r = Math.sin(time) * 0.5 + 0.5;\n    const g = Math.sin(time + 2) * 0.5 + 0.5;\n    const b = Math.sin(time + 4) * 0.5 + 0.5;\n    animatedTint.set((r * 255 << 16) + (g * 255 << 8) + (b * 255));\n  };\n</script>\n```\n\n### Reactive Mesh Properties\n\n```html\n<Canvas>\n  <Mesh \n    geometry={meshGeometry}\n    texture={selectedTexture}\n    tint={meshTint}\n    roundPixels={pixelPerfect}\n    x={meshX}\n    y={meshY}\n  />\n  \n  <!-- UI Controls -->\n  <Container x={10} y={10}>\n    <Text text=\"Mesh Controls\" style={{ fill: 'white' }} />\n  </Container>\n</Canvas>\n\n<script>\n  import { signal, computed } from 'canvasengine';\n  import { Geometry } from 'pixi.js';\n\n  // Reactive properties\n  const meshX = signal(200);\n  const meshY = signal(150);\n  const meshTint = signal(0xffffff);\n  const pixelPerfect = signal(true);\n  const textureIndex = signal(0);\n\n  const textures = [\n    'assets/texture1.png',\n    'assets/texture2.png',\n    'assets/texture3.png'\n  ];\n\n  const selectedTexture = computed(() => textures[textureIndex()]);\n\n  // Create mesh geometry\n  const meshGeometry = new Geometry()\n    .addAttribute('aPosition', [\n      -50, -50, 50, -50, 50, 50, -50, 50\n    ], 2)\n    .addAttribute('aUV', [\n      0, 1, 1, 1, 1, 0, 0, 0\n    ], 2)\n    .addIndex([0, 1, 2, 0, 2, 3]);\n\n  // Methods to control the mesh\n  const changeTint = (color) => {\n    meshTint.set(color);\n  };\n\n  const moveToPosition = (x, y) => {\n    meshX.set(x);\n    meshY.set(y);\n  };\n\n  const nextTexture = () => {\n    textureIndex.set((textureIndex() + 1) % textures.length);\n  };\n</script>\n```\n\n## Advanced Usage\n\n### Custom Geometry Creation\n\n```html\n<Canvas>\n  <Mesh geometry={starGeometry} texture=\"assets/star.png\" x={400} y={300} />\n</Canvas>\n\n<script>\n  import { Geometry } from 'pixi.js';\n\n  // Create a custom star geometry\n  function createStarGeometry(points = 5, outerRadius = 50, innerRadius = 25) {\n    const vertices = [];\n    const uvs = [];\n    const indices = [];\n    \n    // Center vertex\n    vertices.push(0, 0);\n    uvs.push(0.5, 0.5);\n    \n    // Star points\n    for (let i = 0; i < points * 2; i++) {\n      const angle = (i / (points * 2)) * Math.PI * 2;\n      const radius = i % 2 === 0 ? outerRadius : innerRadius;\n      \n      const x = Math.cos(angle) * radius;\n      const y = Math.sin(angle) * radius;\n      \n      vertices.push(x, y);\n      uvs.push((x / outerRadius + 1) * 0.5, (y / outerRadius + 1) * 0.5);\n      \n      // Create triangles from center\n      if (i > 0) {\n        indices.push(0, i, i + 1);\n      }\n    }\n    \n    // Close the star\n    indices.push(0, points * 2, 1);\n    \n    return new Geometry()\n      .addAttribute('aPosition', vertices, 2)\n      .addAttribute('aUV', uvs, 2)\n      .addIndex(indices);\n  }\n\n  const starGeometry = createStarGeometry(5, 50, 25);\n</script>\n```\n\n### Performance Tips\n\n1. **Reuse Geometries**: Create geometries once and reuse them across multiple mesh instances\n2. **Batch Similar Meshes**: Group meshes with the same shader and texture for better performance\n3. **Use Appropriate Precision**: Use `roundPixels` for pixel-perfect rendering when needed\n4. **Optimize Shaders**: Keep fragment shaders simple for better performance on mobile devices\n\n### Conditional Rendering\n\n```html\n<Canvas>\n  <Container>\n    @if (showMesh) {\n      <Mesh \n        geometry={triangleGeometry}\n        texture=\"assets/triangle.png\"\n        x={100}\n        y={100}\n      />\n    }\n  </Container>\n</Canvas>\n\n<script>\n  import { signal } from 'canvasengine';\n  import { Geometry } from 'pixi.js';\n\n  const showMesh = signal(true);\n  \n  const triangleGeometry = new Geometry()\n    .addAttribute('aPosition', [0, 0, 100, 0, 50, 100], 2)\n    .addIndex([0, 1, 2]);\n</script>\n```\n\n### Multiple Meshes with Loops\n\n```html\n<Canvas>\n  <Container>\n    @for (mesh of meshes) {\n      <Mesh \n        geometry={@mesh.geometry}\n        texture={@mesh.texture}\n        x={@mesh.x}\n        y={@mesh.y}\n        tint={@mesh.tint}\n      />\n    }\n  </Container>\n</Canvas>\n\n<script>\n  import { signal } from 'canvasengine';\n  import { Geometry } from 'pixi.js';\n\n  const quadGeometry = new Geometry()\n    .addAttribute('aPosition', [-25, -25, 25, -25, 25, 25, -25, 25], 2)\n    .addAttribute('aUV', [0, 1, 1, 1, 1, 0, 0, 0], 2)\n    .addIndex([0, 1, 2, 0, 2, 3]);\n\n  const meshes = signal([\n    { geometry: quadGeometry, texture: 'assets/mesh1.png', x: 100, y: 100, tint: 0xff0000 },\n    { geometry: quadGeometry, texture: 'assets/mesh2.png', x: 200, y: 100, tint: 0x00ff00 },\n    { geometry: quadGeometry, texture: 'assets/mesh3.png', x: 300, y: 100, tint: 0x0000ff }\n  ]);\n</script>\n```\n"
  },
  {
    "path": "docs/components/navigation.md",
    "content": "# Navigation Component\n\n::: Warning Experimental\nThis component is experimental and may change in the future.\n:::\n\n<script setup>\nimport focusNavigationDomExample from './examples/focus-navigation-dom.js'\n</script>\n\nThe `Navigation` component provides a flexible and primitive focus navigation system for CanvasEngine. It allows you to manage focus navigation between focusable child elements using keyboard, gamepad, or programmatic control.\n\nThis component is especially useful for creating menu systems, lists, and any interface that requires keyboard/gamepad navigation.\n\n## Basic Usage\n\n```html\n<Navigation tabindex={0}>\n  <Button tabindex={0} text=\"Button 1\" />\n  <Button tabindex={1} text=\"Button 2\" />\n  <Button tabindex={2} text=\"Button 3\" />\n</Navigation>\n```\n\n## Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `tabindex` | `number` | Focus index for the container (default: 0 if present) |\n| `controls` | `Controls \\| Signal<Controls>` | Controls configuration (you drive `tabindex` updates in your handlers) |\n| `onFocusChange` | `(index: number, element: Element \\| null) => void` | Callback when focus changes |\n| `autoScroll` | `boolean \\| ScrollOptions` | Enable automatic scrolling to focused element (default: false) |\n| `viewport` | `Viewport` | Viewport instance to use for scrolling (optional, uses context viewport by default) |\n\nYou can also use all properties from [DisplayObject](/components/display-object).\n\n## Making Elements Focusable\n\nTo make an element focusable, add a `tabindex` attribute:\n\n### Canvas Components\n\nFor Canvas components (Button, Sprite, Rect, etc.), use the `tabindex` prop directly:\n\n```html\n<Navigation tabindex={0}>\n  <Button tabindex={0} text=\"Item 1\" />\n  <Button tabindex={1} text=\"Item 2\" />\n  <Button tabindex={2} text=\"Item 3\" />\n</Navigation>\n```\n\n### DOM Elements\n\nFor DOM elements (inside DOMContainer), use `attrs.tabindex`:\n\n```html\n<Navigation tabindex={0}>\n  <DOMContainer>\n    <button attrs={{ tabindex: 0 }}>Button 1</button>\n    <button attrs={{ tabindex: 1 }}>Button 2</button>\n    <button attrs={{ tabindex: 2 }}>Button 3</button>\n  </DOMContainer>\n</Navigation>\n```\n\n## DOM Navigation with Scoped Styles\n\nHere's a complete example demonstrating focus navigation within a `DOMContainer` with scoped CSS styling. This example shows how keyboard controls can be used to navigate through DOM buttons, with visual feedback through focus states.\n\n<Playground v-bind=\"focusNavigationDomExample\" />\n\n### Key Features\n\n- **Keyboard Navigation**: Use arrow keys (up/down) to navigate through the button list\n- **Gamepad Support**: Automatically works with gamepad directional buttons\n- **Action Trigger**: Press Space or Enter to trigger button action\n- **Scoped Styles**: CSS is scoped to the playground instance and properly injected\n- **Smooth Transitions**: Visual feedback with hover and focus states via CSS\n- **Auto-Scroll**: Container has overflow handling for scrollable content\n\n## Navigation with Controls\n\nThe `Navigation` wires the Controls directive, but you drive navigation by updating\nthe `tabindex` signal in your handlers (see `sample/src/focus-navigation-dom.ce`).\n\n```html\n<script>\nimport { signal, createTabindexNavigator } from 'canvasengine'\n\nconst tabindex = signal(0)\nconst items = signal([0, 1, 2])\nconst nav = createTabindexNavigator(tabindex, { count: () => items().length }, 'wrap')\n\nconst controls = signal({\n  up: {\n    repeat: true,\n    bind: 'up',\n    throttle: 150,\n    keyDown() {\n      nav.next(-1)\n    }\n  },\n  down: {\n    repeat: true,\n    bind: 'down',\n    throttle: 150,\n    keyDown() {\n      nav.next(1)\n    }\n  },\n  action: {\n    bind: ['space', 'enter']\n  }\n})\n</script>\n\n<Navigation tabindex={tabindex} controls={controls}>\n  <Button tabindex={0} text=\"Item 1\" />\n  <Button tabindex={1} text=\"Item 2\" />\n  <Button tabindex={2} text=\"Item 3\" />\n</Navigation>\n```\n\n## Automatic Scrolling with Viewport\n\nWhen using a `Viewport` with a long list, you can enable automatic scrolling to keep the focused element visible:\n\n```html\n<Viewport worldWidth={2000} worldHeight={5000}>\n  <Navigation tabindex={0} autoScroll={true}>\n    <Button tabindex={0} y={0} text=\"Item 1\" />\n    <Button tabindex={1} y={100} text=\"Item 2\" />\n    <Button tabindex={2} y={200} text=\"Item 3\" />\n    <!-- ... many more items ... -->\n    <Button tabindex={49} y={4900} text=\"Item 50\" />\n  </Navigation>\n</Viewport>\n```\n\n### Scroll Options\n\nYou can customize the scroll behavior:\n\n```html\n<Navigation \n  tabindex={0} \n  autoScroll={{ \n    padding: 50,    // Padding around the element in pixels (default: 0)\n    smooth: true,   // Enable smooth scrolling animation (default: false)\n    center: true,   // Center the element in the viewport (default: true)\n    duration: 300   // Animation duration in ms if smooth=true (default: 300)\n  }}\n>\n  <!-- ... -->\n</Navigation>\n```\n\n## Reacting to Focus Changes\n\n### Using onFocusChange Callback\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst selectedIndex = signal(0)\n\nconst handleFocusChange = (index, element) => {\n  if (index !== null) {\n    selectedIndex.set(index)\n    console.log('Focus changed to index:', index)\n  }\n}\n</script>\n\n<Navigation \n  tabindex={0} \n  onFocusChange={handleFocusChange}\n>\n  <Button tabindex={0} text=\"Item 1\" />\n  <Button tabindex={1} text=\"Item 2\" />\n  <Button tabindex={2} text=\"Item 3\" />\n</Navigation>\n```\n\n### Two-way Synchronization with Signals\n\nYou can pass a signal directly to the `tabindex` property of the `Navigation`. This enables two-way synchronization:\n1. When the focus changes (via keyboard, gamepad, or `FocusManager`), the signal is automatically updated.\n2. When you update the signal manually, the focus automatically moves to the new index.\n\n> [!IMPORTANT]\n> When using a signal for `tabindex`, you **should not** update the same signal inside `onFocusChange` or `handleFocusChange`, as this is handled automatically and could lead to unnecessary updates.\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst selectedIndex = signal(0)\n\n// You can change the focus at any time by updating the signal\nconst goToSecondItem = () => {\n  selectedIndex.set(1)\n}\n</script>\n\n<!-- The signal is automatically synced with the focus state -->\n<Navigation tabindex={selectedIndex}>\n  <Button tabindex={0} text=\"Item 1\" />\n  <Button tabindex={1} text=\"Item 2\" />\n  <Button tabindex={2} text=\"Item 3\" />\n</Navigation>\n\n<Button text=\"Go to Item 2\" click={goToSecondItem} />\n```\n\n### Tabindex Boundary Helper\n\nWhen you update `tabindex` yourself (for example, from Controls), you may want to\nhandle bounds (wrap or clamp). Use `createTabindexNavigator` to keep that logic in one place:\n\n```html\n<script>\nimport { signal, createTabindexNavigator } from 'canvasengine'\n\nconst selectedIndex = signal(0)\nconst items = signal([0, 1, 2])\n\nconst nav = createTabindexNavigator(\n  selectedIndex,\n  { count: () => items().length },\n  'wrap'\n)\n</script>\n```\n\n### Using Hooks\n\nYou can use reactive hooks to track focus state:\n\n```html\n<script>\nimport { useFocusIndex, useFocusedElement, useFocusChange } from 'canvasengine'\nimport { mount, effect } from 'canvasengine'\n\nmount((element) => {\n  // Find Navigation\n  const findNavigation = (el) => {\n    if (el.tag === 'Navigation') return el\n    if (el.children) {\n      for (const child of Array.isArray(el.children) ? el.children : [el.children]) {\n        const found = findNavigation(child)\n        if (found) return found\n      }\n    }\n    return null\n  }\n\n  const navigation = findNavigation(element)\n  if (navigation) {\n    const containerId = navigation.componentInstance.getContainerId()\n    \n    // Get current index signal\n    const focusIndex = useFocusIndex(containerId)\n    effect(() => {\n      console.log('Current focus index:', focusIndex?.())\n    })\n    \n    // Get focused element signal\n    const focusedElement = useFocusedElement(containerId)\n    effect(() => {\n      const element = focusedElement?.()\n      if (element) {\n        console.log('Focused element:', element)\n      }\n    })\n    \n    // Subscribe to focus changes\n    useFocusChange(containerId, (index, element) => {\n      console.log('Focus changed to index', index)\n    })\n  }\n})\n</script>\n```\n\n## Nested Navigation\n\nNested `Navigation` instances are scoped: the parent only registers focusables\nin its own subtree and ignores children managed by nested containers.\n\n## Programmatic Navigation\n\nYou can control focus programmatically using the `FocusManager`:\n\n```html\n<script>\nimport { focusManager } from 'canvasengine'\nimport { mount } from 'canvasengine'\n\nmount((element) => {\n  const navigation = findNavigation(element)\n  if (navigation) {\n    const containerId = navigation.componentInstance.getContainerId()\n    \n    // Set focus to specific index\n    focusManager.setIndex(containerId, 2)\n    \n    // Navigate by updating the signal\n    const indexSignal = focusManager.getCurrentIndexSignal(containerId)\n    if (indexSignal) {\n      indexSignal.set(1)\n    }\n    \n    // Get element at index\n    const element = focusManager.getElement(containerId, 1)\n  }\n})\n</script>\n```\n\n## Complete Example\n\nHere's a complete example showing a menu with visual feedback:\n\n```html\n<script>\nimport { signal, computed } from 'canvasengine'\n\nconst selectedIndex = signal(0)\nconst items = signal([\n  { id: 0, label: \"Item 1\", color: \"#ff6b6b\" },\n  { id: 1, label: \"Item 2\", color: \"#4ecdc4\" },\n  { id: 2, label: \"Item 3\", color: \"#45b7d1\" },\n  { id: 3, label: \"Item 4\", color: \"#f9ca24\" },\n  { id: 4, label: \"Item 5\", color: \"#6c5ce7\" },\n])\n\nconst controls = signal({\n  up: {\n    repeat: true,\n    bind: 'up',\n    keyDown() {\n      console.log('Up pressed')\n    }\n  },\n  down: {\n    repeat: true,\n    bind: 'down',\n    keyDown() {\n      console.log('Down pressed')\n    }\n  },\n  action: {\n    bind: ['space', 'enter'],\n    keyDown() {\n      console.log('Action pressed on item', selectedIndex())\n    }\n  }\n})\n\nconst handleFocusChange = (index, element) => {\n  if (index !== null) {\n    selectedIndex.set(index)\n  }\n}\n</script>\n\n<Canvas backgroundColor=\"#2c3e50\">\n  <Container x={400} y={300}>\n    <Text \n      text=\"Focus Navigation Example\" \n      x={0} \n      y={-250} \n      anchor={{ x: 0.5, y: 0.5 }}\n      style={{ fontSize: 32, fill: \"#ecf0f1\" }}\n    />\n    \n    <Navigation \n      tabindex={0} \n      controls={controls}\n      onFocusChange={handleFocusChange}\n    >\n      <Container y={-100}>\n        @for (item of items) {\n          <Container y={item().id * 80}>\n            <Rect\n              tabindex={item().id}\n              width={300}\n              height={60}\n              x={0}\n              y={0}\n              anchor={{ x: 0.5, y: 0.5 }}\n              color={item().color}\n              alpha={computed(() => selectedIndex() === item().id ? 1 : 0.5)}\n            />\n            <Text\n              text={item().label}\n              x={0}\n              y={0}\n              anchor={{ x: 0.5, y: 0.5 }}\n              style={{ fontSize: 24, fill: \"#ffffff\" }}\n            />\n            @if (selectedIndex() === item().id) {\n              <Rect\n                width={320}\n                height={80}\n                x={0}\n                y={0}\n                anchor={{ x: 0.5, y: 0.5 }}\n                color=\"#ffffff\"\n                alpha={0.2}\n              />\n            }\n          </Container>\n        }\n      </Container>\n    </Navigation>\n  </Container>\n</Canvas>\n```\n\n## Long List with Viewport\n\nFor long lists that require scrolling:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst items = signal(\n  Array.from({ length: 50 }, (_, i) => ({\n    id: i,\n    label: `Item ${i + 1}`,\n    y: i * 100\n  }))\n)\n\nconst controls = signal({\n  up: { repeat: true, bind: 'up' },\n  down: { repeat: true, bind: 'down' },\n  action: { bind: ['space', 'enter'] }\n})\n</script>\n\n<Viewport worldWidth={2000} worldHeight={5000}>\n  <Navigation \n    tabindex={0} \n    controls={controls}\n    autoScroll={{ smooth: true, center: true }}\n  >\n    @for (item of items) {\n      <Button \n        tabindex={item().id} \n        y={item().y} \n        text={item().label}\n      />\n    }\n  </Navigation>\n</Viewport>\n```\n\n## API Reference\n\n### FocusManager\n\nThe `FocusManager` is a singleton that manages all focus containers. You can access it directly:\n\n```typescript\nimport { focusManager } from 'canvasengine'\n\n// Register a container (done automatically by Navigation)\nfocusManager.registerContainer(id, data)\n\n// Navigate\nfocusManager.navigate(containerId, 'next' | 'previous')\n\n// Set focus index\nfocusManager.setIndex(containerId, index)\n\n// Get element at index\nconst element = focusManager.getElement(containerId, index)\n\n// Get signals\nconst indexSignal = focusManager.getCurrentIndexSignal(containerId)\nconst elementSignal = focusManager.getFocusedElementSignal(containerId)\n```\n\n### Hooks\n\n#### `useFocusIndex(containerId: string)`\n\nReturns the current focus index signal for a container.\n\n```typescript\nconst focusIndex = useFocusIndex('my-container')\neffect(() => {\n  console.log('Current index:', focusIndex?.())\n})\n```\n\n#### `useFocusedElement(containerId: string)`\n\nReturns the current focused element signal for a container.\n\n```typescript\nconst focusedElement = useFocusedElement('my-container')\neffect(() => {\n  const element = focusedElement?.()\n  if (element) {\n    console.log('Focused element:', element)\n  }\n})\n```\n\n#### `useFocusChange(containerId: string, callback: (index: number | null, element: Element | null) => void)`\n\nSubscribes to focus changes and calls the callback whenever focus changes.\n\n```typescript\nuseFocusChange('my-container', (index, element) => {\n  console.log('Focus changed to index', index)\n})\n```\n\n## Best Practices\n\n1. **Use sequential tabindex values**: Start from 0 and increment by 1 for each focusable element\n2. **Handle focus changes reactively**: Use `onFocusChange` or hooks to update UI state\n3. **Enable auto-scroll for long lists**: Use `autoScroll={true}` when elements might be outside the viewport\n4. **Combine with Controls**: Provide a `controls` prop for automatic keyboard/gamepad navigation\n5. **Visual feedback**: Always provide visual indication of which element is focused\n\n## Limitations\n\n- Focusable elements must be direct or nested children of the `Navigation`\n- Tabindex values should be unique within a container\n- Elements with `tabindex < 0` are not registered as focusable\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/components/nine-slice-sprite.md",
    "content": "# Use NineSliceSprite component\n\n```html\n<NineSliceSprite\n  image=\"button.png\"\n  width={200}\n  height={100}\n  leftWidth={10}\n  rightWidth={10}\n  topHeight={10}\n  bottomHeight={10}\n  roundPixels={true}\n/>\n```\n\n## Properties\n\nYou can use all properties from Display Object plus the following:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `image` | string | Path to the image file to be used as texture |\n| `texture` | Texture | Direct texture object to use instead of image path |\n| `width` | number | Total width of the nine-slice sprite |\n| `height` | number | Total height of the nine-slice sprite |\n| `leftWidth` | number | Width of the left edge that should not be scaled |\n| `rightWidth` | number | Width of the right edge that should not be scaled |\n| `topHeight` | number | Height of the top edge that should not be scaled |\n| `bottomHeight` | number | Height of the bottom edge that should not be scaled |\n| `roundPixels` | boolean | If true, the sprite's position will be rounded to integers |\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/components/sprite.md",
    "content": "# Sprite Component\n\n## Simple Image:\n\n```html\n<Sprite \n    image=\"path/to/image.png\"\n/>\n```\n\n## Part of an image:\n\n```html\n<Sprite \n    image=\"path/to/image.png\"\n    rectangle={{ x: 0, y: 0, width: 100, height: 100 }}\n/>\n```\n\n## Sprite Sheet:\n\n### With explicit dimensions:\n\n```html\n<script>\nconst definition = {\n    id: \"hero\",\n    image: \"./hero_2.png\",\n    width: 1248,\n    height: 2016,\n    framesWidth: 6,\n    framesHeight: 4,\n    textures: {\n        stand: {\n             animations: ({ direction }) => [\n                [ { time: 0, frameX: 0, frameY: 0 } ]\n             ]\n        },\n        walk: {\n             animations: ({ direction }) => [\n                [ \n                  { time: 0, frameX: 0, frameY: 1 },\n                  { time: 10, frameX: 1, frameY: 1 },\n                  { time: 20, frameX: 2, frameY: 1 }\n                ]\n             ]\n        }\n    }\n}\n\nconst onFinish = () => {\n    console.log(\"Animation finished\")\n}\n</script>\n\n<Sprite \n    sheet={{\n        definition,\n        playing: \"stand\",\n        params: {\n            direction: \"right\"\n        },\n        onFinish\n    }}\n/>\n```\n\n### With auto-detected dimensions:\n\nThe `width` and `height` parameters are optional. If not provided, they will be automatically detected from the image dimensions when the sprite is loaded.\n\n```html\n<script>\nconst definition = {\n    id: \"explosion\",\n    image: \"./exp.png\",\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n        default: {\n             animations: () => [\n                [ \n                    { time: 0, frameX: 0, frameY: 0 },\n                    { time: 10, frameX: 1, frameY: 0 },\n                    { time: 20, frameX: 2, frameY: 0 },\n                    { time: 30, frameX: 3, frameY: 0 }\n                ]\n             ]\n        }\n    }\n}\n</script>\n\n<Sprite \n    sheet={{\n        definition,\n        playing: \"default\"\n    }}\n/>\n```\n\n## Sprite with Hitbox:\n\n```html\n<Sprite \n    image=\"path/to/character.png\"\n    hitbox={{ w: 32, h: 48 }}\n/>\n```\n\nWhen using a hitbox, the sprite's anchor can be automatically calculated from the hitbox bounds, `rectHeight`, and `spriteRealSize` so the visual sprite aligns with the desired reference point inside the collision box. This is particularly useful for character sprites where the visual representation is larger than the actual collision area.\n\nBy default, `hitbox.anchorMode` is `\"top-left\"`, which preserves the legacy behavior: the sprite is positioned so the top-left of the hitbox area inside the frame matches the sprite position.\n\n### Hitbox Anchor Modes\n\n```html\n<Sprite\n    image=\"path/to/character.png\"\n    hitbox={{ w: 32, h: 48, anchorMode: \"top-left\" }}\n/>\n```\n\n`\"top-left\"`:\n- Default mode.\n- Aligns the sprite so the top-left corner of the hitbox matches the sprite position.\n- Useful when your `x`/`y` coordinates already represent the top-left of a collision box.\n\n```html\n<Sprite\n    image=\"path/to/character.png\"\n    hitbox={{ w: 32, h: 48, anchorMode: \"center\" }}\n/>\n```\n\n`\"center\"`:\n- Uses the center of the hitbox as the sprite anchor.\n- Useful when your entity position should represent the center of its collision area.\n\n```html\n<Sprite\n    image=\"path/to/character.png\"\n    hitbox={{ w: 32, h: 48, anchorMode: \"foot\" }}\n/>\n```\n\n`\"foot\"`:\n- Uses the bottom-center of the visible sprite area as the anchor.\n- Useful for character-based games where `x`/`y` should represent the feet or ground contact point.\n\n::: tip\nWhen `spriteRealSize` is provided on a spritesheet definition, CanvasEngine uses it to remove transparent margins from the hitbox anchor calculation. Without `spriteRealSize`, the full frame size is used.\n:::\n\n## DOMSprite: objectFit, width/height, class, style\n\nWhen a `Sprite` is rendered inside a `DOMContainer`, it is routed to `DOMSprite`. You can use DOM-specific props to control sizing and containment.\n\n### Contain a frame inside a fixed box\n\nUse `objectFit=\"contain\"` with `width`/`height` to scale the frame to fit the box while preserving its aspect ratio.\n\n```html\n<DOMContainer>\n  <Sprite\n    objectFit=\"contain\"\n    width={100}\n    height={100}\n    sheet={{\n      definition,\n      playing: \"default\"\n    }}\n  />\n</DOMContainer>\n```\n\n### class and style\n\nYou can pass `class` and `style` directly on `Sprite`/`DOMSprite` when used inside a `DOMContainer`.\n\n```html\n<DOMContainer>\n  <Sprite\n    class=\"avatar\"\n    style={{ border: \"1px solid red\" }}\n    image=\"./hero.png\"\n  />\n</DOMContainer>\n```\n\n## Available Sheet Definition Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `id` | string | Unique identifier for the spritesheet |\n| `image` | string | Path to the spritesheet image |\n| `width` | number | (Optional) Total width of the spritesheet image. If not provided, will be automatically detected from the image dimensions |\n| `height` | number | (Optional) Total height of the spritesheet image. If not provided, will be automatically detected from the image dimensions |\n| `framesWidth` | number | Number of frames horizontally in the spritesheet |\n| `framesHeight` | number | Number of frames vertically in the spritesheet |\n| `rectWidth` | number | (Optional) Width of each frame if not equal to width/framesWidth |\n| `rectHeight` | number | (Optional) Height of each frame if not equal to height/framesHeight |\n| `offset` | `{ x: number, y: number }` | (Optional) Offset to start frame cutting from |\n| `sound` | string | (Optional) Path to sound file that plays when animation starts |\n| `spriteRealSize` | number \\| `{ width: number, height: number }` | (Optional) Real size of sprite for collision detection and hitbox anchor calculations |\n| `anchor` | [number, number] | (Optional) Anchor point [x, y] for positioning (0-1) |\n| `scale` | [number, number] | (Optional) Scale factor [x, y] |\n| `skew` | [number, number] | (Optional) Skew value [x, y] |\n| `pivot` | [number, number] | (Optional) Pivot point [x, y] for rotation |\n| `opacity` | number | (Optional) Opacity value (0-1) |\n| `textures` | object | Contains named animations and their frame definitions |\n\n## Animation Frame Parameters\n\nEach frame in an animation can have these properties:\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `time` | number | Time (in frames) when this frame should be displayed |\n| `frameX` | number | Horizontal frame index in the spritesheet |\n| `frameY` | number | Vertical frame index in the spritesheet |\n| `x` | number | (Optional) X position offset for this frame |\n| `y` | number | (Optional) Y position offset for this frame |\n| `angle` | number | (Optional) Rotation angle for this frame |\n| `rotation` | number | (Optional) Alternative rotation value |\n| `visible` | boolean | (Optional) Whether the frame is visible |\n| `opacity` | number | (Optional) Frame-specific opacity (0-1) |\n| `anchor` | [number, number] | (Optional) Frame-specific anchor point |\n| `scale` | [number, number] | (Optional) Frame-specific scale |\n| `skew` | [number, number] | (Optional) Frame-specific skew |\n| `pivot` | [number, number] | (Optional) Frame-specific pivot point |\n| `sound` | string | (Optional) Sound to play when this frame is reached |\n\n## Global Asset Loader\n\nWhen a component contains multiple sprites with images, you can track the loading progress of all assets using the global asset loader available in the component context. This is useful for displaying a loading screen or progress bar before all assets are ready.\n\n### Basic Usage\n\nThe global loader is automatically available in the component context. Access it using the `mount` function:\n\n```html\n<Canvas>\n  <Sprite image=\"hero.png\" />\n  <Sprite image=\"enemy.png\" />\n  <Sprite sheet={{ definition: spritesheetDef }} />\n</Canvas>\n\n<script>\nimport { mount } from 'canvasengine'\n\nmount((element) => {\n  const loader = element.props.context?.globalLoader\n  \n  if (loader) {\n    // Track overall progress\n    loader.onProgress((progress) => {\n      console.log(`Loading: ${(progress * 100).toFixed(0)}%`)\n      // Update your progress bar here\n    })\n    \n    // Know when all assets are loaded\n    loader.onComplete(() => {\n      console.log('All assets loaded!')\n      // Hide your loader here\n    })\n  }\n})\n</script>\n```\n\n### Progress Tracking\n\nThe global loader automatically tracks:\n- Simple images loaded via the `image` prop\n- Spritesheet images from `sheet.definition.image`\n- All animation textures in spritesheets\n\nThe progress value ranges from 0 to 1, where:\n- `0` = No assets loaded\n- `1` = All assets loaded\n\n### Example: Loading Screen\n\n```html\n<Canvas>\n  <Sprite image=\"background.png\" />\n  <Sprite image=\"player.png\" />\n  <Sprite sheet={{ definition: enemySpritesheet }} />\n</Canvas>\n\n<script>\nimport { mount, signal } from 'canvasengine'\n\nconst isLoading = signal(true)\nconst loadingProgress = signal(0)\n\nmount((element) => {\n  const loader = element.props.context?.globalLoader\n  \n  if (loader) {\n    loader.onProgress((progress) => {\n      loadingProgress.set(progress)\n    })\n    \n    loader.onComplete(() => {\n      isLoading.set(false)\n    })\n  }\n})\n</script>\n```\n\n### API Reference\n\nThe global loader provides the following methods:\n\n| Method | Description |\n|--------|-------------|\n| `onProgress(callback)` | Register a callback for progress updates. Returns an unsubscribe function. |\n| `onComplete(callback)` | Register a callback when all assets are loaded. Returns an unsubscribe function. |\n| `getGlobalProgress()` | Get the current global progress (0-1) |\n| `getAssetCount()` | Get the number of assets being tracked |\n| `getCompletedCount()` | Get the number of completed assets |\n\n## Sprite Props\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `image` | string | Path to the image (when not using a spritesheet) |\n| `rectangle` | `{ x, y, width, height }` | (Optional) Extract only part of the image |\n| `sheet` | object | Spritesheet configuration |\n| `sheet.definition` | object | The spritesheet definition object |\n| `sheet.playing` | string | Name of the animation to play |\n| `sheet.params` | object | Parameters passed to the animation function |\n| `sheet.onFinish` | function | Callback when animation completes |\n| `loader` | object | Loading configuration (per-sprite) |\n| `loader.onProgress` | function | Progress callback for loading (per-sprite) |\n| `loader.onComplete` | function | Completion callback for loading (per-sprite) |\n| `scaleMode` | number | PIXI.js scale mode for the texture |\n| `hitbox` | `{ w: number, h: number, anchorMode?: \"top-left\" \\| \"center\" \\| \"foot\" }` | (Optional) Collision box dimensions and alignment mode. Automatically calculates anchor positioning based on the hitbox, `rectHeight`, and `spriteRealSize` |\n\n::: tip\nThe `loader` prop on individual sprites tracks that specific sprite's loading progress, while `context.globalLoader` tracks all sprites in the component tree. Use the global loader for overall progress, and individual loaders for sprite-specific handling.\n:::\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/components/svg.md",
    "content": "# SVG Component\n\nThe SVG component allows you to render SVG graphics in your CanvasEngine applications. There are three ways to use SVG graphics:\n\n## Direct SVG Tags\n\nYou can use SVG directly in your templates. The compiler will automatically convert SVG tags to the appropriate component:\n\n```html\n<svg viewBox=\"0 0 100 100\" width=\"100\" height=\"100\">\n  <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"blue\" stroke=\"black\" stroke-width=\"2\"/>\n  <path d=\"M 10 80 Q 52.5 10, 95 80 T 180 80\" stroke=\"red\" fill=\"transparent\"/>\n</svg>\n```\n\nThis approach is perfect for simple, static SVG graphics that you want to embed directly in your template.\n\n## Loading SVG from URL\n\nUse the `Svg` component with the `src` prop to load SVG files from external sources:\n\n```html\n<Svg src=\"/assets/logo.svg\" x={10} y={20} />\n```\n\nThis method is ideal for:\n- Loading SVG files from your assets folder\n- Dynamically loading different SVG files\n- Reusing SVG graphics across multiple components\n\n## SVG from String Content\n\nUse the `Svg` component with the `content` prop to render SVG from a string variable:\n\n```html\n<script>\nconst svgContent = `\n  <svg viewBox=\"0 0 200 200\" width=\"200\" height=\"200\">\n    <rect x=\"10\" y=\"10\" width=\"180\" height=\"180\" fill=\"lightblue\" stroke=\"navy\" stroke-width=\"3\"/>\n    <circle cx=\"100\" cy=\"100\" r=\"50\" fill=\"yellow\"/>\n    <text x=\"100\" y=\"110\" text-anchor=\"middle\" font-family=\"Arial\" font-size=\"16\" fill=\"black\">\n      Hello SVG!\n    </text>\n  </svg>\n`;\n</script>\n\n<Svg content={svgContent} />\n```\n\nThis approach is useful for:\n- Generating SVG content dynamically\n- Building SVG from data or user input\n- Creating complex SVG graphics programmatically\n\n## SVG Component Props\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `src` | string | URL path to an SVG file to load |\n| `content` | string | Direct SVG content as a string |\n| `svg` | string | (Legacy) SVG content string for backward compatibility |\n\n## Performance Considerations\n\n- **Direct SVG tags** are the most efficient for static graphics as they're compiled at build time\n- **src prop** is best for external files as it leverages PixiJS's asset loading system\n- **content prop** is flexible but requires runtime parsing\n\n\n<!-- @include: ./_display-object.md --> "
  },
  {
    "path": "docs/components/text.md",
    "content": "# Use Text component\n\nCommon example:\n\n```html\n<Text text=\"Hello World\" size=\"20\" />\n```\n\n## Properties\n\nYou can use all properties from Display Object \n\n### style\n\nStyle object from [PixiJS Text](https://pixijs.download/release/docs/text.TextStyle.html)\n\n### text\n\n`text?: string`\n\nLe texte à afficher\n\n### color\n\n`color?: string`\n\nLa couleur du texte (raccourci pour style.fill)\n\n### size\n\n`size?: string`\n\nLa taille de la police (raccourci pour style.fontSize)\n\n### fontFamily\n\n`fontFamily?: string`\n\nLa famille de police à utiliser (raccourci pour style.fontFamily)\n\n## typewriter\n\n```html\n<Text text=\"Hello World\" typewriter=\"{}\" />\n```\n\n`typewriter?: {\n  speed?: number;\n  onComplete?: () => void;\n  skip?: Trigger;\n  sound?: {\n    src: string;\n    volume?: number;\n    rate?: number;\n  };\n}`\n\nObject to configure typewriter effect:\n- `speed`: Animation speed of the typewriter effect\n- `onComplete`: Callback function when the animation completes\n- `skip`: Trigger to skip the current animation\n- `sound`: Sound configuration for typewriter effect\n  - `src`: Path to the audio file to play for each character\n  - `volume`: Volume level from 0.0 to 1.0 (default: 0.5)\n  - `rate`: Playback rate/speed of the sound (default: 1.0)\n\n### Example with skip trigger\n\n```html\n<Text text=\"Hello World\" typewriter={ { skip } } />\n\n<script>\nimport { trigger } from 'canvasengine'\n\nconst skip = trigger()\n\n// skip the typewriter effect\nskip.start()\n</script>\n```\n\n### Example with sound effect\n\n```html\n<Text \n  text=\"Hello World! This is a typewriter effect with sound.\" \n  typewriter={{ \n    speed: 1,\n    sound: {\n      src: \"/assets/typewriter.mp3\",\n      volume: 0.3,\n      rate: 1.2\n    }\n  }} \n/>\n```\n\nThis will play a typewriter sound effect for each character as the text appears. The sound system automatically calculates the duration of the audio file and uses it to prevent overlapping sounds, ensuring a clean typewriter effect even at high speeds.\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/components/tiling-sprite.md",
    "content": "# Use TilingSprite component\n\nThe TilingSprite component allows you to create a repeating sprite pattern that can be scaled and positioned.\n\n## Props\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `image` | `string` | Path to the image that will be used as the tiling texture |\n| `tileScale` | `{ x: number; y: number }` | Scale of the tiling pattern on both axes |\n| `tilePosition` | `{ x: number; y: number }` | Position offset of the tiling pattern |\n| `width` | `number` | Width of the tiling sprite container |\n| `height` | `number` | Height of the tiling sprite container |\n\n## Examples\n\nBasic usage:\n```html\n<TilingSprite image=\"path/to/image.png\" />\n```\n\nWith custom size:\n```html\n<TilingSprite \n  image=\"path/to/image.png\"\n  width={500}\n  height={300}\n/>\n```\n\nWith scale and position:\n```html\n<TilingSprite \n  image=\"path/to/image.png\"\n  tileScale={{ x: 2, y: 2 }}\n  tilePosition={{ x: 100, y: 50 }}\n  width={800}\n  height={600}\n/>\n```\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/components/video.md",
    "content": "# Use Video component\n\n```html\n<Video src=\"myvideo.mp4\" play={true} />\n```\n\n## Props\n\n- `src`: string\n- `paused`: boolean\n- `loop`: boolean\n- `muted`: boolean\n\n- `loader`: {\n    - `onComplete`: (texture: Texture) => void;\n    - `onProgress`: (progress: number) => void;\n}\n\n\n## Events\n\n- `play`: () => void;\n- `pause`: () => void;\n- `ended`: () => void;\n- `progress`: (progress: number) => void;\n"
  },
  {
    "path": "docs/components/viewport.md",
    "content": "# Use Viewport component\n\nCommon example:\n\n```html\n<Viewport worldWidth=\"2000\" worldHeight=\"2000\" clamp={ {direction: 'all'} } />\n```\n\n## Properties\n\nYou can use all properties from Display Object\n\n## Viewport Options\n\nThe Viewport component supports several options inherited from pixi-viewport:\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `drag` | boolean or object | Enable dragging the viewport |\n| `wheel` | boolean or object | Enable mouse wheel scrolling |\n| `pinch` | boolean or object | Enable pinch to zoom |\n| `decelerate` | boolean or object | Enable deceleration (momentum) after dragging |\n| `clamp` | object | Restrict viewport movement |\n\nExample with options:\n\n```html\n<Viewport \n  worldWidth=\"2000\" \n  worldHeight=\"2000\" \n  drag={true}\n  wheel={true}\n  pinch={true}\n  decelerate={true}\n  clamp={ {direction: 'all'} } \n/>\n```\n\n## Viewport Events\n\nThe Viewport component supports all events from pixi-viewport:\n\n| Event | Description |\n|-------|-------------|\n| `bounce-x-end` | Fired when bounce on the x-axis ends |\n| `bounce-x-start` | Fired when bounce on the x-axis starts |\n| `bounce-y-end` | Fired when bounce on the y-axis ends |\n| `bounce-y-start` | Fired when bounce on the y-axis starts |\n| `clicked` | Fired when viewport is clicked |\n| `drag-end` | Fired when drag ends |\n| `drag-start` | Fired when drag starts |\n| `frame-end` | Fired when frame ends |\n| `mouse-edge-end` | Fired when mouse-edge ends |\n| `mouse-edge-start` | Fired when mouse-edge starts |\n| `moved` | Fired when viewport moves |\n| `moved-end` | Fired when viewport stops moving |\n| `pinch-end` | Fired when pinch ends |\n| `pinch-start` | Fired when pinch starts |\n| `snap-end` | Fired when snap ends |\n| `snap-start` | Fired when snap starts |\n| `snap-zoom-end` | Fired when snap-zoom ends |\n| `snap-zoom-start` | Fired when snap-zoom starts |\n| `wheel-scroll` | Fired when mouse wheel is scrolled |\n| `zoomed` | Fired when viewport is zoomed |\n| `zoomed-end` | Fired when viewport stops zooming |\n\nExample with event:\n\n```html\n<Viewport \n  worldWidth=\"2000\" \n  worldHeight=\"2000\"\n/>\n```\n\n## Viewport Follow Directive\n\nThe `viewportFollow` directive allows an element to be followed by the viewport. When applied, the viewport will automatically center on the element as it moves.\n\nThis directive must be used within a `Viewport` component context.\n\n### Usage\n\n```html\n<Viewport worldWidth=\"2000\" worldHeight=\"2000\" clamp={ {direction: 'all'} }>\n    <Rect viewportFollow x={0} y={0} width={100} height={100} color=\"red\" />\n</Viewport>\n\n<script>\n    const viewportFollow = true // null to disable\n</script>\n```\n\nIn this example, the red rectangle will be followed by the viewport, keeping it centered in the view as it moves around within the 2000x2000 world space.\n\n### Usage with options\n\n```html\n<Viewport worldWidth=\"2000\" worldHeight=\"2000\" clamp={ {direction: 'all'} }>\n    <Rect viewportFollow x={0} y={0} width={100} height={100} color=\"red\" />\n</Viewport>\n\n<script>\n    const viewportFollow = {\n        speed: 0.1,\n        acceleration: 0.1,\n        radius: 100\n    }\n</script>\n```\n\n- `speed` number 0 optional to follow in pixels/frame (0=teleport to location)\n- `acceleration` number optional set acceleration to accelerate and decelerate at this rate; speed cannot be 0 to use acceleration\n- `radius` number optional radius (in world coordinates) of center circle where movement is allowed without moving the viewport * @returns {Viewport} this\n\n### Requirements\n\n- Must be used on an element that is a child of a `Viewport` component\n- The parent `Viewport` component must have defined dimensions (`worldWidth` and `worldHeight`)\n\n::: warning\n**Important**: When an element has `viewportFollow` set to `true`, it will automatically disable the dragging functionality of the parent viewport. This is by design as viewport dragging would conflict with the following behavior.\n:::\n\n## Performance Optimization\n\nWhen rendering large numbers of elements (1000+) inside a Viewport, consider these optimization strategies:\n\n### 1. Viewport Culling\n\nThe `viewportCull` directive automatically hides elements outside the visible area, significantly reducing render overhead:\n\n```html\n<Viewport worldWidth=\"5000\" worldHeight=\"5000\" drag={true}>\n  <Container viewportCull={true}>\n    @for (item of items) {\n      <Sprite image={item().image} x={item().x} y={item().y} />\n    }\n  </Container>\n</Viewport>\n```\n\n::: tip\nCulling is most effective when only a small portion of the world is visible at once. If most elements are always on screen, culling overhead may not be worth it.\n:::\n\n### 2. Reduce Signal Granularity\n\nInstead of creating signals for every animated property, use direct Pixi manipulation in `tick()`:\n\n```html\n<script>\n  import { tick, mount } from 'canvasengine';\n  \n  // BAD: 5 signals per element = expensive with 1000+ elements\n  const items = signal(data.map(d => ({\n    x: signal(d.x),\n    y: signal(d.y),\n    rotation: signal(0),    // Don't do this for animations!\n    alpha: signal(1),       // Don't do this for animations!\n    scale: signal(1),       // Don't do this for animations!\n  })));\n  \n  // GOOD: Only position signals, animate imperatively\n  const items = signal(data.map(d => ({\n    x: signal(d.x),\n    y: signal(d.y),\n    rotationSpeed: Math.random() * 0.1,\n  })));\n  \n  tick((tickValue, element) => {\n    const viewport = element.componentInstance.children[0];\n    viewport.children.forEach((sprite, i) => {\n      sprite.rotation += items()[i].rotationSpeed;\n    });\n  });\n</script>\n```\n\n### 3. Throttle Updates\n\nFor non-critical animations, update every N frames instead of every frame:\n\n```html\n<script>\n  tick((tickValue) => {\n    if (tickValue.frame % 2 !== 0) return; // Skip every other frame\n    \n    // Animation logic here\n  });\n</script>\n```\n\n### 4. Level of Detail (LOD)\n\nReduce animation complexity based on element count:\n\n```html\n<script>\n  tick((tickValue, element) => {\n    const count = items().length;\n    \n    sprites.forEach(sprite => {\n      sprite.rotation += 0.01; // Always animate rotation\n      \n      if (count < 3000) {\n        sprite.alpha = Math.sin(tickValue.frame * 0.05); // Alpha only below 3k\n      }\n      if (count < 1000) {\n        sprite.scale.set(1 + Math.sin(tickValue.frame * 0.02) * 0.1); // Scale only below 1k\n      }\n    });\n  });\n</script>\n```\n\n### Performance Summary\n\n| Element Count | Recommended Strategy |\n|---------------|---------------------|\n| < 500 | Full reactivity (signals for all props) |\n| 500 - 2000 | Imperative animations + position signals |\n| 2000 - 5000 | + Viewport culling + throttled updates |\n| > 5000 | + LOD + consider chunked rendering |\n\n<!-- @include: ./_display-object.md -->\n"
  },
  {
    "path": "docs/concepts/animation.md",
    "content": "# Animation\n\nCanvasEngine provides powerful tools for creating animations. At the core of the animation system are `animatedSignal` and `animatedSequence`.\n\n## `animatedSignal`\n\nAn `animatedSignal` is a special type of signal whose changes can be animated over time. It's built on top of the reactive system and integrates with `popmotion` for the animation logic.\n\n### Creation\n\nYou create an `animatedSignal` by providing an initial value and optional animation options:\n\n```html\n<script>\nimport { animatedSignal } from 'canvasengine';\n\nconst opacity = animatedSignal(1, { duration: 500 }); // Initial opacity 1, animates over 500ms\nconst positionX = animatedSignal(0, { duration: 1000, ease: (t) => t * t }); // Animates x and y\n\nconst click = () => {\n  opacity.set(0)\n  positionX.set(100)\n}\n</script>\n\n<Rect width={300} height={300} color=\"green\" x={positionX} click alpha={opacity} />\n```\n\n### Updating Value\n\nYou can update the value of an `animatedSignal` in two ways:\n\n1.  **`set(newValue, options?)`**: This method animates the signal from its current value to `newValue`. It returns a Promise that resolves when the animation is complete. You can optionally provide animation options specific to this transition.\n\n    ```html\n    <script>\n    import { animatedSignal } from 'canvasengine';\n\n    const opacity = animatedSignal(1, { duration: 500 });\n    const positionX = animatedSignal(0, { duration: 1000 });\n\n    // Example of using set\n    async function animateElement() {\n      await opacity.set(0.5); // Fades to 50%\n      await positionX.set(100, { duration: 2000 }); // Moves to 100 over 2 seconds\n    }\n\n    // Call it or attach to an event\n    // animateElement();\n    </script>\n\n    <Rect width={100} height={100} color=\"blue\" alpha={opacity} x={positionX} click={animateElement} />\n    ```\n\n2.  **`update(updaterFn)`**: This method takes a function that receives the current value and should return the new value. The transition to the new value will be animated using the default or previously set animation options for the signal.\n\n    ```html\n    <script>\n    import { animatedSignal } from 'canvasengine';\n\n    const scale = animatedSignal(1, { duration: 300 });\n    const rotation = animatedSignal(0, { duration: 500 });\n\n    // Example of using update\n    function modifyElement() {\n      scale.update(currentScale => currentScale * 1.2); // Scales up by 20%\n      rotation.update(currentRotation => currentRotation + 45); // Rotates by 45 degrees\n    }\n    // Call it or attach to an event\n    // modifyElement();\n    </script>\n\n    <Rect width={100} height={100} color=\"red\" scale={scale} rotation={rotation} click={modifyElement} />\n    ```\n\n### Accessing Value\n\nTo get the current value of an `animatedSignal`, you call it as a function:\n\n```html\n<script>\nimport { animatedSignal, effect } from 'canvasengine';\n\nconst rectOpacity = animatedSignal(1);\nconst rectPositionX = animatedSignal(50);\n\neffect(() => {\n  // Logs the current opacity value whenever it changes\n  console.log('rectOpacity:', rectOpacity());\n});\n\neffect(() => {\n  // Logs the current x position whenever it changes\n  console.log('rectPositionX:', rectPositionX());\n});\n\nconst toggleValues = () => {\n  if (rectOpacity() === 1) {\n    rectOpacity.set(0.5);\n    rectPositionX.set(150);\n  } else {\n    rectOpacity.set(1);\n    rectPositionX.set(50);\n  }\n};\n</script>\n\n<Rect width={80} height={80} color=\"purple\" alpha={rectOpacity} x={rectPositionX} click={toggleValues} />\n```\n\n### Animation State\n\nEach `animatedSignal` has an `animatedState` property. This is a `WritableSignal` that holds an object with the following properties:\n\n*   `current`: The current value of the signal during an animation.\n*   `start`: The value at the beginning of the current or last animation.\n*   `end`: The target value of the current or last animation.\n\nYou can subscribe to this state to react to changes during an animation:\n\n```html\n<script>\nimport { animatedSignal, effect } from 'canvasengine';\n\nconst progressWidth = animatedSignal(0, { duration: 2000 });\nlet currentProgress = 0;\n\neffect(() => {\n  const state = progressWidth.animatedState();\n  currentProgress = state.current;\n  console.log(`Animation progress: from ${state.start} to ${state.end}, current is ${state.current}`);\n  // Here currentProgress could be used to set the width of a visual element\n});\n\nconst startProgressAnimation = () => {\n  progressWidth.set(100);\n};\n\nconst resetProgressAnimation = () => {\n  progressWidth.set(0);\n}\n\nconst handleProgressClick = () => {\n  if (progressWidth() === 0) {\n    startProgressAnimation();\n  } else {\n    resetProgressAnimation();\n  }\n}\n</script>\n\n<!-- Conceptual Rect acting as a progress bar -->\n<Rect width={progressWidth} height=\"20\" color=\"orange\" click={handleProgressClick} />\n<!-- Text to display progress -->\n<Text text={`Progress: ${progressWidth()}%`} x=\"10\" y=\"40\" />\n```\n\n### Example\n\n```html\n<script>\nimport { animatedSignal, effect } from 'canvasengine';\n\nconst xPosition = animatedSignal(10, { duration: 1000 });\nconst boxOpacity = animatedSignal(1, { duration: 750 });\nconst boxColor = signal('blue'); // Non-animated signal for color\n\n// Log the value whenever it changes\neffect(() => {\n  console.log('xPosition is now:', xPosition());\n});\n\neffect(() => {\n  console.log('boxOpacity is now:', boxOpacity());\n});\n\n// Log the detailed animation state for xPosition\neffect(() => {\n  const animState = xPosition.animatedState();\n  console.log(\n    `xPosition Animation: from ${animState.start} to ${animState.end}. Current: ${animState.current}`\n  );\n});\n\nasync function animateMyBox() {\n  console.log('Starting animation for MyBox...');\n  boxColor.set('red'); // Change color immediately\n  // Parallel animation using Promise.all\n  await Promise.all([\n    xPosition.set(150), // Move right\n    boxOpacity.set(0.3)  // Fade out a bit\n  ]);\n  console.log('Animation to x:150, opacity:0.3 finished.');\n  \n  boxColor.set('green');\n  await xPosition.set(10, { duration: 500 }); // Animate back faster\n  console.log('Animation back to x:10 finished.');\n\n  boxColor.set('blue');\n  boxOpacity.set(1); // Fade back in, default duration\n  xPosition.update(val => val + 70); // Animate to 80 using default duration (1000ms)\n  console.log('Fade in and x-update to 80 initiated.');\n}\n\n</script>\n\n<Rect x={xPosition} y=\"50\" width=\"50\" height=\"50\" color={boxColor} alpha={boxOpacity} click={animateMyBox} />\n```\n\n## `animatedSequence`\n\nThe `animatedSequence` function allows you to orchestrate multiple animations, running them sequentially or in parallel. This is particularly useful for creating complex animation timelines.\n\n### How it Works\n\n`animatedSequence` takes an array as its argument. Each element in this array can be either:\n\n1.  A function that returns a `Promise` (typically an `animatedSignal.set()` call). These functions are executed one after another (sequentially).\n2.  An array of such promise-returning functions. All functions within this inner array are executed simultaneously (in parallel). The sequence will only proceed to the next step once all promises in the parallel block have resolved.\n\n### Usage\n\n```html\n<script>\nimport { animatedSignal, animatedSequence, signal } from 'canvasengine';\n\n// Define some animated signals for our Rects\nconst rect1X = animatedSignal(10, { duration: 500 });\nconst rect2Y = animatedSignal(10, { duration: 700 });\nconst rect3Scale = animatedSignal(1, { duration: 300 });\nconst rectsVisible = signal(true);\n\nasync function runRectSequence() {\n  console.log('Starting Rect animation sequence...');\n  rectsVisible.set(true);\n\n  await animatedSequence([\n    // Step 1: Animate rect1X to 100\n    () => rect1X.set(100),\n\n    // Step 2: Animate rect2Y to 50 and rect3Scale to 1.5 in parallel\n    [\n      () => rect2Y.set(50),\n      () => rect3Scale.set(1.5)\n    ],\n\n    // Step 3: Animate rect1X back to 10\n    () => rect1X.set(10),\n\n    // Step 4: Animate all three values simultaneously to new targets\n    [\n      () => rect1X.set(30),\n      () => rect2Y.set(20),\n      () => rect3Scale.set(0.8)\n    ],\n    \n    // Step 5: Hide the rects (not animated, but part of sequence)\n    async () => {\n        // Example of a non-animated action within the sequence\n        await Promise.all([rect1X.set(200, {duration: 300}), rect2Y.set(200, {duration: 300}), rect3Scale.set(0.1, {duration: 300})]);\n        rectsVisible.set(false);\n    }\n  ]);\n\n  console.log('Rect sequence complete!');\n  // console.log(`Final values: rect1X=${rect1X()}, rect2Y=${rect2Y()}, rect3Scale=${rect3Scale()}`);\n}\n\nconst resetRects = () => {\n    rect1X.set(10, {duration: 0});\n    rect2Y.set(10, {duration: 0});\n    rect3Scale.set(1, {duration: 0});\n    rectsVisible.set(true);\n}\n\n</script>\n```\n\n### Key Features:\n\n*   **Sequential Execution**: Animations in the main array are performed one by one.\n*   **Parallel Execution**: Animations within a nested array are performed concurrently.\n*   **Promise-based**: It leverages Promises to manage the timing and completion of animations. The `animatedSequence` function itself returns a Promise that resolves when the entire sequence is finished.\n\nThis structure provides a flexible way to define intricate animation chains.\n"
  },
  {
    "path": "docs/concepts/child-component.md",
    "content": "# Child Component\n\nA child component is a component that is defined inside another component.\n\n`child.ce`\n\n```html\n<Container>\n  <Rect width={100} height={100} color=\"red\" />\n</Container>\n```\n\n`parent.ce`\n\n```html\n<Canvas>\n  <Child />\n</Canvas>\n\n<script>\n  import Child from \"./child.ce\";\n</script>\n```\n\n## Input props\n\nYou can define input props for a child component.\n\n`child.ce`\n```html\n<script>\n  const { title } = defineProps({\n    title: 'Hello World' // default value\n  })\n\n  console.log(title())\n</script>\n\n<Text text={title} />\n```\n\nIn this example, the `title` prop is passed to the `Text` component.\n\n> Not need to import `defineProps` in the child component.\n\nUse in component parent:\n\n`parent.ce`\n```html\n<Canvas>\n  <Child title=\"Hello World\" />\n</Canvas>\n\n<script>\n import Child from './child.ce'\n</script>\n```\n\n::: tip\nNote that retrieved properties, **even static ones**, are transformed into signals and you must read them into the child as signals.\n\nExample: `title()`\n:::\n\n::: tip\n\nIf you don't want to set the default values, just do:\n\n```html\n<script>\n  const { title } = defineProps()\n</script>\n```\n:::"
  },
  {
    "path": "docs/concepts/context.md",
    "content": ""
  },
  {
    "path": "docs/concepts/dependencies.md",
    "content": "# Dependencies\n\nThe `dependencies` prop allows you to delay component mounting until all specified dependencies are ready (not `undefined`). This is useful for scenarios where a component needs to wait for asynchronous data loading or reactive signals to become available before rendering.\n\n## Overview\n\nWhen you provide a `dependencies` prop to a component, the component will not mount until all dependencies are defined. Dependencies can be:\n\n- **Signals**: Reactive signals that may start as `undefined` and become defined later\n- **Promises**: Async operations that resolve to a value (must not resolve to `undefined`)\n- **Direct values**: Any value that is not `undefined`\n\n## Basic Usage\n\n### With Signal Dependencies\n\n```html\n<script>\n  import { signal, mount } from 'canvasengine';\n\n  // Start with undefined dependency\n  const userData = signal(undefined);\n\n  // Load data asynchronously\n  setTimeout(() => {\n    userData.set({ name: 'John', score: 100 });\n  }, 1000);\n</script>\n\n<Container dependencies={[userData]}>\n  <Text text={`Welcome ${userData().name}!`} />\n  <Text text={`Score: ${userData().score}`} />\n</Container>\n```\n\nIn this example, the `Container` and its children will not mount until `userData` becomes defined. The `mount` hook will only be called after the signal is set to a value.\n\n### With Promise Dependencies\n\n```html\n<script>\n  import { mount } from 'canvasengine';\n\n  // Simulate async data loading\n  const loadUserData = () => {\n    return new Promise((resolve) => {\n      setTimeout(() => {\n        resolve({ name: 'Jane', level: 5 });\n      }, 2000);\n    });\n  };\n\n  const userDataPromise = loadUserData();\n</script>\n\n<Container dependencies={[userDataPromise]}>\n  <Text text=\"User data loaded!\" />\n</Container>\n```\n\nThe component will wait for the promise to resolve before mounting. If the promise resolves to `undefined`, the component will not mount.\n\n### Mixed Dependencies\n\nYou can combine signals and promises:\n\n```html\n<script>\n  import { signal } from 'canvasengine';\n\n  const config = signal(undefined);\n  const assetsPromise = Promise.resolve({ sprites: [] });\n\n  // Load config\n  setTimeout(() => {\n    config.set({ theme: 'dark' });\n  }, 500);\n</script>\n\n<Container dependencies={[config, assetsPromise]}>\n  <Text text=\"All dependencies ready!\" />\n</Container>\n```\n\nThe component will mount only when both the signal becomes defined AND the promise resolves to a non-undefined value.\n\n## Using with h() Function\n\nWhen using CanvasEngine without the compiler, you can pass dependencies using the `h()` function:\n\n```typescript\nimport { h, signal, Container, Text } from 'canvasengine';\n\nconst userData = signal(undefined);\n\n// Later...\nuserData.set({ name: 'Alice' });\n\nconst component = h(Container, {\n  dependencies: [userData]\n}, \n  h(Text, { text: 'User loaded!' })\n);\n```\n\n## Behavior\n\n- **Immediate mounting**: If all dependencies are already defined when the component is created, it mounts immediately\n- **Delayed mounting**: If any dependency is `undefined`, the component waits and subscribes to signal changes\n- **Reactive updates**: For signal dependencies, the component automatically subscribes and mounts when all signals become defined\n- **Promise handling**: Promise dependencies are awaited, and the component mounts if the resolved value is not `undefined`\n- **No dependencies**: If the `dependencies` prop is not provided, the component mounts normally\n\n## Use Cases\n\n### Loading Game Assets\n\n```html\n<script>\n  import { signal } from 'canvasengine';\n\n  const textures = signal(undefined);\n  const sounds = signal(undefined);\n\n  // Load assets\n  Promise.all([\n    loadTextures(),\n    loadSounds()\n  ]).then(([tex, snd]) => {\n    textures.set(tex);\n    sounds.set(snd);\n  });\n</script>\n\n<Container dependencies={[textures, sounds]}>\n  <Text text=\"All assets loaded! Game ready.\" />\n</Container>\n```\n\n### Waiting for User Authentication\n\n```html\n<script>\n  import { signal } from 'canvasengine';\n\n  const user = signal(undefined);\n\n  // Authenticate user\n  authenticateUser().then(userData => {\n    user.set(userData);\n  });\n</script>\n\n<Container dependencies={[user]}>\n  <Text text={`Welcome back, ${user().username}!`} />\n</Container>\n```\n\n### Conditional Component Rendering\n\n```html\n<script>\n  import { signal } from 'canvasengine';\n\n  const gameState = signal(undefined);\n  const playerData = signal(undefined);\n\n  // Initialize game\n  initializeGame().then(() => {\n    gameState.set('ready');\n    playerData.set({ health: 100 });\n  });\n</script>\n\n<Container dependencies={[gameState, playerData]}>\n  <Text text=\"Game initialized!\" />\n</Container>\n```\n\n## Important Notes\n\n- A dependency is considered \"ready\" when its value is **not** `undefined`\n- The value `null` is considered ready (only `undefined` blocks mounting)\n- All dependencies must be ready simultaneously for the component to mount\n- Once mounted, the component will not unmount if dependencies become `undefined` again\n- The `mount` hook is only called after all dependencies are ready\n\n"
  },
  {
    "path": "docs/concepts/dynamic-components.md",
    "content": "# Dynamic Components\n\nCanvasEngine allows you to create and use dynamic components that can be defined directly in your application or loaded dynamically at runtime.\n\n## Defining Custom Components\n\nYou can define your own components directly in your application using the script tag:\n\n```html\n<script>\nconst MyComponent = {\n  name: 'MyComponent',\n  props: {\n    width: Number,\n    height: Number,\n    color: String\n  }\n};\n</script>\n\n<!-- Using the custom component -->\n<MyComponent.name ...props />\n```\n"
  },
  {
    "path": "docs/concepts/examples/conditional-rendering.js",
    "content": "export default {\n  title: \"Grade System with @if/@else if/@else\",\n  description: \"Click the buttons to change the score and see different grades\",\n  files: {\n    \"app.ce\": `<Canvas backgroundColor=\"#2c3e50\" width=\"100%\" height=\"100%\">\n    <Container \n        width=\"100%\" \n        height=\"100%\" \n        flexDirection=\"column\"\n        alignItems=\"center\"\n        justifyContent=\"center\"\n        gap={30}>\n        \n        <Container y={-40}>\n            <Text text={scoreStr} color=\"white\" size={24} y={-80} />\n            <Button text=\"Increment\" click={() => score.update(s => s + 1)} />\n        </Container>\n        \n        @if (score >= 9) {\n            <Text text=\"Grade: A+\" color=\"#FFD700\" size={48} fontWeight=\"bold\" />\n            <Text text=\"Excellent work!\" color=\"#FFD700\" size={18} />\n        }\n        @else if (score >= 8) {\n            <Text text=\"Grade: A\" color=\"#32CD32\" size={48} fontWeight=\"bold\" />\n            <Text text=\"Great job!\" color=\"#32CD32\" size={18} />\n        }\n        @else if (score >= 7) {\n            <Text text=\"Grade: B\" color=\"#1E90FF\" size={48} fontWeight=\"bold\" />\n            <Text text=\"Good work!\" color=\"#1E90FF\" size={18} />\n        }\n        @else if (score >= 6) {\n            <Text text=\"Grade: C\" color=\"#FFA500\" size={48} fontWeight=\"bold\" />\n            <Text text=\"Keep trying!\" color=\"#FFA500\" size={18} />\n        }\n        @else {\n            <Text text=\"Grade: F\" color=\"#FF6347\" size={48} fontWeight=\"bold\" />\n            <Text text=\"Need improvement\" color=\"#FF6347\" size={18} />\n        }\n\n        \n    \n    </Container>\n</Canvas>\n\n<script>\nimport { signal } from 'canvasengine';\n\nconst score = signal(5);\nconst scoreStr = computed(() => \\`Score: \\${score()}\\`);\n</script>`\n  }\n}; "
  },
  {
    "path": "docs/concepts/lifecycle.md",
    "content": "# Lifecycle\n\nLifecycle is a core concept in Canvas Engine. It is used to manage the lifecycle of a component.\n\n## Mounting\n\n```html\n<script>\n  import { mount } from 'canvasengine';\n\n  mount((element) => {\n    console.log('Mounting', element);\n  });\n</script>\n\n <Rect x=\"5\" y=\"5\" width=\"10\" height=\"10\" color=\"red\" />\n```\n\nElement is the root element of the component. Here, it is the `Graphics` element (`Rect` is a `Graphics` element).\n\n> View the [Element Object](/api/element) for more information.\n\n## Unmount\n\nTo unmount a component, you can return a function from the mount function.\n\n```html\n<script>\n  import { mount } from 'canvasengine';\n\n  mount(() => {\n     return () => {\n      console.log('Unmounting');\n     }\n  });\n</script>\n```\n\n## Tick\n\nUse tick to run code on every frame.\n\n```html\n<script>\n  import { tick } from 'canvasengine';\n\n  tick((params: Tick) => {\n    console.log('Tick');\n  });\n</script>\n```\n\nParams contains the following properties:\n\n- `timestamp`: The current timestamp in milliseconds.\n- `deltaTime`: The time elapsed since the last tick in milliseconds.\n- `frame`: The current frame number.\n- `deltaRatio`: The ratio of the delta time to the frame time.\n"
  },
  {
    "path": "docs/concepts/reactive.md",
    "content": "# Reactive Programming\n\nCanvasEngine uses a reactive programming model to manage state and animations. This is a declarative way to manage state and animations, and it is different from the traditional imperative programming model.\n\nIn CanvasEngine, you define signals that represent values that can change over time. When a signal changes, all the components that depend on that signal are automatically updated. This is known as reactive data binding.\n\n## Signals\n\nSignals are created using the `signal` function. For example:\n\n```html\n<script>\n  import { signal } from 'canvasengine';\n\n  const x = signal(0);\n  const y = signal(0);\n</script>\n\n<Rect x y width={10} height={10} color=\"red\" />\n```\n\nIn this example, the `Rect` component will be drawn at the initial position of `(0, 0)`. When the `x` or `y` signal changes, the `Rect` component will be re-rendered at the new position.\n\n## Animated Signals\n\nAnimated signals are a type of signal that can be animated over time. They are created using the `animatedSignal` function. For example:\n\n```html\n<script>\n  import { animatedSignal } from 'canvasengine';\n\n  const x = animatedSignal(0);\n  const y = animatedSignal(0);\n</script>\n\n<Rect x={x} y={y} width={10} height={10} color=\"red\" />\n```\n\nIn this example, the `Rect` component will be drawn at the initial position of `(0, 0)`. When the `x` or `y` signal changes, the `Rect` component will be re-rendered at the new position.\n\n## Computed Signals\n\nComputed signals are a type of signal that can be computed from other signals. They are created using the `computed` function. For example:\n\n```html\n<script>\n  import { computed, signal } from 'canvasengine';\n\n  const x = signal(0);\n  const y = signal(0);\n\n  const distance = computed(() => Math.sqrt(x() ** 2 + y() ** 2));\n</script>\n\n<Text x={x} y={y} text={distance} />\n```\n\nIn this example, the `Text` component will display the distance between the `x` and `y` signals. When the `x` or `y` signal changes, the `distance` signal will be re-computed and the `Text` component will be re-rendered with the new distance.\n\n## Effects\n\nEffects are a type of signal that can be used to perform side effects. They are created using the `effect` function. For example:\n\n```html\n<script>\n  import { effect, signal } from 'canvasengine';\n\n  const x = signal(0);\n  const y = signal(0);\n\n  effect(() => {\n    console.log(`x: ${x()}, y: ${y()}`);\n  });\n</script>\n\n <Rect x y width={10} height={10} color=\"red\" />\n ```\n\nIn this example, the `effect` function will log the value of the `x` and `y` signals to the console. When the `x` or `y` signal changes, the `effect` function will be re-run and the new value of the `x` and `y` signals will be logged to the console."
  },
  {
    "path": "docs/concepts/ref.md",
    "content": ""
  },
  {
    "path": "docs/concepts/slot.md",
    "content": "# Children Components Slots\n\nIn CanvasEngine, you can access child components that are passed to a parent component.\n\n```html\n<Child>\n    <Rect width={100} height={100} color=\"red\" x={0} y={0} />\n</Child>\n\n<script>\n    import Child from './child.ce'\n</script>\n```\n\nHow to access the children components in the `Child` component?\n\n## Basic Usage\n\nIn the `Child` component, you can access the children components using the `defineProps()` function.\n\n```html\n<slot />\n\n<script>\nconst { children } = defineProps()\nconst slot = children[0]\n</script>\n```\n\nChildren are accessible as an array, where `children[0]` is the first child, `children[1]` is the second child, etc.\n\n## Multiple Children\n\nYou can pass multiple children to a component:\n\n```html\n@for (child of children) {\n    <child />\n}\n\n<script>\n    import { signal } from 'canvasengine'\n    \n    const { children } = defineProps()\n</script>\n```\n\n## Dynamic Child Switching\n\nYou can dynamically switch between children using signals. You can also use the `attach` prop to attach a child to a container.\n\n```html\n<Container attach={activeChild} />\n\n<script>\n    import { signal } from 'canvasengine'\n    \n    const { children } = defineProps()\n    const activeChild = signal(children[0])\n\n    // Switch to second child after 1 second\n    setTimeout(() => {\n        activeChild.set(children[1])\n    }, 1000)\n</script>\n```\n\nThis pattern is useful for creating dynamic interfaces where you need to swap components based on certain conditions or user interactions.\n"
  },
  {
    "path": "docs/concepts/styling.md",
    "content": "# Styling\n\nCanvasEngine allows you to add CSS styles to your components using the `<style>` tag. Styles are automatically injected into the document head and can be scoped to specific components.\n\n## Basic Usage\n\nYou can add a `<style>` tag to any `.ce` file:\n\n```html\n<Canvas>\n  <DOMContainer>\n    <button>Click me</button>\n  </DOMContainer>\n</Canvas>\n\n<style>\n  button {\n    background-color: red;\n    color: white;\n    padding: 10px 20px;\n    border: none;\n    border-radius: 5px;\n  }\n</style>\n\n<script>\n</script>\n```\n\nThe CSS is automatically injected into the document's `<head>` when the component is loaded. This allows you to style DOM elements (like `<button>`, `<input>`, etc.) used within `DOMContainer` components.\n\n## Scoped Styles\n\nTo scope styles to a specific component instance, use the `scoped` attribute on the `<style>` tag:\n\n```html\n<Canvas>\n  <DOMContainer>\n    <button>Click me</button>\n  </DOMContainer>\n</Canvas>\n\n<style scoped>\n  button {\n    background-color: blue;\n    color: white;\n  }\n</style>\n\n<script>\n</script>\n```\n\nWhen you use `scoped`, CanvasEngine automatically:\n\n1. **Generates a unique hash** (8 letters) based on the file path\n2. **Prefixes all CSS selectors** with this unique class\n3. **Applies the class** to all `DOMContainer` elements in the component\n\nThis ensures that the styles only apply to DOM elements within this specific component instance, preventing style leakage to other components.\n\n### Multiple DOMContainer Elements\n\nAll `DOMContainer` elements in a scoped component receive the same scope class:\n\n```html\n<Canvas>\n  <DOMContainer>\n    <div>First container</div>\n  </DOMContainer>\n  <DOMContainer>\n    <div>Second container</div>\n  </DOMContainer>\n</Canvas>\n\n<style scoped>\n  div {\n    padding: 10px;\n    border: 1px solid black;\n  }\n</style>\n\n<script>\n</script>\n```\n\nBoth `DOMContainer` elements will have the same scope class, so the styles apply consistently across all of them.\n\n## Preserving @rules\n\nWhen using scoped styles, CSS `@rules` like `@media` queries are preserved and not scoped:\n\n```html\n<Canvas>\n  <DOMContainer>\n    <button>Responsive Button</button>\n  </DOMContainer>\n</Canvas>\n\n<style scoped>\n  @media (max-width: 600px) {\n    button {\n      font-size: 14px;\n    }\n  }\n  \n  button {\n    color: blue;\n  }\n</style>\n\n<script>\n</script>\n```\n\nThe `@media` query remains unchanged, while the regular `button` selector is scoped. This allows you to use media queries and other CSS features normally within scoped styles.\n\n## Combining Scoped and Global Styles\n\nYou can have both scoped and unscoped styles in the same file:\n\n```html\n<Canvas>\n  <DOMContainer>\n    <button class=\"primary\">Primary Button</button>\n  </DOMContainer>\n</Canvas>\n\n<style>\n  /* Global styles - apply to all components */\n  .primary {\n    font-weight: bold;\n  }\n</style>\n\n<style scoped>\n  /* Scoped styles - only apply to this component */\n  button {\n    background-color: blue;\n    color: white;\n  }\n</style>\n\n<script>\n</script>\n```\n\n## Best Practices\n\n1. **Use scoped styles for component-specific styling**: This prevents style conflicts and makes your styles more maintainable.\n\n2. **Use global styles sparingly**: Global styles apply to all components, so use them only for truly global styles (like reset styles or theme variables).\n\n3. **Style DOM elements only**: CSS styles work with DOM elements (rendered via `DOMContainer` or `DOMElement`). They don't affect CanvasEngine components like `Sprite`, `Text`, or `Container`.\n\n4. **Keep styles simple**: Complex CSS may require additional testing. The scoping mechanism works best with standard CSS selectors."
  },
  {
    "path": "docs/concepts/template-syntax.md",
    "content": "# Template Syntax\n\n<script setup>\nimport conditionalRenderingExample from './examples/conditional-rendering.js'\n</script>\n\n## Static properties\n\nYou can use static properties in your components.\n\n```html\n<Text text=\"Hello World\" />\n```\n\n## Binding properties\n\nYou can use reactive properties in your components. Use the `{}` syntax to bind a property.\n```html\n<Text text={text} />\n\n<script>\n  const text = 'Hello World';\n</script>\n```\n\n::: tip\nIf the attribute name is the same as the variable, you can simplify:\n\n```html\n<Text text />\n\n<script>\n  const text = 'Hello World';\n</script>\n```\n:::\n\n::: warning Grammar v2\nThe compiler now uses grammar v2 by default. Literal `@` prefixes inside expressions are no longer supported (only `@if`, `@else`, `@for` remain). If you need the legacy grammar, set `CANVASENGINE_COMPILER_V1=1`.\n:::\n\n### Expressions and computed\n\nThe compiler only wraps expressions containing a function call in `computed`. Simple expressions stay as-is.\n\n```html\n<Text text={1 + 1} />\n<Text text={nb() + 1} />\n```\n\nCompiles to:\n\n```js\nh(Text, { text: 1 + 1 })\nh(Text, { text: computed(() => nb() + 1) })\n```\n\n## Event listeners\n\nYou can use event listeners in your components\n\n```html\n<Rect width={100} height={100} color=\"red\" click={click} />\n\n<script>\n  const click = () => {\n    console.log(\"clicked\");\n  };\n</script>\n```\n\n::: tip\nIf the attribute name is the same as the variable, you can simplify:\n\n```html\n<Rect width={100} height={100} color=\"red\" click />\n\n<script>\n  const click = () => {\n    console.log(\"clicked\");\n  };\n</script>\n```\n:::\n\n::: tip\nYou can use arrow functions in your event listeners.\n\n```html\n<Rect width={100} height={100} color=\"red\" click={() => console.log(\"clicked\")} />\n```\n:::\n\n> Use PixiJS events (https://pixijs.download/release/docs/scene.Container.html)\n\n## Conditional rendering\n\nYou can use the `@if` directive to conditionally render a component.\n\n```angular-html\n<Container>\n   @if (show) {\n     <Text text=\"Hello World\" />\n   }\n</Container>\n\n<script>\n  const show = true;\n</script>\n```\n\n> `@if` cannot be used in the root, so we put it in `Container`\n\n### @if/@else if/@else\n\nYou can use `@else if` and `@else` to create more complex conditional logic:\n\n```angular-html\n<Container>\n   @if (score() >= 90) {\n     <Text text=\"Grade: A+\" color=\"gold\" />\n   }\n   @else if (score() >= 80) {\n     <Text text=\"Grade: A\" color=\"green\" />\n   }\n   @else if (score() >= 70) {\n     <Text text=\"Grade: B\" color=\"blue\" />\n   }\n   @else if (score() >= 60) {\n     <Text text=\"Grade: C\" color=\"orange\" />\n   }\n   @else {\n     <Text text=\"Grade: F\" color=\"red\" />\n   }\n</Container>\n\n<script>\n  const score = signal(85);\n</script>\n```\n\n### Interactive Example\n\nTry this interactive example to see how `@if/@else if/@else` works:\n\n<Playground v-bind=\"conditionalRenderingExample\" />\n\n## Loops\n\nYou can use the `@for` directive to loop over an array or an object.\n\n```angular-html\n<Container>\n  @for (item of items) {\n    <Text text={item} />\n  }\n</Container>\n\n<script>\n  const items = ['Hello', 'World'];\n</script>\n```\n\n> `@for` cannot be used in the root, so we put it in `Container`\n\n::: warning With objects array\n\nIf `item` is a signal (see chapter on reactivity), use `item()` to access it.\n\n```angular-html\n<Container>\n  @for (item of items) {\n    <Text text={item().text} />\n  }\n</Container>\n\n\n<script>\n  const items = [{\n    text: 'Hello'\n  }, {\n    text: 'World'\n  }];\n</script>\n```\n:::\n\n### With objects\n\nYou can use the `@for` directive to loop over an object.\n\n```angular-html\n<Container>\n  @for ((item, key) of items) {\n    <Text text={item} /> - <Text text={key} />\n  }\n</Container>\n\n<script>\n  const items = { 'Hello': 'World', 'Foo': 'Bar' }\n</script>\n```\n\n### Advanced usage\n\nThe `@for` directive supports advanced iteration options:\n\n#### Using method calls\n\nYou can iterate over the result of a function call:\n\n```html\n<Container>\n  @for (item of getItems()) {\n    <Text text={item} />\n  }\n</Container>\n\n<script>\n  function getItems() {\n    return ['Hello', 'World'];\n  }\n</script>\n```\n\n#### Using method calls with parameters\n\nYou can pass parameters to the function:\n\n```html\n<Container>\n  @for (item of getItems(5, 'prefix')) {\n    <Text text={item} />\n  }\n</Container>\n\n<script>\n  function getItems(count, prefix) {\n    return Array.from({length: count}, (_, i) => `${prefix}-${i+1}`);\n  }\n</script>\n```\n\n#### Using object properties and methods\n\nYou can iterate over object properties and methods:\n\n```html\n<Container>\n  @for (sprite of sprites.items) {\n    <Sprite texture={sprite.texture} />\n  }\n</Container>\n\n<script>\n  const sprites = {\n    items: [\n      { texture: 'player.png' },\n      { texture: 'enemy.png' }\n    ]\n  };\n</script>\n```\n\nOr combine object properties with method calls:\n\n```html\n<Container>\n  @for (sprite of gameState.getVisibleSprites(maxCount)) {\n    <Sprite texture={sprite.texture} />\n  }\n</Container>\n\n<script>\n  const maxCount = 10;\n  const gameState = {\n    getVisibleSprites(limit) {\n      // Return only visible sprites, limited by count\n      return sprites.filter(s => s.visible).slice(0, limit);\n    }\n  };\n</script>\n```\n"
  },
  {
    "path": "docs/concepts/trigger.md",
    "content": "# Trigger\n\nTrigger is a type of signal that can be used to pass data to a component. They are created using the `trigger` function. For example:\n\n```html\n<script>\n  import { trigger, on } from 'canvasengine';\n\n  const myTrigger = trigger()\n\n  on(myTrigger, () => {\n    console.log('Click')\n  })\n\n  const run = () => {\n    myTrigger.start()\n  }\n</script>\n\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={run} />\n```\n\n\n::: tip native events\n\nif you're using native events (such as click, it takes care of the trigger automatically)\n\n```html\n<script>\n  import { trigger, on } from 'canvasengine';\n\n  const click = trigger()\n\n  on(click, () => {\n    console.log('Click')\n  })\n</script>\n\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click />\n```\n:::\n\n## With data\n\n```html\n<script>\n  import { trigger, on } from 'canvasengine';\n\n  const myTrigger = trigger()\n\n  on(myTrigger, (data) => {\n    console.log(data)\n  })\n\n  const run = () => {\n    myTrigger.start({\n      message: 'Hello World'\n    })\n  }\n</script>\n\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={run} />\n```\n\n::: tip\n\nyou can set global data that will be merged with the start method\n\n```html\n<script>\n  import { trigger, on } from 'canvasengine';\n\n  const myTrigger = trigger({\n    myData: 'myData'\n  })\n\n  on(myTrigger, async (data) => {\n    console.log('Triggered with data:', data) // { myData: 'myData', otherData: 'otherData' }\n  })\n\n  myTrigger.start({\n    otherData: 'otherData'\n  })\n</script>\n```\n:::\n\n## Use in child component\n\n`child.ce`\n```html\n<script>\n  import { on } from 'canvasengine';\n\n  const { myEvent } = defineProps()\n\n  on(myEvent, () => {\n    console.log('Event triggered')\n  })\n</script>\n```\n\n`parent.ce`\n\n```html\n<script>\n  import Child from './child.ce';\n\n  const myTrigger = trigger();\n</script>\n\n<Child myEvent={myTrigger} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={myTrigger} />\n```\n\n## Async\n\nYou can use `await` to wait for the trigger to finish.\n\n```html{6,11}\n<script>\n  import { trigger, on } from 'canvasengine';\n\n  const myTrigger = trigger();\n\n  on(myTrigger, async (data) => {\n    console.log('Triggered with data:', data)\n  })\n\n  async function run() {\n    await myTrigger.start({\n      message: 'Hello World'\n    })\n  }\n\n  run()\n</script>\n```\n"
  },
  {
    "path": "docs/directives/controls.md",
    "content": "# Use Controls directive\n\nThe controls directive allows you to control the movement and actions of a display object using keyboard and gamepad inputs. It automatically supports both input methods when available.\n\nCommon example:\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nenum Direction {\n    Up,\n    Down,\n    Left,\n    Right\n}\n\nconst x = signal(0);\nconst y = signal(0);\nconst speed = signal(10);\nconst direction = signal(Direction.Down);\n\nconst controls = signal({\n    down: {\n      repeat: true,\n      bind: [\"down\", 'bottom_right', 'bottom_left'],\n      throttle: 150,\n      keyDown() {\n        y.update((y) => y + speed());\n        direction.set(Direction.Down);\n      },\n    },\n    up: {\n      repeat: true,\n      bind: ['up', 'top_left', 'top_right'],\n      throttle: 150,\n      keyDown() {\n        y.update((y) => y - speed());\n        direction.set(Direction.Up);\n      },\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        x.update((x) => x - speed());\n        direction.set(Direction.Left);\n      },\n    },\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown(_, payload) {\n        const power = payload?.power ?? 1;\n        x.update((x) => x + speed() * power);\n        direction.set(Direction.Right);\n      },\n    },\n  });\n\n</script>\n\n<Sprite \n    image=\"path/to/image.png\" \n    sheet = {\n        {\n            params: {\n                direction\n            }\n        }\n    }\n    controls\n    x\n    y\n/>\n```\n\n## Getting the Controls Instance\n\nTo access the controls directive instance and use its methods, you can use the `mount()` hook:\n\n```html\n<script>\nimport { signal, mount } from \"canvasengine\";\n\n// ... controls configuration ...\n\nmount((element) => {\n  const controlsInstance = element.directives.controls;\n  \n  if (controlsInstance) {\n    // Get a specific control\n    const leftControl = controlsInstance.getControl('left');\n    \n    // Get all controls\n    const allControls = controlsInstance.getControls();\n    \n    // Stop listening to inputs\n    controlsInstance.stopInputs();\n    \n    // Resume listening to inputs\n    controlsInstance.listenInputs();\n    \n    // Programmatically trigger a control\n    controlsInstance.applyControl('right', true); // keydown\n    controlsInstance.applyControl('right', false); // keyup\n    \n    // Access the controls options\n    const options = controlsInstance.options;\n  }\n});\n</script>\n```\n\n## Throttle per Control\n\nYou can throttle a specific control by adding `throttle` (milliseconds) to its options.\nThis is useful for focus navigation or any action you want to rate-limit.\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nconst tabindex = signal(0);\n\nconst controls = signal({\n  up: {\n    repeat: true,\n    bind: \"up\",\n    throttle: 150,\n    keyDown() {\n      tabindex.update((value) => Math.max(0, value - 1));\n    }\n  },\n  down: {\n    repeat: true,\n    bind: \"down\",\n    throttle: 150,\n    keyDown() {\n      tabindex.update((value) => value + 1);\n    }\n  }\n});\n</script>\n```\n\n### Available Methods\n\nThe `ControlsDirective` instance provides the following methods:\n\n- `getControl(inputName: string)` - Get a specific control by input name\n- `getControls()` - Get all bound controls\n- `applyControl(controlName: string, isDown?: boolean, payload?: any)` - Programmatically trigger a control (payload can carry extra data, e.g. joystick power)\n- `stopInputs()` - Stop listening to inputs (both keyboard and gamepad)\n- `listenInputs()` - Resume listening to inputs (both keyboard and gamepad)\n- `options` - Access the controls configuration object\n- `keyboard` - Get the keyboard controls instance (if available)\n- `gamepad` - Get the gamepad controls instance (if available)\n\n## Gamepad Support\n\nThe controls directive automatically detects and activates gamepad support when `joypad.js` is available in your project. Gamepad controls work alongside keyboard controls, allowing players to use either input method seamlessly.\n\n### Automatic Activation\n\nGamepad support is automatically enabled when:\n1. `joypad.js` library is loaded in your project\n2. A gamepad is connected to the system\n\nNo additional configuration is required for basic gamepad functionality.\n\n### Gamepad Configuration\n\nYou can customize gamepad behavior by adding a `gamepad` property to your controls configuration:\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nconst controls = signal({\n  up: {\n    repeat: true,\n    bind: Input.Up,\n    keyDown() {\n      // Handle up movement\n    }\n  },\n  // ... other controls ...\n  \n  // Optional: Customize gamepad behavior\n  gamepad: {\n    enabled: true, // Enable/disable gamepad (default: true)\n    buttonMapping: { // Map gamepad buttons to controls (optional)\n      'button_0': 'action',  // A button -> action\n      'button_1': 'back',    // B button -> back\n      'button_9': 'back'     // Start button -> back\n    },\n    axisMapping: { // Map stick directions (optional)\n      'top': 'up',\n      'bottom': 'down',\n      'left': 'left',\n      'right': 'right'\n    },\n    moveInterval: 400, // Movement repeat interval in ms (default: 400)\n    onConnect: () => console.log('Gamepad connected!'), // Optional callback\n    onDisconnect: () => console.log('Gamepad disconnected!'), // Optional callback\n    gamepadConnected: gamepadConnectedSignal // Optional signal to track connection status\n  }\n});\n</script>\n```\n\n### Default Button Mapping\n\nIf not specified, the following default mappings are used:\n\n- `button_0` → `action` control\n- `button_1` → `back` control\n- `button_9` → `back` control\n\n### Default Axis Mapping\n\nAnalog stick movements are mapped to direction controls:\n\n- `top` → `up`\n- `bottom` → `down`\n- `left` → `left`\n- `right` → `right`\n\n### Using Joystick Power/Intensity\n\nGamepad controls automatically pass the joystick intensity (power) to the `keyDown` callback via the `payload` parameter. The power value ranges from 0.0 to 1.0, representing how far the joystick is pushed.\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nconst x = signal(0);\nconst y = signal(0);\nconst speed = signal(10);\n\nconst controls = signal({\n  up: {\n    repeat: true,\n    bind: \"up\",\n    keyDown(_, payload) {\n      const power = payload?.power ?? 1;\n      y.update((y) => y - speed() * power);\n    }\n  },\n  down: {\n    repeat: true,\n    bind: \"down\",\n    keyDown(_, payload) {\n      const power = payload?.power ?? 1;\n      y.update((y) => y + speed() * power);\n    }\n  },\n  left: {\n    repeat: true,\n    bind: \"left\",\n    keyDown(_, payload) {\n      const power = payload?.power ?? 1;\n      x.update((x) => x - speed() * power);\n    }\n  },\n  right: {\n    repeat: true,\n    bind: \"right\",\n    keyDown(_, payload) {\n      const power = payload?.power ?? 1;\n      x.update((x) => x + speed() * power);\n    }\n  }\n});\n</script>\n```\n\nThe power value allows for variable-speed movement based on how far the joystick is pushed, providing more precise control similar to analog input.\n\n### Gamepad Connection Tracking\n\nYou can track gamepad connection status using a signal:\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\n// Create a signal to track gamepad connection status\nconst gamepadConnected = signal(false);\n\nconst controls = signal({\n  // ... other controls ...\n  gamepad: {\n    enabled: true,\n    // Signal will be automatically updated when gamepad connects/disconnects\n    gamepadConnected: gamepadConnected,\n    onConnect() {\n      console.log('Gamepad connected!');\n    },\n    onDisconnect() {\n      console.log('Gamepad disconnected!');\n    }\n  }\n});\n\n// Use the signal in your UI\n// gamepadConnected() will be true when connected, false otherwise\n</script>\n```\n\n### Accessing Gamepad Instance\n\nYou can access the gamepad controls instance to customize behavior at runtime:\n\n```html\n<script>\nimport { mount } from \"canvasengine\";\n\nmount((element) => {\n  const controlsInstance = element.directives.controls;\n  \n  if (controlsInstance && controlsInstance.gamepad) {\n    // Update gamepad configuration\n    controlsInstance.gamepad.updateGamepadConfig({\n      enabled: true,\n      buttonMapping: {\n        'button_0': 'jump',\n        'button_1': 'attack'\n      }\n    });\n  }\n});\n</script>\n```\n\n### Installing joypad.js\n\nTo enable gamepad support, install the `joypad.js` library:\n\n```bash\nnpm install joypad.js\n```\n\nThen import it in your project:\n\n```javascript\nimport 'joypad.js';\n```\n\nThe controls directive will automatically detect and use it.\n"
  },
  {
    "path": "docs/directives/drag.md",
    "content": "# Using the Drag Directive\n\nThe Drag directive allows you to make display objects draggable with the mouse or touch. This is useful for creating interactive elements that users can move around the canvas.\n\n## Basic Usage\n\nTo make an element draggable, simply add the `drag` attribute to it:\n\n```html\n<Sprite image=\"path/to/image.png\" drag />\n```\n\n## Configuration Options\n\nYou can configure the drag behavior by passing an object with options:\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nconst drag = {\n  direction: 'all', // 'all', 'x', or 'y'\n  snap: 10, // Optional: snap to grid with specified interval\n  keyToPress: ['ShiftLeft', 'ShiftRight'], // Optional: keys that must be pressed to enable dragging\n  start() {\n    console.log(\"Drag started\");\n  },\n  move(event) {\n    console.log(\"Dragging\", event.global.x, event.global.y);\n  },\n  end() {\n    console.log(\"Drag ended\");\n  }\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" drag={drag} />\n```\n\n### Available Options\n\n- `direction`: Controls the axis of movement ('all', 'x', or 'y')\n- `snap`: Optional number that determines grid snapping\n- `keyToPress`: Optional array of key codes that must be pressed for dragging to work\n- `start()`: Callback function triggered when dragging starts\n- `move(event)`: Callback function called continuously during dragging\n- `end()`: Callback function triggered when dragging ends\n\n### Key Modifiers for Dragging\n\nThe `keyToPress` option allows you to require specific keyboard keys to be pressed for dragging to work. This is useful for creating more complex interactions or preventing accidental dragging.\n\n```html\n<script>\nconst drag = {\n  // Only enable dragging when Shift key is pressed\n  keyToPress: ['ShiftLeft', 'ShiftRight']\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" drag={drag} />\n```\n\nYou can use standard [KeyboardEvent.code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code) values or common key names:\n\n```html\n<script>\n// Examples of different key configurations\nconst dragWithShift = { keyToPress: ['shift'] };  // Either Shift key\nconst dragWithCtrl = { keyToPress: ['ctrl'] };    // Either Control key\nconst dragWithAlt = { keyToPress: ['alt'] };      // Either Alt key\nconst dragWithSpace = { keyToPress: ['space'] };  // Space bar\n</script>\n```\n\nThe drag operation will start only when the specified key is pressed during mouse/touch interaction, and will end if the key is released during dragging.\n\n### Disabling Drag\n\nTo disable drag functionality on an element that previously had it, you can pass an empty object:\n\n```html\n<script>\n// Enable drag\nconst dragEnabled = signal({\n  direction: 'all'\n});\n\n// Later, to disable drag:\ndragEnabled.set({});\n</script>\n\n<Sprite image=\"path/to/image.png\" drag={dragEnabled} />\n```\n\n## Viewport Integration\n\nWhen used within a Viewport, the Drag directive can automatically scroll the viewport when dragging elements near the edges. This is particularly useful for large game maps or workspaces.\n\nTo enable viewport scrolling, add the `viewport` property to your drag configuration:\n\n```html\n<script>\nconst drag = {\n  // Basic drag options\n  direction: 'all',\n  keyToPress: ['space'], // Optional: require space bar to be pressed\n  \n  // Viewport scrolling options\n  viewport: {\n    edgeThreshold: 100, // Distance from edge to trigger scrolling (pixels)\n    maxSpeed: 10        // Maximum scrolling speed\n  }\n};\n</script>\n\n<Viewport worldWidth={2000} worldHeight={2000}>\n  <Sprite image=\"path/to/image.png\" drag />\n</Viewport>\n```\n\n### Viewport Options\n\n- `edgeThreshold`: Distance in pixels from the viewport edge that triggers scrolling\n- `maxSpeed`: Maximum speed of viewport scrolling when an element is dragged to the edge\n\n::: warning\nThe drag directive is incompatible with elements that have `viewportFollow` enabled. If you want to make an element draggable that previously had viewport following enabled, you must set `viewportFollow` to `false` first:\n\n```html\n<script>\nimport { signal } from \"canvasengine\";\n\nconst viewportFollow = signal(false); // Must be false for drag to work properly\nconst drag = signal({\n  direction: 'all'\n});\n</script>\n\n<Sprite \n  image=\"path/to/image.png\" \n  viewportFollow\n  drag\n/>\n```\n:::\n"
  },
  {
    "path": "docs/directives/flash.md",
    "content": "# Using the Flash Directive\n\nThe Flash directive allows you to create a flash animation effect on display objects when a trigger is activated. This is useful for creating visual feedback effects, such as when an element is hit, selected, or when an important event occurs.\n\n## Basic Usage\n\nTo make an element flash, add the `flash` attribute with a trigger:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst flashTrigger = trigger();\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={{ trigger: flashTrigger }} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => flashTrigger.start()} />\n```\n\nWhen you click the red rectangle, the sprite will flash.\n\n## Configuration Options\n\nYou can configure the flash behavior by passing an object with options:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst flashTrigger = trigger();\n\nconst flashConfig = {\n  trigger: flashTrigger,\n  type: 'alpha',        // 'alpha', 'tint', or 'both'\n  duration: 300,        // Duration in milliseconds\n  cycles: 1,            // Number of flash cycles\n  alpha: 0.3,           // Alpha value when flashing (0 to 1)\n  tint: 0xffffff,      // Tint color when flashing (hex)\n  onStart() {\n    console.log(\"Flash started\");\n  },\n  onComplete() {\n    console.log(\"Flash completed\");\n  }\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={flashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => flashTrigger.start()} />\n```\n\n### Available Options\n\n- `trigger`: **Required**. The trigger that activates the flash animation\n- `type`: Type of flash effect - `'alpha'` (opacity), `'tint'` (color), or `'both'` (default: `'alpha'`)\n- `duration`: Duration of the flash animation in milliseconds (default: `300`)\n- `cycles`: Number of flash cycles (flash on/off) (default: `1`)\n- `alpha`: Alpha value when flashing, from 0 to 1 (default: `0.3`)\n- `tint`: Tint color when flashing as hex value (default: `0xffffff` - white)\n- `originalAlpha`: Original alpha value to restore (auto-detected if not provided)\n- `originalTint`: Original tint value to restore (auto-detected if not provided)\n- `onStart()`: Callback function triggered when flash starts\n- `onComplete()`: Callback function triggered when flash completes\n\n## Flash Types\n\n### Alpha Flash (Opacity)\n\nCreates a flash effect by changing the opacity of the element:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst alphaFlashTrigger = trigger();\n\nconst alphaFlashConfig = {\n  trigger: alphaFlashTrigger,\n  type: 'alpha',\n  alpha: 0.2,  // Flash to 20% opacity\n  duration: 400\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={alphaFlashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => alphaFlashTrigger.start()} />\n```\n\n### Tint Flash (Color)\n\nCreates a flash effect by changing the color tint of the element:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst tintFlashTrigger = trigger();\n\nconst tintFlashConfig = {\n  trigger: tintFlashTrigger,\n  type: 'tint',\n  tint: 0xff0000,  // Flash to red\n  duration: 300\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={tintFlashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => tintFlashTrigger.start()} />\n```\n\n### Both Alpha and Tint\n\nCreates a flash effect using both opacity and color:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst bothFlashTrigger = trigger();\n\nconst bothFlashConfig = {\n  trigger: bothFlashTrigger,\n  type: 'both',\n  alpha: 0.5,\n  tint: 0x00ff00,  // Flash to green with reduced opacity\n  duration: 500\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={bothFlashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => bothFlashTrigger.start()} />\n```\n\n## Multiple Flash Cycles\n\nYou can create multiple flash cycles for a more dramatic effect:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst multiFlashTrigger = trigger();\n\nconst multiFlashConfig = {\n  trigger: multiFlashTrigger,\n  type: 'alpha',\n  cycles: 3,  // Flash 3 times\n  duration: 600\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={multiFlashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => multiFlashTrigger.start()} />\n```\n\n## Using with Trigger Data\n\nYou can pass data through the trigger to customize the flash effect:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst flashTrigger = trigger();\n\non(flashTrigger, (data) => {\n  console.log('Flash triggered with data:', data);\n});\n\nconst flashConfig = {\n  trigger: flashTrigger,\n  type: 'alpha',\n  duration: 300\n};\n\nconst handleClick = () => {\n  // Trigger flash with custom data\n  flashTrigger.start({\n    type: 'tint',\n    tint: 0xff0000,  // Override to red flash\n    duration: 500\n  });\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={flashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={handleClick} />\n```\n\n## Advanced Usage\n\n### Flash on Multiple Events\n\nYou can use the same trigger for multiple elements:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst globalFlash = trigger();\n\nconst flashConfig = {\n  trigger: globalFlash,\n  type: 'alpha',\n  alpha: 0.2,\n  duration: 300\n};\n</script>\n\n<!-- Multiple elements flash together -->\n<Sprite image=\"path/to/image1.png\" flash={flashConfig} />\n<Sprite image=\"path/to/image2.png\" flash={flashConfig} />\n<Sprite image=\"path/to/image3.png\" flash={flashConfig} />\n\n<!-- Trigger flash from multiple sources -->\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => globalFlash.start()} />\n<Rect x=\"20\" y=\"0\" width=\"10\" height=\"10\" color=\"blue\" click={() => globalFlash.start()} />\n```\n\n### Flash with Async/Await\n\nSince triggers support async/await, you can wait for the flash to complete:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst flashTrigger = trigger();\n\non(flashTrigger, async (data) => {\n  console.log('Flash started');\n  // The flash animation will complete before this promise resolves\n  console.log('Flash completed');\n});\n\nconst flashConfig = {\n  trigger: flashTrigger,\n  type: 'alpha',\n  duration: 300\n};\n\nasync function handleClick() {\n  await flashTrigger.start();\n  console.log('Animation finished, can proceed with next action');\n}\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={flashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={handleClick} />\n```\n\n### Dynamic Flash Configuration\n\nYou can use signals to make flash configuration reactive:\n\n```html\n<script>\nimport { trigger, signal } from 'canvasengine';\n\nconst flashTrigger = trigger();\nconst flashType = signal('alpha');\nconst flashDuration = signal(300);\n\nconst flashConfig = {\n  trigger: flashTrigger,\n  type: flashType,\n  duration: flashDuration\n};\n\n// Later, update the configuration\nflashType.set('tint');\nflashDuration.set(500);\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={flashConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={() => flashTrigger.start()} />\n```\n\n## Use Cases\n\n### Flash on Click\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst flashTrigger = trigger();\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={{ trigger: flashTrigger }} click={() => flashTrigger.start()} />\n```\n\n### Flash on Hit/Damage\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst hitFlash = trigger();\n\nconst flashConfig = {\n  trigger: hitFlash,\n  type: 'both',\n  alpha: 0.5,\n  tint: 0xff0000,  // Red flash\n  duration: 200,\n  cycles: 2\n};\n\nfunction takeDamage() {\n  hitFlash.start();\n}\n</script>\n\n<Sprite image=\"path/to/character.png\" flash={flashConfig} />\n```\n\n### Flash on Selection\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst selectFlash = trigger();\n\nconst flashConfig = {\n  trigger: selectFlash,\n  type: 'tint',\n  tint: 0x00ff00,  // Green flash\n  duration: 150\n};\n</script>\n\n<Sprite image=\"path/to/item.png\" flash={flashConfig} />\n```\n\n### Flash on Error\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst errorFlash = trigger();\n\non(errorFlash, () => {\n  console.error('An error occurred!');\n});\n\nconst flashConfig = {\n  trigger: errorFlash,\n  type: 'both',\n  alpha: 0.3,\n  tint: 0xff0000,  // Red flash\n  duration: 300,\n  cycles: 3,\n  onStart() {\n    console.log('Error flash started');\n  }\n};\n\nfunction handleError() {\n  errorFlash.start();\n}\n</script>\n\n<Sprite image=\"path/to/image.png\" flash={flashConfig} />\n```\n\n## Tips\n\n- **Alpha values**: Range from 0 (fully transparent) to 1 (fully opaque). Lower values create more dramatic flashes.\n- **Tint colors**: Use hex color values (e.g., `0xff0000` for red, `0x00ff00` for green, `0x0000ff` for blue).\n- **Duration**: Shorter durations (100-300ms) create quick, snappy flashes. Longer durations (500-1000ms) create more noticeable effects.\n- **Cycles**: Higher cycle counts create more dramatic, attention-grabbing effects. Use 2-3 cycles for important notifications.\n- **Type selection**: \n  - Use `'alpha'` for subtle, elegant flashes\n  - Use `'tint'` for colorful, vibrant flashes\n  - Use `'both'` for maximum visual impact\n\n::: tip\nThe flash animation automatically restores the element's original alpha and tint values when complete, so you don't need to manually reset them.\n:::\n\n::: warning\nIf you're using the flash directive with elements that have alpha or tint animations, make sure the flash doesn't conflict with other property updates. The flash temporarily modifies these properties during the animation.\n:::\n\n"
  },
  {
    "path": "docs/directives/shake.md",
    "content": "# Using the Shake Directive\n\nThe Shake directive allows you to create a shake animation effect on display objects when a trigger is activated. This is useful for creating visual feedback effects, such as when an element is hit, clicked, or when an error occurs.\n\n## Basic Usage\n\nTo make an element shake, add the `shake` attribute with a trigger:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst shakeTrigger = trigger();\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={{ trigger: shakeTrigger }} />\n\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={shakeTrigger} />\n```\n\nWhen you click the red rectangle, the sprite will shake.\n\n## Configuration Options\n\nYou can configure the shake behavior by passing an object with options:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst shakeTrigger = trigger();\n\nconst shakeConfig = {\n  trigger: shakeTrigger,\n  intensity: 15,        // Shake intensity in pixels\n  duration: 500,        // Duration in milliseconds\n  frequency: 10,        // Number of oscillations\n  direction: 'both',    // 'x', 'y', or 'both'\n  onStart() {\n    console.log(\"Shake started\");\n  },\n  onComplete() {\n    console.log(\"Shake completed\");\n  }\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeConfig} />\n\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={shakeTrigger} />\n```\n\n### Available Options\n\n- `trigger`: **Required**. The trigger that activates the shake animation\n- `intensity`: Shake intensity in pixels (default: `10`)\n- `duration`: Duration of the shake animation in milliseconds (default: `500`)\n- `frequency`: Number of shake oscillations during the animation (default: `10`)\n- `direction`: Direction of the shake - `'x'`, `'y'`, or `'both'` (default: `'both'`)\n- `onStart()`: Callback function triggered when shake starts\n- `onComplete()`: Callback function triggered when shake completes\n\n## Using with Trigger Data\n\nYou can pass data through the trigger to customize the shake effect:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst shakeTrigger = trigger();\n\non(shakeTrigger, (data) => {\n  console.log('Shake triggered with data:', data);\n});\n\nconst shakeConfig = {\n  trigger: shakeTrigger,\n  intensity: 10,\n  duration: 500\n};\n\nconst handleClick = () => {\n  // Trigger shake with custom data\n  shakeTrigger.start({\n    intensity: 20,  // Override intensity for this shake\n    duration: 1000\n  });\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={handleClick} />\n```\n\n## Direction Options\n\nYou can control which axis the shake affects:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst shakeX = trigger();\nconst shakeY = trigger();\nconst shakeBoth = trigger();\n\nconst shakeHorizontal = {\n  trigger: shakeX,\n  direction: 'x',  // Only shake horizontally\n  intensity: 15\n};\n\nconst shakeVertical = {\n  trigger: shakeY,\n  direction: 'y',  // Only shake vertically\n  intensity: 15\n};\n\nconst shakeAll = {\n  trigger: shakeBoth,\n  direction: 'both',  // Shake in both directions\n  intensity: 15\n};\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeHorizontal} />\n<Sprite image=\"path/to/image2.png\" shake={shakeVertical} />\n<Sprite image=\"path/to/image3.png\" shake={shakeAll} />\n```\n\n## Advanced Usage\n\n### Shake on Multiple Events\n\nYou can use the same trigger for multiple elements or multiple events:\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst globalShake = trigger();\n\nconst shakeConfig = {\n  trigger: globalShake,\n  intensity: 20,\n  duration: 300\n};\n</script>\n\n<!-- Multiple elements shake together -->\n<Sprite image=\"path/to/image1.png\" shake={shakeConfig} />\n<Sprite image=\"path/to/image2.png\" shake={shakeConfig} />\n<Sprite image=\"path/to/image3.png\" shake={shakeConfig} />\n\n<!-- Trigger shake from multiple sources -->\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={globalShake} />\n<Rect x=\"20\" y=\"0\" width=\"10\" height=\"10\" color=\"blue\" click={globalShake} />\n```\n\n### Shake with Async/Await\n\nSince triggers support async/await, you can wait for the shake to complete:\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst shakeTrigger = trigger();\n\non(shakeTrigger, async (data) => {\n  console.log('Shake started');\n  // The shake animation will complete before this promise resolves\n  console.log('Shake completed');\n});\n\nconst shakeConfig = {\n  trigger: shakeTrigger,\n  intensity: 15,\n  duration: 500\n};\n\nasync function handleClick() {\n  await shakeTrigger.start();\n  console.log('Animation finished, can proceed with next action');\n}\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={handleClick} />\n```\n\n### Dynamic Shake Configuration\n\nYou can use signals to make shake configuration reactive:\n\n```html\n<script>\nimport { trigger, signal } from 'canvasengine';\n\nconst shakeTrigger = trigger();\nconst intensity = signal(10);\nconst duration = signal(500);\n\nconst shakeConfig = {\n  trigger: shakeTrigger,\n  intensity: intensity,\n  duration: duration\n};\n\n// Later, update the configuration\nintensity.set(20);\nduration.set(1000);\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeConfig} />\n<Rect x=\"0\" y=\"0\" width=\"10\" height=\"10\" color=\"red\" click={shakeTrigger} />\n```\n\n## Use Cases\n\n### Shake on Click\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst shakeTrigger = trigger();\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={{ trigger: shakeTrigger }} click={shakeTrigger} />\n```\n\n### Shake on Error\n\n```html\n<script>\nimport { trigger, on } from 'canvasengine';\n\nconst errorShake = trigger();\n\non(errorShake, () => {\n  console.error('An error occurred!');\n});\n\nconst shakeConfig = {\n  trigger: errorShake,\n  intensity: 20,\n  duration: 300,\n  onStart() {\n    console.log('Error shake started');\n  }\n};\n\nfunction handleError() {\n  errorShake.start();\n}\n</script>\n\n<Sprite image=\"path/to/image.png\" shake={shakeConfig} />\n```\n\n### Shake on Hit/Damage\n\n```html\n<script>\nimport { trigger } from 'canvasengine';\n\nconst hitShake = trigger();\n\nconst shakeConfig = {\n  trigger: hitShake,\n  intensity: 25,\n  duration: 400,\n  frequency: 15,\n  direction: 'both'\n};\n\nfunction takeDamage() {\n  hitShake.start();\n}\n</script>\n\n<Sprite image=\"path/to/character.png\" shake={shakeConfig} />\n```\n\n## Tips\n\n- **Intensity**: Higher values create more dramatic shakes. Values between 5-30 pixels work well for most use cases.\n- **Duration**: Shorter durations (200-500ms) create quick, snappy shakes. Longer durations (500-1000ms) create more dramatic effects.\n- **Frequency**: Higher frequencies (10-20) create rapid, intense shakes. Lower frequencies (5-10) create slower, more noticeable shakes.\n- **Direction**: Use `'x'` or `'y'` for directional effects, such as shaking a health bar horizontally when taking damage.\n\n::: tip\nThe shake animation automatically resets the element's position to its original location when complete, so you don't need to manually reset it.\n:::\n\n::: warning\nIf you're using the shake directive with elements that have position animations, make sure the shake doesn't conflict with other position updates. The shake temporarily modifies the position during the animation.\n:::\n\n"
  },
  {
    "path": "docs/directives/sound.md",
    "content": "# Sound Directive\n\nThe Sound directive allows you to add audio capabilities to your game elements in CanvasEngine. It integrates with the [Howler.js](https://howlerjs.com/) library to provide a powerful and flexible audio solution.\n\n## Basic Usage\n\nTo use the Sound directive, add it to any element in your component:\n\n```typescript\n<Sprite \n  sound={{ \n    src: \"explosion.mp3\", \n    autoplay: true \n  }} \n  image=\"explosion.png\" \n/>\n```\n\n## Properties\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `src` | `string` or `string[]` | Path(s) to the audio file(s) to be loaded |\n| `autoplay` | `boolean` | Whether the sound should play automatically when loaded |\n| `loop` | `boolean` | Whether the sound should loop indefinitely |\n| `volume` | `number` | Initial volume from 0.0 to 1.0 |\n| `playing` | `boolean` | Whether the sound is currently playing |\n| `mute` | `boolean` | Whether the sound is muted |\n| `seek` | `number` | The position to seek to in the sound (in seconds) |\n| `rate` | `number` | The playback rate (speed) of the sound |\n\n## Events\n\nThe Sound directive supports all Howler.js events:\n\n| Event | Description |\n|-------|-------------|\n| `load` | Fires when the sound is loaded |\n| `loaderror` | Fires when the sound fails to load |\n| `playerror` | Fires when the sound fails to play |\n| `play` | Fires when the sound begins playing |\n| `end` | Fires when the sound finishes playing |\n| `pause` | Fires when the sound is paused |\n| `stop` | Fires when the sound is stopped |\n| `mute` | Fires when the sound is muted/unmuted |\n| `volume` | Fires when the sound's volume changes |\n| `rate` | Fires when the sound's playback rate changes |\n| `seek` | Fires when the sound is seeked |\n| `fade` | Fires when the sound's volume fades |\n| `unlock` | Fires when the sound is unlocked (mobile devices) |\n\n## Reactive Usage\n\nYou can control sound properties reactively using signals:\n\n```html\n<script>\nimport { signal } from 'canvasengine'\n\nconst playing = false\nconst sound = signal({\n  src: \"exp.mp3\",\n  loop: false,\n  volume: 1,\n  playing\n})\n\nconst toggleSound = () => {\n  sound.update(val => ({ ...val, playing: !val.playing }))\n}\n</script>\n<Sprite sound={sound} image=\"exp.png\" click={toggleSound} />\n```\n\n## Spatial Sound\n\nThe Sound directive also supports spatial audio, where volume changes based on the listener's position:\n\n```html\n<Container>\n  <Sprite soundListenerPosition={{ x: cameraX, y: cameraY }} />\n  \n  <Sprite \n    sound={{ \n      src: \"ambient.mp3\", \n      loop: true,\n      spatial: {\n        maxVolume: 1,\n        maxDistance: 500\n      }\n    }} \n    x={position.x}\n    y={position.y}\n  />\n</Container>\n\n<script>\n  import { signal } from 'canvasengine'\n\n  const cameraX = signal(0)\n  const cameraY = signal(0)\n  const position = signal({ x: 0, y: 0 })\n</script>\n```\n\nFor spatial sound to work:\n1. Add the `soundListenerPosition` directive to the camera or any other element that represents the listener's position\n2. Add the `spatial` property to the sound configuration, which can include:\n   - `maxVolume`: The maximum volume when the listener is at the sound's position\n   - `maxDistance`: The distance at which the sound becomes inaudible"
  },
  {
    "path": "docs/get_started/installation.md",
    "content": "# Installation\n\n## From template\n\n```bash\nnpx degit RSamaium/CanvasEngine/starter my-project\ncd my-project\nnpm install\nnpm run dev # and go to localhost:5173\n```\n\n## In existing project\n\n> Your project must already be under Vite.\n\n```bash\nnpm i canvasengine @canvasengine/compiler\n```\n\nAdd in `vite.config.ts`\n\n```ts\nimport { defineConfig } from 'vite';\nimport canvasengine from '@canvasengine/compiler';\n\nexport default defineConfig({\n  plugins: [canvasengine()],\n});\n```\n"
  },
  {
    "path": "docs/get_started/readme.md",
    "content": "# Get Started\n\nCanvas Engine is a framework for creating 2D games using a reactive programming model. It is built on top of the Canvas API and is designed to be easy to use and understand.\n\n## Installation\n\n```bash\nnpm install canvasengine\n```\n\n## Usage\n\n1. Create a new file, for example `main.ce`:\n\n```html\n<Canvas \n    backgroundColor=\"white\" \n    flexDirection=\"column\" \n    justifyContent=\"center\" \n    alignItems=\"center\" \n    width=\"100%\" \n    height=\"100%\"\n>\n    <Text text=\"Hello World\" />\n</Canvas>\n```\n\n2. Create a new file, for example `main.ts`:\n\n```typescript\nimport { bootstrapCanvas } from \"canvasengine\";\nimport Main from \"./main.ce\";\n\nbootstrapCanvas(document.getElementById(\"root\"), Main);\n```\n"
  },
  {
    "path": "docs/get_started/start.md",
    "content": "# Start with CanvasEngine\n\n## 1. Add div with id `root` to your HTML\n\nIn your `index.html` file, add a `div` with the id `root`:\n\n```html\n<div id=\"root\"></div>\n```\n\n## 2. Create a Canvas Component\n\nCreate a new file `app.ce` in your project root: \n\n```html\n<Canvas>\n  <Text text=\"Hello World\" />\n</Canvas>\n```\n\n::: warning\nThe start file must always begin with the `<Canvas>` tag.\n:::\n\n## 3. Add the `bootstrapCanvas` function to your entry file\n\n```ts\nimport App from './app.ce';\nimport { bootstrapCanvas } from 'canvasengine';\n\nbootstrapCanvas(document.getElementById(\"root\"), App).then(() => {\n    console.log(\"CanvasEngine initialized\");\n});\n```\n\n## 4. Run your project\n\nRun your project with the following command:\n\n```bash\nnpm run dev\n```\n"
  },
  {
    "path": "docs/index.md",
    "content": "# Canvas Engine\n\nCanvasEngine is a reactive HTML5 Canvas management library built on top of PixiJS and Vite. It provides a component-oriented approach to canvas rendering, similar to modern frontend frameworks.\n\n## Features\n\n- Reactive components with signals\n- Use flexbox in Canvas!\n- Easy Animation system \n- Keyboard, Gamepad and Virtual Joystick support\n- Tiled Map Editor integration\n- Particle Emitter\n- Audio System\n- Viewport with pan/zoom and culling\n- [Performance optimizations for large scenes](/advanced/performance)\n"
  },
  {
    "path": "docs/package.json",
    "content": "{\n  \"name\": \"docs\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"dev\": \"vitepress dev\",\n    \"build\": \"vitepress build\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"@codemirror/basic-setup\": \"^0.20.0\",\n    \"@codemirror/lang-html\": \"^6.4.9\",\n    \"@codemirror/state\": \"^6.5.2\",\n    \"@codemirror/theme-one-dark\": \"^6.1.2\",\n    \"@codemirror/view\": \"^6.37.2\",\n    \"@codesandbox/sandpack-themes\": \"^2.0.21\",\n    \"codemirror\": \"^6.0.1\",\n    \"esbuild-wasm\": \"^0.25.5\",\n    \"peggy\": \"^4.2.0\",\n    \"sandpack-vue3\": \"^3.1.12\",\n    \"vite\": \"^6.3.5\",\n    \"vitepress\": \"^1.6.3\"\n  },\n  \"type\": \"module\",\n  \"devDependencies\": {\n    \"markdown-it-container\": \"^4.0.0\",\n    \"vitepress-plugin-llms\": \"^1.3.4\",\n    \"vitepress-plugin-sandpack\": \"^1.1.4\"\n  }\n}\n"
  },
  {
    "path": "docs/presets/_before.md",
    "content": "## Install\n\nPlease install the `@canvasengine/presets` package first.\n\n```bash\nnpm install @canvasengine/presets\n```\n\nThen, you can use the presets in your project."
  },
  {
    "path": "docs/presets/bar.md",
    "content": "# Bar\n\n<!-- @include: ./_before.md -->\n\n## Usage\n\n```html\n<Canvas>\n    <Bar width={200} height={20} value={50} maxValue={100} backgroundColor=\"#333\" foregroundColor=\"#f00\" />\n</Canvas>\n\n<script>\n    import { Bar } from '@canvasengine/presets'\n</script>\n```\n\n## Props\n\n| Prop | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| backgroundColor | string | No | '#333333' | Background color of the bar |\n| foregroundColor | string | No | '#ffffff' | Color of the progress bar |\n| value | number | Yes | - | Current value of the progress bar |\n| maxValue | number | Yes | - | Maximum value of the progress bar |\n| width | number | Yes | - | Width of the bar in pixels |\n| height | number | Yes | - | Height of the bar in pixels |\n"
  },
  {
    "path": "docs/presets/fog-of-war.md",
    "content": "# Fog Of War\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`FogOfWar` provides an Age-of-Empires style fog system with 3 states:\n\n- `visible`: fully transparent (currently seen)\n- `explored`: darkened memory\n- `unknown`: opaque black\n\nIt works well inside `Viewport`, supports smooth rendering, and can expose visibility queries for gameplay objects.\n\n## Basic Usage\n\n```html\n<Canvas>\n  <Viewport worldWidth={2048} worldHeight={2048} sortableChildren={true}>\n    <FogOfWar\n      mapWidth={2048}\n      mapHeight={2048}\n      tileSize={32}\n      smooth={true}\n      renderScale={2}\n      edgeSoftness={22}\n      visionSources={visionSources}\n      updateHz={15}\n      zIndex={1000}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { computed, signal } from 'canvasengine'\n  import { FogOfWar } from '@canvasengine/presets'\n\n  const playerX = signal(300)\n  const playerY = signal(260)\n\n  const visionSources = computed(() => [\n    { x: playerX(), y: playerY(), radius: 220, enabled: true },\n  ])\n</script>\n```\n\n## Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `mapWidth` | `number \\| Signal<number>` | required | World/map width in pixels |\n| `mapHeight` | `number \\| Signal<number>` | required | World/map height in pixels |\n| `tileSize` | `number \\| Signal<number>` | `32` | Fog grid cell size in pixels |\n| `smooth` | `boolean \\| Signal<boolean>` | `true` | Enables smooth fog interpolation |\n| `renderScale` | `number \\| Signal<number>` | `2` | Internal fog resolution multiplier (higher = smoother, heavier CPU) |\n| `edgeSoftness` | `number \\| Signal<number>` | `22` | Soft transition width (pixels) around vision circles |\n| `visionSources` | `Array<VisionSource> \\| Signal<Array<VisionSource>>` | `[]` | Vision emitters |\n| `updateHz` | `number \\| Signal<number>` | `15` | Fog recomputation frequency |\n| `colors` | `object \\| Signal<object>` | `{ unknown: [0,0,0,1], explored: [0,0,0,0.55] }` | Fog colors/alpha |\n| `initialExplored` | `boolean \\| Signal<boolean>` | `false` | Reveal all as explored on start |\n| `controller` | `FogOfWarController` | none | Exposes `clarityAt/isVisibleAt/stateAt` for object visibility logic |\n| `zIndex` | `number \\| Signal<number>` | inherited | Render order (forwarded to Sprite) |\n\n### `VisionSource`\n\n```ts\ntype VisionSource = {\n  x: number | (() => number)\n  y: number | (() => number)\n  radius: number | (() => number)\n  enabled?: boolean | (() => boolean)\n}\n```\n\n### `FogOfWarController`\n\n```ts\nimport { createFogOfWarController } from '@canvasengine/presets'\n\nconst fog = createFogOfWarController()\n\nfog.clarityAt(x, y) // 0..1\nfog.isVisibleAt(x, y, 0.72) // true only in \"very clear\" zone\nfog.isExploredAt(x, y) // true if already discovered\nfog.stateAt(x, y) // \"visible\" | \"explored\" | \"unknown\"\n```\n\n## Gameplay Visibility Example\n\nUse this when some objects should stay normal (current behavior), while others are visible only in clear vision.\n\n```html\n<Rect x={relicX} y={relicY} width={34} height={34} color=\"#ffd166\" />\n<Rect x={enemyX} y={enemyY} width={34} height={34} color=\"#5ee7ff\" visible={enemyVisible} />\n\n<FogOfWar\n  mapWidth={worldWidth}\n  mapHeight={worldHeight}\n  visionSources={visionSources}\n  controller={fog}\n  smooth={true}\n  renderScale={2}\n  edgeSoftness={22}\n/>\n\n<script>\n  import { computed } from 'canvasengine'\n  import { createFogOfWarController } from '@canvasengine/presets'\n\n  const fog = createFogOfWarController()\n  const enemyVisible = computed(() => fog.isVisibleAt(enemyX() + 17, enemyY() + 17, 0.72))\n</script>\n```\n\n## `fogVisibility` Directive\n\nYou can also attach visibility logic directly on an element.\n\n```html\n<Sprite\n  image=\"enemy.png\"\n  x={enemyX}\n  y={enemyY}\n  fogVisibility={{\n    controller: fog,\n    mode: 'visible',\n    threshold: 0.72,\n    point: {\n      x: computed(() => enemyX() + 16),\n      y: computed(() => enemyY() + 16),\n    },\n    hideAs: 'visible'\n  }}\n/>\n```\n\nDirective options:\n\n- `controller`: `FogOfWar` controller created with `createFogOfWarController()`\n- `mode`: `'visible' | 'explored'` (`'visible'` by default)\n- `threshold`: clear zone threshold (`0..1`, default `0.65`)\n- `point`: optional sample point `{ x, y }` in world coordinates\n- `hideAs`: `'visible'` (hide/show) or `'alpha'` (fade only)\n- `hiddenAlpha`: alpha used when hidden with `hideAs: 'alpha'`\n- `sampleHz`: recomputation frequency (default `30`)\n\n## Notes\n\n- Use `computed()` for `visionSources` so updates track unit movement naturally.\n- For draw order over gameplay, set `Viewport sortableChildren={true}` and a high `zIndex` on `FogOfWar`.\n- Current version uses circle vision per source (no LOS occlusion blocking yet).\n"
  },
  {
    "path": "docs/presets/footprints.md",
    "content": "# Footprints\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`Footprints` adds fading footprints behind moving sprites.\n\n- No footprint image is required: the shape is generated procedurally.\n- Footprints are emitted from sprites tagged with `footprintCaster`.\n- You can tune rendering per surface profile (`sand`, `snow`, custom names).\n\n## Basic Usage\n\n```html\n<Canvas>\n  <Viewport worldWidth={2048} worldHeight={1280} sortableChildren={true}>\n    <Footprints\n      profiles={surfaceProfiles}\n      defaultSurface=\"sand\"\n      updateHz={45}\n      maxFootprints={320}\n    />\n\n    <Sprite\n      x={heroX}\n      y={heroY}\n      controls={heroControls}\n      sheet={heroSheet}\n      footprintCaster={heroFootprintCaster}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { signal } from 'canvasengine'\n  import { Footprints } from '@canvasengine/presets'\n\n  const heroY = signal(840)\n  const snowLine = 560\n\n  const heroFootprintCaster = {\n    minStepDistance: 16,\n    stepIntervalMs: 70,\n    leftOffset: { x: -10, y: 2 },\n    rightOffset: { x: 10, y: 2 },\n    surface: () => (heroY() <= snowLine ? 'snow' : 'sand'),\n  }\n\n  const surfaceProfiles = {\n    sand: {\n      tint: '#7f5d34',\n      lifetimeMs: 1800,\n      startAlpha: 0.34,\n      blurStart: 0.35,\n      blurEnd: 1.6,\n      erosionStart: 0.62,\n      blendMode: 'multiply',\n    },\n    snow: {\n      tint: '#889db6',\n      lifetimeMs: 2600,\n      startAlpha: 0.26,\n      blurStart: 0.62,\n      blurEnd: 2.35,\n      erosionStart: 0.43,\n      blendMode: 'multiply',\n    },\n  }\n</script>\n```\n\n## Preset Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `profiles` | `Record<string, SurfaceProfile> \\| Signal<Record> \\| () => Record` | Built-in (`default`, `sand`, `snow`) | Surface rendering profiles |\n| `defaultSurface` | `string \\| Signal<string> \\| () => string` | `'default'` | Fallback profile name |\n| `maxFootprints` | `number \\| Signal<number> \\| () => number` | `260` | Maximum active footprints before recycling oldest |\n| `updateHz` | `number \\| Signal<number> \\| () => number` | `30` | Recompute/update frequency |\n\n## `SurfaceProfile`\n\n| Field | Type | Default | Description |\n|------|------|---------|-------------|\n| `lifetimeMs` | `number` | `1800` | Lifetime before disappearance |\n| `startAlpha` | `number` | `0.32` | Initial opacity |\n| `endAlpha` | `number` | `0` | Final opacity |\n| `tint` | `string \\| number` | `0x2d2a26` | Footprint tint color |\n| `blendMode` | `string \\| number` | `'multiply'` | Blend mode used by footprint sprites |\n| `scale` | `number` | `1` | Base scale multiplier |\n| `blurStart` | `number` | `0.45` | Initial blur strength |\n| `blurEnd` | `number` | `1.9` | Final blur strength |\n| `erosionStart` | `number` | `0.54` | Normalized time (`0..1`) where erosion starts |\n| `depth` | `number` | `0.58` | Depression intensity (`0..1`) for center darkening |\n| `rimStrength` | `number` | `0.14` | Strength of the soft raised edge highlight |\n\n## `footprintCaster` Options\n\nAttach on each sprite that should leave footprints:\n\n```html\n<Sprite\n  image=\"hero.png\"\n  footprintCaster={{\n    minStepDistance: 16,\n    minSpeed: 44,\n    stepIntervalMs: 70,\n    leftOffset: { x: -10, y: 2 },\n    rightOffset: { x: 10, y: 2 },\n    surface: 'sand',\n    size: 0.94,\n    alpha: 1,\n    blur: 0.1,\n    angleOffset: 0,\n    jitter: 11,\n  }}\n/>\n```\n\n| Field | Type | Default | Description |\n|------|------|---------|-------------|\n| `enabled` | `boolean` | `true` | Enable/disable emitter on this sprite |\n| `footAnchor` | `{ x, y }` | `{ x: 0.5, y: 1 }` | Ground anchor inside sprite bounds |\n| `leftOffset` | `{ x, y }` | `{ x: -10, y: 1 }` | Offset for left foot (local walk basis) |\n| `rightOffset` | `{ x, y }` | `{ x: 10, y: 1 }` | Offset for right foot (local walk basis) |\n| `minStepDistance` | `number` | `18` | Distance needed before emitting a new footprint |\n| `minSpeed` | `number` | `36` | Minimum movement speed in px/s required to emit |\n| `stepIntervalMs` | `number` | `85` | Minimum delay between two emissions |\n| `size` | `number` | `1` | Additional footprint size multiplier |\n| `alpha` | `number` | `1` | Opacity multiplier |\n| `blur` | `number` | `0` | Extra blur added to profile blur |\n| `surface` | `string` | `defaultSurface` | Profile name for this caster |\n| `angleOffset` | `number` | `0` | Extra rotation offset in degrees |\n| `jitter` | `number` | `8` | Random rotation variation in degrees |\n\nIf the footprint appears visually reversed in your art direction, set `angleOffset: 180`.\n\n## Conditional Rules (Terrain / Zones / X-Y)\n\nYou can make all important `footprintCaster` fields reactive (functions/signals),\nso emission can change by zone, terrain, or position ranges.\n\n```html\n<script>\n  const zones = [\n    { x1: 860, y1: 760, x2: 1260, y2: 980, surface: 'mud', enabled: true, step: 13 },\n    { x1: 1460, y1: 840, x2: 1880, y2: 1100, surface: 'rock', enabled: false, step: 20 },\n    { x1: 0, y1: 0, x2: 2048, y2: 560, surface: 'snow', enabled: true, step: 14 },\n    { x1: 0, y1: 560, x2: 2048, y2: 1280, surface: 'sand', enabled: true, step: 18 },\n  ]\n\n  const inZone = (x, y, z) => x >= z.x1 && x <= z.x2 && y >= z.y1 && y <= z.y2\n  const zoneAt = (x, y) => zones.find((z) => inZone(x, y, z)) ?? zones[zones.length - 1]\n\n  const heroFootprintCaster = {\n    enabled: () => zoneAt(heroX(), heroY()).enabled,\n    surface: () => zoneAt(heroX(), heroY()).surface,\n    minStepDistance: () => zoneAt(heroX(), heroY()).step,\n  }\n</script>\n```\n\n## Tuning Tips\n\n- Start with `blendMode: 'multiply'` for both sand and snow.\n- Keep `minStepDistance` between `14` and `22` for readable spacing.\n- In snow, use longer `lifetimeMs` and larger `blurEnd`.\n- In sand, increase `erosionStart` so traces break up sooner.\n"
  },
  {
    "path": "docs/presets/fx.md",
    "content": "# Fx\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`Fx` is a small particle effect preset system built into `@canvasengine/presets`.\n\n- No external FX dependency is required.\n- Effects can use procedural shapes, images, Pixi textures, or spritesheet frames.\n- Effects can be triggered once, started on mount, or looped.\n- Built-in presets are available through `FX_PRESETS`.\n\n## Basic Usage\n\n```html\n<Canvas>\n  <Fx name=\"hitSpark\" trigger={hit} x={240} y={180} />\n  <Fx name=\"campfire\" x={420} y={300} loop />\n</Canvas>\n\n<script>\n  import { Fx } from '@canvasengine/presets'\n  import { trigger } from 'canvasengine'\n\n  const hit = trigger()\n\n  setInterval(() => {\n    hit.start()\n  }, 900)\n</script>\n```\n\n## Built-in Presets\n\n```js\nimport { FX_PRESETS } from '@canvasengine/presets'\n```\n\nAvailable preset names:\n\n- `hitSpark`\n- `slashSpark`\n- `impactBurst`\n- `smokePuff`\n- `dustStep`\n- `dashDust`\n- `magicBurst`\n- `healPulse`\n- `campfire`\n- `torchFire`\n- `pickup`\n- `levelUp`\n- `explosionSmall`\n\n## Custom Preset\n\n```html\n<Fx preset={coinSpark} trigger={pickup} x={playerX} y={playerY} />\n\n<script>\n  const coinSpark = {\n    duration: 300,\n    emitters: [\n      {\n        burst: 18,\n        angle: [0, 360],\n        speed: [80, 220],\n        particle: {\n          shape: 'star',\n          lifetime: [260, 620],\n          color: ['#ffffff', '#ffd84a'],\n          alpha: [1, 0],\n          scale: [0.2, 0.7],\n          blendMode: 'add',\n        },\n      },\n    ],\n  }\n</script>\n```\n\n## Creating Your Own FX\n\nAn FX preset has three levels:\n\n- `Fx` component: where the effect is placed and when it starts.\n- `FxPreset`: global timing and the list of emitters.\n- `FxEmitterConfig`: how particles are emitted.\n- `FxParticleConfig`: what each particle looks like and how it evolves.\n\nStart with a small burst:\n\n```js\nconst hit = {\n  duration: 220,\n  emitters: [\n    {\n      burst: 16,\n      angle: [0, 360],\n      speed: [100, 260],\n      particle: {\n        shape: 'spark',\n        lifetime: [160, 360],\n        color: ['#ffffff', '#ff9f43'],\n        alpha: [1, 0],\n        scale: [0.18, 0],\n        rotationSpeed: [-360, 360],\n        blendMode: 'add',\n        ease: 'outCubic',\n      },\n    },\n  ],\n}\n```\n\nUse it with a trigger:\n\n```html\n<Fx preset={hit} trigger={hitTrigger} x={enemyX} y={enemyY} />\n```\n\nFor a looped effect, use `rate` and `loop`:\n\n```js\nconst aura = {\n  duration: 1000,\n  emitters: [\n    {\n      loop: true,\n      rate: 18,\n      angle: [-120, -60],\n      speed: [10, 46],\n      spreadX: 18,\n      particle: {\n        shape: 'softCircle',\n        lifetime: [600, 1200],\n        color: ['#8fffe0', '#4aa8ff'],\n        alpha: [0.45, 0],\n        scale: [0.25, 1.2],\n        blendMode: 'add',\n      },\n    },\n  ],\n}\n```\n\nUse it with `loop` on the component:\n\n```html\n<Fx preset={aura} x={playerX} y={playerY} loop />\n```\n\n### Tuning Rules\n\n- Use `burst` for instantaneous effects: hit, pickup, explosion, landing.\n- Use `rate` for continuous effects: fire, aura, smoke, fireflies.\n- `angle` is in degrees. `0` goes right, `90` goes down, `-90` goes up.\n- Use the component `rotation` to orient directional presets such as slash or dash effects.\n- Keep short combat particles around `120-450ms`.\n- Keep smoke, healing, and magic particles around `500-1200ms`.\n- Prefer `blendMode: 'add'` for light, magic, fire, sparks, and stars.\n- Prefer normal blend mode for smoke, dust, leaves, and debris.\n- If many effects can overlap, lower `rate`, `burst`, or set `maxParticles`.\n\n### Design Pattern\n\nMost polished effects combine two emitters:\n\n- one fast emitter for the readable impact shape;\n- one slower emitter for glow, smoke, dust, or secondary particles.\n\nExample:\n\n```js\nconst impactWithSmoke = {\n  duration: 280,\n  emitters: [\n    {\n      burst: 20,\n      angle: [0, 360],\n      speed: [140, 320],\n      particle: {\n        shape: 'spark',\n        lifetime: [140, 340],\n        color: ['#ffffff', '#ffb347'],\n        alpha: [1, 0],\n        scale: [0.2, 0],\n        blendMode: 'add',\n      },\n    },\n    {\n      burst: 8,\n      angle: [0, 360],\n      speed: [20, 70],\n      particle: {\n        shape: 'softCircle',\n        lifetime: [360, 760],\n        color: '#777777',\n        alpha: [0.25, 0],\n        scale: [0.35, 1.4],\n      },\n    },\n  ],\n}\n```\n\n## Image Particles\n\nA single transparent image is enough for most effects.\n\nRecommended image format:\n\n- `png` or `webp`\n- transparent background\n- centered artwork\n- `32x32`, `64x64`, or `128x128`\n- white or grayscale if you want to apply `tint` / `color`\n\n```js\nconst smoke = {\n  emitters: [\n    {\n      burst: 16,\n      angle: [-120, -60],\n      speed: [12, 48],\n      particle: {\n        image: '/fx/smoke.png',\n        lifetime: [600, 1200],\n        scale: [0.4, 1.8],\n        alpha: [0.35, 0],\n      },\n    },\n  ],\n}\n```\n\n### Prompt for a Single Particle Image\n\nUse this kind of prompt when you want one reusable particle texture:\n\n```txt\nCreate a single game VFX particle sprite: [spark / smoke puff / flame ember / magic star].\nCentered object, isolated, transparent background, square image, clean alpha edges.\nWhite or grayscale material so it can be tinted in-engine.\nSoft falloff, no hard black outline, no text, no UI, no scene, no ground shadow.\nThe particle must fit entirely inside the canvas with safe padding on every side.\nExport as transparent PNG, 1024x1024.\n```\n\nGood variants:\n\n```txt\nSingle soft smoke particle, centered, transparent background, grayscale, soft circular falloff, no scene, no text, no border, transparent PNG, 1024x1024.\n```\n\n```txt\nSingle bright slash spark particle, horizontal streak, centered, transparent background, white core with soft glow, no scene, no text, safe padding, transparent PNG, 1024x1024.\n```\n\nAfter generation, resize to `64x64` or `128x128` for runtime use.\n\n## Spritesheet Frames\n\nSpritesheets are useful when you have many FX images, random variants, or animated particles.\n\n```js\nconst fire = {\n  emitters: [\n    {\n      loop: true,\n      rate: 24,\n      particle: {\n        spritesheet: '/fx/fx-spritesheet.json',\n        frames: ['fire_01.png', 'fire_02.png', 'fire_03.png', 'fire_04.png'],\n        frameMode: 'animated',\n        frameRate: 12,\n        lifetime: [360, 720],\n        alpha: [0.9, 0],\n        scale: [0.4, 1.1],\n        blendMode: 'add',\n      },\n    },\n  ],\n}\n```\n\n### Prompt for a Spritesheet\n\nCanvasEngine expects Pixi-compatible spritesheet data when using `spritesheet`.\nImage generation tools usually create only the PNG. Use a packer such as Aseprite,\nTexturePacker, or Free Texture Packer to export the Pixi JSON file.\n\nPrompt for animated frames:\n\n```txt\nCreate a 4x4 spritesheet for a looping game VFX animation: [small flame / magic sparkle / smoke dissolve].\nTransparent background. Equal-size cells. Each frame centered with consistent registration.\nNo text, no numbers, no grid lines, no scene, no camera perspective, no cropped particles.\nKeep the effect inside each cell with safe padding.\nWhite or grayscale if it should be tinted in-engine.\nOutput as one transparent PNG spritesheet.\n```\n\nPrompt for random variants:\n\n```txt\nCreate a spritesheet with 12 different small particle variants: [gold spark / dust mote / blue magic star].\nTransparent background, equal-size cells, one centered particle per cell, consistent scale, safe padding.\nNo text, no labels, no grid lines, no background, no shadows outside the particles.\nOutput as one transparent PNG spritesheet.\n```\n\nRecommended export:\n\n- use square cells: `64x64` for sparks/stars, `128x128` for smoke/fire;\n- keep frame names stable, for example `spark_01.png`, `spark_02.png`;\n- export a Pixi JSON spritesheet and reference those names in `frames`;\n- use `frameMode: 'random'` for variants;\n- use `frameMode: 'animated'` and `frameRate` for frame-by-frame particles.\n\n## Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `name` | `string \\| Signal<string>` | `'hitSpark'` | Built-in preset name |\n| `preset` | `FxPreset \\| Signal<FxPreset>` | - | Custom preset object |\n| `trigger` | `Trigger` | - | Starts a new effect when triggered |\n| `autostart` | `boolean` | `false` | Starts once when mounted |\n| `loop` | `boolean` | `false` | Keeps emitters active |\n| `enabled` | `boolean \\| Signal<boolean>` | `true` | Enables or disables spawning |\n| `x`, `y` | `number \\| Signal<number>` | `0` | Effect container position |\n| `rotation` | `number \\| Signal<number>` | `0` | Effect container rotation |\n| `scale` | `number \\| Signal<number>` | `1` | Effect container scale |\n| `alpha` | `number \\| Signal<number>` | `1` | Effect container alpha |\n| `timeScale` | `number \\| Signal<number>` | `1` | Multiplies update speed |\n| `maxParticles` | `number` | `600` | Particle cap |\n| `preload` | `boolean` | `true` | Loads image/spritesheet assets before spawning |\n| `missingTexture` | `'shape' \\| 'skip' \\| 'error'` | `'shape'` | Behavior when an image texture is unavailable |\n| `onStart` | `(instance) => void` | - | Called when an effect starts |\n| `onComplete` | `(instance) => void` | - | Called when all particles are done |\n| `onParticleSpawn` | `(particle) => void` | - | Called for each spawned particle |\n\nExtra display props such as `zIndex` are forwarded to the underlying `Container`.\n\n## `FxPreset`\n\n| Field | Type | Description |\n|------|------|-------------|\n| `delay` | `number` | Delay before the preset starts, in ms |\n| `duration` | `number` | Preset emission duration, in ms |\n| `emitters` | `FxEmitterConfig[]` | Emitters used by the preset |\n\n## `FxEmitterConfig`\n\n| Field | Type | Description |\n|------|------|-------------|\n| `delay` | `number` | Delay before this emitter starts |\n| `duration` | `number` | Emitter duration |\n| `loop` | `boolean` | Keeps this emitter active |\n| `burst` | `number` | Number of particles emitted immediately |\n| `rate` | `number` | Particles emitted per second |\n| `maxParticles` | `number` | Emitter particle cap |\n| `x`, `y` | `number` | Local emitter offset |\n| `spreadX`, `spreadY` | `number` | Random spawn spread |\n| `angle` | `number \\| [number, number]` | Direction in degrees |\n| `speed` | `number \\| [number, number]` | Initial speed in px/s |\n| `accelerationX`, `accelerationY` | `number` | Acceleration in px/s |\n| `gravity` | `number` | Vertical acceleration in px/s |\n| `particle` | `FxParticleConfig` | Particle appearance and lifetime |\n\n## `FxParticleConfig`\n\n| Field | Type | Description |\n|------|------|-------------|\n| `shape` | `'circle' \\| 'softCircle' \\| 'spark' \\| 'square' \\| 'star'` | Procedural fallback shape |\n| `image` | `string` | Single image URL |\n| `texture` | `Texture` | Existing Pixi texture |\n| `spritesheet` | `string` | Pixi spritesheet JSON URL |\n| `frame` | `string` | Single spritesheet frame |\n| `frames` | `string[]` | Multiple spritesheet frames |\n| `frameMode` | `'first' \\| 'random' \\| 'animated'` | Frame selection mode |\n| `frameRate` | `number` | Animated frame rate |\n| `lifetime` | `number \\| [number, number]` | Lifetime in ms |\n| `color`, `tint` | `string \\| number \\| [start, end]` | Particle tint |\n| `alpha` | `number \\| [number, number]` | Alpha over lifetime |\n| `scale` | `number \\| [number, number]` | Scale over lifetime |\n| `rotation` | `number \\| [number, number]` | Initial rotation in degrees |\n| `rotationSpeed` | `number \\| [number, number]` | Rotation speed in degrees/s |\n| `blendMode` | `string` | Pixi blend mode |\n| `anchor` | `{ x, y }` | Sprite anchor |\n| `ease` | `'linear' \\| 'outQuad' \\| 'outCubic' \\| 'inQuad'` | Lifetime interpolation |\n"
  },
  {
    "path": "docs/presets/loading.md",
    "content": "# Loading\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\nThe Loading component creates an animated circular loading spinner with customizable appearance and rotation speed. The spinner consists of multiple segments arranged in a circle that rotate continuously, creating a smooth loading indicator perfect for indicating asynchronous operations or loading states in your game.\n\n## Features\n\n- **Smooth Animation**: Continuous rotation using the tick system for frame-perfect animation\n- **Customizable Appearance**: Adjust size, color, number of segments, and rotation speed\n- **Alpha Variation**: Active segments are fully opaque while inactive segments have reduced opacity for a polished look\n- **Signal Support**: All parameters can be controlled dynamically using signals\n- **Lightweight**: Simple Graphics-based rendering for optimal performance\n\n## Basic Usage\n\n```html\n<Canvas>\n    <!-- Basic loading spinner with default settings -->\n    <Loading />\n</Canvas>\n\n<script>\n    import { Loading } from '@canvasengine/presets'\n</script>\n```\n\n## Advanced Usage\n\n### Static Configuration\n\n```html\n<Canvas>\n    <!-- Custom size and color -->\n    <Loading \n        size={50}\n        color=\"#e74c3c\"\n    />\n    \n    <!-- Fast spinning loader with more segments -->\n    <Loading \n        speed={360}\n        segments={12}\n        segmentWidth={4}\n    />\n    \n    <!-- Large loader with background circle -->\n    <Loading \n        size={80}\n        color=\"#2ecc71\"\n        backgroundColor=\"#ecf0f1\"\n        segmentWidth={5}\n        inactiveAlpha={0.2}\n    />\n</Canvas>\n```\n\n### Dynamic Control with Signals\n\n```html\n<Canvas>\n    <Loading \n        size={loaderSize}\n        speed={loaderSpeed}\n        color={loaderColor}\n    />\n</Canvas>\n\n<script>\n    import { Loading } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n    \n    // Create reactive signals\n    const loaderSize = signal(30)\n    const loaderSpeed = signal(180)\n    const loaderColor = signal('#3498db')\n    \n    // Control loader dynamically\n    function showLargeLoader() {\n        loaderSize.set(60)\n        loaderSpeed.set(240)\n    }\n    \n    function hideLoader() {\n        loaderSize.set(0)\n    }\n</script>\n```\n\n### Positioning the Loader\n\n```html\n<Canvas>\n    <!-- Centered loader -->\n    <Loading \n        x={400}\n        y={300}\n        size={40}\n    />\n    \n    <!-- Multiple loaders at different positions -->\n    <Loading x={100} y={100} size={25} color=\"#e74c3c\" />\n    <Loading x={700} y={100} size={25} color=\"#2ecc71\" />\n    <Loading x={400} y={500} size={25} color=\"#f39c12\" />\n</Canvas>\n```\n\n## Props\n\n| Prop | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| size | `number` \\| `Signal<number>` | No | 30 | Size of the loading spinner (radius in pixels) |\n| color | `string` \\| `Signal<string>` | No | '#3498db' | Color of the spinner segments |\n| backgroundColor | `string` \\| `Signal<string>` | No | - | Background color of the spinner (optional) |\n| speed | `number` \\| `Signal<number>` | No | 180 | Rotation speed in degrees per second |\n| segments | `number` \\| `Signal<number>` | No | 8 | Number of segments in the spinner |\n| segmentWidth | `number` \\| `Signal<number>` | No | 3 | Width of each segment in pixels |\n| inactiveAlpha | `number` \\| `Signal<number>` | No | 0.3 | Alpha value for inactive segments (0-1) |\n\nAnd use all the properties of the `Container` component (x, y, anchor, scale, etc.).\n\n## Parameter Guidelines\n\n### Size\n- **10 - 20**: Small, subtle loader\n- **25 - 40**: Standard size for most use cases\n- **50 - 80**: Large, prominent loader\n- **100+**: Extra large for splash screens or main loading states\n\n### Speed\n- **90 - 120**: Slow, gentle rotation\n- **150 - 200**: Normal speed (recommended)\n- **240 - 360**: Fast rotation\n- **360+**: Very fast, energetic rotation\n\n### Segments\n- **4 - 6**: Minimal, simple look\n- **8 - 10**: Standard (recommended)\n- **12 - 16**: More detailed, smoother appearance\n- **20+**: Very detailed, may impact performance\n\n### Segment Width\n- **1 - 2**: Thin, delicate segments\n- **3 - 4**: Standard width (recommended)\n- **5 - 8**: Thick, bold segments\n- **10+**: Very thick, may overlap\n\n### Inactive Alpha\n- **0.1 - 0.2**: Strong contrast, very visible active segments\n- **0.3 - 0.4**: Balanced contrast (recommended)\n- **0.5 - 0.7**: Subtle contrast, softer appearance\n- **0.8 - 0.9**: Minimal contrast, almost uniform\n\n## Loading Presets\n\nHere are some pre-configured loading spinner styles:\n\n```javascript\n// Minimal Loader\n<Loading size={20} segments={6} segmentWidth={2} inactiveAlpha={0.2} />\n\n// Standard Loader\n<Loading size={30} color=\"#3498db\" speed={180} segments={8} />\n\n// Fast Loader\n<Loading size={40} color=\"#e74c3c\" speed={360} segments={12} />\n\n// Large Prominent Loader\n<Loading \n    size={60} \n    color=\"#2ecc71\" \n    backgroundColor=\"#ecf0f1\" \n    segmentWidth={5} \n    inactiveAlpha={0.25}\n/>\n\n// Subtle Loader\n<Loading \n    size={25} \n    color=\"#95a5a6\" \n    speed={120} \n    inactiveAlpha={0.5} \n/>\n```\n\n## Use Cases\n\n### Loading Screen\n\n```html\n<Canvas>\n    <Container x={400} y={300} anchor={{ x: 0.5, y: 0.5 }}>\n        <Text text=\"Loading...\" y={-50} anchor={{ x: 0.5, y: 0.5 }} />\n        <Loading size={40} />\n    </Container>\n</Canvas>\n```\n\n### Button Loading State\n\n```html\n<Canvas>\n    <Container x={400} y={300}>\n        <Button>\n            {isLoading ? (\n                <Loading size={15} color=\"#fff\" />\n            ) : (\n                <Text text=\"Submit\" />\n            )}\n        </Button>\n    </Container>\n</Canvas>\n```\n\n### Multiple Loading Indicators\n\n```html\n<Canvas>\n    <!-- Show different loaders for different async operations -->\n    <Loading \n        x={200} \n        y={150} \n        size={25} \n        color={dataLoading ? '#3498db' : '#95a5a6'} \n    />\n    <Loading \n        x={600} \n        y={150} \n        size={25} \n        color={assetsLoading ? '#2ecc71' : '#95a5a6'} \n    />\n</Canvas>\n```\n\n## Performance Notes\n\n- The Loading component uses Graphics-based rendering for optimal performance\n- Animation runs smoothly at 60fps using the tick system\n- Multiple loaders can be rendered simultaneously without performance issues\n- Consider reducing segment count (4-6) for mobile devices if needed\n\n## Technical Details\n\nThe Loading component:\n\n1. **Uses Graphics element** to draw multiple radial segments\n2. **Animates rotation** using the tick system with deltaTime for frame-perfect timing\n3. **Calculates opacity** based on segment position for smooth visual transition\n4. **Supports reactive updates** through signal-based props\n5. **Forces redraw** on each frame to ensure smooth animation\n\nThe spinner draws segments as arcs arranged in a circle, with each segment's opacity varying based on its position relative to the rotation angle, creating a smooth visual effect.\n\n"
  },
  {
    "path": "docs/presets/night-ambiant.md",
    "content": "# NightAmbiant\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`NightAmbiant` adds a night overlay with dynamic light spots.\n\n- If a `Viewport` is present in context, the filter is attached to it automatically.\n- Otherwise, it attaches to the parent container.\n- All props are reactive and support signal/function values.\n\n## Basic Usage\n\n```html\n<Canvas backgroundColor=\"#1a472a\">\n    <Viewport worldWidth={2048} worldHeight={2048} screen>\n        <NightAmbiant\n            lightSpots={lightSpots}\n            darkness={0.8}\n            darkColor=\"#0a1020\"\n            fogColor=\"#141a2a\"\n        />\n    </Viewport>\n</Canvas>\n\n<script>\n    import { NightAmbiant } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n\n    const playerX = signal(400)\n    const playerY = signal(300)\n\n    const lightSpots = () => [\n        {\n            x: playerX,\n            y: playerY,\n            radius: 170,\n            intensity: 1.0,\n            flicker: true,\n            flickerSpeed: 15,\n        },\n        { x: 280, y: 260, radius: 180, intensity: 0.95, flicker: true, flickerSpeed: 13 },\n    ]\n</script>\n```\n\n## Without Viewport\n\n```html\n<Canvas>\n    <Container>\n        <NightAmbiant lightSpots={spots} />\n        <Sprite image=\"back.png\" />\n    </Container>\n</Canvas>\n```\n\n## Reactive CRUD Example\n\n```html\n<script>\n    import { signal } from 'canvasengine'\n\n    const spots = signal([\n        { x: 280, y: 260, radius: 180, intensity: 0.95, flicker: true, flickerSpeed: 13 },\n    ])\n\n    function addSpot() {\n        spots.update((list) => [\n            ...list,\n            { x: 720, y: 540, radius: 130, intensity: 0.8, pulse: true, pulseSpeed: 1.5 },\n        ])\n    }\n\n    function removeFirstSpot() {\n        spots.update((list) => list.slice(1))\n    }\n</script>\n```\n\n## Props\n\n| Prop | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| lightSpots | `Array<SpotInput>` \\| `Signal` \\| `() => Array` | No | `[]` | Main reactive list of light spots |\n| spots | Same as `lightSpots` | No | - | Alias for compatibility |\n| darkness | `number` \\| `Signal<number>` \\| `() => number` | No | `0.75` | Darkness intensity outside light spots (`0` = no darkening, `1` = full black) |\n| darkColor | `Color` \\| `Signal<Color>` \\| `() => Color` | No | `#000000` | Tint color applied in dark zones (colored night effect) |\n| fogColor | `Color` \\| `Signal<Color>` \\| `() => Color` | No | `#141424` | Fog color that fades in around light spots |\n| fogRadius | `number` \\| `Signal<number>` \\| `() => number` | No | `0.5` | Distance from light center where fog starts (`0..1`) |\n| fogSoftness | `number` \\| `Signal<number>` \\| `() => number` | No | `0.35` | Width of the fog transition (higher = softer edge) |\n\n### SpotInput fields\n\n| Field | Type | Required | Default | Description |\n|-------|------|----------|---------|-------------|\n| x | `number` \\| `Signal<number>` \\| `() => number` | Yes | - | X position in world coordinates |\n| y | `number` \\| `Signal<number>` \\| `() => number` | Yes | - | Y position in world coordinates |\n| radius | `number` | No | `180` | Light radius in pixels |\n| intensity | `number` | No | `1.0` | Light intensity (`0..2`) |\n| flicker | `boolean` | No | `false` | Enable flickering effect (like a candle) |\n| flickerSpeed | `number` | No | `12` | Speed of the flicker animation |\n| pulse | `boolean` | No | `false` | Enable pulsing effect (slow breathing) |\n| pulseSpeed | `number` | No | `2` | Speed of the pulse animation |\n| phase | `number` | No | auto | Phase offset for animations (to desync multiple lights) |\n\n### Color format\n\n`Color` supports multiple formats:\n\n- Hex string: `\"#0a1020\"`, `\"#abc\"`\n- Number: `0x0a1020`\n- RGB tuple (0-255): `[10, 16, 32]`\n- Normalized RGB (0-1): `[0.04, 0.06, 0.12]`\n"
  },
  {
    "path": "docs/presets/sprite-shadows.md",
    "content": "# SpriteShadows\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`SpriteShadows` adds RPG-style projected shadows for sprites.\n\n- Shadow direction is automatically **opposite** to the light source.\n- Each caster renders a soft silhouette with blur and alpha gradient.\n- Supports one dominant source (`strongest`) or blended two-source direction (`blend2`).\n\nTo cast a shadow, a sprite must be tagged with `shadowCaster`.\n\n## Basic Usage\n\n```html\n<Canvas>\n  <Viewport worldWidth={2048} worldHeight={2048} sortableChildren={true}>\n    <Sprite image=\"back.png\" />\n\n    <SpriteShadows\n      lights={lights}\n      mode=\"strongest\"\n      updateHz={60}\n      shadowColor=\"#05070d\"\n    />\n\n    <Sprite\n      image=\"hero.png\"\n      x={heroX}\n      y={heroY}\n      anchor={{ x: 0.5, y: 0.86 }}\n      shadowCaster={{\n        height: 96,\n        alpha: 0.6,\n        blur: 4,\n        gradientPower: 2.2,\n        hardness: 0.45,\n      }}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { computed, signal } from 'canvasengine'\n  import { SpriteShadows } from '@canvasengine/presets'\n\n  const heroX = signal(620)\n  const heroY = signal(540)\n\n  const lights = computed(() => [\n    { x: heroX(), y: heroY() - 120, z: 230, radius: 360, intensity: 1.2 },\n    { x: 760, y: 430, z: 170, radius: 300, intensity: 1.0 },\n  ])\n</script>\n```\n\n## With SpriteSheet Animations\n\n`SpriteShadows` also works with animated `Sprite sheet={...}`.\n\n```html\n<Sprite\n  x={heroX}\n  y={heroY}\n  sheet={{ definition: heroSheetDefinition, playing: 'walk' }}\n  shadowCaster={{ height: 92, blur: 4, gradientPower: 2.1 }}\n/>\n```\n\n## Preset Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `lights` | `Array<LightInput> \\| Signal<Array> \\| () => Array` | `[]` | Main reactive light list |\n| `sources` | Same as `lights` | `[]` | Alias of `lights` |\n| `mode` | `'strongest' \\| 'blend2'` | `'strongest'` | Light selection strategy per caster |\n| `updateHz` | `number \\| Signal<number> \\| () => number` | `30` | Shadow recompute frequency |\n| `shadowColor` | `string \\| number` | `0x000000` | Base tint color of silhouettes |\n\n### `LightInput`\n\n| Field | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| `x` | `number \\| Signal<number> \\| () => number` | Yes | - | Light X position |\n| `y` | `number \\| Signal<number> \\| () => number` | Yes | - | Light Y position |\n| `z` | `number \\| Signal<number> \\| () => number` | No | `220` | Light height (higher = shorter shadow) |\n| `radius` | `number \\| Signal<number> \\| () => number` | No | `360` | Influence radius |\n| `intensity` | `number \\| Signal<number> \\| () => number` | No | `1` | Influence multiplier (`0..2`) |\n| `shadowWeight` | `number \\| Signal<number> \\| () => number` | No | `1` | Priority weight for shadow selection (useful for torches) |\n| `enabled` | `boolean \\| Signal<boolean> \\| () => boolean` | No | `true` | Enable/disable source |\n\n## `shadowCaster` Options\n\nAttach on each sprite that must cast a shadow:\n\n```html\n<Sprite\n  image=\"npc.png\"\n  shadowCaster={{\n    height: 88,\n    footOffset: { x: 0, y: 4 },\n    alpha: 0.55,\n    blur: 3.6,\n    gradientPower: 2.1,\n    hardness: 0.5,\n    minLength: 10,\n    maxLength: 260,\n    contactAlpha: 0.28,\n    contactScale: 0.3,\n  }}\n/>\n```\n\n| Field | Type | Default | Description |\n|------|------|---------|-------------|\n| `enabled` | `boolean` | `true` | Enable/disable this caster |\n| `height` | `number` | `72` | Approximate sprite height used for projection |\n| `footOffset` | `{ x, y }` | `{ x: 0, y: 0 }` | Offset of ground contact point |\n| `footAnchor` | `{ x, y }` | `{ x: 0.5, y: 1 }` | Ground point inside sprite bounds |\n| `alpha` | `number` | `0.56` | Global silhouette opacity |\n| `blur` | `number` | `3.5` | Blur strength |\n| `gradientPower` | `number` | `2` | Alpha falloff along shadow length |\n| `hardness` | `number` | `0.42` | Shadow sharpness (`0..1`) |\n| `minLength` | `number` | `10` | Minimum projected length |\n| `maxLength` | `number` | `280` | Maximum projected length |\n| `contactAlpha` | `number` | `0.28` | Opacity of contact shadow at feet |\n| `contactScale` | `number` | `0.28` | Contact shadow ellipse size factor |\n| `anchorX` | `number` | caster anchor or `0.5` | Horizontal anchor override for silhouette |\n\n## RPG Tuning Tips\n\n- For torches/candles: lower `z` and medium `blur`.\n- For moon/sun style: higher `z`, larger `radius`, lower `intensity`.\n- Keep `mode=\"strongest\"` for readability and lower CPU.\n- Use `blend2` only when multiple nearby lights must affect direction.\n"
  },
  {
    "path": "docs/presets/tilemap.md",
    "content": "# TileMap\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\nThe TileMap component integrates with **Tiled Map Editor** to render tilemaps in your Canvas Engine application. It supports TMX files, tilesets, object layers, and advanced features like z-layer reorganization.\n\n## Usage\n\n```html\n<Canvas>\n    <TiledMap \n        map={map} \n        createLayersPerTilesZ={true} \n        basePath=\"/map\" \n        objectLayer={(layer) => <Rect width={32} height={32} color=\"red\" />} \n    />\n</Canvas>\n\n<script>\n    import { TiledMap } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n    \n    let map = signal(null)\n    \n    fetch('/map/simplemap.tmx')\n        .then((res) => res.text())\n        .then((text) => {\n            map.set(text)\n        })\n</script>\n```\n\n## Properties\n\n| Property | Type | Default | Description |\n|----------|------|---------|-------------|\n| `map` | `Signal<string \\| null>` | - | Signal containing the TMX file content as a string |\n| `basePath` | `string` | - | Base path for loading tileset images and other assets |\n| `createLayersPerTilesZ` | `boolean` | `false` | Reorganizes layers based on the `z` property of tiles in the tileset |\n| `objectLayer` | `(layer: TiledLayer) => JSX.Element` | - | Callback function to render custom components for object layers |\n\nAnd uses all the properties of the `Container` component.\n\n## Loading TMX Files\n\nThe `map` property expects a signal containing the TMX file content as a string. You need to fetch the TMX file and set it to the signal:\n\n```javascript\nlet map = signal(null)\n\nfetch('/map/simplemap.tmx')\n    .then((res) => res.text())\n    .then((text) => {\n        map.set(text)\n    })\n```\n\nThe component will automatically load associated tilesets based on the `basePath` property.\n\n## Base Path Configuration\n\nThe `basePath` property defines where your map assets are located. All tileset images referenced in the TMX file will be loaded relative to this path:\n\n```html\n<TiledMap map={map} basePath=\"/assets/maps\" />\n```\n\nIf your TMX file references `tileset.png`, it will be loaded from `/assets/maps/tileset.png`.\n\n## Z-Layer Reorganization\n\nWhen `createLayersPerTilesZ` is enabled, the component reorganizes tile layers based on the `z` property defined in your tileset tiles:\n\n```html\n<TiledMap map={map} createLayersPerTilesZ={true} />\n```\n\n### How Z-Layer Works\n\n- **z=0**: Ground/terrain tiles (default layer)\n- **z=1**: Objects above the ground\n- **z=2**: Objects above z=1 layer\n- And so on...\n\nTiles without a `z` property are treated as `z=0`. The component creates separate layers for each z-value, ensuring proper rendering order.\n\n### Setting Z Properties in Tiled\n\nIn Tiled Map Editor:\n1. Select your tileset\n2. Choose a tile\n3. Add a custom property named `z` with an integer value\n4. Tiles with higher z values will render above tiles with lower z values\n\n## Object Layers\n\nUse the `objectLayer` callback to render custom components for object layers defined in your TMX file:\n\n```html\n<TiledMap \n    map={map} \n    objectLayer={(layer) => {\n        // Render different components based on layer properties\n        if (layer.name === 'enemies') {\n            return <Enemy x={layer.x} y={layer.y} />\n        }\n        return <Rect width={32} height={32} color=\"red\" />\n    }} \n/>\n```\n\nThe callback receives a `TiledLayer` object containing all the layer information from your TMX file.\n\n## Supported Tiled Features\n\n- ✅ Tile layers\n- ✅ Object layers  \n- ✅ Image layers\n- ✅ Group layers\n- ✅ Tileset animations\n- ✅ Tile properties (including custom z-ordering)\n- ✅ Multiple tilesets\n- ✅ Tile flipping and rotation\n- ✅ Layer properties and visibility\n\n## Performance Tips\n\n1. **Optimize tileset images**: Use power-of-2 dimensions for better GPU performance\n2. **Limit z-layers**: Too many z-layers can impact performance\n3. **Use object layers sparingly**: Complex object layers with many custom components can be expensive\n4. **Consider map size**: Very large maps may benefit from chunking or culling techniques\n"
  },
  {
    "path": "docs/presets/weather.md",
    "content": "# Weather\n\n<!-- @include: ./_before.md -->\n\n## Overview\n\n`Weather` is a shader-based overlay preset for:\n\n- rain\n- snow\n- fog (RPG-style)\n- cloud (with optional sun rays)\n\nIt supports static values and reactive signals, can be used inside or outside `Viewport`, and forwards display props like `zIndex` to the underlying `Mesh`.\n\n## What Is Included\n\n`@canvasengine/presets` exports:\n\n- `Weather`\n- `RAIN_PRESETS`\n- `SNOW_PRESETS`\n- `FOG_PRESETS`\n- `CLOUD_PRESETS`\n- `WEATHER_PRESETS`\n\n## Basic Usage\n\n```html\n<Canvas>\n  <Weather effect=\"rain\" />\n  <Weather effect=\"snow\" />\n  <Weather effect=\"fog\" />\n  <Weather effect=\"cloud\" />\n</Canvas>\n\n<script>\n  import { Weather } from '@canvasengine/presets'\n</script>\n```\n\n## Using Built-in Presets\n\n```html\n<Canvas>\n  <Weather\n    effect={rainPreset.effect}\n    speed={rainPreset.speed}\n    windDirection={rainPreset.windDirection}\n    windStrength={rainPreset.windStrength}\n    density={rainPreset.density}\n    maxDrops={rainPreset.maxDrops}\n  />\n</Canvas>\n\n<script>\n  import { Weather, RAIN_PRESETS } from '@canvasengine/presets'\n\n  const rainPreset = RAIN_PRESETS.steadyRain\n</script>\n```\n\n### Preset Names\n\n- Rain: `lightRain`, `steadyRain`, `stormRain`\n- Snow: `lightSnow`, `winterSnow`, `blizzardSnow`\n- Fog: `rpgMorningMist`, `rpgForestFog`, `rpgSwampFog`, `rpgNightFog`, `rpgHeavyFog`\n- Cloud: `lightClouds`, `overcastClouds`, `stormClouds`, `goldenHourRays`, `sunnySoftRays`, `sunsetTwinkleRays`, `dramaticCrepuscularRays`, `morningHazeRays`\n\n## Viewport and Layering\n\n### Viewport behavior\n\nWhen `Weather` is placed inside `Viewport`:\n\n- fog/cloud follow world/camera movement\n- weather resolution tracks visible viewport bounds\n\n### Draw order (on top of sprites)\n\nUse `sortableChildren` on `Viewport` and a high `zIndex` on `Weather`.\n\n```html\n<Canvas>\n  <Viewport worldWidth={2048} worldHeight={2048} sortableChildren={true}>\n    <Sprite image=\"back.png\" zIndex={1} />\n    <Weather effect=\"fog\" zIndex={1000} />\n  </Viewport>\n</Canvas>\n```\n\n## Cloud Sun Rays\n\nCloud mode supports sun shafts with directional control and twinkle.\n\nImportant behavior:\n\n- rays do not scroll on X over time\n- animation is handled by twinkle (`rayTwinkle`, `rayTwinkleSpeed`)\n\n```html\n<Weather\n  effect=\"cloud\"\n  speed={0.12}\n  density={0.75}\n  height={0.84}\n  scale={1.55}\n  sunIntensity={1.35}\n  sunAngle={0.64}\n  raySpread={0.8}\n  rayTwinkle={1.0}\n  rayTwinkleSpeed={1.6}\n/>\n```\n\n## Dynamic Control with Signals\n\n```html\n<Canvas>\n  <Weather\n    effect={effectType}\n    speed={speed}\n    density={density}\n    sunIntensity={sunIntensity}\n    rayTwinkle={rayTwinkle}\n  />\n</Canvas>\n\n<script>\n  import { Weather } from '@canvasengine/presets'\n  import { signal } from 'canvasengine'\n\n  const effectType = signal('cloud')\n  const speed = signal(0.12)\n  const density = signal(0.75)\n  const sunIntensity = signal(1.2)\n  const rayTwinkle = signal(0.8)\n</script>\n```\n\n## Props\n\n| Prop | Type | Default | Used by | Description |\n|------|------|---------|---------|-------------|\n| `effect` | `string \\| Signal<string>` | `'rain'` | all | `'rain'`, `'snow'`, `'fog'`, `'cloud'` |\n| `speed` | `number \\| Signal<number>` | `0.5` | all | Movement/fall speed |\n| `windDirection` | `number \\| Signal<number>` | `0.0` | rain/snow | Horizontal wind direction |\n| `windStrength` | `number \\| Signal<number>` | `0.2` | rain/snow | Wind influence |\n| `density` | `number \\| Signal<number>` | `120.0` | all | Particle density or fog/cloud intensity |\n| `maxDrops` | `number \\| Signal<number>` | `80.0` | rain/snow | Particle cap (`uMaxDrops`/`uMaxFlakes`) |\n| `height` | `number \\| Signal<number>` | `1.0` | fog/cloud | Vertical concentration |\n| `scale` | `number \\| Signal<number>` | `2.0` | fog/cloud | Noise scale |\n| `sunIntensity` | `number \\| Signal<number>` | `0.85` | cloud | Sun ray intensity |\n| `sunAngle` | `number \\| Signal<number>` | `0.85` | cloud | Sun direction angle (radians) |\n| `raySpread` | `number \\| Signal<number>` | `1.0` | cloud | Ray spread width |\n| `rayTwinkle` | `number \\| Signal<number>` | `0.45` | cloud | Twinkle amount |\n| `rayTwinkleSpeed` | `number \\| Signal<number>` | `1.0` | cloud | Twinkle speed |\n| `resolution` | `[number, number] \\| Signal<[number, number]>` | auto | all | Override internal resolution |\n\n### Forwarded display props\n\n`Weather` forwards extra props to `Mesh` (for example: `zIndex`, `alpha`, `blendMode`, `visible`, `x`, `y`, etc.).\n\n## Recommended Ranges\n\n- Rain/Snow `density`: `80` to `320`\n- Fog `density`: `0.7` to `1.7`\n- Fog `height`: `0.45` to `0.9`\n- Cloud `density`: `0.5` to `1.3`\n- Cloud `sunIntensity`: `0.1` to `1.5`\n- Cloud `raySpread`: `0.68` to `1.35`\n- Cloud `rayTwinkle`: `0.0` to `1.0` (or more for stylized effects)\n\n## Troubleshooting\n\n### I don't see the weather\n\n- increase `density`\n- ensure `effect` matches props (e.g. cloud rays need `effect=\"cloud\"`)\n- if inside `Viewport`, set `sortableChildren={true}` and `Weather zIndex` high enough\n\n### Fog/cloud should move with camera\n\n- place `Weather` inside `Viewport`\n- do not override `resolution` with unrelated values unless needed\n\n### Rays should not drift sideways\n\n- current cloud implementation keeps ray pattern stable in X and animates via twinkle controls\n"
  },
  {
    "path": "docs/public/[A]Dirt_pipo.tsx",
    "content": "<?xml version=\"1.0\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]Dirt_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"336\" columns=\"8\">\n  <image source=\"[A]Dirt_pipo.png\" width=\"256\" height=\"1344\"/>\n  <wangsets>\n    <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n      <wangcolor color=\"#22E282\" tile=\"0\" probability=\"1\"/>\n      <wangcolor color=\"#A904AE\" tile=\"48\" probability=\"1\"/>\n      <wangcolor color=\"#9A8B82\" tile=\"96\" probability=\"1\"/>\n      <wangcolor color=\"#FC9C29\" tile=\"144\" probability=\"1\"/>\n      <wangcolor color=\"#565085\" tile=\"192\" probability=\"1\"/>\n      <wangcolor color=\"#69B230\" tile=\"240\" probability=\"1\"/>\n      <wangcolor color=\"#2021FC\" tile=\"288\" probability=\"1\"/>\n      <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"8\" wangid=\"0,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"9\" wangid=\"0,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"10\" wangid=\"1,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"11\" wangid=\"0,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"12\" wangid=\"1,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"13\" wangid=\"1,1,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"14\" wangid=\"1,1,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"15\" wangid=\"1,0,0,0,1,1,1,1\"/>\n      <wangtile tileid=\"16\" wangid=\"1,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"17\" wangid=\"1,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"18\" wangid=\"1,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"19\" wangid=\"1,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"20\" wangid=\"1,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"21\" wangid=\"1,1,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"22\" wangid=\"1,1,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"23\" wangid=\"1,0,0,0,0,0,1,1\"/>\n      <wangtile tileid=\"24\" wangid=\"1,1,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"25\" wangid=\"1,0,0,0,1,0,1,1\"/>\n      <wangtile tileid=\"26\" wangid=\"0,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"27\" wangid=\"0,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"28\" wangid=\"1,1,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"29\" wangid=\"1,1,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"30\" wangid=\"1,0,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"31\" wangid=\"1,1,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"32\" wangid=\"1,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"33\" wangid=\"1,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"34\" wangid=\"1,0,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"35\" wangid=\"1,1,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"36\" wangid=\"1,0,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"37\" wangid=\"1,1,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"38\" wangid=\"1,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"39\" wangid=\"1,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"40\" wangid=\"1,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"41\" wangid=\"1,1,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"42\" wangid=\"1,0,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"43\" wangid=\"1,1,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"44\" wangid=\"1,0,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"45\" wangid=\"1,1,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"46\" wangid=\"1,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"49\" wangid=\"0,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"50\" wangid=\"0,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"51\" wangid=\"0,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"52\" wangid=\"0,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"53\" wangid=\"0,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"54\" wangid=\"0,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"55\" wangid=\"0,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"56\" wangid=\"0,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"57\" wangid=\"0,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"58\" wangid=\"2,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"59\" wangid=\"0,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"60\" wangid=\"2,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"61\" wangid=\"2,2,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"62\" wangid=\"2,2,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"63\" wangid=\"2,0,0,0,2,2,2,2\"/>\n      <wangtile tileid=\"64\" wangid=\"2,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"65\" wangid=\"2,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"66\" wangid=\"2,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"67\" wangid=\"2,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"68\" wangid=\"2,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"69\" wangid=\"2,2,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"70\" wangid=\"2,2,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"71\" wangid=\"2,0,0,0,0,0,2,2\"/>\n      <wangtile tileid=\"72\" wangid=\"2,2,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"73\" wangid=\"2,0,0,0,2,0,2,2\"/>\n      <wangtile tileid=\"74\" wangid=\"0,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"75\" wangid=\"0,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"76\" wangid=\"2,2,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"77\" wangid=\"2,2,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"78\" wangid=\"2,0,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"79\" wangid=\"2,2,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"80\" wangid=\"2,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"81\" wangid=\"2,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"82\" wangid=\"2,0,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"83\" wangid=\"2,2,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"84\" wangid=\"2,0,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"85\" wangid=\"2,2,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"86\" wangid=\"2,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"87\" wangid=\"2,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"88\" wangid=\"2,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"89\" wangid=\"2,2,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"90\" wangid=\"2,0,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"91\" wangid=\"2,2,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"92\" wangid=\"2,0,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"93\" wangid=\"2,2,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"94\" wangid=\"2,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"97\" wangid=\"0,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"98\" wangid=\"0,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"99\" wangid=\"0,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"100\" wangid=\"0,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"101\" wangid=\"0,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"102\" wangid=\"0,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"103\" wangid=\"0,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"104\" wangid=\"0,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"105\" wangid=\"0,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"106\" wangid=\"3,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"107\" wangid=\"0,0,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"108\" wangid=\"3,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"109\" wangid=\"3,3,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"110\" wangid=\"3,3,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"111\" wangid=\"3,0,0,0,3,3,3,3\"/>\n      <wangtile tileid=\"112\" wangid=\"3,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"113\" wangid=\"3,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"114\" wangid=\"3,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"115\" wangid=\"3,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"116\" wangid=\"3,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"117\" wangid=\"3,3,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"118\" wangid=\"3,3,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"119\" wangid=\"3,0,0,0,0,0,3,3\"/>\n      <wangtile tileid=\"120\" wangid=\"3,3,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"121\" wangid=\"3,0,0,0,3,0,3,3\"/>\n      <wangtile tileid=\"122\" wangid=\"0,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"123\" wangid=\"0,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"124\" wangid=\"3,3,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"125\" wangid=\"3,3,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"126\" wangid=\"3,0,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"127\" wangid=\"3,3,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"128\" wangid=\"3,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"129\" wangid=\"3,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"130\" wangid=\"3,0,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"131\" wangid=\"3,3,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"132\" wangid=\"3,0,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"133\" wangid=\"3,3,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"134\" wangid=\"3,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"135\" wangid=\"3,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"136\" wangid=\"3,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"137\" wangid=\"3,3,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"138\" wangid=\"3,0,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"139\" wangid=\"3,3,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"140\" wangid=\"3,0,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"141\" wangid=\"3,3,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"142\" wangid=\"3,0,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"145\" wangid=\"0,0,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"146\" wangid=\"0,0,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"147\" wangid=\"0,0,0,0,0,0,4,0\"/>\n      <wangtile tileid=\"148\" wangid=\"0,0,0,0,4,0,0,0\"/>\n      <wangtile tileid=\"149\" wangid=\"0,0,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"150\" wangid=\"0,0,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"151\" wangid=\"0,0,0,0,4,4,4,0\"/>\n      <wangtile tileid=\"152\" wangid=\"0,0,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"153\" wangid=\"0,0,0,0,4,0,4,0\"/>\n      <wangtile tileid=\"154\" wangid=\"4,0,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"155\" wangid=\"0,0,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"156\" wangid=\"4,0,0,0,4,0,0,0\"/>\n      <wangtile tileid=\"157\" wangid=\"4,4,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"158\" wangid=\"4,4,4,4,4,4,4,4\"/>\n      <wangtile tileid=\"159\" wangid=\"4,0,0,0,4,4,4,4\"/>\n      <wangtile tileid=\"160\" wangid=\"4,0,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"161\" wangid=\"4,0,0,0,0,0,4,0\"/>\n      <wangtile tileid=\"162\" wangid=\"4,0,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"163\" wangid=\"4,0,0,0,4,0,4,0\"/>\n      <wangtile tileid=\"164\" wangid=\"4,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"165\" wangid=\"4,4,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"166\" wangid=\"4,4,4,0,0,0,4,4\"/>\n      <wangtile tileid=\"167\" wangid=\"4,0,0,0,0,0,4,4\"/>\n      <wangtile tileid=\"168\" wangid=\"4,4,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"169\" wangid=\"4,0,0,0,4,0,4,4\"/>\n      <wangtile tileid=\"170\" wangid=\"0,0,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"171\" wangid=\"0,0,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"172\" wangid=\"4,4,4,0,4,4,4,4\"/>\n      <wangtile tileid=\"173\" wangid=\"4,4,4,4,4,0,4,4\"/>\n      <wangtile tileid=\"174\" wangid=\"4,0,4,0,4,0,4,4\"/>\n      <wangtile tileid=\"175\" wangid=\"4,4,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"176\" wangid=\"4,0,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"177\" wangid=\"4,0,0,0,4,4,4,0\"/>\n      <wangtile tileid=\"178\" wangid=\"4,0,4,0,0,0,4,4\"/>\n      <wangtile tileid=\"179\" wangid=\"4,4,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"180\" wangid=\"4,0,4,4,4,4,4,4\"/>\n      <wangtile tileid=\"181\" wangid=\"4,4,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"182\" wangid=\"4,0,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"183\" wangid=\"4,0,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"184\" wangid=\"4,0,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"185\" wangid=\"4,4,4,0,4,0,4,4\"/>\n      <wangtile tileid=\"186\" wangid=\"4,0,4,0,4,4,4,4\"/>\n      <wangtile tileid=\"187\" wangid=\"4,4,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"188\" wangid=\"4,0,4,4,4,0,4,4\"/>\n      <wangtile tileid=\"189\" wangid=\"4,4,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"190\" wangid=\"4,0,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"193\" wangid=\"0,0,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"194\" wangid=\"0,0,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"195\" wangid=\"0,0,0,0,0,0,5,0\"/>\n      <wangtile tileid=\"196\" wangid=\"0,0,0,0,5,0,0,0\"/>\n      <wangtile tileid=\"197\" wangid=\"0,0,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"198\" wangid=\"0,0,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"199\" wangid=\"0,0,0,0,5,5,5,0\"/>\n      <wangtile tileid=\"200\" wangid=\"0,0,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"201\" wangid=\"0,0,0,0,5,0,5,0\"/>\n      <wangtile tileid=\"202\" wangid=\"5,0,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"203\" wangid=\"0,0,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"204\" wangid=\"5,0,0,0,5,0,0,0\"/>\n      <wangtile tileid=\"205\" wangid=\"5,5,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"206\" wangid=\"5,5,5,5,5,5,5,5\"/>\n      <wangtile tileid=\"207\" wangid=\"5,0,0,0,5,5,5,5\"/>\n      <wangtile tileid=\"208\" wangid=\"5,0,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"209\" wangid=\"5,0,0,0,0,0,5,0\"/>\n      <wangtile tileid=\"210\" wangid=\"5,0,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"211\" wangid=\"5,0,0,0,5,0,5,0\"/>\n      <wangtile tileid=\"212\" wangid=\"5,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"213\" wangid=\"5,5,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"214\" wangid=\"5,5,5,0,0,0,5,5\"/>\n      <wangtile tileid=\"215\" wangid=\"5,0,0,0,0,0,5,5\"/>\n      <wangtile tileid=\"216\" wangid=\"5,5,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"217\" wangid=\"5,0,0,0,5,0,5,5\"/>\n      <wangtile tileid=\"218\" wangid=\"0,0,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"219\" wangid=\"0,0,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"220\" wangid=\"5,5,5,0,5,5,5,5\"/>\n      <wangtile tileid=\"221\" wangid=\"5,5,5,5,5,0,5,5\"/>\n      <wangtile tileid=\"222\" wangid=\"5,0,5,0,5,0,5,5\"/>\n      <wangtile tileid=\"223\" wangid=\"5,5,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"224\" wangid=\"5,0,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"225\" wangid=\"5,0,0,0,5,5,5,0\"/>\n      <wangtile tileid=\"226\" wangid=\"5,0,5,0,0,0,5,5\"/>\n      <wangtile tileid=\"227\" wangid=\"5,5,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"228\" wangid=\"5,0,5,5,5,5,5,5\"/>\n      <wangtile tileid=\"229\" wangid=\"5,5,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"230\" wangid=\"5,0,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"231\" wangid=\"5,0,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"232\" wangid=\"5,0,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"233\" wangid=\"5,5,5,0,5,0,5,5\"/>\n      <wangtile tileid=\"234\" wangid=\"5,0,5,0,5,5,5,5\"/>\n      <wangtile tileid=\"235\" wangid=\"5,5,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"236\" wangid=\"5,0,5,5,5,0,5,5\"/>\n      <wangtile tileid=\"237\" wangid=\"5,5,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"238\" wangid=\"5,0,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"241\" wangid=\"0,0,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"242\" wangid=\"0,0,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"243\" wangid=\"0,0,0,0,0,0,6,0\"/>\n      <wangtile tileid=\"244\" wangid=\"0,0,0,0,6,0,0,0\"/>\n      <wangtile tileid=\"245\" wangid=\"0,0,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"246\" wangid=\"0,0,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"247\" wangid=\"0,0,0,0,6,6,6,0\"/>\n      <wangtile tileid=\"248\" wangid=\"0,0,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"249\" wangid=\"0,0,0,0,6,0,6,0\"/>\n      <wangtile tileid=\"250\" wangid=\"6,0,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"251\" wangid=\"0,0,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"252\" wangid=\"6,0,0,0,6,0,0,0\"/>\n      <wangtile tileid=\"253\" wangid=\"6,6,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"254\" wangid=\"6,6,6,6,6,6,6,6\"/>\n      <wangtile tileid=\"255\" wangid=\"6,0,0,0,6,6,6,6\"/>\n      <wangtile tileid=\"256\" wangid=\"6,0,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"257\" wangid=\"6,0,0,0,0,0,6,0\"/>\n      <wangtile tileid=\"258\" wangid=\"6,0,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"259\" wangid=\"6,0,0,0,6,0,6,0\"/>\n      <wangtile tileid=\"260\" wangid=\"6,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"261\" wangid=\"6,6,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"262\" wangid=\"6,6,6,0,0,0,6,6\"/>\n      <wangtile tileid=\"263\" wangid=\"6,0,0,0,0,0,6,6\"/>\n      <wangtile tileid=\"264\" wangid=\"6,6,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"265\" wangid=\"6,0,0,0,6,0,6,6\"/>\n      <wangtile tileid=\"266\" wangid=\"0,0,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"267\" wangid=\"0,0,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"268\" wangid=\"6,6,6,0,6,6,6,6\"/>\n      <wangtile tileid=\"269\" wangid=\"6,6,6,6,6,0,6,6\"/>\n      <wangtile tileid=\"270\" wangid=\"6,0,6,0,6,0,6,6\"/>\n      <wangtile tileid=\"271\" wangid=\"6,6,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"272\" wangid=\"6,0,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"273\" wangid=\"6,0,0,0,6,6,6,0\"/>\n      <wangtile tileid=\"274\" wangid=\"6,0,6,0,0,0,6,6\"/>\n      <wangtile tileid=\"275\" wangid=\"6,6,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"276\" wangid=\"6,0,6,6,6,6,6,6\"/>\n      <wangtile tileid=\"277\" wangid=\"6,6,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"278\" wangid=\"6,0,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"279\" wangid=\"6,0,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"280\" wangid=\"6,0,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"281\" wangid=\"6,6,6,0,6,0,6,6\"/>\n      <wangtile tileid=\"282\" wangid=\"6,0,6,0,6,6,6,6\"/>\n      <wangtile tileid=\"283\" wangid=\"6,6,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"284\" wangid=\"6,0,6,6,6,0,6,6\"/>\n      <wangtile tileid=\"285\" wangid=\"6,6,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"286\" wangid=\"6,0,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"289\" wangid=\"0,0,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"290\" wangid=\"0,0,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"291\" wangid=\"0,0,0,0,0,0,7,0\"/>\n      <wangtile tileid=\"292\" wangid=\"0,0,0,0,7,0,0,0\"/>\n      <wangtile tileid=\"293\" wangid=\"0,0,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"294\" wangid=\"0,0,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"295\" wangid=\"0,0,0,0,7,7,7,0\"/>\n      <wangtile tileid=\"296\" wangid=\"0,0,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"297\" wangid=\"0,0,0,0,7,0,7,0\"/>\n      <wangtile tileid=\"298\" wangid=\"7,0,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"299\" wangid=\"0,0,7,0,7,0,7,0\"/>\n      <wangtile tileid=\"300\" wangid=\"7,0,0,0,7,0,0,0\"/>\n      <wangtile tileid=\"301\" wangid=\"7,7,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"302\" wangid=\"7,7,7,7,7,7,7,7\"/>\n      <wangtile tileid=\"303\" wangid=\"7,0,0,0,7,7,7,7\"/>\n      <wangtile tileid=\"304\" wangid=\"7,0,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"305\" wangid=\"7,0,0,0,0,0,7,0\"/>\n      <wangtile tileid=\"306\" wangid=\"7,0,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"307\" wangid=\"7,0,0,0,7,0,7,0\"/>\n      <wangtile tileid=\"308\" wangid=\"7,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"309\" wangid=\"7,7,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"310\" wangid=\"7,7,7,0,0,0,7,7\"/>\n      <wangtile tileid=\"311\" wangid=\"7,0,0,0,0,0,7,7\"/>\n      <wangtile tileid=\"312\" wangid=\"7,7,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"313\" wangid=\"7,0,0,0,7,0,7,7\"/>\n      <wangtile tileid=\"314\" wangid=\"0,0,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"315\" wangid=\"0,0,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"316\" wangid=\"7,7,7,0,7,7,7,7\"/>\n      <wangtile tileid=\"317\" wangid=\"7,7,7,7,7,0,7,7\"/>\n      <wangtile tileid=\"318\" wangid=\"7,0,7,0,7,0,7,7\"/>\n      <wangtile tileid=\"319\" wangid=\"7,7,7,0,7,0,7,0\"/>\n      <wangtile tileid=\"320\" wangid=\"7,0,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"321\" wangid=\"7,0,0,0,7,7,7,0\"/>\n      <wangtile tileid=\"322\" wangid=\"7,0,7,0,0,0,7,7\"/>\n      <wangtile tileid=\"323\" wangid=\"7,7,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"324\" wangid=\"7,0,7,7,7,7,7,7\"/>\n      <wangtile tileid=\"325\" wangid=\"7,7,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"326\" wangid=\"7,0,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"327\" wangid=\"7,0,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"328\" wangid=\"7,0,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"329\" wangid=\"7,7,7,0,7,0,7,7\"/>\n      <wangtile tileid=\"330\" wangid=\"7,0,7,0,7,7,7,7\"/>\n      <wangtile tileid=\"331\" wangid=\"7,7,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"332\" wangid=\"7,0,7,7,7,0,7,7\"/>\n      <wangtile tileid=\"333\" wangid=\"7,7,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"334\" wangid=\"7,0,7,0,7,0,7,0\"/>\n    </wangset>\n  </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[A]Flower_pipo.tsx",
    "content": "<?xml version=\"1.0\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]Flower_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"96\" columns=\"8\">\n  <image source=\"[A]Flower_pipo.png\" width=\"256\" height=\"384\"/>\n  <wangsets>\n    <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n      <wangcolor color=\"#6517E2\" tile=\"0\" probability=\"1\"/>\n      <wangcolor color=\"#8DA00E\" tile=\"48\" probability=\"1\"/>\n      <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"8\" wangid=\"0,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"9\" wangid=\"0,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"10\" wangid=\"1,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"11\" wangid=\"0,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"12\" wangid=\"1,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"13\" wangid=\"1,1,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"14\" wangid=\"1,1,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"15\" wangid=\"1,0,0,0,1,1,1,1\"/>\n      <wangtile tileid=\"16\" wangid=\"1,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"17\" wangid=\"1,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"18\" wangid=\"1,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"19\" wangid=\"1,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"20\" wangid=\"1,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"21\" wangid=\"1,1,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"22\" wangid=\"1,1,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"23\" wangid=\"1,0,0,0,0,0,1,1\"/>\n      <wangtile tileid=\"24\" wangid=\"1,1,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"25\" wangid=\"1,0,0,0,1,0,1,1\"/>\n      <wangtile tileid=\"26\" wangid=\"0,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"27\" wangid=\"0,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"28\" wangid=\"1,1,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"29\" wangid=\"1,1,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"30\" wangid=\"1,0,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"31\" wangid=\"1,1,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"32\" wangid=\"1,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"33\" wangid=\"1,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"34\" wangid=\"1,0,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"35\" wangid=\"1,1,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"36\" wangid=\"1,0,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"37\" wangid=\"1,1,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"38\" wangid=\"1,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"39\" wangid=\"1,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"40\" wangid=\"1,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"41\" wangid=\"1,1,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"42\" wangid=\"1,0,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"43\" wangid=\"1,1,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"44\" wangid=\"1,0,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"45\" wangid=\"1,1,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"46\" wangid=\"1,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"49\" wangid=\"0,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"50\" wangid=\"0,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"51\" wangid=\"0,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"52\" wangid=\"0,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"53\" wangid=\"0,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"54\" wangid=\"0,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"55\" wangid=\"0,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"56\" wangid=\"0,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"57\" wangid=\"0,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"58\" wangid=\"2,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"59\" wangid=\"0,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"60\" wangid=\"2,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"61\" wangid=\"2,2,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"62\" wangid=\"2,2,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"63\" wangid=\"2,0,0,0,2,2,2,2\"/>\n      <wangtile tileid=\"64\" wangid=\"2,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"65\" wangid=\"2,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"66\" wangid=\"2,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"67\" wangid=\"2,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"68\" wangid=\"2,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"69\" wangid=\"2,2,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"70\" wangid=\"2,2,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"71\" wangid=\"2,0,0,0,0,0,2,2\"/>\n      <wangtile tileid=\"72\" wangid=\"2,2,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"73\" wangid=\"2,0,0,0,2,0,2,2\"/>\n      <wangtile tileid=\"74\" wangid=\"0,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"75\" wangid=\"0,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"76\" wangid=\"2,2,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"77\" wangid=\"2,2,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"78\" wangid=\"2,0,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"79\" wangid=\"2,2,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"80\" wangid=\"2,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"81\" wangid=\"2,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"82\" wangid=\"2,0,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"83\" wangid=\"2,2,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"84\" wangid=\"2,0,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"85\" wangid=\"2,2,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"86\" wangid=\"2,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"87\" wangid=\"2,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"88\" wangid=\"2,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"89\" wangid=\"2,2,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"90\" wangid=\"2,0,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"91\" wangid=\"2,2,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"92\" wangid=\"2,0,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"93\" wangid=\"2,2,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"94\" wangid=\"2,0,2,0,2,0,2,0\"/>\n    </wangset>\n  </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[A]Grass_pipo.tsx",
    "content": "<?xml version=\"1.0\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]Grass_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"528\" columns=\"8\">\n  <image source=\"[A]Grass_pipo.png\" width=\"256\" height=\"2112\"/>\n  <wangsets>\n    <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n      <wangcolor color=\"#C22B6A\" tile=\"0\" probability=\"1\"/>\n      <wangcolor color=\"#10B3FF\" tile=\"48\" probability=\"1\"/>\n      <wangcolor color=\"#7E13A3\" tile=\"96\" probability=\"1\"/>\n      <wangcolor color=\"#8E0FDA\" tile=\"144\" probability=\"1\"/>\n      <wangcolor color=\"#55B8F0\" tile=\"192\" probability=\"1\"/>\n      <wangcolor color=\"#49B339\" tile=\"240\" probability=\"1\"/>\n      <wangcolor color=\"#6A9E62\" tile=\"288\" probability=\"1\"/>\n      <wangcolor color=\"#20DA18\" tile=\"336\" probability=\"1\"/>\n      <wangcolor color=\"#C92C8A\" tile=\"384\" probability=\"1\"/>\n      <wangcolor color=\"#559A7A\" tile=\"432\" probability=\"1\"/>\n      <wangcolor color=\"#5B877D\" tile=\"480\" probability=\"1\"/>\n      <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"8\" wangid=\"0,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"9\" wangid=\"0,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"10\" wangid=\"1,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"11\" wangid=\"0,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"12\" wangid=\"1,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"13\" wangid=\"1,1,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"14\" wangid=\"1,1,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"15\" wangid=\"1,0,0,0,1,1,1,1\"/>\n      <wangtile tileid=\"16\" wangid=\"1,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"17\" wangid=\"1,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"18\" wangid=\"1,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"19\" wangid=\"1,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"20\" wangid=\"1,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"21\" wangid=\"1,1,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"22\" wangid=\"1,1,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"23\" wangid=\"1,0,0,0,0,0,1,1\"/>\n      <wangtile tileid=\"24\" wangid=\"1,1,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"25\" wangid=\"1,0,0,0,1,0,1,1\"/>\n      <wangtile tileid=\"26\" wangid=\"0,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"27\" wangid=\"0,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"28\" wangid=\"1,1,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"29\" wangid=\"1,1,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"30\" wangid=\"1,0,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"31\" wangid=\"1,1,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"32\" wangid=\"1,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"33\" wangid=\"1,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"34\" wangid=\"1,0,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"35\" wangid=\"1,1,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"36\" wangid=\"1,0,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"37\" wangid=\"1,1,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"38\" wangid=\"1,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"39\" wangid=\"1,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"40\" wangid=\"1,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"41\" wangid=\"1,1,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"42\" wangid=\"1,0,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"43\" wangid=\"1,1,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"44\" wangid=\"1,0,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"45\" wangid=\"1,1,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"46\" wangid=\"1,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"49\" wangid=\"0,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"50\" wangid=\"0,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"51\" wangid=\"0,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"52\" wangid=\"0,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"53\" wangid=\"0,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"54\" wangid=\"0,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"55\" wangid=\"0,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"56\" wangid=\"0,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"57\" wangid=\"0,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"58\" wangid=\"2,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"59\" wangid=\"0,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"60\" wangid=\"2,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"61\" wangid=\"2,2,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"62\" wangid=\"2,2,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"63\" wangid=\"2,0,0,0,2,2,2,2\"/>\n      <wangtile tileid=\"64\" wangid=\"2,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"65\" wangid=\"2,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"66\" wangid=\"2,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"67\" wangid=\"2,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"68\" wangid=\"2,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"69\" wangid=\"2,2,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"70\" wangid=\"2,2,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"71\" wangid=\"2,0,0,0,0,0,2,2\"/>\n      <wangtile tileid=\"72\" wangid=\"2,2,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"73\" wangid=\"2,0,0,0,2,0,2,2\"/>\n      <wangtile tileid=\"74\" wangid=\"0,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"75\" wangid=\"0,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"76\" wangid=\"2,2,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"77\" wangid=\"2,2,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"78\" wangid=\"2,0,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"79\" wangid=\"2,2,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"80\" wangid=\"2,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"81\" wangid=\"2,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"82\" wangid=\"2,0,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"83\" wangid=\"2,2,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"84\" wangid=\"2,0,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"85\" wangid=\"2,2,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"86\" wangid=\"2,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"87\" wangid=\"2,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"88\" wangid=\"2,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"89\" wangid=\"2,2,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"90\" wangid=\"2,0,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"91\" wangid=\"2,2,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"92\" wangid=\"2,0,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"93\" wangid=\"2,2,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"94\" wangid=\"2,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"97\" wangid=\"0,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"98\" wangid=\"0,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"99\" wangid=\"0,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"100\" wangid=\"0,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"101\" wangid=\"0,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"102\" wangid=\"0,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"103\" wangid=\"0,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"104\" wangid=\"0,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"105\" wangid=\"0,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"106\" wangid=\"3,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"107\" wangid=\"0,0,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"108\" wangid=\"3,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"109\" wangid=\"3,3,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"110\" wangid=\"3,3,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"111\" wangid=\"3,0,0,0,3,3,3,3\"/>\n      <wangtile tileid=\"112\" wangid=\"3,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"113\" wangid=\"3,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"114\" wangid=\"3,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"115\" wangid=\"3,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"116\" wangid=\"3,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"117\" wangid=\"3,3,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"118\" wangid=\"3,3,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"119\" wangid=\"3,0,0,0,0,0,3,3\"/>\n      <wangtile tileid=\"120\" wangid=\"3,3,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"121\" wangid=\"3,0,0,0,3,0,3,3\"/>\n      <wangtile tileid=\"122\" wangid=\"0,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"123\" wangid=\"0,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"124\" wangid=\"3,3,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"125\" wangid=\"3,3,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"126\" wangid=\"3,0,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"127\" wangid=\"3,3,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"128\" wangid=\"3,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"129\" wangid=\"3,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"130\" wangid=\"3,0,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"131\" wangid=\"3,3,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"132\" wangid=\"3,0,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"133\" wangid=\"3,3,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"134\" wangid=\"3,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"135\" wangid=\"3,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"136\" wangid=\"3,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"137\" wangid=\"3,3,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"138\" wangid=\"3,0,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"139\" wangid=\"3,3,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"140\" wangid=\"3,0,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"141\" wangid=\"3,3,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"142\" wangid=\"3,0,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"145\" wangid=\"0,0,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"146\" wangid=\"0,0,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"147\" wangid=\"0,0,0,0,0,0,4,0\"/>\n      <wangtile tileid=\"148\" wangid=\"0,0,0,0,4,0,0,0\"/>\n      <wangtile tileid=\"149\" wangid=\"0,0,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"150\" wangid=\"0,0,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"151\" wangid=\"0,0,0,0,4,4,4,0\"/>\n      <wangtile tileid=\"152\" wangid=\"0,0,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"153\" wangid=\"0,0,0,0,4,0,4,0\"/>\n      <wangtile tileid=\"154\" wangid=\"4,0,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"155\" wangid=\"0,0,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"156\" wangid=\"4,0,0,0,4,0,0,0\"/>\n      <wangtile tileid=\"157\" wangid=\"4,4,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"158\" wangid=\"4,4,4,4,4,4,4,4\"/>\n      <wangtile tileid=\"159\" wangid=\"4,0,0,0,4,4,4,4\"/>\n      <wangtile tileid=\"160\" wangid=\"4,0,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"161\" wangid=\"4,0,0,0,0,0,4,0\"/>\n      <wangtile tileid=\"162\" wangid=\"4,0,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"163\" wangid=\"4,0,0,0,4,0,4,0\"/>\n      <wangtile tileid=\"164\" wangid=\"4,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"165\" wangid=\"4,4,4,0,0,0,0,0\"/>\n      <wangtile tileid=\"166\" wangid=\"4,4,4,0,0,0,4,4\"/>\n      <wangtile tileid=\"167\" wangid=\"4,0,0,0,0,0,4,4\"/>\n      <wangtile tileid=\"168\" wangid=\"4,4,4,0,4,0,0,0\"/>\n      <wangtile tileid=\"169\" wangid=\"4,0,0,0,4,0,4,4\"/>\n      <wangtile tileid=\"170\" wangid=\"0,0,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"171\" wangid=\"0,0,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"172\" wangid=\"4,4,4,0,4,4,4,4\"/>\n      <wangtile tileid=\"173\" wangid=\"4,4,4,4,4,0,4,4\"/>\n      <wangtile tileid=\"174\" wangid=\"4,0,4,0,4,0,4,4\"/>\n      <wangtile tileid=\"175\" wangid=\"4,4,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"176\" wangid=\"4,0,4,4,4,0,0,0\"/>\n      <wangtile tileid=\"177\" wangid=\"4,0,0,0,4,4,4,0\"/>\n      <wangtile tileid=\"178\" wangid=\"4,0,4,0,0,0,4,4\"/>\n      <wangtile tileid=\"179\" wangid=\"4,4,4,0,0,0,4,0\"/>\n      <wangtile tileid=\"180\" wangid=\"4,0,4,4,4,4,4,4\"/>\n      <wangtile tileid=\"181\" wangid=\"4,4,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"182\" wangid=\"4,0,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"183\" wangid=\"4,0,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"184\" wangid=\"4,0,4,4,4,4,4,0\"/>\n      <wangtile tileid=\"185\" wangid=\"4,4,4,0,4,0,4,4\"/>\n      <wangtile tileid=\"186\" wangid=\"4,0,4,0,4,4,4,4\"/>\n      <wangtile tileid=\"187\" wangid=\"4,4,4,4,4,0,4,0\"/>\n      <wangtile tileid=\"188\" wangid=\"4,0,4,4,4,0,4,4\"/>\n      <wangtile tileid=\"189\" wangid=\"4,4,4,0,4,4,4,0\"/>\n      <wangtile tileid=\"190\" wangid=\"4,0,4,0,4,0,4,0\"/>\n      <wangtile tileid=\"193\" wangid=\"0,0,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"194\" wangid=\"0,0,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"195\" wangid=\"0,0,0,0,0,0,5,0\"/>\n      <wangtile tileid=\"196\" wangid=\"0,0,0,0,5,0,0,0\"/>\n      <wangtile tileid=\"197\" wangid=\"0,0,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"198\" wangid=\"0,0,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"199\" wangid=\"0,0,0,0,5,5,5,0\"/>\n      <wangtile tileid=\"200\" wangid=\"0,0,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"201\" wangid=\"0,0,0,0,5,0,5,0\"/>\n      <wangtile tileid=\"202\" wangid=\"5,0,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"203\" wangid=\"0,0,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"204\" wangid=\"5,0,0,0,5,0,0,0\"/>\n      <wangtile tileid=\"205\" wangid=\"5,5,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"206\" wangid=\"5,5,5,5,5,5,5,5\"/>\n      <wangtile tileid=\"207\" wangid=\"5,0,0,0,5,5,5,5\"/>\n      <wangtile tileid=\"208\" wangid=\"5,0,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"209\" wangid=\"5,0,0,0,0,0,5,0\"/>\n      <wangtile tileid=\"210\" wangid=\"5,0,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"211\" wangid=\"5,0,0,0,5,0,5,0\"/>\n      <wangtile tileid=\"212\" wangid=\"5,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"213\" wangid=\"5,5,5,0,0,0,0,0\"/>\n      <wangtile tileid=\"214\" wangid=\"5,5,5,0,0,0,5,5\"/>\n      <wangtile tileid=\"215\" wangid=\"5,0,0,0,0,0,5,5\"/>\n      <wangtile tileid=\"216\" wangid=\"5,5,5,0,5,0,0,0\"/>\n      <wangtile tileid=\"217\" wangid=\"5,0,0,0,5,0,5,5\"/>\n      <wangtile tileid=\"218\" wangid=\"0,0,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"219\" wangid=\"0,0,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"220\" wangid=\"5,5,5,0,5,5,5,5\"/>\n      <wangtile tileid=\"221\" wangid=\"5,5,5,5,5,0,5,5\"/>\n      <wangtile tileid=\"222\" wangid=\"5,0,5,0,5,0,5,5\"/>\n      <wangtile tileid=\"223\" wangid=\"5,5,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"224\" wangid=\"5,0,5,5,5,0,0,0\"/>\n      <wangtile tileid=\"225\" wangid=\"5,0,0,0,5,5,5,0\"/>\n      <wangtile tileid=\"226\" wangid=\"5,0,5,0,0,0,5,5\"/>\n      <wangtile tileid=\"227\" wangid=\"5,5,5,0,0,0,5,0\"/>\n      <wangtile tileid=\"228\" wangid=\"5,0,5,5,5,5,5,5\"/>\n      <wangtile tileid=\"229\" wangid=\"5,5,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"230\" wangid=\"5,0,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"231\" wangid=\"5,0,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"232\" wangid=\"5,0,5,5,5,5,5,0\"/>\n      <wangtile tileid=\"233\" wangid=\"5,5,5,0,5,0,5,5\"/>\n      <wangtile tileid=\"234\" wangid=\"5,0,5,0,5,5,5,5\"/>\n      <wangtile tileid=\"235\" wangid=\"5,5,5,5,5,0,5,0\"/>\n      <wangtile tileid=\"236\" wangid=\"5,0,5,5,5,0,5,5\"/>\n      <wangtile tileid=\"237\" wangid=\"5,5,5,0,5,5,5,0\"/>\n      <wangtile tileid=\"238\" wangid=\"5,0,5,0,5,0,5,0\"/>\n      <wangtile tileid=\"241\" wangid=\"0,0,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"242\" wangid=\"0,0,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"243\" wangid=\"0,0,0,0,0,0,6,0\"/>\n      <wangtile tileid=\"244\" wangid=\"0,0,0,0,6,0,0,0\"/>\n      <wangtile tileid=\"245\" wangid=\"0,0,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"246\" wangid=\"0,0,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"247\" wangid=\"0,0,0,0,6,6,6,0\"/>\n      <wangtile tileid=\"248\" wangid=\"0,0,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"249\" wangid=\"0,0,0,0,6,0,6,0\"/>\n      <wangtile tileid=\"250\" wangid=\"6,0,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"251\" wangid=\"0,0,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"252\" wangid=\"6,0,0,0,6,0,0,0\"/>\n      <wangtile tileid=\"253\" wangid=\"6,6,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"254\" wangid=\"6,6,6,6,6,6,6,6\"/>\n      <wangtile tileid=\"255\" wangid=\"6,0,0,0,6,6,6,6\"/>\n      <wangtile tileid=\"256\" wangid=\"6,0,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"257\" wangid=\"6,0,0,0,0,0,6,0\"/>\n      <wangtile tileid=\"258\" wangid=\"6,0,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"259\" wangid=\"6,0,0,0,6,0,6,0\"/>\n      <wangtile tileid=\"260\" wangid=\"6,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"261\" wangid=\"6,6,6,0,0,0,0,0\"/>\n      <wangtile tileid=\"262\" wangid=\"6,6,6,0,0,0,6,6\"/>\n      <wangtile tileid=\"263\" wangid=\"6,0,0,0,0,0,6,6\"/>\n      <wangtile tileid=\"264\" wangid=\"6,6,6,0,6,0,0,0\"/>\n      <wangtile tileid=\"265\" wangid=\"6,0,0,0,6,0,6,6\"/>\n      <wangtile tileid=\"266\" wangid=\"0,0,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"267\" wangid=\"0,0,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"268\" wangid=\"6,6,6,0,6,6,6,6\"/>\n      <wangtile tileid=\"269\" wangid=\"6,6,6,6,6,0,6,6\"/>\n      <wangtile tileid=\"270\" wangid=\"6,0,6,0,6,0,6,6\"/>\n      <wangtile tileid=\"271\" wangid=\"6,6,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"272\" wangid=\"6,0,6,6,6,0,0,0\"/>\n      <wangtile tileid=\"273\" wangid=\"6,0,0,0,6,6,6,0\"/>\n      <wangtile tileid=\"274\" wangid=\"6,0,6,0,0,0,6,6\"/>\n      <wangtile tileid=\"275\" wangid=\"6,6,6,0,0,0,6,0\"/>\n      <wangtile tileid=\"276\" wangid=\"6,0,6,6,6,6,6,6\"/>\n      <wangtile tileid=\"277\" wangid=\"6,6,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"278\" wangid=\"6,0,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"279\" wangid=\"6,0,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"280\" wangid=\"6,0,6,6,6,6,6,0\"/>\n      <wangtile tileid=\"281\" wangid=\"6,6,6,0,6,0,6,6\"/>\n      <wangtile tileid=\"282\" wangid=\"6,0,6,0,6,6,6,6\"/>\n      <wangtile tileid=\"283\" wangid=\"6,6,6,6,6,0,6,0\"/>\n      <wangtile tileid=\"284\" wangid=\"6,0,6,6,6,0,6,6\"/>\n      <wangtile tileid=\"285\" wangid=\"6,6,6,0,6,6,6,0\"/>\n      <wangtile tileid=\"286\" wangid=\"6,0,6,0,6,0,6,0\"/>\n      <wangtile tileid=\"289\" wangid=\"0,0,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"290\" wangid=\"0,0,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"291\" wangid=\"0,0,0,0,0,0,7,0\"/>\n      <wangtile tileid=\"292\" wangid=\"0,0,0,0,7,0,0,0\"/>\n      <wangtile tileid=\"293\" wangid=\"0,0,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"294\" wangid=\"0,0,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"295\" wangid=\"0,0,0,0,7,7,7,0\"/>\n      <wangtile tileid=\"296\" wangid=\"0,0,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"297\" wangid=\"0,0,0,0,7,0,7,0\"/>\n      <wangtile tileid=\"298\" wangid=\"7,0,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"299\" wangid=\"0,0,7,0,7,0,7,0\"/>\n      <wangtile tileid=\"300\" wangid=\"7,0,0,0,7,0,0,0\"/>\n      <wangtile tileid=\"301\" wangid=\"7,7,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"302\" wangid=\"7,7,7,7,7,7,7,7\"/>\n      <wangtile tileid=\"303\" wangid=\"7,0,0,0,7,7,7,7\"/>\n      <wangtile tileid=\"304\" wangid=\"7,0,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"305\" wangid=\"7,0,0,0,0,0,7,0\"/>\n      <wangtile tileid=\"306\" wangid=\"7,0,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"307\" wangid=\"7,0,0,0,7,0,7,0\"/>\n      <wangtile tileid=\"308\" wangid=\"7,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"309\" wangid=\"7,7,7,0,0,0,0,0\"/>\n      <wangtile tileid=\"310\" wangid=\"7,7,7,0,0,0,7,7\"/>\n      <wangtile tileid=\"311\" wangid=\"7,0,0,0,0,0,7,7\"/>\n      <wangtile tileid=\"312\" wangid=\"7,7,7,0,7,0,0,0\"/>\n      <wangtile tileid=\"313\" wangid=\"7,0,0,0,7,0,7,7\"/>\n      <wangtile tileid=\"314\" wangid=\"0,0,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"315\" wangid=\"0,0,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"316\" wangid=\"7,7,7,0,7,7,7,7\"/>\n      <wangtile tileid=\"317\" wangid=\"7,7,7,7,7,0,7,7\"/>\n      <wangtile tileid=\"318\" wangid=\"7,0,7,0,7,0,7,7\"/>\n      <wangtile tileid=\"319\" wangid=\"7,7,7,0,7,0,7,0\"/>\n      <wangtile tileid=\"320\" wangid=\"7,0,7,7,7,0,0,0\"/>\n      <wangtile tileid=\"321\" wangid=\"7,0,0,0,7,7,7,0\"/>\n      <wangtile tileid=\"322\" wangid=\"7,0,7,0,0,0,7,7\"/>\n      <wangtile tileid=\"323\" wangid=\"7,7,7,0,0,0,7,0\"/>\n      <wangtile tileid=\"324\" wangid=\"7,0,7,7,7,7,7,7\"/>\n      <wangtile tileid=\"325\" wangid=\"7,7,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"326\" wangid=\"7,0,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"327\" wangid=\"7,0,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"328\" wangid=\"7,0,7,7,7,7,7,0\"/>\n      <wangtile tileid=\"329\" wangid=\"7,7,7,0,7,0,7,7\"/>\n      <wangtile tileid=\"330\" wangid=\"7,0,7,0,7,7,7,7\"/>\n      <wangtile tileid=\"331\" wangid=\"7,7,7,7,7,0,7,0\"/>\n      <wangtile tileid=\"332\" wangid=\"7,0,7,7,7,0,7,7\"/>\n      <wangtile tileid=\"333\" wangid=\"7,7,7,0,7,7,7,0\"/>\n      <wangtile tileid=\"334\" wangid=\"7,0,7,0,7,0,7,0\"/>\n      <wangtile tileid=\"337\" wangid=\"0,0,8,0,0,0,0,0\"/>\n      <wangtile tileid=\"338\" wangid=\"0,0,8,0,0,0,8,0\"/>\n      <wangtile tileid=\"339\" wangid=\"0,0,0,0,0,0,8,0\"/>\n      <wangtile tileid=\"340\" wangid=\"0,0,0,0,8,0,0,0\"/>\n      <wangtile tileid=\"341\" wangid=\"0,0,8,8,8,0,0,0\"/>\n      <wangtile tileid=\"342\" wangid=\"0,0,8,8,8,8,8,0\"/>\n      <wangtile tileid=\"343\" wangid=\"0,0,0,0,8,8,8,0\"/>\n      <wangtile tileid=\"344\" wangid=\"0,0,8,0,8,0,0,0\"/>\n      <wangtile tileid=\"345\" wangid=\"0,0,0,0,8,0,8,0\"/>\n      <wangtile tileid=\"346\" wangid=\"8,0,8,0,8,0,0,0\"/>\n      <wangtile tileid=\"347\" wangid=\"0,0,8,0,8,0,8,0\"/>\n      <wangtile tileid=\"348\" wangid=\"8,0,0,0,8,0,0,0\"/>\n      <wangtile tileid=\"349\" wangid=\"8,8,8,8,8,0,0,0\"/>\n      <wangtile tileid=\"350\" wangid=\"8,8,8,8,8,8,8,8\"/>\n      <wangtile tileid=\"351\" wangid=\"8,0,0,0,8,8,8,8\"/>\n      <wangtile tileid=\"352\" wangid=\"8,0,8,0,0,0,0,0\"/>\n      <wangtile tileid=\"353\" wangid=\"8,0,0,0,0,0,8,0\"/>\n      <wangtile tileid=\"354\" wangid=\"8,0,8,0,0,0,8,0\"/>\n      <wangtile tileid=\"355\" wangid=\"8,0,0,0,8,0,8,0\"/>\n      <wangtile tileid=\"356\" wangid=\"8,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"357\" wangid=\"8,8,8,0,0,0,0,0\"/>\n      <wangtile tileid=\"358\" wangid=\"8,8,8,0,0,0,8,8\"/>\n      <wangtile tileid=\"359\" wangid=\"8,0,0,0,0,0,8,8\"/>\n      <wangtile tileid=\"360\" wangid=\"8,8,8,0,8,0,0,0\"/>\n      <wangtile tileid=\"361\" wangid=\"8,0,0,0,8,0,8,8\"/>\n      <wangtile tileid=\"362\" wangid=\"0,0,8,0,8,8,8,0\"/>\n      <wangtile tileid=\"363\" wangid=\"0,0,8,8,8,0,8,0\"/>\n      <wangtile tileid=\"364\" wangid=\"8,8,8,0,8,8,8,8\"/>\n      <wangtile tileid=\"365\" wangid=\"8,8,8,8,8,0,8,8\"/>\n      <wangtile tileid=\"366\" wangid=\"8,0,8,0,8,0,8,8\"/>\n      <wangtile tileid=\"367\" wangid=\"8,8,8,0,8,0,8,0\"/>\n      <wangtile tileid=\"368\" wangid=\"8,0,8,8,8,0,0,0\"/>\n      <wangtile tileid=\"369\" wangid=\"8,0,0,0,8,8,8,0\"/>\n      <wangtile tileid=\"370\" wangid=\"8,0,8,0,0,0,8,8\"/>\n      <wangtile tileid=\"371\" wangid=\"8,8,8,0,0,0,8,0\"/>\n      <wangtile tileid=\"372\" wangid=\"8,0,8,8,8,8,8,8\"/>\n      <wangtile tileid=\"373\" wangid=\"8,8,8,8,8,8,8,0\"/>\n      <wangtile tileid=\"374\" wangid=\"8,0,8,0,8,8,8,0\"/>\n      <wangtile tileid=\"375\" wangid=\"8,0,8,8,8,0,8,0\"/>\n      <wangtile tileid=\"376\" wangid=\"8,0,8,8,8,8,8,0\"/>\n      <wangtile tileid=\"377\" wangid=\"8,8,8,0,8,0,8,8\"/>\n      <wangtile tileid=\"378\" wangid=\"8,0,8,0,8,8,8,8\"/>\n      <wangtile tileid=\"379\" wangid=\"8,8,8,8,8,0,8,0\"/>\n      <wangtile tileid=\"380\" wangid=\"8,0,8,8,8,0,8,8\"/>\n      <wangtile tileid=\"381\" wangid=\"8,8,8,0,8,8,8,0\"/>\n      <wangtile tileid=\"382\" wangid=\"8,0,8,0,8,0,8,0\"/>\n      <wangtile tileid=\"385\" wangid=\"0,0,9,0,0,0,0,0\"/>\n      <wangtile tileid=\"386\" wangid=\"0,0,9,0,0,0,9,0\"/>\n      <wangtile tileid=\"387\" wangid=\"0,0,0,0,0,0,9,0\"/>\n      <wangtile tileid=\"388\" wangid=\"0,0,0,0,9,0,0,0\"/>\n      <wangtile tileid=\"389\" wangid=\"0,0,9,9,9,0,0,0\"/>\n      <wangtile tileid=\"390\" wangid=\"0,0,9,9,9,9,9,0\"/>\n      <wangtile tileid=\"391\" wangid=\"0,0,0,0,9,9,9,0\"/>\n      <wangtile tileid=\"392\" wangid=\"0,0,9,0,9,0,0,0\"/>\n      <wangtile tileid=\"393\" wangid=\"0,0,0,0,9,0,9,0\"/>\n      <wangtile tileid=\"394\" wangid=\"9,0,9,0,9,0,0,0\"/>\n      <wangtile tileid=\"395\" wangid=\"0,0,9,0,9,0,9,0\"/>\n      <wangtile tileid=\"396\" wangid=\"9,0,0,0,9,0,0,0\"/>\n      <wangtile tileid=\"397\" wangid=\"9,9,9,9,9,0,0,0\"/>\n      <wangtile tileid=\"398\" wangid=\"9,9,9,9,9,9,9,9\"/>\n      <wangtile tileid=\"399\" wangid=\"9,0,0,0,9,9,9,9\"/>\n      <wangtile tileid=\"400\" wangid=\"9,0,9,0,0,0,0,0\"/>\n      <wangtile tileid=\"401\" wangid=\"9,0,0,0,0,0,9,0\"/>\n      <wangtile tileid=\"402\" wangid=\"9,0,9,0,0,0,9,0\"/>\n      <wangtile tileid=\"403\" wangid=\"9,0,0,0,9,0,9,0\"/>\n      <wangtile tileid=\"404\" wangid=\"9,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"405\" wangid=\"9,9,9,0,0,0,0,0\"/>\n      <wangtile tileid=\"406\" wangid=\"9,9,9,0,0,0,9,9\"/>\n      <wangtile tileid=\"407\" wangid=\"9,0,0,0,0,0,9,9\"/>\n      <wangtile tileid=\"408\" wangid=\"9,9,9,0,9,0,0,0\"/>\n      <wangtile tileid=\"409\" wangid=\"9,0,0,0,9,0,9,9\"/>\n      <wangtile tileid=\"410\" wangid=\"0,0,9,0,9,9,9,0\"/>\n      <wangtile tileid=\"411\" wangid=\"0,0,9,9,9,0,9,0\"/>\n      <wangtile tileid=\"412\" wangid=\"9,9,9,0,9,9,9,9\"/>\n      <wangtile tileid=\"413\" wangid=\"9,9,9,9,9,0,9,9\"/>\n      <wangtile tileid=\"414\" wangid=\"9,0,9,0,9,0,9,9\"/>\n      <wangtile tileid=\"415\" wangid=\"9,9,9,0,9,0,9,0\"/>\n      <wangtile tileid=\"416\" wangid=\"9,0,9,9,9,0,0,0\"/>\n      <wangtile tileid=\"417\" wangid=\"9,0,0,0,9,9,9,0\"/>\n      <wangtile tileid=\"418\" wangid=\"9,0,9,0,0,0,9,9\"/>\n      <wangtile tileid=\"419\" wangid=\"9,9,9,0,0,0,9,0\"/>\n      <wangtile tileid=\"420\" wangid=\"9,0,9,9,9,9,9,9\"/>\n      <wangtile tileid=\"421\" wangid=\"9,9,9,9,9,9,9,0\"/>\n      <wangtile tileid=\"422\" wangid=\"9,0,9,0,9,9,9,0\"/>\n      <wangtile tileid=\"423\" wangid=\"9,0,9,9,9,0,9,0\"/>\n      <wangtile tileid=\"424\" wangid=\"9,0,9,9,9,9,9,0\"/>\n      <wangtile tileid=\"425\" wangid=\"9,9,9,0,9,0,9,9\"/>\n      <wangtile tileid=\"426\" wangid=\"9,0,9,0,9,9,9,9\"/>\n      <wangtile tileid=\"427\" wangid=\"9,9,9,9,9,0,9,0\"/>\n      <wangtile tileid=\"428\" wangid=\"9,0,9,9,9,0,9,9\"/>\n      <wangtile tileid=\"429\" wangid=\"9,9,9,0,9,9,9,0\"/>\n      <wangtile tileid=\"430\" wangid=\"9,0,9,0,9,0,9,0\"/>\n      <wangtile tileid=\"433\" wangid=\"0,0,10,0,0,0,0,0\"/>\n      <wangtile tileid=\"434\" wangid=\"0,0,10,0,0,0,10,0\"/>\n      <wangtile tileid=\"435\" wangid=\"0,0,0,0,0,0,10,0\"/>\n      <wangtile tileid=\"436\" wangid=\"0,0,0,0,10,0,0,0\"/>\n      <wangtile tileid=\"437\" wangid=\"0,0,10,10,10,0,0,0\"/>\n      <wangtile tileid=\"438\" wangid=\"0,0,10,10,10,10,10,0\"/>\n      <wangtile tileid=\"439\" wangid=\"0,0,0,0,10,10,10,0\"/>\n      <wangtile tileid=\"440\" wangid=\"0,0,10,0,10,0,0,0\"/>\n      <wangtile tileid=\"441\" wangid=\"0,0,0,0,10,0,10,0\"/>\n      <wangtile tileid=\"442\" wangid=\"10,0,10,0,10,0,0,0\"/>\n      <wangtile tileid=\"443\" wangid=\"0,0,10,0,10,0,10,0\"/>\n      <wangtile tileid=\"444\" wangid=\"10,0,0,0,10,0,0,0\"/>\n      <wangtile tileid=\"445\" wangid=\"10,10,10,10,10,0,0,0\"/>\n      <wangtile tileid=\"446\" wangid=\"10,10,10,10,10,10,10,10\"/>\n      <wangtile tileid=\"447\" wangid=\"10,0,0,0,10,10,10,10\"/>\n      <wangtile tileid=\"448\" wangid=\"10,0,10,0,0,0,0,0\"/>\n      <wangtile tileid=\"449\" wangid=\"10,0,0,0,0,0,10,0\"/>\n      <wangtile tileid=\"450\" wangid=\"10,0,10,0,0,0,10,0\"/>\n      <wangtile tileid=\"451\" wangid=\"10,0,0,0,10,0,10,0\"/>\n      <wangtile tileid=\"452\" wangid=\"10,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"453\" wangid=\"10,10,10,0,0,0,0,0\"/>\n      <wangtile tileid=\"454\" wangid=\"10,10,10,0,0,0,10,10\"/>\n      <wangtile tileid=\"455\" wangid=\"10,0,0,0,0,0,10,10\"/>\n      <wangtile tileid=\"456\" wangid=\"10,10,10,0,10,0,0,0\"/>\n      <wangtile tileid=\"457\" wangid=\"10,0,0,0,10,0,10,10\"/>\n      <wangtile tileid=\"458\" wangid=\"0,0,10,0,10,10,10,0\"/>\n      <wangtile tileid=\"459\" wangid=\"0,0,10,10,10,0,10,0\"/>\n      <wangtile tileid=\"460\" wangid=\"10,10,10,0,10,10,10,10\"/>\n      <wangtile tileid=\"461\" wangid=\"10,10,10,10,10,0,10,10\"/>\n      <wangtile tileid=\"462\" wangid=\"10,0,10,0,10,0,10,10\"/>\n      <wangtile tileid=\"463\" wangid=\"10,10,10,0,10,0,10,0\"/>\n      <wangtile tileid=\"464\" wangid=\"10,0,10,10,10,0,0,0\"/>\n      <wangtile tileid=\"465\" wangid=\"10,0,0,0,10,10,10,0\"/>\n      <wangtile tileid=\"466\" wangid=\"10,0,10,0,0,0,10,10\"/>\n      <wangtile tileid=\"467\" wangid=\"10,10,10,0,0,0,10,0\"/>\n      <wangtile tileid=\"468\" wangid=\"10,0,10,10,10,10,10,10\"/>\n      <wangtile tileid=\"469\" wangid=\"10,10,10,10,10,10,10,0\"/>\n      <wangtile tileid=\"470\" wangid=\"10,0,10,0,10,10,10,0\"/>\n      <wangtile tileid=\"471\" wangid=\"10,0,10,10,10,0,10,0\"/>\n      <wangtile tileid=\"472\" wangid=\"10,0,10,10,10,10,10,0\"/>\n      <wangtile tileid=\"473\" wangid=\"10,10,10,0,10,0,10,10\"/>\n      <wangtile tileid=\"474\" wangid=\"10,0,10,0,10,10,10,10\"/>\n      <wangtile tileid=\"475\" wangid=\"10,10,10,10,10,0,10,0\"/>\n      <wangtile tileid=\"476\" wangid=\"10,0,10,10,10,0,10,10\"/>\n      <wangtile tileid=\"477\" wangid=\"10,10,10,0,10,10,10,0\"/>\n      <wangtile tileid=\"478\" wangid=\"10,0,10,0,10,0,10,0\"/>\n      <wangtile tileid=\"481\" wangid=\"0,0,11,0,0,0,0,0\"/>\n      <wangtile tileid=\"482\" wangid=\"0,0,11,0,0,0,11,0\"/>\n      <wangtile tileid=\"483\" wangid=\"0,0,0,0,0,0,11,0\"/>\n      <wangtile tileid=\"484\" wangid=\"0,0,0,0,11,0,0,0\"/>\n      <wangtile tileid=\"485\" wangid=\"0,0,11,11,11,0,0,0\"/>\n      <wangtile tileid=\"486\" wangid=\"0,0,11,11,11,11,11,0\"/>\n      <wangtile tileid=\"487\" wangid=\"0,0,0,0,11,11,11,0\"/>\n      <wangtile tileid=\"488\" wangid=\"0,0,11,0,11,0,0,0\"/>\n      <wangtile tileid=\"489\" wangid=\"0,0,0,0,11,0,11,0\"/>\n      <wangtile tileid=\"490\" wangid=\"11,0,11,0,11,0,0,0\"/>\n      <wangtile tileid=\"491\" wangid=\"0,0,11,0,11,0,11,0\"/>\n      <wangtile tileid=\"492\" wangid=\"11,0,0,0,11,0,0,0\"/>\n      <wangtile tileid=\"493\" wangid=\"11,11,11,11,11,0,0,0\"/>\n      <wangtile tileid=\"494\" wangid=\"11,11,11,11,11,11,11,11\"/>\n      <wangtile tileid=\"495\" wangid=\"11,0,0,0,11,11,11,11\"/>\n      <wangtile tileid=\"496\" wangid=\"11,0,11,0,0,0,0,0\"/>\n      <wangtile tileid=\"497\" wangid=\"11,0,0,0,0,0,11,0\"/>\n      <wangtile tileid=\"498\" wangid=\"11,0,11,0,0,0,11,0\"/>\n      <wangtile tileid=\"499\" wangid=\"11,0,0,0,11,0,11,0\"/>\n      <wangtile tileid=\"500\" wangid=\"11,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"501\" wangid=\"11,11,11,0,0,0,0,0\"/>\n      <wangtile tileid=\"502\" wangid=\"11,11,11,0,0,0,11,11\"/>\n      <wangtile tileid=\"503\" wangid=\"11,0,0,0,0,0,11,11\"/>\n      <wangtile tileid=\"504\" wangid=\"11,11,11,0,11,0,0,0\"/>\n      <wangtile tileid=\"505\" wangid=\"11,0,0,0,11,0,11,11\"/>\n      <wangtile tileid=\"506\" wangid=\"0,0,11,0,11,11,11,0\"/>\n      <wangtile tileid=\"507\" wangid=\"0,0,11,11,11,0,11,0\"/>\n      <wangtile tileid=\"508\" wangid=\"11,11,11,0,11,11,11,11\"/>\n      <wangtile tileid=\"509\" wangid=\"11,11,11,11,11,0,11,11\"/>\n      <wangtile tileid=\"510\" wangid=\"11,0,11,0,11,0,11,11\"/>\n      <wangtile tileid=\"511\" wangid=\"11,11,11,0,11,0,11,0\"/>\n      <wangtile tileid=\"512\" wangid=\"11,0,11,11,11,0,0,0\"/>\n      <wangtile tileid=\"513\" wangid=\"11,0,0,0,11,11,11,0\"/>\n      <wangtile tileid=\"514\" wangid=\"11,0,11,0,0,0,11,11\"/>\n      <wangtile tileid=\"515\" wangid=\"11,11,11,0,0,0,11,0\"/>\n      <wangtile tileid=\"516\" wangid=\"11,0,11,11,11,11,11,11\"/>\n      <wangtile tileid=\"517\" wangid=\"11,11,11,11,11,11,11,0\"/>\n      <wangtile tileid=\"518\" wangid=\"11,0,11,0,11,11,11,0\"/>\n      <wangtile tileid=\"519\" wangid=\"11,0,11,11,11,0,11,0\"/>\n      <wangtile tileid=\"520\" wangid=\"11,0,11,11,11,11,11,0\"/>\n      <wangtile tileid=\"521\" wangid=\"11,11,11,0,11,0,11,11\"/>\n      <wangtile tileid=\"522\" wangid=\"11,0,11,0,11,11,11,11\"/>\n      <wangtile tileid=\"523\" wangid=\"11,11,11,11,11,0,11,0\"/>\n      <wangtile tileid=\"524\" wangid=\"11,0,11,11,11,0,11,11\"/>\n      <wangtile tileid=\"525\" wangid=\"11,11,11,0,11,11,11,0\"/>\n      <wangtile tileid=\"526\" wangid=\"11,0,11,0,11,0,11,0\"/>\n    </wangset>\n  </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[A]Wall-Up_pipo.tsx",
    "content": "<?xml version=\"1.0\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]Wall-Up_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"96\" columns=\"8\">\n  <image source=\"[A]Wall-Up_pipo.png\" width=\"256\" height=\"384\"/>\n  <wangsets>\n    <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n      <wangcolor color=\"#B2711B\" tile=\"0\" probability=\"1\"/>\n      <wangcolor color=\"#403BD4\" tile=\"48\" probability=\"1\"/>\n      <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"8\" wangid=\"0,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"9\" wangid=\"0,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"10\" wangid=\"1,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"11\" wangid=\"0,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"12\" wangid=\"1,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"13\" wangid=\"1,1,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"14\" wangid=\"1,1,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"15\" wangid=\"1,0,0,0,1,1,1,1\"/>\n      <wangtile tileid=\"16\" wangid=\"1,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"17\" wangid=\"1,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"18\" wangid=\"1,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"19\" wangid=\"1,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"20\" wangid=\"1,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"21\" wangid=\"1,1,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"22\" wangid=\"1,1,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"23\" wangid=\"1,0,0,0,0,0,1,1\"/>\n      <wangtile tileid=\"24\" wangid=\"1,1,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"25\" wangid=\"1,0,0,0,1,0,1,1\"/>\n      <wangtile tileid=\"26\" wangid=\"0,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"27\" wangid=\"0,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"28\" wangid=\"1,1,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"29\" wangid=\"1,1,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"30\" wangid=\"1,0,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"31\" wangid=\"1,1,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"32\" wangid=\"1,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"33\" wangid=\"1,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"34\" wangid=\"1,0,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"35\" wangid=\"1,1,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"36\" wangid=\"1,0,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"37\" wangid=\"1,1,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"38\" wangid=\"1,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"39\" wangid=\"1,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"40\" wangid=\"1,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"41\" wangid=\"1,1,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"42\" wangid=\"1,0,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"43\" wangid=\"1,1,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"44\" wangid=\"1,0,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"45\" wangid=\"1,1,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"46\" wangid=\"1,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"49\" wangid=\"0,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"50\" wangid=\"0,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"51\" wangid=\"0,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"52\" wangid=\"0,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"53\" wangid=\"0,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"54\" wangid=\"0,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"55\" wangid=\"0,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"56\" wangid=\"0,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"57\" wangid=\"0,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"58\" wangid=\"2,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"59\" wangid=\"0,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"60\" wangid=\"2,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"61\" wangid=\"2,2,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"62\" wangid=\"2,2,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"63\" wangid=\"2,0,0,0,2,2,2,2\"/>\n      <wangtile tileid=\"64\" wangid=\"2,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"65\" wangid=\"2,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"66\" wangid=\"2,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"67\" wangid=\"2,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"68\" wangid=\"2,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"69\" wangid=\"2,2,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"70\" wangid=\"2,2,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"71\" wangid=\"2,0,0,0,0,0,2,2\"/>\n      <wangtile tileid=\"72\" wangid=\"2,2,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"73\" wangid=\"2,0,0,0,2,0,2,2\"/>\n      <wangtile tileid=\"74\" wangid=\"0,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"75\" wangid=\"0,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"76\" wangid=\"2,2,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"77\" wangid=\"2,2,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"78\" wangid=\"2,0,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"79\" wangid=\"2,2,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"80\" wangid=\"2,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"81\" wangid=\"2,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"82\" wangid=\"2,0,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"83\" wangid=\"2,2,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"84\" wangid=\"2,0,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"85\" wangid=\"2,2,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"86\" wangid=\"2,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"87\" wangid=\"2,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"88\" wangid=\"2,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"89\" wangid=\"2,2,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"90\" wangid=\"2,0,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"91\" wangid=\"2,2,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"92\" wangid=\"2,0,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"93\" wangid=\"2,2,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"94\" wangid=\"2,0,2,0,2,0,2,0\"/>\n    </wangset>\n  </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[A]WaterFall_pipo.tsx",
    "content": "<?xml version=\"1.0\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]WaterFall_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"576\" columns=\"32\">\n  <image source=\"[A]WaterFall_pipo.png\" width=\"1024\" height=\"576\"/>\n  <tile id=\"0\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"0\" duration=\"100\"/>\n      <frame tileid=\"8\" duration=\"100\"/>\n      <frame tileid=\"16\" duration=\"100\"/>\n      <frame tileid=\"24\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"1\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"1\" duration=\"100\"/>\n      <frame tileid=\"9\" duration=\"100\"/>\n      <frame tileid=\"17\" duration=\"100\"/>\n      <frame tileid=\"25\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"2\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"2\" duration=\"100\"/>\n      <frame tileid=\"10\" duration=\"100\"/>\n      <frame tileid=\"18\" duration=\"100\"/>\n      <frame tileid=\"26\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"3\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"3\" duration=\"100\"/>\n      <frame tileid=\"11\" duration=\"100\"/>\n      <frame tileid=\"19\" duration=\"100\"/>\n      <frame tileid=\"27\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"4\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"4\" duration=\"100\"/>\n      <frame tileid=\"12\" duration=\"100\"/>\n      <frame tileid=\"20\" duration=\"100\"/>\n      <frame tileid=\"28\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"5\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"5\" duration=\"100\"/>\n      <frame tileid=\"13\" duration=\"100\"/>\n      <frame tileid=\"21\" duration=\"100\"/>\n      <frame tileid=\"29\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"6\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"6\" duration=\"100\"/>\n      <frame tileid=\"14\" duration=\"100\"/>\n      <frame tileid=\"22\" duration=\"100\"/>\n      <frame tileid=\"30\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"7\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"7\" duration=\"100\"/>\n      <frame tileid=\"15\" duration=\"100\"/>\n      <frame tileid=\"23\" duration=\"100\"/>\n      <frame tileid=\"31\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"8\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"9\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"10\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"11\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"12\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"13\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"14\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"15\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"16\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"17\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"18\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"19\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"20\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"21\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"22\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"23\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"24\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"25\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"26\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"27\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"28\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"29\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"30\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"31\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"32\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"32\" duration=\"100\"/>\n      <frame tileid=\"40\" duration=\"100\"/>\n      <frame tileid=\"48\" duration=\"100\"/>\n      <frame tileid=\"56\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"33\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"33\" duration=\"100\"/>\n      <frame tileid=\"41\" duration=\"100\"/>\n      <frame tileid=\"49\" duration=\"100\"/>\n      <frame tileid=\"57\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"34\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"34\" duration=\"100\"/>\n      <frame tileid=\"42\" duration=\"100\"/>\n      <frame tileid=\"50\" duration=\"100\"/>\n      <frame tileid=\"58\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"35\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"35\" duration=\"100\"/>\n      <frame tileid=\"43\" duration=\"100\"/>\n      <frame tileid=\"51\" duration=\"100\"/>\n      <frame tileid=\"59\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"36\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"36\" duration=\"100\"/>\n      <frame tileid=\"44\" duration=\"100\"/>\n      <frame tileid=\"52\" duration=\"100\"/>\n      <frame tileid=\"60\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"37\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"37\" duration=\"100\"/>\n      <frame tileid=\"45\" duration=\"100\"/>\n      <frame tileid=\"53\" duration=\"100\"/>\n      <frame tileid=\"61\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"38\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"38\" duration=\"100\"/>\n      <frame tileid=\"46\" duration=\"100\"/>\n      <frame tileid=\"54\" duration=\"100\"/>\n      <frame tileid=\"62\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"39\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"39\" duration=\"100\"/>\n      <frame tileid=\"47\" duration=\"100\"/>\n      <frame tileid=\"55\" duration=\"100\"/>\n      <frame tileid=\"63\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"40\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"41\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"42\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"43\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"44\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"45\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"46\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"47\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"48\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"49\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"50\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"51\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"52\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"53\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"54\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"55\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"56\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"57\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"58\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"59\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"60\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"61\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"62\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"63\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"64\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"64\" duration=\"100\"/>\n      <frame tileid=\"72\" duration=\"100\"/>\n      <frame tileid=\"80\" duration=\"100\"/>\n      <frame tileid=\"88\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"65\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"65\" duration=\"100\"/>\n      <frame tileid=\"73\" duration=\"100\"/>\n      <frame tileid=\"81\" duration=\"100\"/>\n      <frame tileid=\"89\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"66\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"66\" duration=\"100\"/>\n      <frame tileid=\"74\" duration=\"100\"/>\n      <frame tileid=\"82\" duration=\"100\"/>\n      <frame tileid=\"90\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"67\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"67\" duration=\"100\"/>\n      <frame tileid=\"75\" duration=\"100\"/>\n      <frame tileid=\"83\" duration=\"100\"/>\n      <frame tileid=\"91\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"68\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"68\" duration=\"100\"/>\n      <frame tileid=\"76\" duration=\"100\"/>\n      <frame tileid=\"84\" duration=\"100\"/>\n      <frame tileid=\"92\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"69\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"69\" duration=\"100\"/>\n      <frame tileid=\"77\" duration=\"100\"/>\n      <frame tileid=\"85\" duration=\"100\"/>\n      <frame tileid=\"93\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"70\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"70\" duration=\"100\"/>\n      <frame tileid=\"78\" duration=\"100\"/>\n      <frame tileid=\"86\" duration=\"100\"/>\n      <frame tileid=\"94\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"71\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"71\" duration=\"100\"/>\n      <frame tileid=\"79\" duration=\"100\"/>\n      <frame tileid=\"87\" duration=\"100\"/>\n      <frame tileid=\"95\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"72\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"73\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"74\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"75\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"76\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"77\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"78\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"79\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"80\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"81\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"82\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"83\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"84\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"85\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"86\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"87\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"88\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"89\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"90\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"91\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"92\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"93\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"94\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"95\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"96\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"96\" duration=\"100\"/>\n      <frame tileid=\"104\" duration=\"100\"/>\n      <frame tileid=\"112\" duration=\"100\"/>\n      <frame tileid=\"120\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"97\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"97\" duration=\"100\"/>\n      <frame tileid=\"105\" duration=\"100\"/>\n      <frame tileid=\"113\" duration=\"100\"/>\n      <frame tileid=\"121\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"98\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"98\" duration=\"100\"/>\n      <frame tileid=\"106\" duration=\"100\"/>\n      <frame tileid=\"114\" duration=\"100\"/>\n      <frame tileid=\"122\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"99\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"99\" duration=\"100\"/>\n      <frame tileid=\"107\" duration=\"100\"/>\n      <frame tileid=\"115\" duration=\"100\"/>\n      <frame tileid=\"123\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"100\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"100\" duration=\"100\"/>\n      <frame tileid=\"108\" duration=\"100\"/>\n      <frame tileid=\"116\" duration=\"100\"/>\n      <frame tileid=\"124\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"101\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"101\" duration=\"100\"/>\n      <frame tileid=\"109\" duration=\"100\"/>\n      <frame tileid=\"117\" duration=\"100\"/>\n      <frame tileid=\"125\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"102\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"102\" duration=\"100\"/>\n      <frame tileid=\"110\" duration=\"100\"/>\n      <frame tileid=\"118\" duration=\"100\"/>\n      <frame tileid=\"126\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"103\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"103\" duration=\"100\"/>\n      <frame tileid=\"111\" duration=\"100\"/>\n      <frame tileid=\"119\" duration=\"100\"/>\n      <frame tileid=\"127\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"104\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"105\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"106\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"107\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"108\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"109\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"110\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"111\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"112\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"113\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"114\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"115\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"116\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"117\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"118\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"119\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"120\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"121\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"122\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"123\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"124\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"125\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"126\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"127\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"128\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"128\" duration=\"100\"/>\n      <frame tileid=\"136\" duration=\"100\"/>\n      <frame tileid=\"144\" duration=\"100\"/>\n      <frame tileid=\"152\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"129\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"129\" duration=\"100\"/>\n      <frame tileid=\"137\" duration=\"100\"/>\n      <frame tileid=\"145\" duration=\"100\"/>\n      <frame tileid=\"153\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"130\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"130\" duration=\"100\"/>\n      <frame tileid=\"138\" duration=\"100\"/>\n      <frame tileid=\"146\" duration=\"100\"/>\n      <frame tileid=\"154\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"131\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"131\" duration=\"100\"/>\n      <frame tileid=\"139\" duration=\"100\"/>\n      <frame tileid=\"147\" duration=\"100\"/>\n      <frame tileid=\"155\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"132\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"132\" duration=\"100\"/>\n      <frame tileid=\"140\" duration=\"100\"/>\n      <frame tileid=\"148\" duration=\"100\"/>\n      <frame tileid=\"156\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"133\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"133\" duration=\"100\"/>\n      <frame tileid=\"141\" duration=\"100\"/>\n      <frame tileid=\"149\" duration=\"100\"/>\n      <frame tileid=\"157\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"134\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"134\" duration=\"100\"/>\n      <frame tileid=\"142\" duration=\"100\"/>\n      <frame tileid=\"150\" duration=\"100\"/>\n      <frame tileid=\"158\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"135\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"135\" duration=\"100\"/>\n      <frame tileid=\"143\" duration=\"100\"/>\n      <frame tileid=\"151\" duration=\"100\"/>\n      <frame tileid=\"159\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"136\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"137\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"138\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"139\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"140\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"141\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"142\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"143\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"144\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"145\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"146\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"147\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"148\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"149\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"150\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"151\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"152\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"153\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"154\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"155\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"156\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"157\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"158\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"159\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"160\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"160\" duration=\"100\"/>\n      <frame tileid=\"168\" duration=\"100\"/>\n      <frame tileid=\"176\" duration=\"100\"/>\n      <frame tileid=\"184\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"161\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"161\" duration=\"100\"/>\n      <frame tileid=\"169\" duration=\"100\"/>\n      <frame tileid=\"177\" duration=\"100\"/>\n      <frame tileid=\"185\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"162\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"162\" duration=\"100\"/>\n      <frame tileid=\"170\" duration=\"100\"/>\n      <frame tileid=\"178\" duration=\"100\"/>\n      <frame tileid=\"186\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"163\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"163\" duration=\"100\"/>\n      <frame tileid=\"171\" duration=\"100\"/>\n      <frame tileid=\"179\" duration=\"100\"/>\n      <frame tileid=\"187\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"164\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"164\" duration=\"100\"/>\n      <frame tileid=\"172\" duration=\"100\"/>\n      <frame tileid=\"180\" duration=\"100\"/>\n      <frame tileid=\"188\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"165\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"165\" duration=\"100\"/>\n      <frame tileid=\"173\" duration=\"100\"/>\n      <frame tileid=\"181\" duration=\"100\"/>\n      <frame tileid=\"189\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"166\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"166\" duration=\"100\"/>\n      <frame tileid=\"174\" duration=\"100\"/>\n      <frame tileid=\"182\" duration=\"100\"/>\n      <frame tileid=\"190\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"167\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"167\" duration=\"100\"/>\n      <frame tileid=\"175\" duration=\"100\"/>\n      <frame tileid=\"183\" duration=\"100\"/>\n      <frame tileid=\"191\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"168\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"169\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"170\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"171\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"172\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"173\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"174\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"175\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"176\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"177\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"178\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"179\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"180\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"181\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"182\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"183\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"184\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"185\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"186\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"187\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"188\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"189\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"190\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"191\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"192\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"192\" duration=\"100\"/>\n      <frame tileid=\"200\" duration=\"100\"/>\n      <frame tileid=\"208\" duration=\"100\"/>\n      <frame tileid=\"216\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"193\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"193\" duration=\"100\"/>\n      <frame tileid=\"201\" duration=\"100\"/>\n      <frame tileid=\"209\" duration=\"100\"/>\n      <frame tileid=\"217\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"194\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"194\" duration=\"100\"/>\n      <frame tileid=\"202\" duration=\"100\"/>\n      <frame tileid=\"210\" duration=\"100\"/>\n      <frame tileid=\"218\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"195\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"195\" duration=\"100\"/>\n      <frame tileid=\"203\" duration=\"100\"/>\n      <frame tileid=\"211\" duration=\"100\"/>\n      <frame tileid=\"219\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"196\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"196\" duration=\"100\"/>\n      <frame tileid=\"204\" duration=\"100\"/>\n      <frame tileid=\"212\" duration=\"100\"/>\n      <frame tileid=\"220\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"197\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"197\" duration=\"100\"/>\n      <frame tileid=\"205\" duration=\"100\"/>\n      <frame tileid=\"213\" duration=\"100\"/>\n      <frame tileid=\"221\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"198\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"198\" duration=\"100\"/>\n      <frame tileid=\"206\" duration=\"100\"/>\n      <frame tileid=\"214\" duration=\"100\"/>\n      <frame tileid=\"222\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"199\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"199\" duration=\"100\"/>\n      <frame tileid=\"207\" duration=\"100\"/>\n      <frame tileid=\"215\" duration=\"100\"/>\n      <frame tileid=\"223\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"200\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"201\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"202\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"203\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"204\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"205\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"206\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"207\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"208\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"209\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"210\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"211\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"212\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"213\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"214\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"215\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"216\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"217\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"218\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"219\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"220\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"221\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"222\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"223\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"224\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"224\" duration=\"100\"/>\n      <frame tileid=\"232\" duration=\"100\"/>\n      <frame tileid=\"240\" duration=\"100\"/>\n      <frame tileid=\"248\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"225\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"225\" duration=\"100\"/>\n      <frame tileid=\"233\" duration=\"100\"/>\n      <frame tileid=\"241\" duration=\"100\"/>\n      <frame tileid=\"249\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"226\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"226\" duration=\"100\"/>\n      <frame tileid=\"234\" duration=\"100\"/>\n      <frame tileid=\"242\" duration=\"100\"/>\n      <frame tileid=\"250\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"227\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"227\" duration=\"100\"/>\n      <frame tileid=\"235\" duration=\"100\"/>\n      <frame tileid=\"243\" duration=\"100\"/>\n      <frame tileid=\"251\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"228\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"228\" duration=\"100\"/>\n      <frame tileid=\"236\" duration=\"100\"/>\n      <frame tileid=\"244\" duration=\"100\"/>\n      <frame tileid=\"252\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"229\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"229\" duration=\"100\"/>\n      <frame tileid=\"237\" duration=\"100\"/>\n      <frame tileid=\"245\" duration=\"100\"/>\n      <frame tileid=\"253\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"230\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"230\" duration=\"100\"/>\n      <frame tileid=\"238\" duration=\"100\"/>\n      <frame tileid=\"246\" duration=\"100\"/>\n      <frame tileid=\"254\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"231\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"231\" duration=\"100\"/>\n      <frame tileid=\"239\" duration=\"100\"/>\n      <frame tileid=\"247\" duration=\"100\"/>\n      <frame tileid=\"255\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"232\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"233\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"234\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"235\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"236\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"237\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"238\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"239\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"240\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"241\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"242\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"243\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"244\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"245\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"246\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"247\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"248\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"249\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"250\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"251\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"252\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"253\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"254\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"255\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"256\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"256\" duration=\"100\"/>\n      <frame tileid=\"264\" duration=\"100\"/>\n      <frame tileid=\"272\" duration=\"100\"/>\n      <frame tileid=\"280\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"257\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"257\" duration=\"100\"/>\n      <frame tileid=\"265\" duration=\"100\"/>\n      <frame tileid=\"273\" duration=\"100\"/>\n      <frame tileid=\"281\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"258\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"258\" duration=\"100\"/>\n      <frame tileid=\"266\" duration=\"100\"/>\n      <frame tileid=\"274\" duration=\"100\"/>\n      <frame tileid=\"282\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"259\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"259\" duration=\"100\"/>\n      <frame tileid=\"267\" duration=\"100\"/>\n      <frame tileid=\"275\" duration=\"100\"/>\n      <frame tileid=\"283\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"260\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"260\" duration=\"100\"/>\n      <frame tileid=\"268\" duration=\"100\"/>\n      <frame tileid=\"276\" duration=\"100\"/>\n      <frame tileid=\"284\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"261\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"261\" duration=\"100\"/>\n      <frame tileid=\"269\" duration=\"100\"/>\n      <frame tileid=\"277\" duration=\"100\"/>\n      <frame tileid=\"285\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"262\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"262\" duration=\"100\"/>\n      <frame tileid=\"270\" duration=\"100\"/>\n      <frame tileid=\"278\" duration=\"100\"/>\n      <frame tileid=\"286\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"263\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"263\" duration=\"100\"/>\n      <frame tileid=\"271\" duration=\"100\"/>\n      <frame tileid=\"279\" duration=\"100\"/>\n      <frame tileid=\"287\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"264\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"265\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"266\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"267\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"268\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"269\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"270\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"271\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"272\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"273\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"274\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"275\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"276\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"277\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"278\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"279\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"280\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"281\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"282\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"283\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"284\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"285\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"286\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"287\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"288\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"288\" duration=\"100\"/>\n      <frame tileid=\"296\" duration=\"100\"/>\n      <frame tileid=\"304\" duration=\"100\"/>\n      <frame tileid=\"312\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"289\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"289\" duration=\"100\"/>\n      <frame tileid=\"297\" duration=\"100\"/>\n      <frame tileid=\"305\" duration=\"100\"/>\n      <frame tileid=\"313\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"290\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"290\" duration=\"100\"/>\n      <frame tileid=\"298\" duration=\"100\"/>\n      <frame tileid=\"306\" duration=\"100\"/>\n      <frame tileid=\"314\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"291\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"291\" duration=\"100\"/>\n      <frame tileid=\"299\" duration=\"100\"/>\n      <frame tileid=\"307\" duration=\"100\"/>\n      <frame tileid=\"315\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"292\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"292\" duration=\"100\"/>\n      <frame tileid=\"300\" duration=\"100\"/>\n      <frame tileid=\"308\" duration=\"100\"/>\n      <frame tileid=\"316\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"293\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"293\" duration=\"100\"/>\n      <frame tileid=\"301\" duration=\"100\"/>\n      <frame tileid=\"309\" duration=\"100\"/>\n      <frame tileid=\"317\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"294\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"294\" duration=\"100\"/>\n      <frame tileid=\"302\" duration=\"100\"/>\n      <frame tileid=\"310\" duration=\"100\"/>\n      <frame tileid=\"318\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"295\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"295\" duration=\"100\"/>\n      <frame tileid=\"303\" duration=\"100\"/>\n      <frame tileid=\"311\" duration=\"100\"/>\n      <frame tileid=\"319\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"296\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"297\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"298\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"299\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"300\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"301\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"302\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"303\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"304\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"305\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"306\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"307\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"308\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"309\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"310\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"311\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"312\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"313\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"314\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"315\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"316\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"317\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"318\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"319\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"320\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"320\" duration=\"100\"/>\n      <frame tileid=\"328\" duration=\"100\"/>\n      <frame tileid=\"336\" duration=\"100\"/>\n      <frame tileid=\"344\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"321\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"321\" duration=\"100\"/>\n      <frame tileid=\"329\" duration=\"100\"/>\n      <frame tileid=\"337\" duration=\"100\"/>\n      <frame tileid=\"345\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"322\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"322\" duration=\"100\"/>\n      <frame tileid=\"330\" duration=\"100\"/>\n      <frame tileid=\"338\" duration=\"100\"/>\n      <frame tileid=\"346\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"323\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"323\" duration=\"100\"/>\n      <frame tileid=\"331\" duration=\"100\"/>\n      <frame tileid=\"339\" duration=\"100\"/>\n      <frame tileid=\"347\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"324\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"324\" duration=\"100\"/>\n      <frame tileid=\"332\" duration=\"100\"/>\n      <frame tileid=\"340\" duration=\"100\"/>\n      <frame tileid=\"348\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"325\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"325\" duration=\"100\"/>\n      <frame tileid=\"333\" duration=\"100\"/>\n      <frame tileid=\"341\" duration=\"100\"/>\n      <frame tileid=\"349\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"326\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"326\" duration=\"100\"/>\n      <frame tileid=\"334\" duration=\"100\"/>\n      <frame tileid=\"342\" duration=\"100\"/>\n      <frame tileid=\"350\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"327\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"327\" duration=\"100\"/>\n      <frame tileid=\"335\" duration=\"100\"/>\n      <frame tileid=\"343\" duration=\"100\"/>\n      <frame tileid=\"351\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"328\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"329\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"330\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"331\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"332\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"333\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"334\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"335\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"336\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"337\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"338\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"339\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"340\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"341\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"342\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"343\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"344\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"345\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"346\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"347\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"348\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"349\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"350\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"351\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"352\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"352\" duration=\"100\"/>\n      <frame tileid=\"360\" duration=\"100\"/>\n      <frame tileid=\"368\" duration=\"100\"/>\n      <frame tileid=\"376\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"353\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"353\" duration=\"100\"/>\n      <frame tileid=\"361\" duration=\"100\"/>\n      <frame tileid=\"369\" duration=\"100\"/>\n      <frame tileid=\"377\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"354\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"354\" duration=\"100\"/>\n      <frame tileid=\"362\" duration=\"100\"/>\n      <frame tileid=\"370\" duration=\"100\"/>\n      <frame tileid=\"378\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"355\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"355\" duration=\"100\"/>\n      <frame tileid=\"363\" duration=\"100\"/>\n      <frame tileid=\"371\" duration=\"100\"/>\n      <frame tileid=\"379\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"356\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"356\" duration=\"100\"/>\n      <frame tileid=\"364\" duration=\"100\"/>\n      <frame tileid=\"372\" duration=\"100\"/>\n      <frame tileid=\"380\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"357\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"357\" duration=\"100\"/>\n      <frame tileid=\"365\" duration=\"100\"/>\n      <frame tileid=\"373\" duration=\"100\"/>\n      <frame tileid=\"381\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"358\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"358\" duration=\"100\"/>\n      <frame tileid=\"366\" duration=\"100\"/>\n      <frame tileid=\"374\" duration=\"100\"/>\n      <frame tileid=\"382\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"359\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"359\" duration=\"100\"/>\n      <frame tileid=\"367\" duration=\"100\"/>\n      <frame tileid=\"375\" duration=\"100\"/>\n      <frame tileid=\"383\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"360\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"361\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"362\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"363\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"364\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"365\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"366\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"367\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"368\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"369\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"370\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"371\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"372\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"373\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"374\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"375\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"376\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"377\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"378\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"379\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"380\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"381\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"382\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"383\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"384\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"384\" duration=\"100\"/>\n      <frame tileid=\"392\" duration=\"100\"/>\n      <frame tileid=\"400\" duration=\"100\"/>\n      <frame tileid=\"408\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"385\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"385\" duration=\"100\"/>\n      <frame tileid=\"393\" duration=\"100\"/>\n      <frame tileid=\"401\" duration=\"100\"/>\n      <frame tileid=\"409\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"386\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"386\" duration=\"100\"/>\n      <frame tileid=\"394\" duration=\"100\"/>\n      <frame tileid=\"402\" duration=\"100\"/>\n      <frame tileid=\"410\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"387\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"387\" duration=\"100\"/>\n      <frame tileid=\"395\" duration=\"100\"/>\n      <frame tileid=\"403\" duration=\"100\"/>\n      <frame tileid=\"411\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"388\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"388\" duration=\"100\"/>\n      <frame tileid=\"396\" duration=\"100\"/>\n      <frame tileid=\"404\" duration=\"100\"/>\n      <frame tileid=\"412\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"389\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"389\" duration=\"100\"/>\n      <frame tileid=\"397\" duration=\"100\"/>\n      <frame tileid=\"405\" duration=\"100\"/>\n      <frame tileid=\"413\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"390\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"390\" duration=\"100\"/>\n      <frame tileid=\"398\" duration=\"100\"/>\n      <frame tileid=\"406\" duration=\"100\"/>\n      <frame tileid=\"414\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"391\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"391\" duration=\"100\"/>\n      <frame tileid=\"399\" duration=\"100\"/>\n      <frame tileid=\"407\" duration=\"100\"/>\n      <frame tileid=\"415\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"392\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"393\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"394\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"395\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"396\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"397\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"398\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"399\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"400\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"401\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"402\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"403\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"404\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"405\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"406\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"407\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"408\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"409\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"410\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"411\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"412\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"413\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"414\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"415\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"416\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"416\" duration=\"100\"/>\n      <frame tileid=\"424\" duration=\"100\"/>\n      <frame tileid=\"432\" duration=\"100\"/>\n      <frame tileid=\"440\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"417\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"417\" duration=\"100\"/>\n      <frame tileid=\"425\" duration=\"100\"/>\n      <frame tileid=\"433\" duration=\"100\"/>\n      <frame tileid=\"441\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"418\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"418\" duration=\"100\"/>\n      <frame tileid=\"426\" duration=\"100\"/>\n      <frame tileid=\"434\" duration=\"100\"/>\n      <frame tileid=\"442\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"419\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"419\" duration=\"100\"/>\n      <frame tileid=\"427\" duration=\"100\"/>\n      <frame tileid=\"435\" duration=\"100\"/>\n      <frame tileid=\"443\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"420\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"420\" duration=\"100\"/>\n      <frame tileid=\"428\" duration=\"100\"/>\n      <frame tileid=\"436\" duration=\"100\"/>\n      <frame tileid=\"444\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"421\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"421\" duration=\"100\"/>\n      <frame tileid=\"429\" duration=\"100\"/>\n      <frame tileid=\"437\" duration=\"100\"/>\n      <frame tileid=\"445\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"422\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"422\" duration=\"100\"/>\n      <frame tileid=\"430\" duration=\"100\"/>\n      <frame tileid=\"438\" duration=\"100\"/>\n      <frame tileid=\"446\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"423\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"423\" duration=\"100\"/>\n      <frame tileid=\"431\" duration=\"100\"/>\n      <frame tileid=\"439\" duration=\"100\"/>\n      <frame tileid=\"447\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"424\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"425\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"426\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"427\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"428\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"429\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"430\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"431\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"432\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"433\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"434\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"435\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"436\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"437\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"438\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"439\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"440\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"441\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"442\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"443\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"444\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"445\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"446\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"447\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"448\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"448\" duration=\"100\"/>\n      <frame tileid=\"456\" duration=\"100\"/>\n      <frame tileid=\"464\" duration=\"100\"/>\n      <frame tileid=\"472\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"449\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"449\" duration=\"100\"/>\n      <frame tileid=\"457\" duration=\"100\"/>\n      <frame tileid=\"465\" duration=\"100\"/>\n      <frame tileid=\"473\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"450\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"450\" duration=\"100\"/>\n      <frame tileid=\"458\" duration=\"100\"/>\n      <frame tileid=\"466\" duration=\"100\"/>\n      <frame tileid=\"474\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"451\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"451\" duration=\"100\"/>\n      <frame tileid=\"459\" duration=\"100\"/>\n      <frame tileid=\"467\" duration=\"100\"/>\n      <frame tileid=\"475\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"452\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"452\" duration=\"100\"/>\n      <frame tileid=\"460\" duration=\"100\"/>\n      <frame tileid=\"468\" duration=\"100\"/>\n      <frame tileid=\"476\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"453\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"453\" duration=\"100\"/>\n      <frame tileid=\"461\" duration=\"100\"/>\n      <frame tileid=\"469\" duration=\"100\"/>\n      <frame tileid=\"477\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"454\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"454\" duration=\"100\"/>\n      <frame tileid=\"462\" duration=\"100\"/>\n      <frame tileid=\"470\" duration=\"100\"/>\n      <frame tileid=\"478\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"455\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"455\" duration=\"100\"/>\n      <frame tileid=\"463\" duration=\"100\"/>\n      <frame tileid=\"471\" duration=\"100\"/>\n      <frame tileid=\"479\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"456\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"457\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"458\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"459\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"460\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"461\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"462\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"463\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"464\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"465\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"466\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"467\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"468\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"469\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"470\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"471\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"472\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"473\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"474\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"475\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"476\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"477\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"478\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"479\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"480\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"480\" duration=\"100\"/>\n      <frame tileid=\"488\" duration=\"100\"/>\n      <frame tileid=\"496\" duration=\"100\"/>\n      <frame tileid=\"504\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"481\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"481\" duration=\"100\"/>\n      <frame tileid=\"489\" duration=\"100\"/>\n      <frame tileid=\"497\" duration=\"100\"/>\n      <frame tileid=\"505\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"482\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"482\" duration=\"100\"/>\n      <frame tileid=\"490\" duration=\"100\"/>\n      <frame tileid=\"498\" duration=\"100\"/>\n      <frame tileid=\"506\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"483\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"483\" duration=\"100\"/>\n      <frame tileid=\"491\" duration=\"100\"/>\n      <frame tileid=\"499\" duration=\"100\"/>\n      <frame tileid=\"507\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"484\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"484\" duration=\"100\"/>\n      <frame tileid=\"492\" duration=\"100\"/>\n      <frame tileid=\"500\" duration=\"100\"/>\n      <frame tileid=\"508\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"485\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"485\" duration=\"100\"/>\n      <frame tileid=\"493\" duration=\"100\"/>\n      <frame tileid=\"501\" duration=\"100\"/>\n      <frame tileid=\"509\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"486\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"486\" duration=\"100\"/>\n      <frame tileid=\"494\" duration=\"100\"/>\n      <frame tileid=\"502\" duration=\"100\"/>\n      <frame tileid=\"510\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"487\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"487\" duration=\"100\"/>\n      <frame tileid=\"495\" duration=\"100\"/>\n      <frame tileid=\"503\" duration=\"100\"/>\n      <frame tileid=\"511\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"488\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"489\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"490\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"491\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"492\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"493\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"494\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"495\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"496\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"497\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"498\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"499\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"500\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"501\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"502\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"503\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"504\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"505\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"506\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"507\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"508\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"509\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"510\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"511\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"512\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"512\" duration=\"100\"/>\n      <frame tileid=\"520\" duration=\"100\"/>\n      <frame tileid=\"528\" duration=\"100\"/>\n      <frame tileid=\"536\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"513\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"513\" duration=\"100\"/>\n      <frame tileid=\"521\" duration=\"100\"/>\n      <frame tileid=\"529\" duration=\"100\"/>\n      <frame tileid=\"537\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"514\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"514\" duration=\"100\"/>\n      <frame tileid=\"522\" duration=\"100\"/>\n      <frame tileid=\"530\" duration=\"100\"/>\n      <frame tileid=\"538\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"515\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"515\" duration=\"100\"/>\n      <frame tileid=\"523\" duration=\"100\"/>\n      <frame tileid=\"531\" duration=\"100\"/>\n      <frame tileid=\"539\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"516\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"516\" duration=\"100\"/>\n      <frame tileid=\"524\" duration=\"100\"/>\n      <frame tileid=\"532\" duration=\"100\"/>\n      <frame tileid=\"540\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"517\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"517\" duration=\"100\"/>\n      <frame tileid=\"525\" duration=\"100\"/>\n      <frame tileid=\"533\" duration=\"100\"/>\n      <frame tileid=\"541\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"518\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"518\" duration=\"100\"/>\n      <frame tileid=\"526\" duration=\"100\"/>\n      <frame tileid=\"534\" duration=\"100\"/>\n      <frame tileid=\"542\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"519\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"519\" duration=\"100\"/>\n      <frame tileid=\"527\" duration=\"100\"/>\n      <frame tileid=\"535\" duration=\"100\"/>\n      <frame tileid=\"543\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"520\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"521\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"522\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"523\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"524\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"525\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"526\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"527\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"528\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"529\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"530\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"531\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"532\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"533\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"534\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"535\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"536\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"537\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"538\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"539\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"540\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"541\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"542\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"543\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"544\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"544\" duration=\"100\"/>\n      <frame tileid=\"552\" duration=\"100\"/>\n      <frame tileid=\"560\" duration=\"100\"/>\n      <frame tileid=\"568\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"545\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"545\" duration=\"100\"/>\n      <frame tileid=\"553\" duration=\"100\"/>\n      <frame tileid=\"561\" duration=\"100\"/>\n      <frame tileid=\"569\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"546\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"546\" duration=\"100\"/>\n      <frame tileid=\"554\" duration=\"100\"/>\n      <frame tileid=\"562\" duration=\"100\"/>\n      <frame tileid=\"570\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"547\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"547\" duration=\"100\"/>\n      <frame tileid=\"555\" duration=\"100\"/>\n      <frame tileid=\"563\" duration=\"100\"/>\n      <frame tileid=\"571\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"548\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"548\" duration=\"100\"/>\n      <frame tileid=\"556\" duration=\"100\"/>\n      <frame tileid=\"564\" duration=\"100\"/>\n      <frame tileid=\"572\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"549\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"549\" duration=\"100\"/>\n      <frame tileid=\"557\" duration=\"100\"/>\n      <frame tileid=\"565\" duration=\"100\"/>\n      <frame tileid=\"573\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"550\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"550\" duration=\"100\"/>\n      <frame tileid=\"558\" duration=\"100\"/>\n      <frame tileid=\"566\" duration=\"100\"/>\n      <frame tileid=\"574\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"551\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n    <animation>\n      <frame tileid=\"551\" duration=\"100\"/>\n      <frame tileid=\"559\" duration=\"100\"/>\n      <frame tileid=\"567\" duration=\"100\"/>\n      <frame tileid=\"575\" duration=\"100\"/>\n    </animation>\n  </tile>\n  <tile id=\"552\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"553\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"554\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"555\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"556\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"557\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"558\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"559\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"560\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"561\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"562\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"563\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"564\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"565\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"566\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"567\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"568\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"569\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"570\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"571\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"572\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"573\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"574\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <tile id=\"575\">\n    <properties>\n      <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    </properties>\n  </tile>\n  <wangsets>\n    <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n      <wangcolor color=\"#456610\" tile=\"0\" probability=\"1\"/>\n      <wangcolor color=\"#D74E5A\" tile=\"192\" probability=\"1\"/>\n      <wangcolor color=\"#D62478\" tile=\"384\" probability=\"1\"/>\n      <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"32\" wangid=\"0,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"33\" wangid=\"0,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"34\" wangid=\"1,0,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"35\" wangid=\"0,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"36\" wangid=\"1,0,0,0,1,0,0,0\"/>\n      <wangtile tileid=\"37\" wangid=\"1,1,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"38\" wangid=\"1,1,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"39\" wangid=\"1,0,0,0,1,1,1,1\"/>\n      <wangtile tileid=\"64\" wangid=\"1,0,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"65\" wangid=\"1,0,0,0,0,0,1,0\"/>\n      <wangtile tileid=\"66\" wangid=\"1,0,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"67\" wangid=\"1,0,0,0,1,0,1,0\"/>\n      <wangtile tileid=\"68\" wangid=\"1,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"69\" wangid=\"1,1,1,0,0,0,0,0\"/>\n      <wangtile tileid=\"70\" wangid=\"1,1,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"71\" wangid=\"1,0,0,0,0,0,1,1\"/>\n      <wangtile tileid=\"96\" wangid=\"1,1,1,0,1,0,0,0\"/>\n      <wangtile tileid=\"97\" wangid=\"1,0,0,0,1,0,1,1\"/>\n      <wangtile tileid=\"98\" wangid=\"0,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"99\" wangid=\"0,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"100\" wangid=\"1,1,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"101\" wangid=\"1,1,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"102\" wangid=\"1,0,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"103\" wangid=\"1,1,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"128\" wangid=\"1,0,1,1,1,0,0,0\"/>\n      <wangtile tileid=\"129\" wangid=\"1,0,0,0,1,1,1,0\"/>\n      <wangtile tileid=\"130\" wangid=\"1,0,1,0,0,0,1,1\"/>\n      <wangtile tileid=\"131\" wangid=\"1,1,1,0,0,0,1,0\"/>\n      <wangtile tileid=\"132\" wangid=\"1,0,1,1,1,1,1,1\"/>\n      <wangtile tileid=\"133\" wangid=\"1,1,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"134\" wangid=\"1,0,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"135\" wangid=\"1,0,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"160\" wangid=\"1,0,1,1,1,1,1,0\"/>\n      <wangtile tileid=\"161\" wangid=\"1,1,1,0,1,0,1,1\"/>\n      <wangtile tileid=\"162\" wangid=\"1,0,1,0,1,1,1,1\"/>\n      <wangtile tileid=\"163\" wangid=\"1,1,1,1,1,0,1,0\"/>\n      <wangtile tileid=\"164\" wangid=\"1,0,1,1,1,0,1,1\"/>\n      <wangtile tileid=\"165\" wangid=\"1,1,1,0,1,1,1,0\"/>\n      <wangtile tileid=\"166\" wangid=\"1,0,1,0,1,0,1,0\"/>\n      <wangtile tileid=\"193\" wangid=\"0,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"194\" wangid=\"0,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"195\" wangid=\"0,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"196\" wangid=\"0,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"197\" wangid=\"0,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"198\" wangid=\"0,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"199\" wangid=\"0,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"224\" wangid=\"0,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"225\" wangid=\"0,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"226\" wangid=\"2,0,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"227\" wangid=\"0,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"228\" wangid=\"2,0,0,0,2,0,0,0\"/>\n      <wangtile tileid=\"229\" wangid=\"2,2,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"230\" wangid=\"2,2,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"231\" wangid=\"2,0,0,0,2,2,2,2\"/>\n      <wangtile tileid=\"256\" wangid=\"2,0,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"257\" wangid=\"2,0,0,0,0,0,2,0\"/>\n      <wangtile tileid=\"258\" wangid=\"2,0,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"259\" wangid=\"2,0,0,0,2,0,2,0\"/>\n      <wangtile tileid=\"260\" wangid=\"2,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"261\" wangid=\"2,2,2,0,0,0,0,0\"/>\n      <wangtile tileid=\"262\" wangid=\"2,2,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"263\" wangid=\"2,0,0,0,0,0,2,2\"/>\n      <wangtile tileid=\"288\" wangid=\"2,2,2,0,2,0,0,0\"/>\n      <wangtile tileid=\"289\" wangid=\"2,0,0,0,2,0,2,2\"/>\n      <wangtile tileid=\"290\" wangid=\"0,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"291\" wangid=\"0,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"292\" wangid=\"2,2,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"293\" wangid=\"2,2,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"294\" wangid=\"2,0,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"295\" wangid=\"2,2,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"320\" wangid=\"2,0,2,2,2,0,0,0\"/>\n      <wangtile tileid=\"321\" wangid=\"2,0,0,0,2,2,2,0\"/>\n      <wangtile tileid=\"322\" wangid=\"2,0,2,0,0,0,2,2\"/>\n      <wangtile tileid=\"323\" wangid=\"2,2,2,0,0,0,2,0\"/>\n      <wangtile tileid=\"324\" wangid=\"2,0,2,2,2,2,2,2\"/>\n      <wangtile tileid=\"325\" wangid=\"2,2,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"326\" wangid=\"2,0,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"327\" wangid=\"2,0,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"352\" wangid=\"2,0,2,2,2,2,2,0\"/>\n      <wangtile tileid=\"353\" wangid=\"2,2,2,0,2,0,2,2\"/>\n      <wangtile tileid=\"354\" wangid=\"2,0,2,0,2,2,2,2\"/>\n      <wangtile tileid=\"355\" wangid=\"2,2,2,2,2,0,2,0\"/>\n      <wangtile tileid=\"356\" wangid=\"2,0,2,2,2,0,2,2\"/>\n      <wangtile tileid=\"357\" wangid=\"2,2,2,0,2,2,2,0\"/>\n      <wangtile tileid=\"358\" wangid=\"2,0,2,0,2,0,2,0\"/>\n      <wangtile tileid=\"385\" wangid=\"0,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"386\" wangid=\"0,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"387\" wangid=\"0,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"388\" wangid=\"0,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"389\" wangid=\"0,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"390\" wangid=\"0,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"391\" wangid=\"0,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"416\" wangid=\"0,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"417\" wangid=\"0,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"418\" wangid=\"3,0,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"419\" wangid=\"0,0,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"420\" wangid=\"3,0,0,0,3,0,0,0\"/>\n      <wangtile tileid=\"421\" wangid=\"3,3,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"422\" wangid=\"3,3,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"423\" wangid=\"3,0,0,0,3,3,3,3\"/>\n      <wangtile tileid=\"448\" wangid=\"3,0,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"449\" wangid=\"3,0,0,0,0,0,3,0\"/>\n      <wangtile tileid=\"450\" wangid=\"3,0,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"451\" wangid=\"3,0,0,0,3,0,3,0\"/>\n      <wangtile tileid=\"452\" wangid=\"3,0,0,0,0,0,0,0\"/>\n      <wangtile tileid=\"453\" wangid=\"3,3,3,0,0,0,0,0\"/>\n      <wangtile tileid=\"454\" wangid=\"3,3,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"455\" wangid=\"3,0,0,0,0,0,3,3\"/>\n      <wangtile tileid=\"480\" wangid=\"3,3,3,0,3,0,0,0\"/>\n      <wangtile tileid=\"481\" wangid=\"3,0,0,0,3,0,3,3\"/>\n      <wangtile tileid=\"482\" wangid=\"0,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"483\" wangid=\"0,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"484\" wangid=\"3,3,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"485\" wangid=\"3,3,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"486\" wangid=\"3,0,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"487\" wangid=\"3,3,3,0,3,0,3,0\"/>\n      <wangtile tileid=\"512\" wangid=\"3,0,3,3,3,0,0,0\"/>\n      <wangtile tileid=\"513\" wangid=\"3,0,0,0,3,3,3,0\"/>\n      <wangtile tileid=\"514\" wangid=\"3,0,3,0,0,0,3,3\"/>\n      <wangtile tileid=\"515\" wangid=\"3,3,3,0,0,0,3,0\"/>\n      <wangtile tileid=\"516\" wangid=\"3,0,3,3,3,3,3,3\"/>\n      <wangtile tileid=\"517\" wangid=\"3,3,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"518\" wangid=\"3,0,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"519\" wangid=\"3,0,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"544\" wangid=\"3,0,3,3,3,3,3,0\"/>\n      <wangtile tileid=\"545\" wangid=\"3,3,3,0,3,0,3,3\"/>\n      <wangtile tileid=\"546\" wangid=\"3,0,3,0,3,3,3,3\"/>\n      <wangtile tileid=\"547\" wangid=\"3,3,3,3,3,0,3,0\"/>\n      <wangtile tileid=\"548\" wangid=\"3,0,3,3,3,0,3,3\"/>\n      <wangtile tileid=\"549\" wangid=\"3,3,3,0,3,3,3,0\"/>\n      <wangtile tileid=\"550\" wangid=\"3,0,3,0,3,0,3,0\"/>\n    </wangset>\n  </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[A]Water_pipo.tsx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[A]Water_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"3072\" columns=\"64\">\n <image source=\"[A]Water_pipo.png\" width=\"2048\" height=\"1536\"/>\n <tile id=\"0\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"0\" duration=\"100\"/>\n   <frame tileid=\"8\" duration=\"100\"/>\n   <frame tileid=\"16\" duration=\"100\"/>\n   <frame tileid=\"24\" duration=\"100\"/>\n   <frame tileid=\"32\" duration=\"100\"/>\n   <frame tileid=\"40\" duration=\"100\"/>\n   <frame tileid=\"48\" duration=\"100\"/>\n   <frame tileid=\"56\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1\" duration=\"100\"/>\n   <frame tileid=\"9\" duration=\"100\"/>\n   <frame tileid=\"17\" duration=\"100\"/>\n   <frame tileid=\"25\" duration=\"100\"/>\n   <frame tileid=\"33\" duration=\"100\"/>\n   <frame tileid=\"41\" duration=\"100\"/>\n   <frame tileid=\"49\" duration=\"100\"/>\n   <frame tileid=\"57\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2\" duration=\"100\"/>\n   <frame tileid=\"10\" duration=\"100\"/>\n   <frame tileid=\"18\" duration=\"100\"/>\n   <frame tileid=\"26\" duration=\"100\"/>\n   <frame tileid=\"34\" duration=\"100\"/>\n   <frame tileid=\"42\" duration=\"100\"/>\n   <frame tileid=\"50\" duration=\"100\"/>\n   <frame tileid=\"58\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3\" duration=\"100\"/>\n   <frame tileid=\"11\" duration=\"100\"/>\n   <frame tileid=\"19\" duration=\"100\"/>\n   <frame tileid=\"27\" duration=\"100\"/>\n   <frame tileid=\"35\" duration=\"100\"/>\n   <frame tileid=\"43\" duration=\"100\"/>\n   <frame tileid=\"51\" duration=\"100\"/>\n   <frame tileid=\"59\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"4\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"4\" duration=\"100\"/>\n   <frame tileid=\"12\" duration=\"100\"/>\n   <frame tileid=\"20\" duration=\"100\"/>\n   <frame tileid=\"28\" duration=\"100\"/>\n   <frame tileid=\"36\" duration=\"100\"/>\n   <frame tileid=\"44\" duration=\"100\"/>\n   <frame tileid=\"52\" duration=\"100\"/>\n   <frame tileid=\"60\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"5\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"5\" duration=\"100\"/>\n   <frame tileid=\"13\" duration=\"100\"/>\n   <frame tileid=\"21\" duration=\"100\"/>\n   <frame tileid=\"29\" duration=\"100\"/>\n   <frame tileid=\"37\" duration=\"100\"/>\n   <frame tileid=\"45\" duration=\"100\"/>\n   <frame tileid=\"53\" duration=\"100\"/>\n   <frame tileid=\"61\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"6\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"6\" duration=\"100\"/>\n   <frame tileid=\"14\" duration=\"100\"/>\n   <frame tileid=\"22\" duration=\"100\"/>\n   <frame tileid=\"30\" duration=\"100\"/>\n   <frame tileid=\"38\" duration=\"100\"/>\n   <frame tileid=\"46\" duration=\"100\"/>\n   <frame tileid=\"54\" duration=\"100\"/>\n   <frame tileid=\"62\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"7\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"7\" duration=\"100\"/>\n   <frame tileid=\"15\" duration=\"100\"/>\n   <frame tileid=\"23\" duration=\"100\"/>\n   <frame tileid=\"31\" duration=\"100\"/>\n   <frame tileid=\"39\" duration=\"100\"/>\n   <frame tileid=\"47\" duration=\"100\"/>\n   <frame tileid=\"55\" duration=\"100\"/>\n   <frame tileid=\"63\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"8\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"9\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"10\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"11\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"12\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"13\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"14\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"15\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"16\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"17\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"18\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"19\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"20\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"21\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"22\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"23\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"24\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"25\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"26\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"27\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"28\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"29\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"30\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"31\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"32\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"33\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"34\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"35\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"36\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"37\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"38\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"39\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"40\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"41\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"42\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"43\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"44\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"45\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"46\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"47\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"48\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"49\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"50\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"51\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"52\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"53\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"54\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"55\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"56\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"57\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"58\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"59\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"60\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"61\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"62\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"63\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"64\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"64\" duration=\"100\"/>\n   <frame tileid=\"72\" duration=\"100\"/>\n   <frame tileid=\"80\" duration=\"100\"/>\n   <frame tileid=\"88\" duration=\"100\"/>\n   <frame tileid=\"96\" duration=\"100\"/>\n   <frame tileid=\"104\" duration=\"100\"/>\n   <frame tileid=\"112\" duration=\"100\"/>\n   <frame tileid=\"120\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"65\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"65\" duration=\"100\"/>\n   <frame tileid=\"73\" duration=\"100\"/>\n   <frame tileid=\"81\" duration=\"100\"/>\n   <frame tileid=\"89\" duration=\"100\"/>\n   <frame tileid=\"97\" duration=\"100\"/>\n   <frame tileid=\"105\" duration=\"100\"/>\n   <frame tileid=\"113\" duration=\"100\"/>\n   <frame tileid=\"121\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"66\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"66\" duration=\"100\"/>\n   <frame tileid=\"74\" duration=\"100\"/>\n   <frame tileid=\"82\" duration=\"100\"/>\n   <frame tileid=\"90\" duration=\"100\"/>\n   <frame tileid=\"98\" duration=\"100\"/>\n   <frame tileid=\"106\" duration=\"100\"/>\n   <frame tileid=\"114\" duration=\"100\"/>\n   <frame tileid=\"122\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"67\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"67\" duration=\"100\"/>\n   <frame tileid=\"75\" duration=\"100\"/>\n   <frame tileid=\"83\" duration=\"100\"/>\n   <frame tileid=\"91\" duration=\"100\"/>\n   <frame tileid=\"99\" duration=\"100\"/>\n   <frame tileid=\"107\" duration=\"100\"/>\n   <frame tileid=\"115\" duration=\"100\"/>\n   <frame tileid=\"123\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"68\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"68\" duration=\"100\"/>\n   <frame tileid=\"76\" duration=\"100\"/>\n   <frame tileid=\"84\" duration=\"100\"/>\n   <frame tileid=\"92\" duration=\"100\"/>\n   <frame tileid=\"100\" duration=\"100\"/>\n   <frame tileid=\"108\" duration=\"100\"/>\n   <frame tileid=\"116\" duration=\"100\"/>\n   <frame tileid=\"124\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"69\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"69\" duration=\"100\"/>\n   <frame tileid=\"77\" duration=\"100\"/>\n   <frame tileid=\"85\" duration=\"100\"/>\n   <frame tileid=\"93\" duration=\"100\"/>\n   <frame tileid=\"101\" duration=\"100\"/>\n   <frame tileid=\"109\" duration=\"100\"/>\n   <frame tileid=\"117\" duration=\"100\"/>\n   <frame tileid=\"125\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"70\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"70\" duration=\"100\"/>\n   <frame tileid=\"78\" duration=\"100\"/>\n   <frame tileid=\"86\" duration=\"100\"/>\n   <frame tileid=\"94\" duration=\"100\"/>\n   <frame tileid=\"102\" duration=\"100\"/>\n   <frame tileid=\"110\" duration=\"100\"/>\n   <frame tileid=\"118\" duration=\"100\"/>\n   <frame tileid=\"126\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"71\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"71\" duration=\"100\"/>\n   <frame tileid=\"79\" duration=\"100\"/>\n   <frame tileid=\"87\" duration=\"100\"/>\n   <frame tileid=\"95\" duration=\"100\"/>\n   <frame tileid=\"103\" duration=\"100\"/>\n   <frame tileid=\"111\" duration=\"100\"/>\n   <frame tileid=\"119\" duration=\"100\"/>\n   <frame tileid=\"127\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"72\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"73\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"74\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"75\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"76\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"77\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"78\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"79\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"80\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"81\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"82\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"83\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"84\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"85\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"86\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"87\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"88\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"89\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"90\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"91\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"92\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"93\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"94\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"95\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"96\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"97\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"98\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"99\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"121\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"128\" duration=\"100\"/>\n   <frame tileid=\"136\" duration=\"100\"/>\n   <frame tileid=\"144\" duration=\"100\"/>\n   <frame tileid=\"152\" duration=\"100\"/>\n   <frame tileid=\"160\" duration=\"100\"/>\n   <frame tileid=\"168\" duration=\"100\"/>\n   <frame tileid=\"176\" duration=\"100\"/>\n   <frame tileid=\"184\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"129\" duration=\"100\"/>\n   <frame tileid=\"137\" duration=\"100\"/>\n   <frame tileid=\"145\" duration=\"100\"/>\n   <frame tileid=\"153\" duration=\"100\"/>\n   <frame tileid=\"161\" duration=\"100\"/>\n   <frame tileid=\"169\" duration=\"100\"/>\n   <frame tileid=\"177\" duration=\"100\"/>\n   <frame tileid=\"185\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"130\" duration=\"100\"/>\n   <frame tileid=\"138\" duration=\"100\"/>\n   <frame tileid=\"146\" duration=\"100\"/>\n   <frame tileid=\"154\" duration=\"100\"/>\n   <frame tileid=\"162\" duration=\"100\"/>\n   <frame tileid=\"170\" duration=\"100\"/>\n   <frame tileid=\"178\" duration=\"100\"/>\n   <frame tileid=\"186\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"131\" duration=\"100\"/>\n   <frame tileid=\"139\" duration=\"100\"/>\n   <frame tileid=\"147\" duration=\"100\"/>\n   <frame tileid=\"155\" duration=\"100\"/>\n   <frame tileid=\"163\" duration=\"100\"/>\n   <frame tileid=\"171\" duration=\"100\"/>\n   <frame tileid=\"179\" duration=\"100\"/>\n   <frame tileid=\"187\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"132\" duration=\"100\"/>\n   <frame tileid=\"140\" duration=\"100\"/>\n   <frame tileid=\"148\" duration=\"100\"/>\n   <frame tileid=\"156\" duration=\"100\"/>\n   <frame tileid=\"164\" duration=\"100\"/>\n   <frame tileid=\"172\" duration=\"100\"/>\n   <frame tileid=\"180\" duration=\"100\"/>\n   <frame tileid=\"188\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"133\" duration=\"100\"/>\n   <frame tileid=\"141\" duration=\"100\"/>\n   <frame tileid=\"149\" duration=\"100\"/>\n   <frame tileid=\"157\" duration=\"100\"/>\n   <frame tileid=\"165\" duration=\"100\"/>\n   <frame tileid=\"173\" duration=\"100\"/>\n   <frame tileid=\"181\" duration=\"100\"/>\n   <frame tileid=\"189\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"134\" duration=\"100\"/>\n   <frame tileid=\"142\" duration=\"100\"/>\n   <frame tileid=\"150\" duration=\"100\"/>\n   <frame tileid=\"158\" duration=\"100\"/>\n   <frame tileid=\"166\" duration=\"100\"/>\n   <frame tileid=\"174\" duration=\"100\"/>\n   <frame tileid=\"182\" duration=\"100\"/>\n   <frame tileid=\"190\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"135\" duration=\"100\"/>\n   <frame tileid=\"143\" duration=\"100\"/>\n   <frame tileid=\"151\" duration=\"100\"/>\n   <frame tileid=\"159\" duration=\"100\"/>\n   <frame tileid=\"167\" duration=\"100\"/>\n   <frame tileid=\"175\" duration=\"100\"/>\n   <frame tileid=\"183\" duration=\"100\"/>\n   <frame tileid=\"191\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"141\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"192\" duration=\"100\"/>\n   <frame tileid=\"200\" duration=\"100\"/>\n   <frame tileid=\"208\" duration=\"100\"/>\n   <frame tileid=\"216\" duration=\"100\"/>\n   <frame tileid=\"224\" duration=\"100\"/>\n   <frame tileid=\"232\" duration=\"100\"/>\n   <frame tileid=\"240\" duration=\"100\"/>\n   <frame tileid=\"248\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"193\" duration=\"100\"/>\n   <frame tileid=\"201\" duration=\"100\"/>\n   <frame tileid=\"209\" duration=\"100\"/>\n   <frame tileid=\"217\" duration=\"100\"/>\n   <frame tileid=\"225\" duration=\"100\"/>\n   <frame tileid=\"233\" duration=\"100\"/>\n   <frame tileid=\"241\" duration=\"100\"/>\n   <frame tileid=\"249\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"194\" duration=\"100\"/>\n   <frame tileid=\"202\" duration=\"100\"/>\n   <frame tileid=\"210\" duration=\"100\"/>\n   <frame tileid=\"218\" duration=\"100\"/>\n   <frame tileid=\"226\" duration=\"100\"/>\n   <frame tileid=\"234\" duration=\"100\"/>\n   <frame tileid=\"242\" duration=\"100\"/>\n   <frame tileid=\"250\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"195\" duration=\"100\"/>\n   <frame tileid=\"203\" duration=\"100\"/>\n   <frame tileid=\"211\" duration=\"100\"/>\n   <frame tileid=\"219\" duration=\"100\"/>\n   <frame tileid=\"227\" duration=\"100\"/>\n   <frame tileid=\"235\" duration=\"100\"/>\n   <frame tileid=\"243\" duration=\"100\"/>\n   <frame tileid=\"251\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"196\" duration=\"100\"/>\n   <frame tileid=\"204\" duration=\"100\"/>\n   <frame tileid=\"212\" duration=\"100\"/>\n   <frame tileid=\"220\" duration=\"100\"/>\n   <frame tileid=\"228\" duration=\"100\"/>\n   <frame tileid=\"236\" duration=\"100\"/>\n   <frame tileid=\"244\" duration=\"100\"/>\n   <frame tileid=\"252\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"197\" duration=\"100\"/>\n   <frame tileid=\"205\" duration=\"100\"/>\n   <frame tileid=\"213\" duration=\"100\"/>\n   <frame tileid=\"221\" duration=\"100\"/>\n   <frame tileid=\"229\" duration=\"100\"/>\n   <frame tileid=\"237\" duration=\"100\"/>\n   <frame tileid=\"245\" duration=\"100\"/>\n   <frame tileid=\"253\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"198\" duration=\"100\"/>\n   <frame tileid=\"206\" duration=\"100\"/>\n   <frame tileid=\"214\" duration=\"100\"/>\n   <frame tileid=\"222\" duration=\"100\"/>\n   <frame tileid=\"230\" duration=\"100\"/>\n   <frame tileid=\"238\" duration=\"100\"/>\n   <frame tileid=\"246\" duration=\"100\"/>\n   <frame tileid=\"254\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"199\" duration=\"100\"/>\n   <frame tileid=\"207\" duration=\"100\"/>\n   <frame tileid=\"215\" duration=\"100\"/>\n   <frame tileid=\"223\" duration=\"100\"/>\n   <frame tileid=\"231\" duration=\"100\"/>\n   <frame tileid=\"239\" duration=\"100\"/>\n   <frame tileid=\"247\" duration=\"100\"/>\n   <frame tileid=\"255\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"256\" duration=\"100\"/>\n   <frame tileid=\"264\" duration=\"100\"/>\n   <frame tileid=\"272\" duration=\"100\"/>\n   <frame tileid=\"280\" duration=\"100\"/>\n   <frame tileid=\"288\" duration=\"100\"/>\n   <frame tileid=\"296\" duration=\"100\"/>\n   <frame tileid=\"304\" duration=\"100\"/>\n   <frame tileid=\"312\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"257\" duration=\"100\"/>\n   <frame tileid=\"265\" duration=\"100\"/>\n   <frame tileid=\"273\" duration=\"100\"/>\n   <frame tileid=\"281\" duration=\"100\"/>\n   <frame tileid=\"289\" duration=\"100\"/>\n   <frame tileid=\"297\" duration=\"100\"/>\n   <frame tileid=\"305\" duration=\"100\"/>\n   <frame tileid=\"313\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"258\" duration=\"100\"/>\n   <frame tileid=\"266\" duration=\"100\"/>\n   <frame tileid=\"274\" duration=\"100\"/>\n   <frame tileid=\"282\" duration=\"100\"/>\n   <frame tileid=\"290\" duration=\"100\"/>\n   <frame tileid=\"298\" duration=\"100\"/>\n   <frame tileid=\"306\" duration=\"100\"/>\n   <frame tileid=\"314\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"259\" duration=\"100\"/>\n   <frame tileid=\"267\" duration=\"100\"/>\n   <frame tileid=\"275\" duration=\"100\"/>\n   <frame tileid=\"283\" duration=\"100\"/>\n   <frame tileid=\"291\" duration=\"100\"/>\n   <frame tileid=\"299\" duration=\"100\"/>\n   <frame tileid=\"307\" duration=\"100\"/>\n   <frame tileid=\"315\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"260\" duration=\"100\"/>\n   <frame tileid=\"268\" duration=\"100\"/>\n   <frame tileid=\"276\" duration=\"100\"/>\n   <frame tileid=\"284\" duration=\"100\"/>\n   <frame tileid=\"292\" duration=\"100\"/>\n   <frame tileid=\"300\" duration=\"100\"/>\n   <frame tileid=\"308\" duration=\"100\"/>\n   <frame tileid=\"316\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"261\" duration=\"100\"/>\n   <frame tileid=\"269\" duration=\"100\"/>\n   <frame tileid=\"277\" duration=\"100\"/>\n   <frame tileid=\"285\" duration=\"100\"/>\n   <frame tileid=\"293\" duration=\"100\"/>\n   <frame tileid=\"301\" duration=\"100\"/>\n   <frame tileid=\"309\" duration=\"100\"/>\n   <frame tileid=\"317\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"262\" duration=\"100\"/>\n   <frame tileid=\"270\" duration=\"100\"/>\n   <frame tileid=\"278\" duration=\"100\"/>\n   <frame tileid=\"286\" duration=\"100\"/>\n   <frame tileid=\"294\" duration=\"100\"/>\n   <frame tileid=\"302\" duration=\"100\"/>\n   <frame tileid=\"310\" duration=\"100\"/>\n   <frame tileid=\"318\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"263\" duration=\"100\"/>\n   <frame tileid=\"271\" duration=\"100\"/>\n   <frame tileid=\"279\" duration=\"100\"/>\n   <frame tileid=\"287\" duration=\"100\"/>\n   <frame tileid=\"295\" duration=\"100\"/>\n   <frame tileid=\"303\" duration=\"100\"/>\n   <frame tileid=\"311\" duration=\"100\"/>\n   <frame tileid=\"319\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"320\" duration=\"100\"/>\n   <frame tileid=\"328\" duration=\"100\"/>\n   <frame tileid=\"336\" duration=\"100\"/>\n   <frame tileid=\"344\" duration=\"100\"/>\n   <frame tileid=\"352\" duration=\"100\"/>\n   <frame tileid=\"360\" duration=\"100\"/>\n   <frame tileid=\"368\" duration=\"100\"/>\n   <frame tileid=\"376\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"321\" duration=\"100\"/>\n   <frame tileid=\"329\" duration=\"100\"/>\n   <frame tileid=\"337\" duration=\"100\"/>\n   <frame tileid=\"345\" duration=\"100\"/>\n   <frame tileid=\"353\" duration=\"100\"/>\n   <frame tileid=\"361\" duration=\"100\"/>\n   <frame tileid=\"369\" duration=\"100\"/>\n   <frame tileid=\"377\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"322\" duration=\"100\"/>\n   <frame tileid=\"330\" duration=\"100\"/>\n   <frame tileid=\"338\" duration=\"100\"/>\n   <frame tileid=\"346\" duration=\"100\"/>\n   <frame tileid=\"354\" duration=\"100\"/>\n   <frame tileid=\"362\" duration=\"100\"/>\n   <frame tileid=\"370\" duration=\"100\"/>\n   <frame tileid=\"378\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"323\" duration=\"100\"/>\n   <frame tileid=\"331\" duration=\"100\"/>\n   <frame tileid=\"339\" duration=\"100\"/>\n   <frame tileid=\"347\" duration=\"100\"/>\n   <frame tileid=\"355\" duration=\"100\"/>\n   <frame tileid=\"363\" duration=\"100\"/>\n   <frame tileid=\"371\" duration=\"100\"/>\n   <frame tileid=\"379\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"324\" duration=\"100\"/>\n   <frame tileid=\"332\" duration=\"100\"/>\n   <frame tileid=\"340\" duration=\"100\"/>\n   <frame tileid=\"348\" duration=\"100\"/>\n   <frame tileid=\"356\" duration=\"100\"/>\n   <frame tileid=\"364\" duration=\"100\"/>\n   <frame tileid=\"372\" duration=\"100\"/>\n   <frame tileid=\"380\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"325\" duration=\"100\"/>\n   <frame tileid=\"333\" duration=\"100\"/>\n   <frame tileid=\"341\" duration=\"100\"/>\n   <frame tileid=\"349\" duration=\"100\"/>\n   <frame tileid=\"357\" duration=\"100\"/>\n   <frame tileid=\"365\" duration=\"100\"/>\n   <frame tileid=\"373\" duration=\"100\"/>\n   <frame tileid=\"381\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"326\" duration=\"100\"/>\n   <frame tileid=\"334\" duration=\"100\"/>\n   <frame tileid=\"342\" duration=\"100\"/>\n   <frame tileid=\"350\" duration=\"100\"/>\n   <frame tileid=\"358\" duration=\"100\"/>\n   <frame tileid=\"366\" duration=\"100\"/>\n   <frame tileid=\"374\" duration=\"100\"/>\n   <frame tileid=\"382\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"327\" duration=\"100\"/>\n   <frame tileid=\"335\" duration=\"100\"/>\n   <frame tileid=\"343\" duration=\"100\"/>\n   <frame tileid=\"351\" duration=\"100\"/>\n   <frame tileid=\"359\" duration=\"100\"/>\n   <frame tileid=\"367\" duration=\"100\"/>\n   <frame tileid=\"375\" duration=\"100\"/>\n   <frame tileid=\"383\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"384\" duration=\"100\"/>\n   <frame tileid=\"392\" duration=\"100\"/>\n   <frame tileid=\"400\" duration=\"100\"/>\n   <frame tileid=\"408\" duration=\"100\"/>\n   <frame tileid=\"416\" duration=\"100\"/>\n   <frame tileid=\"424\" duration=\"100\"/>\n   <frame tileid=\"432\" duration=\"100\"/>\n   <frame tileid=\"440\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"385\" duration=\"100\"/>\n   <frame tileid=\"393\" duration=\"100\"/>\n   <frame tileid=\"401\" duration=\"100\"/>\n   <frame tileid=\"409\" duration=\"100\"/>\n   <frame tileid=\"417\" duration=\"100\"/>\n   <frame tileid=\"425\" duration=\"100\"/>\n   <frame tileid=\"433\" duration=\"100\"/>\n   <frame tileid=\"441\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"386\" duration=\"100\"/>\n   <frame tileid=\"394\" duration=\"100\"/>\n   <frame tileid=\"402\" duration=\"100\"/>\n   <frame tileid=\"410\" duration=\"100\"/>\n   <frame tileid=\"418\" duration=\"100\"/>\n   <frame tileid=\"426\" duration=\"100\"/>\n   <frame tileid=\"434\" duration=\"100\"/>\n   <frame tileid=\"442\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"387\" duration=\"100\"/>\n   <frame tileid=\"395\" duration=\"100\"/>\n   <frame tileid=\"403\" duration=\"100\"/>\n   <frame tileid=\"411\" duration=\"100\"/>\n   <frame tileid=\"419\" duration=\"100\"/>\n   <frame tileid=\"427\" duration=\"100\"/>\n   <frame tileid=\"435\" duration=\"100\"/>\n   <frame tileid=\"443\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"388\" duration=\"100\"/>\n   <frame tileid=\"396\" duration=\"100\"/>\n   <frame tileid=\"404\" duration=\"100\"/>\n   <frame tileid=\"412\" duration=\"100\"/>\n   <frame tileid=\"420\" duration=\"100\"/>\n   <frame tileid=\"428\" duration=\"100\"/>\n   <frame tileid=\"436\" duration=\"100\"/>\n   <frame tileid=\"444\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"389\" duration=\"100\"/>\n   <frame tileid=\"397\" duration=\"100\"/>\n   <frame tileid=\"405\" duration=\"100\"/>\n   <frame tileid=\"413\" duration=\"100\"/>\n   <frame tileid=\"421\" duration=\"100\"/>\n   <frame tileid=\"429\" duration=\"100\"/>\n   <frame tileid=\"437\" duration=\"100\"/>\n   <frame tileid=\"445\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"390\" duration=\"100\"/>\n   <frame tileid=\"398\" duration=\"100\"/>\n   <frame tileid=\"406\" duration=\"100\"/>\n   <frame tileid=\"414\" duration=\"100\"/>\n   <frame tileid=\"422\" duration=\"100\"/>\n   <frame tileid=\"430\" duration=\"100\"/>\n   <frame tileid=\"438\" duration=\"100\"/>\n   <frame tileid=\"446\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"391\" duration=\"100\"/>\n   <frame tileid=\"399\" duration=\"100\"/>\n   <frame tileid=\"407\" duration=\"100\"/>\n   <frame tileid=\"415\" duration=\"100\"/>\n   <frame tileid=\"423\" duration=\"100\"/>\n   <frame tileid=\"431\" duration=\"100\"/>\n   <frame tileid=\"439\" duration=\"100\"/>\n   <frame tileid=\"447\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"448\" duration=\"100\"/>\n   <frame tileid=\"456\" duration=\"100\"/>\n   <frame tileid=\"464\" duration=\"100\"/>\n   <frame tileid=\"472\" duration=\"100\"/>\n   <frame tileid=\"480\" duration=\"100\"/>\n   <frame tileid=\"488\" duration=\"100\"/>\n   <frame tileid=\"496\" duration=\"100\"/>\n   <frame tileid=\"504\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"449\" duration=\"100\"/>\n   <frame tileid=\"457\" duration=\"100\"/>\n   <frame tileid=\"465\" duration=\"100\"/>\n   <frame tileid=\"473\" duration=\"100\"/>\n   <frame tileid=\"481\" duration=\"100\"/>\n   <frame tileid=\"489\" duration=\"100\"/>\n   <frame tileid=\"497\" duration=\"100\"/>\n   <frame tileid=\"505\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"450\" duration=\"100\"/>\n   <frame tileid=\"458\" duration=\"100\"/>\n   <frame tileid=\"466\" duration=\"100\"/>\n   <frame tileid=\"474\" duration=\"100\"/>\n   <frame tileid=\"482\" duration=\"100\"/>\n   <frame tileid=\"490\" duration=\"100\"/>\n   <frame tileid=\"498\" duration=\"100\"/>\n   <frame tileid=\"506\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"451\" duration=\"100\"/>\n   <frame tileid=\"459\" duration=\"100\"/>\n   <frame tileid=\"467\" duration=\"100\"/>\n   <frame tileid=\"475\" duration=\"100\"/>\n   <frame tileid=\"483\" duration=\"100\"/>\n   <frame tileid=\"491\" duration=\"100\"/>\n   <frame tileid=\"499\" duration=\"100\"/>\n   <frame tileid=\"507\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"452\" duration=\"100\"/>\n   <frame tileid=\"460\" duration=\"100\"/>\n   <frame tileid=\"468\" duration=\"100\"/>\n   <frame tileid=\"476\" duration=\"100\"/>\n   <frame tileid=\"484\" duration=\"100\"/>\n   <frame tileid=\"492\" duration=\"100\"/>\n   <frame tileid=\"500\" duration=\"100\"/>\n   <frame tileid=\"508\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"453\" duration=\"100\"/>\n   <frame tileid=\"461\" duration=\"100\"/>\n   <frame tileid=\"469\" duration=\"100\"/>\n   <frame tileid=\"477\" duration=\"100\"/>\n   <frame tileid=\"485\" duration=\"100\"/>\n   <frame tileid=\"493\" duration=\"100\"/>\n   <frame tileid=\"501\" duration=\"100\"/>\n   <frame tileid=\"509\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"454\" duration=\"100\"/>\n   <frame tileid=\"462\" duration=\"100\"/>\n   <frame tileid=\"470\" duration=\"100\"/>\n   <frame tileid=\"478\" duration=\"100\"/>\n   <frame tileid=\"486\" duration=\"100\"/>\n   <frame tileid=\"494\" duration=\"100\"/>\n   <frame tileid=\"502\" duration=\"100\"/>\n   <frame tileid=\"510\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"455\" duration=\"100\"/>\n   <frame tileid=\"463\" duration=\"100\"/>\n   <frame tileid=\"471\" duration=\"100\"/>\n   <frame tileid=\"479\" duration=\"100\"/>\n   <frame tileid=\"487\" duration=\"100\"/>\n   <frame tileid=\"495\" duration=\"100\"/>\n   <frame tileid=\"503\" duration=\"100\"/>\n   <frame tileid=\"511\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"512\" duration=\"100\"/>\n   <frame tileid=\"520\" duration=\"100\"/>\n   <frame tileid=\"528\" duration=\"100\"/>\n   <frame tileid=\"536\" duration=\"100\"/>\n   <frame tileid=\"544\" duration=\"100\"/>\n   <frame tileid=\"552\" duration=\"100\"/>\n   <frame tileid=\"560\" duration=\"100\"/>\n   <frame tileid=\"568\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"513\" duration=\"100\"/>\n   <frame tileid=\"521\" duration=\"100\"/>\n   <frame tileid=\"529\" duration=\"100\"/>\n   <frame tileid=\"537\" duration=\"100\"/>\n   <frame tileid=\"545\" duration=\"100\"/>\n   <frame tileid=\"553\" duration=\"100\"/>\n   <frame tileid=\"561\" duration=\"100\"/>\n   <frame tileid=\"569\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"514\" duration=\"100\"/>\n   <frame tileid=\"522\" duration=\"100\"/>\n   <frame tileid=\"530\" duration=\"100\"/>\n   <frame tileid=\"538\" duration=\"100\"/>\n   <frame tileid=\"546\" duration=\"100\"/>\n   <frame tileid=\"554\" duration=\"100\"/>\n   <frame tileid=\"562\" duration=\"100\"/>\n   <frame tileid=\"570\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"515\" duration=\"100\"/>\n   <frame tileid=\"523\" duration=\"100\"/>\n   <frame tileid=\"531\" duration=\"100\"/>\n   <frame tileid=\"539\" duration=\"100\"/>\n   <frame tileid=\"547\" duration=\"100\"/>\n   <frame tileid=\"555\" duration=\"100\"/>\n   <frame tileid=\"563\" duration=\"100\"/>\n   <frame tileid=\"571\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"516\" duration=\"100\"/>\n   <frame tileid=\"524\" duration=\"100\"/>\n   <frame tileid=\"532\" duration=\"100\"/>\n   <frame tileid=\"540\" duration=\"100\"/>\n   <frame tileid=\"548\" duration=\"100\"/>\n   <frame tileid=\"556\" duration=\"100\"/>\n   <frame tileid=\"564\" duration=\"100\"/>\n   <frame tileid=\"572\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"517\" duration=\"100\"/>\n   <frame tileid=\"525\" duration=\"100\"/>\n   <frame tileid=\"533\" duration=\"100\"/>\n   <frame tileid=\"541\" duration=\"100\"/>\n   <frame tileid=\"549\" duration=\"100\"/>\n   <frame tileid=\"557\" duration=\"100\"/>\n   <frame tileid=\"565\" duration=\"100\"/>\n   <frame tileid=\"573\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"518\" duration=\"100\"/>\n   <frame tileid=\"526\" duration=\"100\"/>\n   <frame tileid=\"534\" duration=\"100\"/>\n   <frame tileid=\"542\" duration=\"100\"/>\n   <frame tileid=\"550\" duration=\"100\"/>\n   <frame tileid=\"558\" duration=\"100\"/>\n   <frame tileid=\"566\" duration=\"100\"/>\n   <frame tileid=\"574\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"519\" duration=\"100\"/>\n   <frame tileid=\"527\" duration=\"100\"/>\n   <frame tileid=\"535\" duration=\"100\"/>\n   <frame tileid=\"543\" duration=\"100\"/>\n   <frame tileid=\"551\" duration=\"100\"/>\n   <frame tileid=\"559\" duration=\"100\"/>\n   <frame tileid=\"567\" duration=\"100\"/>\n   <frame tileid=\"575\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"576\" duration=\"100\"/>\n   <frame tileid=\"584\" duration=\"100\"/>\n   <frame tileid=\"592\" duration=\"100\"/>\n   <frame tileid=\"600\" duration=\"100\"/>\n   <frame tileid=\"608\" duration=\"100\"/>\n   <frame tileid=\"616\" duration=\"100\"/>\n   <frame tileid=\"624\" duration=\"100\"/>\n   <frame tileid=\"632\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"577\" duration=\"100\"/>\n   <frame tileid=\"585\" duration=\"100\"/>\n   <frame tileid=\"593\" duration=\"100\"/>\n   <frame tileid=\"601\" duration=\"100\"/>\n   <frame tileid=\"609\" duration=\"100\"/>\n   <frame tileid=\"617\" duration=\"100\"/>\n   <frame tileid=\"625\" duration=\"100\"/>\n   <frame tileid=\"633\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"578\" duration=\"100\"/>\n   <frame tileid=\"586\" duration=\"100\"/>\n   <frame tileid=\"594\" duration=\"100\"/>\n   <frame tileid=\"602\" duration=\"100\"/>\n   <frame tileid=\"610\" duration=\"100\"/>\n   <frame tileid=\"618\" duration=\"100\"/>\n   <frame tileid=\"626\" duration=\"100\"/>\n   <frame tileid=\"634\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"579\" duration=\"100\"/>\n   <frame tileid=\"587\" duration=\"100\"/>\n   <frame tileid=\"595\" duration=\"100\"/>\n   <frame tileid=\"603\" duration=\"100\"/>\n   <frame tileid=\"611\" duration=\"100\"/>\n   <frame tileid=\"619\" duration=\"100\"/>\n   <frame tileid=\"627\" duration=\"100\"/>\n   <frame tileid=\"635\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"580\" duration=\"100\"/>\n   <frame tileid=\"588\" duration=\"100\"/>\n   <frame tileid=\"596\" duration=\"100\"/>\n   <frame tileid=\"604\" duration=\"100\"/>\n   <frame tileid=\"612\" duration=\"100\"/>\n   <frame tileid=\"620\" duration=\"100\"/>\n   <frame tileid=\"628\" duration=\"100\"/>\n   <frame tileid=\"636\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"581\" duration=\"100\"/>\n   <frame tileid=\"589\" duration=\"100\"/>\n   <frame tileid=\"597\" duration=\"100\"/>\n   <frame tileid=\"605\" duration=\"100\"/>\n   <frame tileid=\"613\" duration=\"100\"/>\n   <frame tileid=\"621\" duration=\"100\"/>\n   <frame tileid=\"629\" duration=\"100\"/>\n   <frame tileid=\"637\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"582\" duration=\"100\"/>\n   <frame tileid=\"590\" duration=\"100\"/>\n   <frame tileid=\"598\" duration=\"100\"/>\n   <frame tileid=\"606\" duration=\"100\"/>\n   <frame tileid=\"614\" duration=\"100\"/>\n   <frame tileid=\"622\" duration=\"100\"/>\n   <frame tileid=\"630\" duration=\"100\"/>\n   <frame tileid=\"638\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"583\" duration=\"100\"/>\n   <frame tileid=\"591\" duration=\"100\"/>\n   <frame tileid=\"599\" duration=\"100\"/>\n   <frame tileid=\"607\" duration=\"100\"/>\n   <frame tileid=\"615\" duration=\"100\"/>\n   <frame tileid=\"623\" duration=\"100\"/>\n   <frame tileid=\"631\" duration=\"100\"/>\n   <frame tileid=\"639\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"640\" duration=\"100\"/>\n   <frame tileid=\"648\" duration=\"100\"/>\n   <frame tileid=\"656\" duration=\"100\"/>\n   <frame tileid=\"664\" duration=\"100\"/>\n   <frame tileid=\"672\" duration=\"100\"/>\n   <frame tileid=\"680\" duration=\"100\"/>\n   <frame tileid=\"688\" duration=\"100\"/>\n   <frame tileid=\"696\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"641\" duration=\"100\"/>\n   <frame tileid=\"649\" duration=\"100\"/>\n   <frame tileid=\"657\" duration=\"100\"/>\n   <frame tileid=\"665\" duration=\"100\"/>\n   <frame tileid=\"673\" duration=\"100\"/>\n   <frame tileid=\"681\" duration=\"100\"/>\n   <frame tileid=\"689\" duration=\"100\"/>\n   <frame tileid=\"697\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"642\" duration=\"100\"/>\n   <frame tileid=\"650\" duration=\"100\"/>\n   <frame tileid=\"658\" duration=\"100\"/>\n   <frame tileid=\"666\" duration=\"100\"/>\n   <frame tileid=\"674\" duration=\"100\"/>\n   <frame tileid=\"682\" duration=\"100\"/>\n   <frame tileid=\"690\" duration=\"100\"/>\n   <frame tileid=\"698\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"643\" duration=\"100\"/>\n   <frame tileid=\"651\" duration=\"100\"/>\n   <frame tileid=\"659\" duration=\"100\"/>\n   <frame tileid=\"667\" duration=\"100\"/>\n   <frame tileid=\"675\" duration=\"100\"/>\n   <frame tileid=\"683\" duration=\"100\"/>\n   <frame tileid=\"691\" duration=\"100\"/>\n   <frame tileid=\"699\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"644\" duration=\"100\"/>\n   <frame tileid=\"652\" duration=\"100\"/>\n   <frame tileid=\"660\" duration=\"100\"/>\n   <frame tileid=\"668\" duration=\"100\"/>\n   <frame tileid=\"676\" duration=\"100\"/>\n   <frame tileid=\"684\" duration=\"100\"/>\n   <frame tileid=\"692\" duration=\"100\"/>\n   <frame tileid=\"700\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"645\" duration=\"100\"/>\n   <frame tileid=\"653\" duration=\"100\"/>\n   <frame tileid=\"661\" duration=\"100\"/>\n   <frame tileid=\"669\" duration=\"100\"/>\n   <frame tileid=\"677\" duration=\"100\"/>\n   <frame tileid=\"685\" duration=\"100\"/>\n   <frame tileid=\"693\" duration=\"100\"/>\n   <frame tileid=\"701\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"646\" duration=\"100\"/>\n   <frame tileid=\"654\" duration=\"100\"/>\n   <frame tileid=\"662\" duration=\"100\"/>\n   <frame tileid=\"670\" duration=\"100\"/>\n   <frame tileid=\"678\" duration=\"100\"/>\n   <frame tileid=\"686\" duration=\"100\"/>\n   <frame tileid=\"694\" duration=\"100\"/>\n   <frame tileid=\"702\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"647\" duration=\"100\"/>\n   <frame tileid=\"655\" duration=\"100\"/>\n   <frame tileid=\"663\" duration=\"100\"/>\n   <frame tileid=\"671\" duration=\"100\"/>\n   <frame tileid=\"679\" duration=\"100\"/>\n   <frame tileid=\"687\" duration=\"100\"/>\n   <frame tileid=\"695\" duration=\"100\"/>\n   <frame tileid=\"703\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"704\" duration=\"100\"/>\n   <frame tileid=\"712\" duration=\"100\"/>\n   <frame tileid=\"720\" duration=\"100\"/>\n   <frame tileid=\"728\" duration=\"100\"/>\n   <frame tileid=\"736\" duration=\"100\"/>\n   <frame tileid=\"744\" duration=\"100\"/>\n   <frame tileid=\"752\" duration=\"100\"/>\n   <frame tileid=\"760\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"705\" duration=\"100\"/>\n   <frame tileid=\"713\" duration=\"100\"/>\n   <frame tileid=\"721\" duration=\"100\"/>\n   <frame tileid=\"729\" duration=\"100\"/>\n   <frame tileid=\"737\" duration=\"100\"/>\n   <frame tileid=\"745\" duration=\"100\"/>\n   <frame tileid=\"753\" duration=\"100\"/>\n   <frame tileid=\"761\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"706\" duration=\"100\"/>\n   <frame tileid=\"714\" duration=\"100\"/>\n   <frame tileid=\"722\" duration=\"100\"/>\n   <frame tileid=\"730\" duration=\"100\"/>\n   <frame tileid=\"738\" duration=\"100\"/>\n   <frame tileid=\"746\" duration=\"100\"/>\n   <frame tileid=\"754\" duration=\"100\"/>\n   <frame tileid=\"762\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"707\" duration=\"100\"/>\n   <frame tileid=\"715\" duration=\"100\"/>\n   <frame tileid=\"723\" duration=\"100\"/>\n   <frame tileid=\"731\" duration=\"100\"/>\n   <frame tileid=\"739\" duration=\"100\"/>\n   <frame tileid=\"747\" duration=\"100\"/>\n   <frame tileid=\"755\" duration=\"100\"/>\n   <frame tileid=\"763\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"708\" duration=\"100\"/>\n   <frame tileid=\"716\" duration=\"100\"/>\n   <frame tileid=\"724\" duration=\"100\"/>\n   <frame tileid=\"732\" duration=\"100\"/>\n   <frame tileid=\"740\" duration=\"100\"/>\n   <frame tileid=\"748\" duration=\"100\"/>\n   <frame tileid=\"756\" duration=\"100\"/>\n   <frame tileid=\"764\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"709\" duration=\"100\"/>\n   <frame tileid=\"717\" duration=\"100\"/>\n   <frame tileid=\"725\" duration=\"100\"/>\n   <frame tileid=\"733\" duration=\"100\"/>\n   <frame tileid=\"741\" duration=\"100\"/>\n   <frame tileid=\"749\" duration=\"100\"/>\n   <frame tileid=\"757\" duration=\"100\"/>\n   <frame tileid=\"765\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"710\" duration=\"100\"/>\n   <frame tileid=\"718\" duration=\"100\"/>\n   <frame tileid=\"726\" duration=\"100\"/>\n   <frame tileid=\"734\" duration=\"100\"/>\n   <frame tileid=\"742\" duration=\"100\"/>\n   <frame tileid=\"750\" duration=\"100\"/>\n   <frame tileid=\"758\" duration=\"100\"/>\n   <frame tileid=\"766\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"711\" duration=\"100\"/>\n   <frame tileid=\"719\" duration=\"100\"/>\n   <frame tileid=\"727\" duration=\"100\"/>\n   <frame tileid=\"735\" duration=\"100\"/>\n   <frame tileid=\"743\" duration=\"100\"/>\n   <frame tileid=\"751\" duration=\"100\"/>\n   <frame tileid=\"759\" duration=\"100\"/>\n   <frame tileid=\"767\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"768\" duration=\"100\"/>\n   <frame tileid=\"776\" duration=\"100\"/>\n   <frame tileid=\"784\" duration=\"100\"/>\n   <frame tileid=\"792\" duration=\"100\"/>\n   <frame tileid=\"800\" duration=\"100\"/>\n   <frame tileid=\"808\" duration=\"100\"/>\n   <frame tileid=\"816\" duration=\"100\"/>\n   <frame tileid=\"824\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"769\" duration=\"100\"/>\n   <frame tileid=\"777\" duration=\"100\"/>\n   <frame tileid=\"785\" duration=\"100\"/>\n   <frame tileid=\"793\" duration=\"100\"/>\n   <frame tileid=\"801\" duration=\"100\"/>\n   <frame tileid=\"809\" duration=\"100\"/>\n   <frame tileid=\"817\" duration=\"100\"/>\n   <frame tileid=\"825\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"770\" duration=\"100\"/>\n   <frame tileid=\"778\" duration=\"100\"/>\n   <frame tileid=\"786\" duration=\"100\"/>\n   <frame tileid=\"794\" duration=\"100\"/>\n   <frame tileid=\"802\" duration=\"100\"/>\n   <frame tileid=\"810\" duration=\"100\"/>\n   <frame tileid=\"818\" duration=\"100\"/>\n   <frame tileid=\"826\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"771\" duration=\"100\"/>\n   <frame tileid=\"779\" duration=\"100\"/>\n   <frame tileid=\"787\" duration=\"100\"/>\n   <frame tileid=\"795\" duration=\"100\"/>\n   <frame tileid=\"803\" duration=\"100\"/>\n   <frame tileid=\"811\" duration=\"100\"/>\n   <frame tileid=\"819\" duration=\"100\"/>\n   <frame tileid=\"827\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"772\" duration=\"100\"/>\n   <frame tileid=\"780\" duration=\"100\"/>\n   <frame tileid=\"788\" duration=\"100\"/>\n   <frame tileid=\"796\" duration=\"100\"/>\n   <frame tileid=\"804\" duration=\"100\"/>\n   <frame tileid=\"812\" duration=\"100\"/>\n   <frame tileid=\"820\" duration=\"100\"/>\n   <frame tileid=\"828\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"773\" duration=\"100\"/>\n   <frame tileid=\"781\" duration=\"100\"/>\n   <frame tileid=\"789\" duration=\"100\"/>\n   <frame tileid=\"797\" duration=\"100\"/>\n   <frame tileid=\"805\" duration=\"100\"/>\n   <frame tileid=\"813\" duration=\"100\"/>\n   <frame tileid=\"821\" duration=\"100\"/>\n   <frame tileid=\"829\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"774\" duration=\"100\"/>\n   <frame tileid=\"782\" duration=\"100\"/>\n   <frame tileid=\"790\" duration=\"100\"/>\n   <frame tileid=\"798\" duration=\"100\"/>\n   <frame tileid=\"806\" duration=\"100\"/>\n   <frame tileid=\"814\" duration=\"100\"/>\n   <frame tileid=\"822\" duration=\"100\"/>\n   <frame tileid=\"830\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"775\" duration=\"100\"/>\n   <frame tileid=\"783\" duration=\"100\"/>\n   <frame tileid=\"791\" duration=\"100\"/>\n   <frame tileid=\"799\" duration=\"100\"/>\n   <frame tileid=\"807\" duration=\"100\"/>\n   <frame tileid=\"815\" duration=\"100\"/>\n   <frame tileid=\"823\" duration=\"100\"/>\n   <frame tileid=\"831\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"832\" duration=\"100\"/>\n   <frame tileid=\"840\" duration=\"100\"/>\n   <frame tileid=\"848\" duration=\"100\"/>\n   <frame tileid=\"856\" duration=\"100\"/>\n   <frame tileid=\"864\" duration=\"100\"/>\n   <frame tileid=\"872\" duration=\"100\"/>\n   <frame tileid=\"880\" duration=\"100\"/>\n   <frame tileid=\"888\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"833\" duration=\"100\"/>\n   <frame tileid=\"841\" duration=\"100\"/>\n   <frame tileid=\"849\" duration=\"100\"/>\n   <frame tileid=\"857\" duration=\"100\"/>\n   <frame tileid=\"865\" duration=\"100\"/>\n   <frame tileid=\"873\" duration=\"100\"/>\n   <frame tileid=\"881\" duration=\"100\"/>\n   <frame tileid=\"889\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"834\" duration=\"100\"/>\n   <frame tileid=\"842\" duration=\"100\"/>\n   <frame tileid=\"850\" duration=\"100\"/>\n   <frame tileid=\"858\" duration=\"100\"/>\n   <frame tileid=\"866\" duration=\"100\"/>\n   <frame tileid=\"874\" duration=\"100\"/>\n   <frame tileid=\"882\" duration=\"100\"/>\n   <frame tileid=\"890\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"835\" duration=\"100\"/>\n   <frame tileid=\"843\" duration=\"100\"/>\n   <frame tileid=\"851\" duration=\"100\"/>\n   <frame tileid=\"859\" duration=\"100\"/>\n   <frame tileid=\"867\" duration=\"100\"/>\n   <frame tileid=\"875\" duration=\"100\"/>\n   <frame tileid=\"883\" duration=\"100\"/>\n   <frame tileid=\"891\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"836\" duration=\"100\"/>\n   <frame tileid=\"844\" duration=\"100\"/>\n   <frame tileid=\"852\" duration=\"100\"/>\n   <frame tileid=\"860\" duration=\"100\"/>\n   <frame tileid=\"868\" duration=\"100\"/>\n   <frame tileid=\"876\" duration=\"100\"/>\n   <frame tileid=\"884\" duration=\"100\"/>\n   <frame tileid=\"892\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"837\" duration=\"100\"/>\n   <frame tileid=\"845\" duration=\"100\"/>\n   <frame tileid=\"853\" duration=\"100\"/>\n   <frame tileid=\"861\" duration=\"100\"/>\n   <frame tileid=\"869\" duration=\"100\"/>\n   <frame tileid=\"877\" duration=\"100\"/>\n   <frame tileid=\"885\" duration=\"100\"/>\n   <frame tileid=\"893\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"838\" duration=\"100\"/>\n   <frame tileid=\"846\" duration=\"100\"/>\n   <frame tileid=\"854\" duration=\"100\"/>\n   <frame tileid=\"862\" duration=\"100\"/>\n   <frame tileid=\"870\" duration=\"100\"/>\n   <frame tileid=\"878\" duration=\"100\"/>\n   <frame tileid=\"886\" duration=\"100\"/>\n   <frame tileid=\"894\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"839\" duration=\"100\"/>\n   <frame tileid=\"847\" duration=\"100\"/>\n   <frame tileid=\"855\" duration=\"100\"/>\n   <frame tileid=\"863\" duration=\"100\"/>\n   <frame tileid=\"871\" duration=\"100\"/>\n   <frame tileid=\"879\" duration=\"100\"/>\n   <frame tileid=\"887\" duration=\"100\"/>\n   <frame tileid=\"895\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"896\" duration=\"100\"/>\n   <frame tileid=\"904\" duration=\"100\"/>\n   <frame tileid=\"912\" duration=\"100\"/>\n   <frame tileid=\"920\" duration=\"100\"/>\n   <frame tileid=\"928\" duration=\"100\"/>\n   <frame tileid=\"936\" duration=\"100\"/>\n   <frame tileid=\"944\" duration=\"100\"/>\n   <frame tileid=\"952\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"897\" duration=\"100\"/>\n   <frame tileid=\"905\" duration=\"100\"/>\n   <frame tileid=\"913\" duration=\"100\"/>\n   <frame tileid=\"921\" duration=\"100\"/>\n   <frame tileid=\"929\" duration=\"100\"/>\n   <frame tileid=\"937\" duration=\"100\"/>\n   <frame tileid=\"945\" duration=\"100\"/>\n   <frame tileid=\"953\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"898\" duration=\"100\"/>\n   <frame tileid=\"906\" duration=\"100\"/>\n   <frame tileid=\"914\" duration=\"100\"/>\n   <frame tileid=\"922\" duration=\"100\"/>\n   <frame tileid=\"930\" duration=\"100\"/>\n   <frame tileid=\"938\" duration=\"100\"/>\n   <frame tileid=\"946\" duration=\"100\"/>\n   <frame tileid=\"954\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"899\" duration=\"100\"/>\n   <frame tileid=\"907\" duration=\"100\"/>\n   <frame tileid=\"915\" duration=\"100\"/>\n   <frame tileid=\"923\" duration=\"100\"/>\n   <frame tileid=\"931\" duration=\"100\"/>\n   <frame tileid=\"939\" duration=\"100\"/>\n   <frame tileid=\"947\" duration=\"100\"/>\n   <frame tileid=\"955\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"900\" duration=\"100\"/>\n   <frame tileid=\"908\" duration=\"100\"/>\n   <frame tileid=\"916\" duration=\"100\"/>\n   <frame tileid=\"924\" duration=\"100\"/>\n   <frame tileid=\"932\" duration=\"100\"/>\n   <frame tileid=\"940\" duration=\"100\"/>\n   <frame tileid=\"948\" duration=\"100\"/>\n   <frame tileid=\"956\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"901\" duration=\"100\"/>\n   <frame tileid=\"909\" duration=\"100\"/>\n   <frame tileid=\"917\" duration=\"100\"/>\n   <frame tileid=\"925\" duration=\"100\"/>\n   <frame tileid=\"933\" duration=\"100\"/>\n   <frame tileid=\"941\" duration=\"100\"/>\n   <frame tileid=\"949\" duration=\"100\"/>\n   <frame tileid=\"957\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"902\" duration=\"100\"/>\n   <frame tileid=\"910\" duration=\"100\"/>\n   <frame tileid=\"918\" duration=\"100\"/>\n   <frame tileid=\"926\" duration=\"100\"/>\n   <frame tileid=\"934\" duration=\"100\"/>\n   <frame tileid=\"942\" duration=\"100\"/>\n   <frame tileid=\"950\" duration=\"100\"/>\n   <frame tileid=\"958\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"903\" duration=\"100\"/>\n   <frame tileid=\"911\" duration=\"100\"/>\n   <frame tileid=\"919\" duration=\"100\"/>\n   <frame tileid=\"927\" duration=\"100\"/>\n   <frame tileid=\"935\" duration=\"100\"/>\n   <frame tileid=\"943\" duration=\"100\"/>\n   <frame tileid=\"951\" duration=\"100\"/>\n   <frame tileid=\"959\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"960\" duration=\"100\"/>\n   <frame tileid=\"968\" duration=\"100\"/>\n   <frame tileid=\"976\" duration=\"100\"/>\n   <frame tileid=\"984\" duration=\"100\"/>\n   <frame tileid=\"992\" duration=\"100\"/>\n   <frame tileid=\"1000\" duration=\"100\"/>\n   <frame tileid=\"1008\" duration=\"100\"/>\n   <frame tileid=\"1016\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"961\" duration=\"100\"/>\n   <frame tileid=\"969\" duration=\"100\"/>\n   <frame tileid=\"977\" duration=\"100\"/>\n   <frame tileid=\"985\" duration=\"100\"/>\n   <frame tileid=\"993\" duration=\"100\"/>\n   <frame tileid=\"1001\" duration=\"100\"/>\n   <frame tileid=\"1009\" duration=\"100\"/>\n   <frame tileid=\"1017\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"962\" duration=\"100\"/>\n   <frame tileid=\"970\" duration=\"100\"/>\n   <frame tileid=\"978\" duration=\"100\"/>\n   <frame tileid=\"986\" duration=\"100\"/>\n   <frame tileid=\"994\" duration=\"100\"/>\n   <frame tileid=\"1002\" duration=\"100\"/>\n   <frame tileid=\"1010\" duration=\"100\"/>\n   <frame tileid=\"1018\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"963\" duration=\"100\"/>\n   <frame tileid=\"971\" duration=\"100\"/>\n   <frame tileid=\"979\" duration=\"100\"/>\n   <frame tileid=\"987\" duration=\"100\"/>\n   <frame tileid=\"995\" duration=\"100\"/>\n   <frame tileid=\"1003\" duration=\"100\"/>\n   <frame tileid=\"1011\" duration=\"100\"/>\n   <frame tileid=\"1019\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"964\" duration=\"100\"/>\n   <frame tileid=\"972\" duration=\"100\"/>\n   <frame tileid=\"980\" duration=\"100\"/>\n   <frame tileid=\"988\" duration=\"100\"/>\n   <frame tileid=\"996\" duration=\"100\"/>\n   <frame tileid=\"1004\" duration=\"100\"/>\n   <frame tileid=\"1012\" duration=\"100\"/>\n   <frame tileid=\"1020\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"965\" duration=\"100\"/>\n   <frame tileid=\"973\" duration=\"100\"/>\n   <frame tileid=\"981\" duration=\"100\"/>\n   <frame tileid=\"989\" duration=\"100\"/>\n   <frame tileid=\"997\" duration=\"100\"/>\n   <frame tileid=\"1005\" duration=\"100\"/>\n   <frame tileid=\"1013\" duration=\"100\"/>\n   <frame tileid=\"1021\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"966\" duration=\"100\"/>\n   <frame tileid=\"974\" duration=\"100\"/>\n   <frame tileid=\"982\" duration=\"100\"/>\n   <frame tileid=\"990\" duration=\"100\"/>\n   <frame tileid=\"998\" duration=\"100\"/>\n   <frame tileid=\"1006\" duration=\"100\"/>\n   <frame tileid=\"1014\" duration=\"100\"/>\n   <frame tileid=\"1022\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"967\" duration=\"100\"/>\n   <frame tileid=\"975\" duration=\"100\"/>\n   <frame tileid=\"983\" duration=\"100\"/>\n   <frame tileid=\"991\" duration=\"100\"/>\n   <frame tileid=\"999\" duration=\"100\"/>\n   <frame tileid=\"1007\" duration=\"100\"/>\n   <frame tileid=\"1015\" duration=\"100\"/>\n   <frame tileid=\"1023\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1000\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1001\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1002\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1003\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1004\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1005\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1006\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1007\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1008\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1009\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1010\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1011\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1012\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1013\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1014\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1015\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1016\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1017\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1018\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1019\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1020\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1021\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1022\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1023\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1024\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1024\" duration=\"100\"/>\n   <frame tileid=\"1032\" duration=\"100\"/>\n   <frame tileid=\"1040\" duration=\"100\"/>\n   <frame tileid=\"1048\" duration=\"100\"/>\n   <frame tileid=\"1056\" duration=\"100\"/>\n   <frame tileid=\"1064\" duration=\"100\"/>\n   <frame tileid=\"1072\" duration=\"100\"/>\n   <frame tileid=\"1080\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1025\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1025\" duration=\"100\"/>\n   <frame tileid=\"1033\" duration=\"100\"/>\n   <frame tileid=\"1041\" duration=\"100\"/>\n   <frame tileid=\"1049\" duration=\"100\"/>\n   <frame tileid=\"1057\" duration=\"100\"/>\n   <frame tileid=\"1065\" duration=\"100\"/>\n   <frame tileid=\"1073\" duration=\"100\"/>\n   <frame tileid=\"1081\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1026\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1026\" duration=\"100\"/>\n   <frame tileid=\"1034\" duration=\"100\"/>\n   <frame tileid=\"1042\" duration=\"100\"/>\n   <frame tileid=\"1050\" duration=\"100\"/>\n   <frame tileid=\"1058\" duration=\"100\"/>\n   <frame tileid=\"1066\" duration=\"100\"/>\n   <frame tileid=\"1074\" duration=\"100\"/>\n   <frame tileid=\"1082\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1027\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1027\" duration=\"100\"/>\n   <frame tileid=\"1035\" duration=\"100\"/>\n   <frame tileid=\"1043\" duration=\"100\"/>\n   <frame tileid=\"1051\" duration=\"100\"/>\n   <frame tileid=\"1059\" duration=\"100\"/>\n   <frame tileid=\"1067\" duration=\"100\"/>\n   <frame tileid=\"1075\" duration=\"100\"/>\n   <frame tileid=\"1083\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1028\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1028\" duration=\"100\"/>\n   <frame tileid=\"1036\" duration=\"100\"/>\n   <frame tileid=\"1044\" duration=\"100\"/>\n   <frame tileid=\"1052\" duration=\"100\"/>\n   <frame tileid=\"1060\" duration=\"100\"/>\n   <frame tileid=\"1068\" duration=\"100\"/>\n   <frame tileid=\"1076\" duration=\"100\"/>\n   <frame tileid=\"1084\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1029\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1029\" duration=\"100\"/>\n   <frame tileid=\"1037\" duration=\"100\"/>\n   <frame tileid=\"1045\" duration=\"100\"/>\n   <frame tileid=\"1053\" duration=\"100\"/>\n   <frame tileid=\"1061\" duration=\"100\"/>\n   <frame tileid=\"1069\" duration=\"100\"/>\n   <frame tileid=\"1077\" duration=\"100\"/>\n   <frame tileid=\"1085\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1030\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1030\" duration=\"100\"/>\n   <frame tileid=\"1038\" duration=\"100\"/>\n   <frame tileid=\"1046\" duration=\"100\"/>\n   <frame tileid=\"1054\" duration=\"100\"/>\n   <frame tileid=\"1062\" duration=\"100\"/>\n   <frame tileid=\"1070\" duration=\"100\"/>\n   <frame tileid=\"1078\" duration=\"100\"/>\n   <frame tileid=\"1086\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1031\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1031\" duration=\"100\"/>\n   <frame tileid=\"1039\" duration=\"100\"/>\n   <frame tileid=\"1047\" duration=\"100\"/>\n   <frame tileid=\"1055\" duration=\"100\"/>\n   <frame tileid=\"1063\" duration=\"100\"/>\n   <frame tileid=\"1071\" duration=\"100\"/>\n   <frame tileid=\"1079\" duration=\"100\"/>\n   <frame tileid=\"1087\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1032\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1033\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1034\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1035\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1036\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1037\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1038\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1039\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1040\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1041\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1042\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1043\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1044\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1045\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1046\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1047\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1048\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1049\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1050\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1051\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1052\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1053\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1054\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1055\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1056\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1057\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1058\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1059\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1060\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1061\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1062\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1063\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1064\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1065\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1066\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1067\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1068\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1069\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1070\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1071\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1072\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1073\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1074\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1075\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1076\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1077\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1078\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1079\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1080\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1081\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1082\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1083\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1084\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1085\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1086\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1087\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1088\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1088\" duration=\"100\"/>\n   <frame tileid=\"1096\" duration=\"100\"/>\n   <frame tileid=\"1104\" duration=\"100\"/>\n   <frame tileid=\"1112\" duration=\"100\"/>\n   <frame tileid=\"1120\" duration=\"100\"/>\n   <frame tileid=\"1128\" duration=\"100\"/>\n   <frame tileid=\"1136\" duration=\"100\"/>\n   <frame tileid=\"1144\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1089\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1089\" duration=\"100\"/>\n   <frame tileid=\"1097\" duration=\"100\"/>\n   <frame tileid=\"1105\" duration=\"100\"/>\n   <frame tileid=\"1113\" duration=\"100\"/>\n   <frame tileid=\"1121\" duration=\"100\"/>\n   <frame tileid=\"1129\" duration=\"100\"/>\n   <frame tileid=\"1137\" duration=\"100\"/>\n   <frame tileid=\"1145\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1090\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1090\" duration=\"100\"/>\n   <frame tileid=\"1098\" duration=\"100\"/>\n   <frame tileid=\"1106\" duration=\"100\"/>\n   <frame tileid=\"1114\" duration=\"100\"/>\n   <frame tileid=\"1122\" duration=\"100\"/>\n   <frame tileid=\"1130\" duration=\"100\"/>\n   <frame tileid=\"1138\" duration=\"100\"/>\n   <frame tileid=\"1146\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1091\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1091\" duration=\"100\"/>\n   <frame tileid=\"1099\" duration=\"100\"/>\n   <frame tileid=\"1107\" duration=\"100\"/>\n   <frame tileid=\"1115\" duration=\"100\"/>\n   <frame tileid=\"1123\" duration=\"100\"/>\n   <frame tileid=\"1131\" duration=\"100\"/>\n   <frame tileid=\"1139\" duration=\"100\"/>\n   <frame tileid=\"1147\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1092\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1092\" duration=\"100\"/>\n   <frame tileid=\"1100\" duration=\"100\"/>\n   <frame tileid=\"1108\" duration=\"100\"/>\n   <frame tileid=\"1116\" duration=\"100\"/>\n   <frame tileid=\"1124\" duration=\"100\"/>\n   <frame tileid=\"1132\" duration=\"100\"/>\n   <frame tileid=\"1140\" duration=\"100\"/>\n   <frame tileid=\"1148\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1093\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1093\" duration=\"100\"/>\n   <frame tileid=\"1101\" duration=\"100\"/>\n   <frame tileid=\"1109\" duration=\"100\"/>\n   <frame tileid=\"1117\" duration=\"100\"/>\n   <frame tileid=\"1125\" duration=\"100\"/>\n   <frame tileid=\"1133\" duration=\"100\"/>\n   <frame tileid=\"1141\" duration=\"100\"/>\n   <frame tileid=\"1149\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1094\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1094\" duration=\"100\"/>\n   <frame tileid=\"1102\" duration=\"100\"/>\n   <frame tileid=\"1110\" duration=\"100\"/>\n   <frame tileid=\"1118\" duration=\"100\"/>\n   <frame tileid=\"1126\" duration=\"100\"/>\n   <frame tileid=\"1134\" duration=\"100\"/>\n   <frame tileid=\"1142\" duration=\"100\"/>\n   <frame tileid=\"1150\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1095\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1095\" duration=\"100\"/>\n   <frame tileid=\"1103\" duration=\"100\"/>\n   <frame tileid=\"1111\" duration=\"100\"/>\n   <frame tileid=\"1119\" duration=\"100\"/>\n   <frame tileid=\"1127\" duration=\"100\"/>\n   <frame tileid=\"1135\" duration=\"100\"/>\n   <frame tileid=\"1143\" duration=\"100\"/>\n   <frame tileid=\"1151\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1096\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1097\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1098\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1099\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1121\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1141\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1152\" duration=\"100\"/>\n   <frame tileid=\"1160\" duration=\"100\"/>\n   <frame tileid=\"1168\" duration=\"100\"/>\n   <frame tileid=\"1176\" duration=\"100\"/>\n   <frame tileid=\"1184\" duration=\"100\"/>\n   <frame tileid=\"1192\" duration=\"100\"/>\n   <frame tileid=\"1200\" duration=\"100\"/>\n   <frame tileid=\"1208\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1153\" duration=\"100\"/>\n   <frame tileid=\"1161\" duration=\"100\"/>\n   <frame tileid=\"1169\" duration=\"100\"/>\n   <frame tileid=\"1177\" duration=\"100\"/>\n   <frame tileid=\"1185\" duration=\"100\"/>\n   <frame tileid=\"1193\" duration=\"100\"/>\n   <frame tileid=\"1201\" duration=\"100\"/>\n   <frame tileid=\"1209\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1154\" duration=\"100\"/>\n   <frame tileid=\"1162\" duration=\"100\"/>\n   <frame tileid=\"1170\" duration=\"100\"/>\n   <frame tileid=\"1178\" duration=\"100\"/>\n   <frame tileid=\"1186\" duration=\"100\"/>\n   <frame tileid=\"1194\" duration=\"100\"/>\n   <frame tileid=\"1202\" duration=\"100\"/>\n   <frame tileid=\"1210\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1155\" duration=\"100\"/>\n   <frame tileid=\"1163\" duration=\"100\"/>\n   <frame tileid=\"1171\" duration=\"100\"/>\n   <frame tileid=\"1179\" duration=\"100\"/>\n   <frame tileid=\"1187\" duration=\"100\"/>\n   <frame tileid=\"1195\" duration=\"100\"/>\n   <frame tileid=\"1203\" duration=\"100\"/>\n   <frame tileid=\"1211\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1156\" duration=\"100\"/>\n   <frame tileid=\"1164\" duration=\"100\"/>\n   <frame tileid=\"1172\" duration=\"100\"/>\n   <frame tileid=\"1180\" duration=\"100\"/>\n   <frame tileid=\"1188\" duration=\"100\"/>\n   <frame tileid=\"1196\" duration=\"100\"/>\n   <frame tileid=\"1204\" duration=\"100\"/>\n   <frame tileid=\"1212\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1157\" duration=\"100\"/>\n   <frame tileid=\"1165\" duration=\"100\"/>\n   <frame tileid=\"1173\" duration=\"100\"/>\n   <frame tileid=\"1181\" duration=\"100\"/>\n   <frame tileid=\"1189\" duration=\"100\"/>\n   <frame tileid=\"1197\" duration=\"100\"/>\n   <frame tileid=\"1205\" duration=\"100\"/>\n   <frame tileid=\"1213\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1158\" duration=\"100\"/>\n   <frame tileid=\"1166\" duration=\"100\"/>\n   <frame tileid=\"1174\" duration=\"100\"/>\n   <frame tileid=\"1182\" duration=\"100\"/>\n   <frame tileid=\"1190\" duration=\"100\"/>\n   <frame tileid=\"1198\" duration=\"100\"/>\n   <frame tileid=\"1206\" duration=\"100\"/>\n   <frame tileid=\"1214\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1159\" duration=\"100\"/>\n   <frame tileid=\"1167\" duration=\"100\"/>\n   <frame tileid=\"1175\" duration=\"100\"/>\n   <frame tileid=\"1183\" duration=\"100\"/>\n   <frame tileid=\"1191\" duration=\"100\"/>\n   <frame tileid=\"1199\" duration=\"100\"/>\n   <frame tileid=\"1207\" duration=\"100\"/>\n   <frame tileid=\"1215\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1216\" duration=\"100\"/>\n   <frame tileid=\"1224\" duration=\"100\"/>\n   <frame tileid=\"1232\" duration=\"100\"/>\n   <frame tileid=\"1240\" duration=\"100\"/>\n   <frame tileid=\"1248\" duration=\"100\"/>\n   <frame tileid=\"1256\" duration=\"100\"/>\n   <frame tileid=\"1264\" duration=\"100\"/>\n   <frame tileid=\"1272\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1217\" duration=\"100\"/>\n   <frame tileid=\"1225\" duration=\"100\"/>\n   <frame tileid=\"1233\" duration=\"100\"/>\n   <frame tileid=\"1241\" duration=\"100\"/>\n   <frame tileid=\"1249\" duration=\"100\"/>\n   <frame tileid=\"1257\" duration=\"100\"/>\n   <frame tileid=\"1265\" duration=\"100\"/>\n   <frame tileid=\"1273\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1218\" duration=\"100\"/>\n   <frame tileid=\"1226\" duration=\"100\"/>\n   <frame tileid=\"1234\" duration=\"100\"/>\n   <frame tileid=\"1242\" duration=\"100\"/>\n   <frame tileid=\"1250\" duration=\"100\"/>\n   <frame tileid=\"1258\" duration=\"100\"/>\n   <frame tileid=\"1266\" duration=\"100\"/>\n   <frame tileid=\"1274\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1219\" duration=\"100\"/>\n   <frame tileid=\"1227\" duration=\"100\"/>\n   <frame tileid=\"1235\" duration=\"100\"/>\n   <frame tileid=\"1243\" duration=\"100\"/>\n   <frame tileid=\"1251\" duration=\"100\"/>\n   <frame tileid=\"1259\" duration=\"100\"/>\n   <frame tileid=\"1267\" duration=\"100\"/>\n   <frame tileid=\"1275\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1220\" duration=\"100\"/>\n   <frame tileid=\"1228\" duration=\"100\"/>\n   <frame tileid=\"1236\" duration=\"100\"/>\n   <frame tileid=\"1244\" duration=\"100\"/>\n   <frame tileid=\"1252\" duration=\"100\"/>\n   <frame tileid=\"1260\" duration=\"100\"/>\n   <frame tileid=\"1268\" duration=\"100\"/>\n   <frame tileid=\"1276\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1221\" duration=\"100\"/>\n   <frame tileid=\"1229\" duration=\"100\"/>\n   <frame tileid=\"1237\" duration=\"100\"/>\n   <frame tileid=\"1245\" duration=\"100\"/>\n   <frame tileid=\"1253\" duration=\"100\"/>\n   <frame tileid=\"1261\" duration=\"100\"/>\n   <frame tileid=\"1269\" duration=\"100\"/>\n   <frame tileid=\"1277\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1222\" duration=\"100\"/>\n   <frame tileid=\"1230\" duration=\"100\"/>\n   <frame tileid=\"1238\" duration=\"100\"/>\n   <frame tileid=\"1246\" duration=\"100\"/>\n   <frame tileid=\"1254\" duration=\"100\"/>\n   <frame tileid=\"1262\" duration=\"100\"/>\n   <frame tileid=\"1270\" duration=\"100\"/>\n   <frame tileid=\"1278\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1223\" duration=\"100\"/>\n   <frame tileid=\"1231\" duration=\"100\"/>\n   <frame tileid=\"1239\" duration=\"100\"/>\n   <frame tileid=\"1247\" duration=\"100\"/>\n   <frame tileid=\"1255\" duration=\"100\"/>\n   <frame tileid=\"1263\" duration=\"100\"/>\n   <frame tileid=\"1271\" duration=\"100\"/>\n   <frame tileid=\"1279\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1280\" duration=\"100\"/>\n   <frame tileid=\"1288\" duration=\"100\"/>\n   <frame tileid=\"1296\" duration=\"100\"/>\n   <frame tileid=\"1304\" duration=\"100\"/>\n   <frame tileid=\"1312\" duration=\"100\"/>\n   <frame tileid=\"1320\" duration=\"100\"/>\n   <frame tileid=\"1328\" duration=\"100\"/>\n   <frame tileid=\"1336\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1281\" duration=\"100\"/>\n   <frame tileid=\"1289\" duration=\"100\"/>\n   <frame tileid=\"1297\" duration=\"100\"/>\n   <frame tileid=\"1305\" duration=\"100\"/>\n   <frame tileid=\"1313\" duration=\"100\"/>\n   <frame tileid=\"1321\" duration=\"100\"/>\n   <frame tileid=\"1329\" duration=\"100\"/>\n   <frame tileid=\"1337\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1282\" duration=\"100\"/>\n   <frame tileid=\"1290\" duration=\"100\"/>\n   <frame tileid=\"1298\" duration=\"100\"/>\n   <frame tileid=\"1306\" duration=\"100\"/>\n   <frame tileid=\"1314\" duration=\"100\"/>\n   <frame tileid=\"1322\" duration=\"100\"/>\n   <frame tileid=\"1330\" duration=\"100\"/>\n   <frame tileid=\"1338\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1283\" duration=\"100\"/>\n   <frame tileid=\"1291\" duration=\"100\"/>\n   <frame tileid=\"1299\" duration=\"100\"/>\n   <frame tileid=\"1307\" duration=\"100\"/>\n   <frame tileid=\"1315\" duration=\"100\"/>\n   <frame tileid=\"1323\" duration=\"100\"/>\n   <frame tileid=\"1331\" duration=\"100\"/>\n   <frame tileid=\"1339\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1284\" duration=\"100\"/>\n   <frame tileid=\"1292\" duration=\"100\"/>\n   <frame tileid=\"1300\" duration=\"100\"/>\n   <frame tileid=\"1308\" duration=\"100\"/>\n   <frame tileid=\"1316\" duration=\"100\"/>\n   <frame tileid=\"1324\" duration=\"100\"/>\n   <frame tileid=\"1332\" duration=\"100\"/>\n   <frame tileid=\"1340\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1285\" duration=\"100\"/>\n   <frame tileid=\"1293\" duration=\"100\"/>\n   <frame tileid=\"1301\" duration=\"100\"/>\n   <frame tileid=\"1309\" duration=\"100\"/>\n   <frame tileid=\"1317\" duration=\"100\"/>\n   <frame tileid=\"1325\" duration=\"100\"/>\n   <frame tileid=\"1333\" duration=\"100\"/>\n   <frame tileid=\"1341\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1286\" duration=\"100\"/>\n   <frame tileid=\"1294\" duration=\"100\"/>\n   <frame tileid=\"1302\" duration=\"100\"/>\n   <frame tileid=\"1310\" duration=\"100\"/>\n   <frame tileid=\"1318\" duration=\"100\"/>\n   <frame tileid=\"1326\" duration=\"100\"/>\n   <frame tileid=\"1334\" duration=\"100\"/>\n   <frame tileid=\"1342\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1287\" duration=\"100\"/>\n   <frame tileid=\"1295\" duration=\"100\"/>\n   <frame tileid=\"1303\" duration=\"100\"/>\n   <frame tileid=\"1311\" duration=\"100\"/>\n   <frame tileid=\"1319\" duration=\"100\"/>\n   <frame tileid=\"1327\" duration=\"100\"/>\n   <frame tileid=\"1335\" duration=\"100\"/>\n   <frame tileid=\"1343\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1344\" duration=\"100\"/>\n   <frame tileid=\"1352\" duration=\"100\"/>\n   <frame tileid=\"1360\" duration=\"100\"/>\n   <frame tileid=\"1368\" duration=\"100\"/>\n   <frame tileid=\"1376\" duration=\"100\"/>\n   <frame tileid=\"1384\" duration=\"100\"/>\n   <frame tileid=\"1392\" duration=\"100\"/>\n   <frame tileid=\"1400\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1345\" duration=\"100\"/>\n   <frame tileid=\"1353\" duration=\"100\"/>\n   <frame tileid=\"1361\" duration=\"100\"/>\n   <frame tileid=\"1369\" duration=\"100\"/>\n   <frame tileid=\"1377\" duration=\"100\"/>\n   <frame tileid=\"1385\" duration=\"100\"/>\n   <frame tileid=\"1393\" duration=\"100\"/>\n   <frame tileid=\"1401\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1346\" duration=\"100\"/>\n   <frame tileid=\"1354\" duration=\"100\"/>\n   <frame tileid=\"1362\" duration=\"100\"/>\n   <frame tileid=\"1370\" duration=\"100\"/>\n   <frame tileid=\"1378\" duration=\"100\"/>\n   <frame tileid=\"1386\" duration=\"100\"/>\n   <frame tileid=\"1394\" duration=\"100\"/>\n   <frame tileid=\"1402\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1347\" duration=\"100\"/>\n   <frame tileid=\"1355\" duration=\"100\"/>\n   <frame tileid=\"1363\" duration=\"100\"/>\n   <frame tileid=\"1371\" duration=\"100\"/>\n   <frame tileid=\"1379\" duration=\"100\"/>\n   <frame tileid=\"1387\" duration=\"100\"/>\n   <frame tileid=\"1395\" duration=\"100\"/>\n   <frame tileid=\"1403\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1348\" duration=\"100\"/>\n   <frame tileid=\"1356\" duration=\"100\"/>\n   <frame tileid=\"1364\" duration=\"100\"/>\n   <frame tileid=\"1372\" duration=\"100\"/>\n   <frame tileid=\"1380\" duration=\"100\"/>\n   <frame tileid=\"1388\" duration=\"100\"/>\n   <frame tileid=\"1396\" duration=\"100\"/>\n   <frame tileid=\"1404\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1349\" duration=\"100\"/>\n   <frame tileid=\"1357\" duration=\"100\"/>\n   <frame tileid=\"1365\" duration=\"100\"/>\n   <frame tileid=\"1373\" duration=\"100\"/>\n   <frame tileid=\"1381\" duration=\"100\"/>\n   <frame tileid=\"1389\" duration=\"100\"/>\n   <frame tileid=\"1397\" duration=\"100\"/>\n   <frame tileid=\"1405\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1350\" duration=\"100\"/>\n   <frame tileid=\"1358\" duration=\"100\"/>\n   <frame tileid=\"1366\" duration=\"100\"/>\n   <frame tileid=\"1374\" duration=\"100\"/>\n   <frame tileid=\"1382\" duration=\"100\"/>\n   <frame tileid=\"1390\" duration=\"100\"/>\n   <frame tileid=\"1398\" duration=\"100\"/>\n   <frame tileid=\"1406\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1351\" duration=\"100\"/>\n   <frame tileid=\"1359\" duration=\"100\"/>\n   <frame tileid=\"1367\" duration=\"100\"/>\n   <frame tileid=\"1375\" duration=\"100\"/>\n   <frame tileid=\"1383\" duration=\"100\"/>\n   <frame tileid=\"1391\" duration=\"100\"/>\n   <frame tileid=\"1399\" duration=\"100\"/>\n   <frame tileid=\"1407\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1408\" duration=\"100\"/>\n   <frame tileid=\"1416\" duration=\"100\"/>\n   <frame tileid=\"1424\" duration=\"100\"/>\n   <frame tileid=\"1432\" duration=\"100\"/>\n   <frame tileid=\"1440\" duration=\"100\"/>\n   <frame tileid=\"1448\" duration=\"100\"/>\n   <frame tileid=\"1456\" duration=\"100\"/>\n   <frame tileid=\"1464\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1409\" duration=\"100\"/>\n   <frame tileid=\"1417\" duration=\"100\"/>\n   <frame tileid=\"1425\" duration=\"100\"/>\n   <frame tileid=\"1433\" duration=\"100\"/>\n   <frame tileid=\"1441\" duration=\"100\"/>\n   <frame tileid=\"1449\" duration=\"100\"/>\n   <frame tileid=\"1457\" duration=\"100\"/>\n   <frame tileid=\"1465\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1410\" duration=\"100\"/>\n   <frame tileid=\"1418\" duration=\"100\"/>\n   <frame tileid=\"1426\" duration=\"100\"/>\n   <frame tileid=\"1434\" duration=\"100\"/>\n   <frame tileid=\"1442\" duration=\"100\"/>\n   <frame tileid=\"1450\" duration=\"100\"/>\n   <frame tileid=\"1458\" duration=\"100\"/>\n   <frame tileid=\"1466\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1411\" duration=\"100\"/>\n   <frame tileid=\"1419\" duration=\"100\"/>\n   <frame tileid=\"1427\" duration=\"100\"/>\n   <frame tileid=\"1435\" duration=\"100\"/>\n   <frame tileid=\"1443\" duration=\"100\"/>\n   <frame tileid=\"1451\" duration=\"100\"/>\n   <frame tileid=\"1459\" duration=\"100\"/>\n   <frame tileid=\"1467\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1412\" duration=\"100\"/>\n   <frame tileid=\"1420\" duration=\"100\"/>\n   <frame tileid=\"1428\" duration=\"100\"/>\n   <frame tileid=\"1436\" duration=\"100\"/>\n   <frame tileid=\"1444\" duration=\"100\"/>\n   <frame tileid=\"1452\" duration=\"100\"/>\n   <frame tileid=\"1460\" duration=\"100\"/>\n   <frame tileid=\"1468\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1413\" duration=\"100\"/>\n   <frame tileid=\"1421\" duration=\"100\"/>\n   <frame tileid=\"1429\" duration=\"100\"/>\n   <frame tileid=\"1437\" duration=\"100\"/>\n   <frame tileid=\"1445\" duration=\"100\"/>\n   <frame tileid=\"1453\" duration=\"100\"/>\n   <frame tileid=\"1461\" duration=\"100\"/>\n   <frame tileid=\"1469\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1414\" duration=\"100\"/>\n   <frame tileid=\"1422\" duration=\"100\"/>\n   <frame tileid=\"1430\" duration=\"100\"/>\n   <frame tileid=\"1438\" duration=\"100\"/>\n   <frame tileid=\"1446\" duration=\"100\"/>\n   <frame tileid=\"1454\" duration=\"100\"/>\n   <frame tileid=\"1462\" duration=\"100\"/>\n   <frame tileid=\"1470\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1415\" duration=\"100\"/>\n   <frame tileid=\"1423\" duration=\"100\"/>\n   <frame tileid=\"1431\" duration=\"100\"/>\n   <frame tileid=\"1439\" duration=\"100\"/>\n   <frame tileid=\"1447\" duration=\"100\"/>\n   <frame tileid=\"1455\" duration=\"100\"/>\n   <frame tileid=\"1463\" duration=\"100\"/>\n   <frame tileid=\"1471\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1472\" duration=\"100\"/>\n   <frame tileid=\"1480\" duration=\"100\"/>\n   <frame tileid=\"1488\" duration=\"100\"/>\n   <frame tileid=\"1496\" duration=\"100\"/>\n   <frame tileid=\"1504\" duration=\"100\"/>\n   <frame tileid=\"1512\" duration=\"100\"/>\n   <frame tileid=\"1520\" duration=\"100\"/>\n   <frame tileid=\"1528\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1473\" duration=\"100\"/>\n   <frame tileid=\"1481\" duration=\"100\"/>\n   <frame tileid=\"1489\" duration=\"100\"/>\n   <frame tileid=\"1497\" duration=\"100\"/>\n   <frame tileid=\"1505\" duration=\"100\"/>\n   <frame tileid=\"1513\" duration=\"100\"/>\n   <frame tileid=\"1521\" duration=\"100\"/>\n   <frame tileid=\"1529\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1474\" duration=\"100\"/>\n   <frame tileid=\"1482\" duration=\"100\"/>\n   <frame tileid=\"1490\" duration=\"100\"/>\n   <frame tileid=\"1498\" duration=\"100\"/>\n   <frame tileid=\"1506\" duration=\"100\"/>\n   <frame tileid=\"1514\" duration=\"100\"/>\n   <frame tileid=\"1522\" duration=\"100\"/>\n   <frame tileid=\"1530\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1475\" duration=\"100\"/>\n   <frame tileid=\"1483\" duration=\"100\"/>\n   <frame tileid=\"1491\" duration=\"100\"/>\n   <frame tileid=\"1499\" duration=\"100\"/>\n   <frame tileid=\"1507\" duration=\"100\"/>\n   <frame tileid=\"1515\" duration=\"100\"/>\n   <frame tileid=\"1523\" duration=\"100\"/>\n   <frame tileid=\"1531\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1476\" duration=\"100\"/>\n   <frame tileid=\"1484\" duration=\"100\"/>\n   <frame tileid=\"1492\" duration=\"100\"/>\n   <frame tileid=\"1500\" duration=\"100\"/>\n   <frame tileid=\"1508\" duration=\"100\"/>\n   <frame tileid=\"1516\" duration=\"100\"/>\n   <frame tileid=\"1524\" duration=\"100\"/>\n   <frame tileid=\"1532\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1477\" duration=\"100\"/>\n   <frame tileid=\"1485\" duration=\"100\"/>\n   <frame tileid=\"1493\" duration=\"100\"/>\n   <frame tileid=\"1501\" duration=\"100\"/>\n   <frame tileid=\"1509\" duration=\"100\"/>\n   <frame tileid=\"1517\" duration=\"100\"/>\n   <frame tileid=\"1525\" duration=\"100\"/>\n   <frame tileid=\"1533\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1478\" duration=\"100\"/>\n   <frame tileid=\"1486\" duration=\"100\"/>\n   <frame tileid=\"1494\" duration=\"100\"/>\n   <frame tileid=\"1502\" duration=\"100\"/>\n   <frame tileid=\"1510\" duration=\"100\"/>\n   <frame tileid=\"1518\" duration=\"100\"/>\n   <frame tileid=\"1526\" duration=\"100\"/>\n   <frame tileid=\"1534\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1479\" duration=\"100\"/>\n   <frame tileid=\"1487\" duration=\"100\"/>\n   <frame tileid=\"1495\" duration=\"100\"/>\n   <frame tileid=\"1503\" duration=\"100\"/>\n   <frame tileid=\"1511\" duration=\"100\"/>\n   <frame tileid=\"1519\" duration=\"100\"/>\n   <frame tileid=\"1527\" duration=\"100\"/>\n   <frame tileid=\"1535\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1536\" duration=\"100\"/>\n   <frame tileid=\"1544\" duration=\"100\"/>\n   <frame tileid=\"1552\" duration=\"100\"/>\n   <frame tileid=\"1560\" duration=\"100\"/>\n   <frame tileid=\"1568\" duration=\"100\"/>\n   <frame tileid=\"1576\" duration=\"100\"/>\n   <frame tileid=\"1584\" duration=\"100\"/>\n   <frame tileid=\"1592\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1537\" duration=\"100\"/>\n   <frame tileid=\"1545\" duration=\"100\"/>\n   <frame tileid=\"1553\" duration=\"100\"/>\n   <frame tileid=\"1561\" duration=\"100\"/>\n   <frame tileid=\"1569\" duration=\"100\"/>\n   <frame tileid=\"1577\" duration=\"100\"/>\n   <frame tileid=\"1585\" duration=\"100\"/>\n   <frame tileid=\"1593\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1538\" duration=\"100\"/>\n   <frame tileid=\"1546\" duration=\"100\"/>\n   <frame tileid=\"1554\" duration=\"100\"/>\n   <frame tileid=\"1562\" duration=\"100\"/>\n   <frame tileid=\"1570\" duration=\"100\"/>\n   <frame tileid=\"1578\" duration=\"100\"/>\n   <frame tileid=\"1586\" duration=\"100\"/>\n   <frame tileid=\"1594\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1539\" duration=\"100\"/>\n   <frame tileid=\"1547\" duration=\"100\"/>\n   <frame tileid=\"1555\" duration=\"100\"/>\n   <frame tileid=\"1563\" duration=\"100\"/>\n   <frame tileid=\"1571\" duration=\"100\"/>\n   <frame tileid=\"1579\" duration=\"100\"/>\n   <frame tileid=\"1587\" duration=\"100\"/>\n   <frame tileid=\"1595\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1540\" duration=\"100\"/>\n   <frame tileid=\"1548\" duration=\"100\"/>\n   <frame tileid=\"1556\" duration=\"100\"/>\n   <frame tileid=\"1564\" duration=\"100\"/>\n   <frame tileid=\"1572\" duration=\"100\"/>\n   <frame tileid=\"1580\" duration=\"100\"/>\n   <frame tileid=\"1588\" duration=\"100\"/>\n   <frame tileid=\"1596\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1541\" duration=\"100\"/>\n   <frame tileid=\"1549\" duration=\"100\"/>\n   <frame tileid=\"1557\" duration=\"100\"/>\n   <frame tileid=\"1565\" duration=\"100\"/>\n   <frame tileid=\"1573\" duration=\"100\"/>\n   <frame tileid=\"1581\" duration=\"100\"/>\n   <frame tileid=\"1589\" duration=\"100\"/>\n   <frame tileid=\"1597\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1542\" duration=\"100\"/>\n   <frame tileid=\"1550\" duration=\"100\"/>\n   <frame tileid=\"1558\" duration=\"100\"/>\n   <frame tileid=\"1566\" duration=\"100\"/>\n   <frame tileid=\"1574\" duration=\"100\"/>\n   <frame tileid=\"1582\" duration=\"100\"/>\n   <frame tileid=\"1590\" duration=\"100\"/>\n   <frame tileid=\"1598\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1543\" duration=\"100\"/>\n   <frame tileid=\"1551\" duration=\"100\"/>\n   <frame tileid=\"1559\" duration=\"100\"/>\n   <frame tileid=\"1567\" duration=\"100\"/>\n   <frame tileid=\"1575\" duration=\"100\"/>\n   <frame tileid=\"1583\" duration=\"100\"/>\n   <frame tileid=\"1591\" duration=\"100\"/>\n   <frame tileid=\"1599\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1600\" duration=\"100\"/>\n   <frame tileid=\"1608\" duration=\"100\"/>\n   <frame tileid=\"1616\" duration=\"100\"/>\n   <frame tileid=\"1624\" duration=\"100\"/>\n   <frame tileid=\"1632\" duration=\"100\"/>\n   <frame tileid=\"1640\" duration=\"100\"/>\n   <frame tileid=\"1648\" duration=\"100\"/>\n   <frame tileid=\"1656\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1601\" duration=\"100\"/>\n   <frame tileid=\"1609\" duration=\"100\"/>\n   <frame tileid=\"1617\" duration=\"100\"/>\n   <frame tileid=\"1625\" duration=\"100\"/>\n   <frame tileid=\"1633\" duration=\"100\"/>\n   <frame tileid=\"1641\" duration=\"100\"/>\n   <frame tileid=\"1649\" duration=\"100\"/>\n   <frame tileid=\"1657\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1602\" duration=\"100\"/>\n   <frame tileid=\"1610\" duration=\"100\"/>\n   <frame tileid=\"1618\" duration=\"100\"/>\n   <frame tileid=\"1626\" duration=\"100\"/>\n   <frame tileid=\"1634\" duration=\"100\"/>\n   <frame tileid=\"1642\" duration=\"100\"/>\n   <frame tileid=\"1650\" duration=\"100\"/>\n   <frame tileid=\"1658\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1603\" duration=\"100\"/>\n   <frame tileid=\"1611\" duration=\"100\"/>\n   <frame tileid=\"1619\" duration=\"100\"/>\n   <frame tileid=\"1627\" duration=\"100\"/>\n   <frame tileid=\"1635\" duration=\"100\"/>\n   <frame tileid=\"1643\" duration=\"100\"/>\n   <frame tileid=\"1651\" duration=\"100\"/>\n   <frame tileid=\"1659\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1604\" duration=\"100\"/>\n   <frame tileid=\"1612\" duration=\"100\"/>\n   <frame tileid=\"1620\" duration=\"100\"/>\n   <frame tileid=\"1628\" duration=\"100\"/>\n   <frame tileid=\"1636\" duration=\"100\"/>\n   <frame tileid=\"1644\" duration=\"100\"/>\n   <frame tileid=\"1652\" duration=\"100\"/>\n   <frame tileid=\"1660\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1605\" duration=\"100\"/>\n   <frame tileid=\"1613\" duration=\"100\"/>\n   <frame tileid=\"1621\" duration=\"100\"/>\n   <frame tileid=\"1629\" duration=\"100\"/>\n   <frame tileid=\"1637\" duration=\"100\"/>\n   <frame tileid=\"1645\" duration=\"100\"/>\n   <frame tileid=\"1653\" duration=\"100\"/>\n   <frame tileid=\"1661\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1606\" duration=\"100\"/>\n   <frame tileid=\"1614\" duration=\"100\"/>\n   <frame tileid=\"1622\" duration=\"100\"/>\n   <frame tileid=\"1630\" duration=\"100\"/>\n   <frame tileid=\"1638\" duration=\"100\"/>\n   <frame tileid=\"1646\" duration=\"100\"/>\n   <frame tileid=\"1654\" duration=\"100\"/>\n   <frame tileid=\"1662\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1607\" duration=\"100\"/>\n   <frame tileid=\"1615\" duration=\"100\"/>\n   <frame tileid=\"1623\" duration=\"100\"/>\n   <frame tileid=\"1631\" duration=\"100\"/>\n   <frame tileid=\"1639\" duration=\"100\"/>\n   <frame tileid=\"1647\" duration=\"100\"/>\n   <frame tileid=\"1655\" duration=\"100\"/>\n   <frame tileid=\"1663\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1664\" duration=\"100\"/>\n   <frame tileid=\"1672\" duration=\"100\"/>\n   <frame tileid=\"1680\" duration=\"100\"/>\n   <frame tileid=\"1688\" duration=\"100\"/>\n   <frame tileid=\"1696\" duration=\"100\"/>\n   <frame tileid=\"1704\" duration=\"100\"/>\n   <frame tileid=\"1712\" duration=\"100\"/>\n   <frame tileid=\"1720\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1665\" duration=\"100\"/>\n   <frame tileid=\"1673\" duration=\"100\"/>\n   <frame tileid=\"1681\" duration=\"100\"/>\n   <frame tileid=\"1689\" duration=\"100\"/>\n   <frame tileid=\"1697\" duration=\"100\"/>\n   <frame tileid=\"1705\" duration=\"100\"/>\n   <frame tileid=\"1713\" duration=\"100\"/>\n   <frame tileid=\"1721\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1666\" duration=\"100\"/>\n   <frame tileid=\"1674\" duration=\"100\"/>\n   <frame tileid=\"1682\" duration=\"100\"/>\n   <frame tileid=\"1690\" duration=\"100\"/>\n   <frame tileid=\"1698\" duration=\"100\"/>\n   <frame tileid=\"1706\" duration=\"100\"/>\n   <frame tileid=\"1714\" duration=\"100\"/>\n   <frame tileid=\"1722\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1667\" duration=\"100\"/>\n   <frame tileid=\"1675\" duration=\"100\"/>\n   <frame tileid=\"1683\" duration=\"100\"/>\n   <frame tileid=\"1691\" duration=\"100\"/>\n   <frame tileid=\"1699\" duration=\"100\"/>\n   <frame tileid=\"1707\" duration=\"100\"/>\n   <frame tileid=\"1715\" duration=\"100\"/>\n   <frame tileid=\"1723\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1668\" duration=\"100\"/>\n   <frame tileid=\"1676\" duration=\"100\"/>\n   <frame tileid=\"1684\" duration=\"100\"/>\n   <frame tileid=\"1692\" duration=\"100\"/>\n   <frame tileid=\"1700\" duration=\"100\"/>\n   <frame tileid=\"1708\" duration=\"100\"/>\n   <frame tileid=\"1716\" duration=\"100\"/>\n   <frame tileid=\"1724\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1669\" duration=\"100\"/>\n   <frame tileid=\"1677\" duration=\"100\"/>\n   <frame tileid=\"1685\" duration=\"100\"/>\n   <frame tileid=\"1693\" duration=\"100\"/>\n   <frame tileid=\"1701\" duration=\"100\"/>\n   <frame tileid=\"1709\" duration=\"100\"/>\n   <frame tileid=\"1717\" duration=\"100\"/>\n   <frame tileid=\"1725\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1670\" duration=\"100\"/>\n   <frame tileid=\"1678\" duration=\"100\"/>\n   <frame tileid=\"1686\" duration=\"100\"/>\n   <frame tileid=\"1694\" duration=\"100\"/>\n   <frame tileid=\"1702\" duration=\"100\"/>\n   <frame tileid=\"1710\" duration=\"100\"/>\n   <frame tileid=\"1718\" duration=\"100\"/>\n   <frame tileid=\"1726\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1671\" duration=\"100\"/>\n   <frame tileid=\"1679\" duration=\"100\"/>\n   <frame tileid=\"1687\" duration=\"100\"/>\n   <frame tileid=\"1695\" duration=\"100\"/>\n   <frame tileid=\"1703\" duration=\"100\"/>\n   <frame tileid=\"1711\" duration=\"100\"/>\n   <frame tileid=\"1719\" duration=\"100\"/>\n   <frame tileid=\"1727\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1728\" duration=\"100\"/>\n   <frame tileid=\"1736\" duration=\"100\"/>\n   <frame tileid=\"1744\" duration=\"100\"/>\n   <frame tileid=\"1752\" duration=\"100\"/>\n   <frame tileid=\"1760\" duration=\"100\"/>\n   <frame tileid=\"1768\" duration=\"100\"/>\n   <frame tileid=\"1776\" duration=\"100\"/>\n   <frame tileid=\"1784\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1729\" duration=\"100\"/>\n   <frame tileid=\"1737\" duration=\"100\"/>\n   <frame tileid=\"1745\" duration=\"100\"/>\n   <frame tileid=\"1753\" duration=\"100\"/>\n   <frame tileid=\"1761\" duration=\"100\"/>\n   <frame tileid=\"1769\" duration=\"100\"/>\n   <frame tileid=\"1777\" duration=\"100\"/>\n   <frame tileid=\"1785\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1730\" duration=\"100\"/>\n   <frame tileid=\"1738\" duration=\"100\"/>\n   <frame tileid=\"1746\" duration=\"100\"/>\n   <frame tileid=\"1754\" duration=\"100\"/>\n   <frame tileid=\"1762\" duration=\"100\"/>\n   <frame tileid=\"1770\" duration=\"100\"/>\n   <frame tileid=\"1778\" duration=\"100\"/>\n   <frame tileid=\"1786\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1731\" duration=\"100\"/>\n   <frame tileid=\"1739\" duration=\"100\"/>\n   <frame tileid=\"1747\" duration=\"100\"/>\n   <frame tileid=\"1755\" duration=\"100\"/>\n   <frame tileid=\"1763\" duration=\"100\"/>\n   <frame tileid=\"1771\" duration=\"100\"/>\n   <frame tileid=\"1779\" duration=\"100\"/>\n   <frame tileid=\"1787\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1732\" duration=\"100\"/>\n   <frame tileid=\"1740\" duration=\"100\"/>\n   <frame tileid=\"1748\" duration=\"100\"/>\n   <frame tileid=\"1756\" duration=\"100\"/>\n   <frame tileid=\"1764\" duration=\"100\"/>\n   <frame tileid=\"1772\" duration=\"100\"/>\n   <frame tileid=\"1780\" duration=\"100\"/>\n   <frame tileid=\"1788\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1733\" duration=\"100\"/>\n   <frame tileid=\"1741\" duration=\"100\"/>\n   <frame tileid=\"1749\" duration=\"100\"/>\n   <frame tileid=\"1757\" duration=\"100\"/>\n   <frame tileid=\"1765\" duration=\"100\"/>\n   <frame tileid=\"1773\" duration=\"100\"/>\n   <frame tileid=\"1781\" duration=\"100\"/>\n   <frame tileid=\"1789\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1734\" duration=\"100\"/>\n   <frame tileid=\"1742\" duration=\"100\"/>\n   <frame tileid=\"1750\" duration=\"100\"/>\n   <frame tileid=\"1758\" duration=\"100\"/>\n   <frame tileid=\"1766\" duration=\"100\"/>\n   <frame tileid=\"1774\" duration=\"100\"/>\n   <frame tileid=\"1782\" duration=\"100\"/>\n   <frame tileid=\"1790\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1735\" duration=\"100\"/>\n   <frame tileid=\"1743\" duration=\"100\"/>\n   <frame tileid=\"1751\" duration=\"100\"/>\n   <frame tileid=\"1759\" duration=\"100\"/>\n   <frame tileid=\"1767\" duration=\"100\"/>\n   <frame tileid=\"1775\" duration=\"100\"/>\n   <frame tileid=\"1783\" duration=\"100\"/>\n   <frame tileid=\"1791\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1792\" duration=\"100\"/>\n   <frame tileid=\"1800\" duration=\"100\"/>\n   <frame tileid=\"1808\" duration=\"100\"/>\n   <frame tileid=\"1816\" duration=\"100\"/>\n   <frame tileid=\"1824\" duration=\"100\"/>\n   <frame tileid=\"1832\" duration=\"100\"/>\n   <frame tileid=\"1840\" duration=\"100\"/>\n   <frame tileid=\"1848\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1793\" duration=\"100\"/>\n   <frame tileid=\"1801\" duration=\"100\"/>\n   <frame tileid=\"1809\" duration=\"100\"/>\n   <frame tileid=\"1817\" duration=\"100\"/>\n   <frame tileid=\"1825\" duration=\"100\"/>\n   <frame tileid=\"1833\" duration=\"100\"/>\n   <frame tileid=\"1841\" duration=\"100\"/>\n   <frame tileid=\"1849\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1794\" duration=\"100\"/>\n   <frame tileid=\"1802\" duration=\"100\"/>\n   <frame tileid=\"1810\" duration=\"100\"/>\n   <frame tileid=\"1818\" duration=\"100\"/>\n   <frame tileid=\"1826\" duration=\"100\"/>\n   <frame tileid=\"1834\" duration=\"100\"/>\n   <frame tileid=\"1842\" duration=\"100\"/>\n   <frame tileid=\"1850\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1795\" duration=\"100\"/>\n   <frame tileid=\"1803\" duration=\"100\"/>\n   <frame tileid=\"1811\" duration=\"100\"/>\n   <frame tileid=\"1819\" duration=\"100\"/>\n   <frame tileid=\"1827\" duration=\"100\"/>\n   <frame tileid=\"1835\" duration=\"100\"/>\n   <frame tileid=\"1843\" duration=\"100\"/>\n   <frame tileid=\"1851\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1796\" duration=\"100\"/>\n   <frame tileid=\"1804\" duration=\"100\"/>\n   <frame tileid=\"1812\" duration=\"100\"/>\n   <frame tileid=\"1820\" duration=\"100\"/>\n   <frame tileid=\"1828\" duration=\"100\"/>\n   <frame tileid=\"1836\" duration=\"100\"/>\n   <frame tileid=\"1844\" duration=\"100\"/>\n   <frame tileid=\"1852\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1797\" duration=\"100\"/>\n   <frame tileid=\"1805\" duration=\"100\"/>\n   <frame tileid=\"1813\" duration=\"100\"/>\n   <frame tileid=\"1821\" duration=\"100\"/>\n   <frame tileid=\"1829\" duration=\"100\"/>\n   <frame tileid=\"1837\" duration=\"100\"/>\n   <frame tileid=\"1845\" duration=\"100\"/>\n   <frame tileid=\"1853\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1798\" duration=\"100\"/>\n   <frame tileid=\"1806\" duration=\"100\"/>\n   <frame tileid=\"1814\" duration=\"100\"/>\n   <frame tileid=\"1822\" duration=\"100\"/>\n   <frame tileid=\"1830\" duration=\"100\"/>\n   <frame tileid=\"1838\" duration=\"100\"/>\n   <frame tileid=\"1846\" duration=\"100\"/>\n   <frame tileid=\"1854\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1799\" duration=\"100\"/>\n   <frame tileid=\"1807\" duration=\"100\"/>\n   <frame tileid=\"1815\" duration=\"100\"/>\n   <frame tileid=\"1823\" duration=\"100\"/>\n   <frame tileid=\"1831\" duration=\"100\"/>\n   <frame tileid=\"1839\" duration=\"100\"/>\n   <frame tileid=\"1847\" duration=\"100\"/>\n   <frame tileid=\"1855\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1856\" duration=\"100\"/>\n   <frame tileid=\"1864\" duration=\"100\"/>\n   <frame tileid=\"1872\" duration=\"100\"/>\n   <frame tileid=\"1880\" duration=\"100\"/>\n   <frame tileid=\"1888\" duration=\"100\"/>\n   <frame tileid=\"1896\" duration=\"100\"/>\n   <frame tileid=\"1904\" duration=\"100\"/>\n   <frame tileid=\"1912\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1857\" duration=\"100\"/>\n   <frame tileid=\"1865\" duration=\"100\"/>\n   <frame tileid=\"1873\" duration=\"100\"/>\n   <frame tileid=\"1881\" duration=\"100\"/>\n   <frame tileid=\"1889\" duration=\"100\"/>\n   <frame tileid=\"1897\" duration=\"100\"/>\n   <frame tileid=\"1905\" duration=\"100\"/>\n   <frame tileid=\"1913\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1858\" duration=\"100\"/>\n   <frame tileid=\"1866\" duration=\"100\"/>\n   <frame tileid=\"1874\" duration=\"100\"/>\n   <frame tileid=\"1882\" duration=\"100\"/>\n   <frame tileid=\"1890\" duration=\"100\"/>\n   <frame tileid=\"1898\" duration=\"100\"/>\n   <frame tileid=\"1906\" duration=\"100\"/>\n   <frame tileid=\"1914\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1859\" duration=\"100\"/>\n   <frame tileid=\"1867\" duration=\"100\"/>\n   <frame tileid=\"1875\" duration=\"100\"/>\n   <frame tileid=\"1883\" duration=\"100\"/>\n   <frame tileid=\"1891\" duration=\"100\"/>\n   <frame tileid=\"1899\" duration=\"100\"/>\n   <frame tileid=\"1907\" duration=\"100\"/>\n   <frame tileid=\"1915\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1860\" duration=\"100\"/>\n   <frame tileid=\"1868\" duration=\"100\"/>\n   <frame tileid=\"1876\" duration=\"100\"/>\n   <frame tileid=\"1884\" duration=\"100\"/>\n   <frame tileid=\"1892\" duration=\"100\"/>\n   <frame tileid=\"1900\" duration=\"100\"/>\n   <frame tileid=\"1908\" duration=\"100\"/>\n   <frame tileid=\"1916\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1861\" duration=\"100\"/>\n   <frame tileid=\"1869\" duration=\"100\"/>\n   <frame tileid=\"1877\" duration=\"100\"/>\n   <frame tileid=\"1885\" duration=\"100\"/>\n   <frame tileid=\"1893\" duration=\"100\"/>\n   <frame tileid=\"1901\" duration=\"100\"/>\n   <frame tileid=\"1909\" duration=\"100\"/>\n   <frame tileid=\"1917\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1862\" duration=\"100\"/>\n   <frame tileid=\"1870\" duration=\"100\"/>\n   <frame tileid=\"1878\" duration=\"100\"/>\n   <frame tileid=\"1886\" duration=\"100\"/>\n   <frame tileid=\"1894\" duration=\"100\"/>\n   <frame tileid=\"1902\" duration=\"100\"/>\n   <frame tileid=\"1910\" duration=\"100\"/>\n   <frame tileid=\"1918\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1863\" duration=\"100\"/>\n   <frame tileid=\"1871\" duration=\"100\"/>\n   <frame tileid=\"1879\" duration=\"100\"/>\n   <frame tileid=\"1887\" duration=\"100\"/>\n   <frame tileid=\"1895\" duration=\"100\"/>\n   <frame tileid=\"1903\" duration=\"100\"/>\n   <frame tileid=\"1911\" duration=\"100\"/>\n   <frame tileid=\"1919\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1920\" duration=\"100\"/>\n   <frame tileid=\"1928\" duration=\"100\"/>\n   <frame tileid=\"1936\" duration=\"100\"/>\n   <frame tileid=\"1944\" duration=\"100\"/>\n   <frame tileid=\"1952\" duration=\"100\"/>\n   <frame tileid=\"1960\" duration=\"100\"/>\n   <frame tileid=\"1968\" duration=\"100\"/>\n   <frame tileid=\"1976\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1921\" duration=\"100\"/>\n   <frame tileid=\"1929\" duration=\"100\"/>\n   <frame tileid=\"1937\" duration=\"100\"/>\n   <frame tileid=\"1945\" duration=\"100\"/>\n   <frame tileid=\"1953\" duration=\"100\"/>\n   <frame tileid=\"1961\" duration=\"100\"/>\n   <frame tileid=\"1969\" duration=\"100\"/>\n   <frame tileid=\"1977\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1922\" duration=\"100\"/>\n   <frame tileid=\"1930\" duration=\"100\"/>\n   <frame tileid=\"1938\" duration=\"100\"/>\n   <frame tileid=\"1946\" duration=\"100\"/>\n   <frame tileid=\"1954\" duration=\"100\"/>\n   <frame tileid=\"1962\" duration=\"100\"/>\n   <frame tileid=\"1970\" duration=\"100\"/>\n   <frame tileid=\"1978\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1923\" duration=\"100\"/>\n   <frame tileid=\"1931\" duration=\"100\"/>\n   <frame tileid=\"1939\" duration=\"100\"/>\n   <frame tileid=\"1947\" duration=\"100\"/>\n   <frame tileid=\"1955\" duration=\"100\"/>\n   <frame tileid=\"1963\" duration=\"100\"/>\n   <frame tileid=\"1971\" duration=\"100\"/>\n   <frame tileid=\"1979\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1924\" duration=\"100\"/>\n   <frame tileid=\"1932\" duration=\"100\"/>\n   <frame tileid=\"1940\" duration=\"100\"/>\n   <frame tileid=\"1948\" duration=\"100\"/>\n   <frame tileid=\"1956\" duration=\"100\"/>\n   <frame tileid=\"1964\" duration=\"100\"/>\n   <frame tileid=\"1972\" duration=\"100\"/>\n   <frame tileid=\"1980\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1925\" duration=\"100\"/>\n   <frame tileid=\"1933\" duration=\"100\"/>\n   <frame tileid=\"1941\" duration=\"100\"/>\n   <frame tileid=\"1949\" duration=\"100\"/>\n   <frame tileid=\"1957\" duration=\"100\"/>\n   <frame tileid=\"1965\" duration=\"100\"/>\n   <frame tileid=\"1973\" duration=\"100\"/>\n   <frame tileid=\"1981\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1926\" duration=\"100\"/>\n   <frame tileid=\"1934\" duration=\"100\"/>\n   <frame tileid=\"1942\" duration=\"100\"/>\n   <frame tileid=\"1950\" duration=\"100\"/>\n   <frame tileid=\"1958\" duration=\"100\"/>\n   <frame tileid=\"1966\" duration=\"100\"/>\n   <frame tileid=\"1974\" duration=\"100\"/>\n   <frame tileid=\"1982\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1927\" duration=\"100\"/>\n   <frame tileid=\"1935\" duration=\"100\"/>\n   <frame tileid=\"1943\" duration=\"100\"/>\n   <frame tileid=\"1951\" duration=\"100\"/>\n   <frame tileid=\"1959\" duration=\"100\"/>\n   <frame tileid=\"1967\" duration=\"100\"/>\n   <frame tileid=\"1975\" duration=\"100\"/>\n   <frame tileid=\"1983\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1984\" duration=\"100\"/>\n   <frame tileid=\"1992\" duration=\"100\"/>\n   <frame tileid=\"2000\" duration=\"100\"/>\n   <frame tileid=\"2008\" duration=\"100\"/>\n   <frame tileid=\"2016\" duration=\"100\"/>\n   <frame tileid=\"2024\" duration=\"100\"/>\n   <frame tileid=\"2032\" duration=\"100\"/>\n   <frame tileid=\"2040\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1985\" duration=\"100\"/>\n   <frame tileid=\"1993\" duration=\"100\"/>\n   <frame tileid=\"2001\" duration=\"100\"/>\n   <frame tileid=\"2009\" duration=\"100\"/>\n   <frame tileid=\"2017\" duration=\"100\"/>\n   <frame tileid=\"2025\" duration=\"100\"/>\n   <frame tileid=\"2033\" duration=\"100\"/>\n   <frame tileid=\"2041\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1986\" duration=\"100\"/>\n   <frame tileid=\"1994\" duration=\"100\"/>\n   <frame tileid=\"2002\" duration=\"100\"/>\n   <frame tileid=\"2010\" duration=\"100\"/>\n   <frame tileid=\"2018\" duration=\"100\"/>\n   <frame tileid=\"2026\" duration=\"100\"/>\n   <frame tileid=\"2034\" duration=\"100\"/>\n   <frame tileid=\"2042\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1987\" duration=\"100\"/>\n   <frame tileid=\"1995\" duration=\"100\"/>\n   <frame tileid=\"2003\" duration=\"100\"/>\n   <frame tileid=\"2011\" duration=\"100\"/>\n   <frame tileid=\"2019\" duration=\"100\"/>\n   <frame tileid=\"2027\" duration=\"100\"/>\n   <frame tileid=\"2035\" duration=\"100\"/>\n   <frame tileid=\"2043\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1988\" duration=\"100\"/>\n   <frame tileid=\"1996\" duration=\"100\"/>\n   <frame tileid=\"2004\" duration=\"100\"/>\n   <frame tileid=\"2012\" duration=\"100\"/>\n   <frame tileid=\"2020\" duration=\"100\"/>\n   <frame tileid=\"2028\" duration=\"100\"/>\n   <frame tileid=\"2036\" duration=\"100\"/>\n   <frame tileid=\"2044\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1989\" duration=\"100\"/>\n   <frame tileid=\"1997\" duration=\"100\"/>\n   <frame tileid=\"2005\" duration=\"100\"/>\n   <frame tileid=\"2013\" duration=\"100\"/>\n   <frame tileid=\"2021\" duration=\"100\"/>\n   <frame tileid=\"2029\" duration=\"100\"/>\n   <frame tileid=\"2037\" duration=\"100\"/>\n   <frame tileid=\"2045\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1990\" duration=\"100\"/>\n   <frame tileid=\"1998\" duration=\"100\"/>\n   <frame tileid=\"2006\" duration=\"100\"/>\n   <frame tileid=\"2014\" duration=\"100\"/>\n   <frame tileid=\"2022\" duration=\"100\"/>\n   <frame tileid=\"2030\" duration=\"100\"/>\n   <frame tileid=\"2038\" duration=\"100\"/>\n   <frame tileid=\"2046\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"1991\" duration=\"100\"/>\n   <frame tileid=\"1999\" duration=\"100\"/>\n   <frame tileid=\"2007\" duration=\"100\"/>\n   <frame tileid=\"2015\" duration=\"100\"/>\n   <frame tileid=\"2023\" duration=\"100\"/>\n   <frame tileid=\"2031\" duration=\"100\"/>\n   <frame tileid=\"2039\" duration=\"100\"/>\n   <frame tileid=\"2047\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"1992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"1999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2000\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2001\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2002\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2003\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2004\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2005\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2006\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2007\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2008\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2009\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2010\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2011\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2012\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2013\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2014\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2015\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2016\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2017\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2018\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2019\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2020\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2021\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2022\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2023\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2024\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2025\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2026\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2027\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2028\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2029\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2030\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2031\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2032\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2033\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2034\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2035\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2036\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2037\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2038\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2039\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2040\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2041\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2042\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2043\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2044\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2045\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2046\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2047\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2048\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2048\" duration=\"100\"/>\n   <frame tileid=\"2056\" duration=\"100\"/>\n   <frame tileid=\"2064\" duration=\"100\"/>\n   <frame tileid=\"2072\" duration=\"100\"/>\n   <frame tileid=\"2080\" duration=\"100\"/>\n   <frame tileid=\"2088\" duration=\"100\"/>\n   <frame tileid=\"2096\" duration=\"100\"/>\n   <frame tileid=\"2104\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2049\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2049\" duration=\"100\"/>\n   <frame tileid=\"2057\" duration=\"100\"/>\n   <frame tileid=\"2065\" duration=\"100\"/>\n   <frame tileid=\"2073\" duration=\"100\"/>\n   <frame tileid=\"2081\" duration=\"100\"/>\n   <frame tileid=\"2089\" duration=\"100\"/>\n   <frame tileid=\"2097\" duration=\"100\"/>\n   <frame tileid=\"2105\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2050\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2050\" duration=\"100\"/>\n   <frame tileid=\"2058\" duration=\"100\"/>\n   <frame tileid=\"2066\" duration=\"100\"/>\n   <frame tileid=\"2074\" duration=\"100\"/>\n   <frame tileid=\"2082\" duration=\"100\"/>\n   <frame tileid=\"2090\" duration=\"100\"/>\n   <frame tileid=\"2098\" duration=\"100\"/>\n   <frame tileid=\"2106\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2051\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2051\" duration=\"100\"/>\n   <frame tileid=\"2059\" duration=\"100\"/>\n   <frame tileid=\"2067\" duration=\"100\"/>\n   <frame tileid=\"2075\" duration=\"100\"/>\n   <frame tileid=\"2083\" duration=\"100\"/>\n   <frame tileid=\"2091\" duration=\"100\"/>\n   <frame tileid=\"2099\" duration=\"100\"/>\n   <frame tileid=\"2107\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2052\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2052\" duration=\"100\"/>\n   <frame tileid=\"2060\" duration=\"100\"/>\n   <frame tileid=\"2068\" duration=\"100\"/>\n   <frame tileid=\"2076\" duration=\"100\"/>\n   <frame tileid=\"2084\" duration=\"100\"/>\n   <frame tileid=\"2092\" duration=\"100\"/>\n   <frame tileid=\"2100\" duration=\"100\"/>\n   <frame tileid=\"2108\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2053\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2053\" duration=\"100\"/>\n   <frame tileid=\"2061\" duration=\"100\"/>\n   <frame tileid=\"2069\" duration=\"100\"/>\n   <frame tileid=\"2077\" duration=\"100\"/>\n   <frame tileid=\"2085\" duration=\"100\"/>\n   <frame tileid=\"2093\" duration=\"100\"/>\n   <frame tileid=\"2101\" duration=\"100\"/>\n   <frame tileid=\"2109\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2054\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2054\" duration=\"100\"/>\n   <frame tileid=\"2062\" duration=\"100\"/>\n   <frame tileid=\"2070\" duration=\"100\"/>\n   <frame tileid=\"2078\" duration=\"100\"/>\n   <frame tileid=\"2086\" duration=\"100\"/>\n   <frame tileid=\"2094\" duration=\"100\"/>\n   <frame tileid=\"2102\" duration=\"100\"/>\n   <frame tileid=\"2110\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2055\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2055\" duration=\"100\"/>\n   <frame tileid=\"2063\" duration=\"100\"/>\n   <frame tileid=\"2071\" duration=\"100\"/>\n   <frame tileid=\"2079\" duration=\"100\"/>\n   <frame tileid=\"2087\" duration=\"100\"/>\n   <frame tileid=\"2095\" duration=\"100\"/>\n   <frame tileid=\"2103\" duration=\"100\"/>\n   <frame tileid=\"2111\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2056\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2057\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2058\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2059\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2060\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2061\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2062\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2063\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2064\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2065\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2066\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2067\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2068\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2069\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2070\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2071\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2072\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2073\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2074\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2075\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2076\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2077\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2078\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2079\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2080\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2081\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2082\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2083\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2084\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2085\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2086\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2087\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2088\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2089\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2090\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2091\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2092\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2093\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2094\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2095\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2096\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2097\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2098\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2099\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2112\" duration=\"100\"/>\n   <frame tileid=\"2120\" duration=\"100\"/>\n   <frame tileid=\"2128\" duration=\"100\"/>\n   <frame tileid=\"2136\" duration=\"100\"/>\n   <frame tileid=\"2144\" duration=\"100\"/>\n   <frame tileid=\"2152\" duration=\"100\"/>\n   <frame tileid=\"2160\" duration=\"100\"/>\n   <frame tileid=\"2168\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2113\" duration=\"100\"/>\n   <frame tileid=\"2121\" duration=\"100\"/>\n   <frame tileid=\"2129\" duration=\"100\"/>\n   <frame tileid=\"2137\" duration=\"100\"/>\n   <frame tileid=\"2145\" duration=\"100\"/>\n   <frame tileid=\"2153\" duration=\"100\"/>\n   <frame tileid=\"2161\" duration=\"100\"/>\n   <frame tileid=\"2169\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2114\" duration=\"100\"/>\n   <frame tileid=\"2122\" duration=\"100\"/>\n   <frame tileid=\"2130\" duration=\"100\"/>\n   <frame tileid=\"2138\" duration=\"100\"/>\n   <frame tileid=\"2146\" duration=\"100\"/>\n   <frame tileid=\"2154\" duration=\"100\"/>\n   <frame tileid=\"2162\" duration=\"100\"/>\n   <frame tileid=\"2170\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2115\" duration=\"100\"/>\n   <frame tileid=\"2123\" duration=\"100\"/>\n   <frame tileid=\"2131\" duration=\"100\"/>\n   <frame tileid=\"2139\" duration=\"100\"/>\n   <frame tileid=\"2147\" duration=\"100\"/>\n   <frame tileid=\"2155\" duration=\"100\"/>\n   <frame tileid=\"2163\" duration=\"100\"/>\n   <frame tileid=\"2171\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2116\" duration=\"100\"/>\n   <frame tileid=\"2124\" duration=\"100\"/>\n   <frame tileid=\"2132\" duration=\"100\"/>\n   <frame tileid=\"2140\" duration=\"100\"/>\n   <frame tileid=\"2148\" duration=\"100\"/>\n   <frame tileid=\"2156\" duration=\"100\"/>\n   <frame tileid=\"2164\" duration=\"100\"/>\n   <frame tileid=\"2172\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2117\" duration=\"100\"/>\n   <frame tileid=\"2125\" duration=\"100\"/>\n   <frame tileid=\"2133\" duration=\"100\"/>\n   <frame tileid=\"2141\" duration=\"100\"/>\n   <frame tileid=\"2149\" duration=\"100\"/>\n   <frame tileid=\"2157\" duration=\"100\"/>\n   <frame tileid=\"2165\" duration=\"100\"/>\n   <frame tileid=\"2173\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2118\" duration=\"100\"/>\n   <frame tileid=\"2126\" duration=\"100\"/>\n   <frame tileid=\"2134\" duration=\"100\"/>\n   <frame tileid=\"2142\" duration=\"100\"/>\n   <frame tileid=\"2150\" duration=\"100\"/>\n   <frame tileid=\"2158\" duration=\"100\"/>\n   <frame tileid=\"2166\" duration=\"100\"/>\n   <frame tileid=\"2174\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2119\" duration=\"100\"/>\n   <frame tileid=\"2127\" duration=\"100\"/>\n   <frame tileid=\"2135\" duration=\"100\"/>\n   <frame tileid=\"2143\" duration=\"100\"/>\n   <frame tileid=\"2151\" duration=\"100\"/>\n   <frame tileid=\"2159\" duration=\"100\"/>\n   <frame tileid=\"2167\" duration=\"100\"/>\n   <frame tileid=\"2175\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2121\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2141\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2176\" duration=\"100\"/>\n   <frame tileid=\"2184\" duration=\"100\"/>\n   <frame tileid=\"2192\" duration=\"100\"/>\n   <frame tileid=\"2200\" duration=\"100\"/>\n   <frame tileid=\"2208\" duration=\"100\"/>\n   <frame tileid=\"2216\" duration=\"100\"/>\n   <frame tileid=\"2224\" duration=\"100\"/>\n   <frame tileid=\"2232\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2177\" duration=\"100\"/>\n   <frame tileid=\"2185\" duration=\"100\"/>\n   <frame tileid=\"2193\" duration=\"100\"/>\n   <frame tileid=\"2201\" duration=\"100\"/>\n   <frame tileid=\"2209\" duration=\"100\"/>\n   <frame tileid=\"2217\" duration=\"100\"/>\n   <frame tileid=\"2225\" duration=\"100\"/>\n   <frame tileid=\"2233\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2178\" duration=\"100\"/>\n   <frame tileid=\"2186\" duration=\"100\"/>\n   <frame tileid=\"2194\" duration=\"100\"/>\n   <frame tileid=\"2202\" duration=\"100\"/>\n   <frame tileid=\"2210\" duration=\"100\"/>\n   <frame tileid=\"2218\" duration=\"100\"/>\n   <frame tileid=\"2226\" duration=\"100\"/>\n   <frame tileid=\"2234\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2179\" duration=\"100\"/>\n   <frame tileid=\"2187\" duration=\"100\"/>\n   <frame tileid=\"2195\" duration=\"100\"/>\n   <frame tileid=\"2203\" duration=\"100\"/>\n   <frame tileid=\"2211\" duration=\"100\"/>\n   <frame tileid=\"2219\" duration=\"100\"/>\n   <frame tileid=\"2227\" duration=\"100\"/>\n   <frame tileid=\"2235\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2180\" duration=\"100\"/>\n   <frame tileid=\"2188\" duration=\"100\"/>\n   <frame tileid=\"2196\" duration=\"100\"/>\n   <frame tileid=\"2204\" duration=\"100\"/>\n   <frame tileid=\"2212\" duration=\"100\"/>\n   <frame tileid=\"2220\" duration=\"100\"/>\n   <frame tileid=\"2228\" duration=\"100\"/>\n   <frame tileid=\"2236\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2181\" duration=\"100\"/>\n   <frame tileid=\"2189\" duration=\"100\"/>\n   <frame tileid=\"2197\" duration=\"100\"/>\n   <frame tileid=\"2205\" duration=\"100\"/>\n   <frame tileid=\"2213\" duration=\"100\"/>\n   <frame tileid=\"2221\" duration=\"100\"/>\n   <frame tileid=\"2229\" duration=\"100\"/>\n   <frame tileid=\"2237\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2182\" duration=\"100\"/>\n   <frame tileid=\"2190\" duration=\"100\"/>\n   <frame tileid=\"2198\" duration=\"100\"/>\n   <frame tileid=\"2206\" duration=\"100\"/>\n   <frame tileid=\"2214\" duration=\"100\"/>\n   <frame tileid=\"2222\" duration=\"100\"/>\n   <frame tileid=\"2230\" duration=\"100\"/>\n   <frame tileid=\"2238\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2183\" duration=\"100\"/>\n   <frame tileid=\"2191\" duration=\"100\"/>\n   <frame tileid=\"2199\" duration=\"100\"/>\n   <frame tileid=\"2207\" duration=\"100\"/>\n   <frame tileid=\"2215\" duration=\"100\"/>\n   <frame tileid=\"2223\" duration=\"100\"/>\n   <frame tileid=\"2231\" duration=\"100\"/>\n   <frame tileid=\"2239\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2240\" duration=\"100\"/>\n   <frame tileid=\"2248\" duration=\"100\"/>\n   <frame tileid=\"2256\" duration=\"100\"/>\n   <frame tileid=\"2264\" duration=\"100\"/>\n   <frame tileid=\"2272\" duration=\"100\"/>\n   <frame tileid=\"2280\" duration=\"100\"/>\n   <frame tileid=\"2288\" duration=\"100\"/>\n   <frame tileid=\"2296\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2241\" duration=\"100\"/>\n   <frame tileid=\"2249\" duration=\"100\"/>\n   <frame tileid=\"2257\" duration=\"100\"/>\n   <frame tileid=\"2265\" duration=\"100\"/>\n   <frame tileid=\"2273\" duration=\"100\"/>\n   <frame tileid=\"2281\" duration=\"100\"/>\n   <frame tileid=\"2289\" duration=\"100\"/>\n   <frame tileid=\"2297\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2242\" duration=\"100\"/>\n   <frame tileid=\"2250\" duration=\"100\"/>\n   <frame tileid=\"2258\" duration=\"100\"/>\n   <frame tileid=\"2266\" duration=\"100\"/>\n   <frame tileid=\"2274\" duration=\"100\"/>\n   <frame tileid=\"2282\" duration=\"100\"/>\n   <frame tileid=\"2290\" duration=\"100\"/>\n   <frame tileid=\"2298\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2243\" duration=\"100\"/>\n   <frame tileid=\"2251\" duration=\"100\"/>\n   <frame tileid=\"2259\" duration=\"100\"/>\n   <frame tileid=\"2267\" duration=\"100\"/>\n   <frame tileid=\"2275\" duration=\"100\"/>\n   <frame tileid=\"2283\" duration=\"100\"/>\n   <frame tileid=\"2291\" duration=\"100\"/>\n   <frame tileid=\"2299\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2244\" duration=\"100\"/>\n   <frame tileid=\"2252\" duration=\"100\"/>\n   <frame tileid=\"2260\" duration=\"100\"/>\n   <frame tileid=\"2268\" duration=\"100\"/>\n   <frame tileid=\"2276\" duration=\"100\"/>\n   <frame tileid=\"2284\" duration=\"100\"/>\n   <frame tileid=\"2292\" duration=\"100\"/>\n   <frame tileid=\"2300\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2245\" duration=\"100\"/>\n   <frame tileid=\"2253\" duration=\"100\"/>\n   <frame tileid=\"2261\" duration=\"100\"/>\n   <frame tileid=\"2269\" duration=\"100\"/>\n   <frame tileid=\"2277\" duration=\"100\"/>\n   <frame tileid=\"2285\" duration=\"100\"/>\n   <frame tileid=\"2293\" duration=\"100\"/>\n   <frame tileid=\"2301\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2246\" duration=\"100\"/>\n   <frame tileid=\"2254\" duration=\"100\"/>\n   <frame tileid=\"2262\" duration=\"100\"/>\n   <frame tileid=\"2270\" duration=\"100\"/>\n   <frame tileid=\"2278\" duration=\"100\"/>\n   <frame tileid=\"2286\" duration=\"100\"/>\n   <frame tileid=\"2294\" duration=\"100\"/>\n   <frame tileid=\"2302\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2247\" duration=\"100\"/>\n   <frame tileid=\"2255\" duration=\"100\"/>\n   <frame tileid=\"2263\" duration=\"100\"/>\n   <frame tileid=\"2271\" duration=\"100\"/>\n   <frame tileid=\"2279\" duration=\"100\"/>\n   <frame tileid=\"2287\" duration=\"100\"/>\n   <frame tileid=\"2295\" duration=\"100\"/>\n   <frame tileid=\"2303\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2304\" duration=\"100\"/>\n   <frame tileid=\"2312\" duration=\"100\"/>\n   <frame tileid=\"2320\" duration=\"100\"/>\n   <frame tileid=\"2328\" duration=\"100\"/>\n   <frame tileid=\"2336\" duration=\"100\"/>\n   <frame tileid=\"2344\" duration=\"100\"/>\n   <frame tileid=\"2352\" duration=\"100\"/>\n   <frame tileid=\"2360\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2305\" duration=\"100\"/>\n   <frame tileid=\"2313\" duration=\"100\"/>\n   <frame tileid=\"2321\" duration=\"100\"/>\n   <frame tileid=\"2329\" duration=\"100\"/>\n   <frame tileid=\"2337\" duration=\"100\"/>\n   <frame tileid=\"2345\" duration=\"100\"/>\n   <frame tileid=\"2353\" duration=\"100\"/>\n   <frame tileid=\"2361\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2306\" duration=\"100\"/>\n   <frame tileid=\"2314\" duration=\"100\"/>\n   <frame tileid=\"2322\" duration=\"100\"/>\n   <frame tileid=\"2330\" duration=\"100\"/>\n   <frame tileid=\"2338\" duration=\"100\"/>\n   <frame tileid=\"2346\" duration=\"100\"/>\n   <frame tileid=\"2354\" duration=\"100\"/>\n   <frame tileid=\"2362\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2307\" duration=\"100\"/>\n   <frame tileid=\"2315\" duration=\"100\"/>\n   <frame tileid=\"2323\" duration=\"100\"/>\n   <frame tileid=\"2331\" duration=\"100\"/>\n   <frame tileid=\"2339\" duration=\"100\"/>\n   <frame tileid=\"2347\" duration=\"100\"/>\n   <frame tileid=\"2355\" duration=\"100\"/>\n   <frame tileid=\"2363\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2308\" duration=\"100\"/>\n   <frame tileid=\"2316\" duration=\"100\"/>\n   <frame tileid=\"2324\" duration=\"100\"/>\n   <frame tileid=\"2332\" duration=\"100\"/>\n   <frame tileid=\"2340\" duration=\"100\"/>\n   <frame tileid=\"2348\" duration=\"100\"/>\n   <frame tileid=\"2356\" duration=\"100\"/>\n   <frame tileid=\"2364\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2309\" duration=\"100\"/>\n   <frame tileid=\"2317\" duration=\"100\"/>\n   <frame tileid=\"2325\" duration=\"100\"/>\n   <frame tileid=\"2333\" duration=\"100\"/>\n   <frame tileid=\"2341\" duration=\"100\"/>\n   <frame tileid=\"2349\" duration=\"100\"/>\n   <frame tileid=\"2357\" duration=\"100\"/>\n   <frame tileid=\"2365\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2310\" duration=\"100\"/>\n   <frame tileid=\"2318\" duration=\"100\"/>\n   <frame tileid=\"2326\" duration=\"100\"/>\n   <frame tileid=\"2334\" duration=\"100\"/>\n   <frame tileid=\"2342\" duration=\"100\"/>\n   <frame tileid=\"2350\" duration=\"100\"/>\n   <frame tileid=\"2358\" duration=\"100\"/>\n   <frame tileid=\"2366\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2311\" duration=\"100\"/>\n   <frame tileid=\"2319\" duration=\"100\"/>\n   <frame tileid=\"2327\" duration=\"100\"/>\n   <frame tileid=\"2335\" duration=\"100\"/>\n   <frame tileid=\"2343\" duration=\"100\"/>\n   <frame tileid=\"2351\" duration=\"100\"/>\n   <frame tileid=\"2359\" duration=\"100\"/>\n   <frame tileid=\"2367\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2368\" duration=\"100\"/>\n   <frame tileid=\"2376\" duration=\"100\"/>\n   <frame tileid=\"2384\" duration=\"100\"/>\n   <frame tileid=\"2392\" duration=\"100\"/>\n   <frame tileid=\"2400\" duration=\"100\"/>\n   <frame tileid=\"2408\" duration=\"100\"/>\n   <frame tileid=\"2416\" duration=\"100\"/>\n   <frame tileid=\"2424\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2369\" duration=\"100\"/>\n   <frame tileid=\"2377\" duration=\"100\"/>\n   <frame tileid=\"2385\" duration=\"100\"/>\n   <frame tileid=\"2393\" duration=\"100\"/>\n   <frame tileid=\"2401\" duration=\"100\"/>\n   <frame tileid=\"2409\" duration=\"100\"/>\n   <frame tileid=\"2417\" duration=\"100\"/>\n   <frame tileid=\"2425\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2370\" duration=\"100\"/>\n   <frame tileid=\"2378\" duration=\"100\"/>\n   <frame tileid=\"2386\" duration=\"100\"/>\n   <frame tileid=\"2394\" duration=\"100\"/>\n   <frame tileid=\"2402\" duration=\"100\"/>\n   <frame tileid=\"2410\" duration=\"100\"/>\n   <frame tileid=\"2418\" duration=\"100\"/>\n   <frame tileid=\"2426\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2371\" duration=\"100\"/>\n   <frame tileid=\"2379\" duration=\"100\"/>\n   <frame tileid=\"2387\" duration=\"100\"/>\n   <frame tileid=\"2395\" duration=\"100\"/>\n   <frame tileid=\"2403\" duration=\"100\"/>\n   <frame tileid=\"2411\" duration=\"100\"/>\n   <frame tileid=\"2419\" duration=\"100\"/>\n   <frame tileid=\"2427\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2372\" duration=\"100\"/>\n   <frame tileid=\"2380\" duration=\"100\"/>\n   <frame tileid=\"2388\" duration=\"100\"/>\n   <frame tileid=\"2396\" duration=\"100\"/>\n   <frame tileid=\"2404\" duration=\"100\"/>\n   <frame tileid=\"2412\" duration=\"100\"/>\n   <frame tileid=\"2420\" duration=\"100\"/>\n   <frame tileid=\"2428\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2373\" duration=\"100\"/>\n   <frame tileid=\"2381\" duration=\"100\"/>\n   <frame tileid=\"2389\" duration=\"100\"/>\n   <frame tileid=\"2397\" duration=\"100\"/>\n   <frame tileid=\"2405\" duration=\"100\"/>\n   <frame tileid=\"2413\" duration=\"100\"/>\n   <frame tileid=\"2421\" duration=\"100\"/>\n   <frame tileid=\"2429\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2374\" duration=\"100\"/>\n   <frame tileid=\"2382\" duration=\"100\"/>\n   <frame tileid=\"2390\" duration=\"100\"/>\n   <frame tileid=\"2398\" duration=\"100\"/>\n   <frame tileid=\"2406\" duration=\"100\"/>\n   <frame tileid=\"2414\" duration=\"100\"/>\n   <frame tileid=\"2422\" duration=\"100\"/>\n   <frame tileid=\"2430\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2375\" duration=\"100\"/>\n   <frame tileid=\"2383\" duration=\"100\"/>\n   <frame tileid=\"2391\" duration=\"100\"/>\n   <frame tileid=\"2399\" duration=\"100\"/>\n   <frame tileid=\"2407\" duration=\"100\"/>\n   <frame tileid=\"2415\" duration=\"100\"/>\n   <frame tileid=\"2423\" duration=\"100\"/>\n   <frame tileid=\"2431\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2432\" duration=\"100\"/>\n   <frame tileid=\"2440\" duration=\"100\"/>\n   <frame tileid=\"2448\" duration=\"100\"/>\n   <frame tileid=\"2456\" duration=\"100\"/>\n   <frame tileid=\"2464\" duration=\"100\"/>\n   <frame tileid=\"2472\" duration=\"100\"/>\n   <frame tileid=\"2480\" duration=\"100\"/>\n   <frame tileid=\"2488\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2433\" duration=\"100\"/>\n   <frame tileid=\"2441\" duration=\"100\"/>\n   <frame tileid=\"2449\" duration=\"100\"/>\n   <frame tileid=\"2457\" duration=\"100\"/>\n   <frame tileid=\"2465\" duration=\"100\"/>\n   <frame tileid=\"2473\" duration=\"100\"/>\n   <frame tileid=\"2481\" duration=\"100\"/>\n   <frame tileid=\"2489\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2434\" duration=\"100\"/>\n   <frame tileid=\"2442\" duration=\"100\"/>\n   <frame tileid=\"2450\" duration=\"100\"/>\n   <frame tileid=\"2458\" duration=\"100\"/>\n   <frame tileid=\"2466\" duration=\"100\"/>\n   <frame tileid=\"2474\" duration=\"100\"/>\n   <frame tileid=\"2482\" duration=\"100\"/>\n   <frame tileid=\"2490\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2435\" duration=\"100\"/>\n   <frame tileid=\"2443\" duration=\"100\"/>\n   <frame tileid=\"2451\" duration=\"100\"/>\n   <frame tileid=\"2459\" duration=\"100\"/>\n   <frame tileid=\"2467\" duration=\"100\"/>\n   <frame tileid=\"2475\" duration=\"100\"/>\n   <frame tileid=\"2483\" duration=\"100\"/>\n   <frame tileid=\"2491\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2436\" duration=\"100\"/>\n   <frame tileid=\"2444\" duration=\"100\"/>\n   <frame tileid=\"2452\" duration=\"100\"/>\n   <frame tileid=\"2460\" duration=\"100\"/>\n   <frame tileid=\"2468\" duration=\"100\"/>\n   <frame tileid=\"2476\" duration=\"100\"/>\n   <frame tileid=\"2484\" duration=\"100\"/>\n   <frame tileid=\"2492\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2437\" duration=\"100\"/>\n   <frame tileid=\"2445\" duration=\"100\"/>\n   <frame tileid=\"2453\" duration=\"100\"/>\n   <frame tileid=\"2461\" duration=\"100\"/>\n   <frame tileid=\"2469\" duration=\"100\"/>\n   <frame tileid=\"2477\" duration=\"100\"/>\n   <frame tileid=\"2485\" duration=\"100\"/>\n   <frame tileid=\"2493\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2438\" duration=\"100\"/>\n   <frame tileid=\"2446\" duration=\"100\"/>\n   <frame tileid=\"2454\" duration=\"100\"/>\n   <frame tileid=\"2462\" duration=\"100\"/>\n   <frame tileid=\"2470\" duration=\"100\"/>\n   <frame tileid=\"2478\" duration=\"100\"/>\n   <frame tileid=\"2486\" duration=\"100\"/>\n   <frame tileid=\"2494\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2439\" duration=\"100\"/>\n   <frame tileid=\"2447\" duration=\"100\"/>\n   <frame tileid=\"2455\" duration=\"100\"/>\n   <frame tileid=\"2463\" duration=\"100\"/>\n   <frame tileid=\"2471\" duration=\"100\"/>\n   <frame tileid=\"2479\" duration=\"100\"/>\n   <frame tileid=\"2487\" duration=\"100\"/>\n   <frame tileid=\"2495\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2496\" duration=\"100\"/>\n   <frame tileid=\"2504\" duration=\"100\"/>\n   <frame tileid=\"2512\" duration=\"100\"/>\n   <frame tileid=\"2520\" duration=\"100\"/>\n   <frame tileid=\"2528\" duration=\"100\"/>\n   <frame tileid=\"2536\" duration=\"100\"/>\n   <frame tileid=\"2544\" duration=\"100\"/>\n   <frame tileid=\"2552\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2497\" duration=\"100\"/>\n   <frame tileid=\"2505\" duration=\"100\"/>\n   <frame tileid=\"2513\" duration=\"100\"/>\n   <frame tileid=\"2521\" duration=\"100\"/>\n   <frame tileid=\"2529\" duration=\"100\"/>\n   <frame tileid=\"2537\" duration=\"100\"/>\n   <frame tileid=\"2545\" duration=\"100\"/>\n   <frame tileid=\"2553\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2498\" duration=\"100\"/>\n   <frame tileid=\"2506\" duration=\"100\"/>\n   <frame tileid=\"2514\" duration=\"100\"/>\n   <frame tileid=\"2522\" duration=\"100\"/>\n   <frame tileid=\"2530\" duration=\"100\"/>\n   <frame tileid=\"2538\" duration=\"100\"/>\n   <frame tileid=\"2546\" duration=\"100\"/>\n   <frame tileid=\"2554\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2499\" duration=\"100\"/>\n   <frame tileid=\"2507\" duration=\"100\"/>\n   <frame tileid=\"2515\" duration=\"100\"/>\n   <frame tileid=\"2523\" duration=\"100\"/>\n   <frame tileid=\"2531\" duration=\"100\"/>\n   <frame tileid=\"2539\" duration=\"100\"/>\n   <frame tileid=\"2547\" duration=\"100\"/>\n   <frame tileid=\"2555\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2500\" duration=\"100\"/>\n   <frame tileid=\"2508\" duration=\"100\"/>\n   <frame tileid=\"2516\" duration=\"100\"/>\n   <frame tileid=\"2524\" duration=\"100\"/>\n   <frame tileid=\"2532\" duration=\"100\"/>\n   <frame tileid=\"2540\" duration=\"100\"/>\n   <frame tileid=\"2548\" duration=\"100\"/>\n   <frame tileid=\"2556\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2501\" duration=\"100\"/>\n   <frame tileid=\"2509\" duration=\"100\"/>\n   <frame tileid=\"2517\" duration=\"100\"/>\n   <frame tileid=\"2525\" duration=\"100\"/>\n   <frame tileid=\"2533\" duration=\"100\"/>\n   <frame tileid=\"2541\" duration=\"100\"/>\n   <frame tileid=\"2549\" duration=\"100\"/>\n   <frame tileid=\"2557\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2502\" duration=\"100\"/>\n   <frame tileid=\"2510\" duration=\"100\"/>\n   <frame tileid=\"2518\" duration=\"100\"/>\n   <frame tileid=\"2526\" duration=\"100\"/>\n   <frame tileid=\"2534\" duration=\"100\"/>\n   <frame tileid=\"2542\" duration=\"100\"/>\n   <frame tileid=\"2550\" duration=\"100\"/>\n   <frame tileid=\"2558\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2503\" duration=\"100\"/>\n   <frame tileid=\"2511\" duration=\"100\"/>\n   <frame tileid=\"2519\" duration=\"100\"/>\n   <frame tileid=\"2527\" duration=\"100\"/>\n   <frame tileid=\"2535\" duration=\"100\"/>\n   <frame tileid=\"2543\" duration=\"100\"/>\n   <frame tileid=\"2551\" duration=\"100\"/>\n   <frame tileid=\"2559\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2560\" duration=\"100\"/>\n   <frame tileid=\"2568\" duration=\"100\"/>\n   <frame tileid=\"2576\" duration=\"100\"/>\n   <frame tileid=\"2584\" duration=\"100\"/>\n   <frame tileid=\"2592\" duration=\"100\"/>\n   <frame tileid=\"2600\" duration=\"100\"/>\n   <frame tileid=\"2608\" duration=\"100\"/>\n   <frame tileid=\"2616\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2561\" duration=\"100\"/>\n   <frame tileid=\"2569\" duration=\"100\"/>\n   <frame tileid=\"2577\" duration=\"100\"/>\n   <frame tileid=\"2585\" duration=\"100\"/>\n   <frame tileid=\"2593\" duration=\"100\"/>\n   <frame tileid=\"2601\" duration=\"100\"/>\n   <frame tileid=\"2609\" duration=\"100\"/>\n   <frame tileid=\"2617\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2562\" duration=\"100\"/>\n   <frame tileid=\"2570\" duration=\"100\"/>\n   <frame tileid=\"2578\" duration=\"100\"/>\n   <frame tileid=\"2586\" duration=\"100\"/>\n   <frame tileid=\"2594\" duration=\"100\"/>\n   <frame tileid=\"2602\" duration=\"100\"/>\n   <frame tileid=\"2610\" duration=\"100\"/>\n   <frame tileid=\"2618\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2563\" duration=\"100\"/>\n   <frame tileid=\"2571\" duration=\"100\"/>\n   <frame tileid=\"2579\" duration=\"100\"/>\n   <frame tileid=\"2587\" duration=\"100\"/>\n   <frame tileid=\"2595\" duration=\"100\"/>\n   <frame tileid=\"2603\" duration=\"100\"/>\n   <frame tileid=\"2611\" duration=\"100\"/>\n   <frame tileid=\"2619\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2564\" duration=\"100\"/>\n   <frame tileid=\"2572\" duration=\"100\"/>\n   <frame tileid=\"2580\" duration=\"100\"/>\n   <frame tileid=\"2588\" duration=\"100\"/>\n   <frame tileid=\"2596\" duration=\"100\"/>\n   <frame tileid=\"2604\" duration=\"100\"/>\n   <frame tileid=\"2612\" duration=\"100\"/>\n   <frame tileid=\"2620\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2565\" duration=\"100\"/>\n   <frame tileid=\"2573\" duration=\"100\"/>\n   <frame tileid=\"2581\" duration=\"100\"/>\n   <frame tileid=\"2589\" duration=\"100\"/>\n   <frame tileid=\"2597\" duration=\"100\"/>\n   <frame tileid=\"2605\" duration=\"100\"/>\n   <frame tileid=\"2613\" duration=\"100\"/>\n   <frame tileid=\"2621\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2566\" duration=\"100\"/>\n   <frame tileid=\"2574\" duration=\"100\"/>\n   <frame tileid=\"2582\" duration=\"100\"/>\n   <frame tileid=\"2590\" duration=\"100\"/>\n   <frame tileid=\"2598\" duration=\"100\"/>\n   <frame tileid=\"2606\" duration=\"100\"/>\n   <frame tileid=\"2614\" duration=\"100\"/>\n   <frame tileid=\"2622\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2567\" duration=\"100\"/>\n   <frame tileid=\"2575\" duration=\"100\"/>\n   <frame tileid=\"2583\" duration=\"100\"/>\n   <frame tileid=\"2591\" duration=\"100\"/>\n   <frame tileid=\"2599\" duration=\"100\"/>\n   <frame tileid=\"2607\" duration=\"100\"/>\n   <frame tileid=\"2615\" duration=\"100\"/>\n   <frame tileid=\"2623\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2624\" duration=\"100\"/>\n   <frame tileid=\"2632\" duration=\"100\"/>\n   <frame tileid=\"2640\" duration=\"100\"/>\n   <frame tileid=\"2648\" duration=\"100\"/>\n   <frame tileid=\"2656\" duration=\"100\"/>\n   <frame tileid=\"2664\" duration=\"100\"/>\n   <frame tileid=\"2672\" duration=\"100\"/>\n   <frame tileid=\"2680\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2625\" duration=\"100\"/>\n   <frame tileid=\"2633\" duration=\"100\"/>\n   <frame tileid=\"2641\" duration=\"100\"/>\n   <frame tileid=\"2649\" duration=\"100\"/>\n   <frame tileid=\"2657\" duration=\"100\"/>\n   <frame tileid=\"2665\" duration=\"100\"/>\n   <frame tileid=\"2673\" duration=\"100\"/>\n   <frame tileid=\"2681\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2626\" duration=\"100\"/>\n   <frame tileid=\"2634\" duration=\"100\"/>\n   <frame tileid=\"2642\" duration=\"100\"/>\n   <frame tileid=\"2650\" duration=\"100\"/>\n   <frame tileid=\"2658\" duration=\"100\"/>\n   <frame tileid=\"2666\" duration=\"100\"/>\n   <frame tileid=\"2674\" duration=\"100\"/>\n   <frame tileid=\"2682\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2627\" duration=\"100\"/>\n   <frame tileid=\"2635\" duration=\"100\"/>\n   <frame tileid=\"2643\" duration=\"100\"/>\n   <frame tileid=\"2651\" duration=\"100\"/>\n   <frame tileid=\"2659\" duration=\"100\"/>\n   <frame tileid=\"2667\" duration=\"100\"/>\n   <frame tileid=\"2675\" duration=\"100\"/>\n   <frame tileid=\"2683\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2628\" duration=\"100\"/>\n   <frame tileid=\"2636\" duration=\"100\"/>\n   <frame tileid=\"2644\" duration=\"100\"/>\n   <frame tileid=\"2652\" duration=\"100\"/>\n   <frame tileid=\"2660\" duration=\"100\"/>\n   <frame tileid=\"2668\" duration=\"100\"/>\n   <frame tileid=\"2676\" duration=\"100\"/>\n   <frame tileid=\"2684\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2629\" duration=\"100\"/>\n   <frame tileid=\"2637\" duration=\"100\"/>\n   <frame tileid=\"2645\" duration=\"100\"/>\n   <frame tileid=\"2653\" duration=\"100\"/>\n   <frame tileid=\"2661\" duration=\"100\"/>\n   <frame tileid=\"2669\" duration=\"100\"/>\n   <frame tileid=\"2677\" duration=\"100\"/>\n   <frame tileid=\"2685\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2630\" duration=\"100\"/>\n   <frame tileid=\"2638\" duration=\"100\"/>\n   <frame tileid=\"2646\" duration=\"100\"/>\n   <frame tileid=\"2654\" duration=\"100\"/>\n   <frame tileid=\"2662\" duration=\"100\"/>\n   <frame tileid=\"2670\" duration=\"100\"/>\n   <frame tileid=\"2678\" duration=\"100\"/>\n   <frame tileid=\"2686\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2631\" duration=\"100\"/>\n   <frame tileid=\"2639\" duration=\"100\"/>\n   <frame tileid=\"2647\" duration=\"100\"/>\n   <frame tileid=\"2655\" duration=\"100\"/>\n   <frame tileid=\"2663\" duration=\"100\"/>\n   <frame tileid=\"2671\" duration=\"100\"/>\n   <frame tileid=\"2679\" duration=\"100\"/>\n   <frame tileid=\"2687\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2688\" duration=\"100\"/>\n   <frame tileid=\"2696\" duration=\"100\"/>\n   <frame tileid=\"2704\" duration=\"100\"/>\n   <frame tileid=\"2712\" duration=\"100\"/>\n   <frame tileid=\"2720\" duration=\"100\"/>\n   <frame tileid=\"2728\" duration=\"100\"/>\n   <frame tileid=\"2736\" duration=\"100\"/>\n   <frame tileid=\"2744\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2689\" duration=\"100\"/>\n   <frame tileid=\"2697\" duration=\"100\"/>\n   <frame tileid=\"2705\" duration=\"100\"/>\n   <frame tileid=\"2713\" duration=\"100\"/>\n   <frame tileid=\"2721\" duration=\"100\"/>\n   <frame tileid=\"2729\" duration=\"100\"/>\n   <frame tileid=\"2737\" duration=\"100\"/>\n   <frame tileid=\"2745\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2690\" duration=\"100\"/>\n   <frame tileid=\"2698\" duration=\"100\"/>\n   <frame tileid=\"2706\" duration=\"100\"/>\n   <frame tileid=\"2714\" duration=\"100\"/>\n   <frame tileid=\"2722\" duration=\"100\"/>\n   <frame tileid=\"2730\" duration=\"100\"/>\n   <frame tileid=\"2738\" duration=\"100\"/>\n   <frame tileid=\"2746\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2691\" duration=\"100\"/>\n   <frame tileid=\"2699\" duration=\"100\"/>\n   <frame tileid=\"2707\" duration=\"100\"/>\n   <frame tileid=\"2715\" duration=\"100\"/>\n   <frame tileid=\"2723\" duration=\"100\"/>\n   <frame tileid=\"2731\" duration=\"100\"/>\n   <frame tileid=\"2739\" duration=\"100\"/>\n   <frame tileid=\"2747\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2692\" duration=\"100\"/>\n   <frame tileid=\"2700\" duration=\"100\"/>\n   <frame tileid=\"2708\" duration=\"100\"/>\n   <frame tileid=\"2716\" duration=\"100\"/>\n   <frame tileid=\"2724\" duration=\"100\"/>\n   <frame tileid=\"2732\" duration=\"100\"/>\n   <frame tileid=\"2740\" duration=\"100\"/>\n   <frame tileid=\"2748\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2693\" duration=\"100\"/>\n   <frame tileid=\"2701\" duration=\"100\"/>\n   <frame tileid=\"2709\" duration=\"100\"/>\n   <frame tileid=\"2717\" duration=\"100\"/>\n   <frame tileid=\"2725\" duration=\"100\"/>\n   <frame tileid=\"2733\" duration=\"100\"/>\n   <frame tileid=\"2741\" duration=\"100\"/>\n   <frame tileid=\"2749\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2694\" duration=\"100\"/>\n   <frame tileid=\"2702\" duration=\"100\"/>\n   <frame tileid=\"2710\" duration=\"100\"/>\n   <frame tileid=\"2718\" duration=\"100\"/>\n   <frame tileid=\"2726\" duration=\"100\"/>\n   <frame tileid=\"2734\" duration=\"100\"/>\n   <frame tileid=\"2742\" duration=\"100\"/>\n   <frame tileid=\"2750\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2695\" duration=\"100\"/>\n   <frame tileid=\"2703\" duration=\"100\"/>\n   <frame tileid=\"2711\" duration=\"100\"/>\n   <frame tileid=\"2719\" duration=\"100\"/>\n   <frame tileid=\"2727\" duration=\"100\"/>\n   <frame tileid=\"2735\" duration=\"100\"/>\n   <frame tileid=\"2743\" duration=\"100\"/>\n   <frame tileid=\"2751\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2752\" duration=\"100\"/>\n   <frame tileid=\"2760\" duration=\"100\"/>\n   <frame tileid=\"2768\" duration=\"100\"/>\n   <frame tileid=\"2776\" duration=\"100\"/>\n   <frame tileid=\"2784\" duration=\"100\"/>\n   <frame tileid=\"2792\" duration=\"100\"/>\n   <frame tileid=\"2800\" duration=\"100\"/>\n   <frame tileid=\"2808\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2753\" duration=\"100\"/>\n   <frame tileid=\"2761\" duration=\"100\"/>\n   <frame tileid=\"2769\" duration=\"100\"/>\n   <frame tileid=\"2777\" duration=\"100\"/>\n   <frame tileid=\"2785\" duration=\"100\"/>\n   <frame tileid=\"2793\" duration=\"100\"/>\n   <frame tileid=\"2801\" duration=\"100\"/>\n   <frame tileid=\"2809\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2754\" duration=\"100\"/>\n   <frame tileid=\"2762\" duration=\"100\"/>\n   <frame tileid=\"2770\" duration=\"100\"/>\n   <frame tileid=\"2778\" duration=\"100\"/>\n   <frame tileid=\"2786\" duration=\"100\"/>\n   <frame tileid=\"2794\" duration=\"100\"/>\n   <frame tileid=\"2802\" duration=\"100\"/>\n   <frame tileid=\"2810\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2755\" duration=\"100\"/>\n   <frame tileid=\"2763\" duration=\"100\"/>\n   <frame tileid=\"2771\" duration=\"100\"/>\n   <frame tileid=\"2779\" duration=\"100\"/>\n   <frame tileid=\"2787\" duration=\"100\"/>\n   <frame tileid=\"2795\" duration=\"100\"/>\n   <frame tileid=\"2803\" duration=\"100\"/>\n   <frame tileid=\"2811\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2756\" duration=\"100\"/>\n   <frame tileid=\"2764\" duration=\"100\"/>\n   <frame tileid=\"2772\" duration=\"100\"/>\n   <frame tileid=\"2780\" duration=\"100\"/>\n   <frame tileid=\"2788\" duration=\"100\"/>\n   <frame tileid=\"2796\" duration=\"100\"/>\n   <frame tileid=\"2804\" duration=\"100\"/>\n   <frame tileid=\"2812\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2757\" duration=\"100\"/>\n   <frame tileid=\"2765\" duration=\"100\"/>\n   <frame tileid=\"2773\" duration=\"100\"/>\n   <frame tileid=\"2781\" duration=\"100\"/>\n   <frame tileid=\"2789\" duration=\"100\"/>\n   <frame tileid=\"2797\" duration=\"100\"/>\n   <frame tileid=\"2805\" duration=\"100\"/>\n   <frame tileid=\"2813\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2758\" duration=\"100\"/>\n   <frame tileid=\"2766\" duration=\"100\"/>\n   <frame tileid=\"2774\" duration=\"100\"/>\n   <frame tileid=\"2782\" duration=\"100\"/>\n   <frame tileid=\"2790\" duration=\"100\"/>\n   <frame tileid=\"2798\" duration=\"100\"/>\n   <frame tileid=\"2806\" duration=\"100\"/>\n   <frame tileid=\"2814\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2759\" duration=\"100\"/>\n   <frame tileid=\"2767\" duration=\"100\"/>\n   <frame tileid=\"2775\" duration=\"100\"/>\n   <frame tileid=\"2783\" duration=\"100\"/>\n   <frame tileid=\"2791\" duration=\"100\"/>\n   <frame tileid=\"2799\" duration=\"100\"/>\n   <frame tileid=\"2807\" duration=\"100\"/>\n   <frame tileid=\"2815\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2816\" duration=\"100\"/>\n   <frame tileid=\"2824\" duration=\"100\"/>\n   <frame tileid=\"2832\" duration=\"100\"/>\n   <frame tileid=\"2840\" duration=\"100\"/>\n   <frame tileid=\"2848\" duration=\"100\"/>\n   <frame tileid=\"2856\" duration=\"100\"/>\n   <frame tileid=\"2864\" duration=\"100\"/>\n   <frame tileid=\"2872\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2817\" duration=\"100\"/>\n   <frame tileid=\"2825\" duration=\"100\"/>\n   <frame tileid=\"2833\" duration=\"100\"/>\n   <frame tileid=\"2841\" duration=\"100\"/>\n   <frame tileid=\"2849\" duration=\"100\"/>\n   <frame tileid=\"2857\" duration=\"100\"/>\n   <frame tileid=\"2865\" duration=\"100\"/>\n   <frame tileid=\"2873\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2818\" duration=\"100\"/>\n   <frame tileid=\"2826\" duration=\"100\"/>\n   <frame tileid=\"2834\" duration=\"100\"/>\n   <frame tileid=\"2842\" duration=\"100\"/>\n   <frame tileid=\"2850\" duration=\"100\"/>\n   <frame tileid=\"2858\" duration=\"100\"/>\n   <frame tileid=\"2866\" duration=\"100\"/>\n   <frame tileid=\"2874\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2819\" duration=\"100\"/>\n   <frame tileid=\"2827\" duration=\"100\"/>\n   <frame tileid=\"2835\" duration=\"100\"/>\n   <frame tileid=\"2843\" duration=\"100\"/>\n   <frame tileid=\"2851\" duration=\"100\"/>\n   <frame tileid=\"2859\" duration=\"100\"/>\n   <frame tileid=\"2867\" duration=\"100\"/>\n   <frame tileid=\"2875\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2820\" duration=\"100\"/>\n   <frame tileid=\"2828\" duration=\"100\"/>\n   <frame tileid=\"2836\" duration=\"100\"/>\n   <frame tileid=\"2844\" duration=\"100\"/>\n   <frame tileid=\"2852\" duration=\"100\"/>\n   <frame tileid=\"2860\" duration=\"100\"/>\n   <frame tileid=\"2868\" duration=\"100\"/>\n   <frame tileid=\"2876\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2821\" duration=\"100\"/>\n   <frame tileid=\"2829\" duration=\"100\"/>\n   <frame tileid=\"2837\" duration=\"100\"/>\n   <frame tileid=\"2845\" duration=\"100\"/>\n   <frame tileid=\"2853\" duration=\"100\"/>\n   <frame tileid=\"2861\" duration=\"100\"/>\n   <frame tileid=\"2869\" duration=\"100\"/>\n   <frame tileid=\"2877\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2822\" duration=\"100\"/>\n   <frame tileid=\"2830\" duration=\"100\"/>\n   <frame tileid=\"2838\" duration=\"100\"/>\n   <frame tileid=\"2846\" duration=\"100\"/>\n   <frame tileid=\"2854\" duration=\"100\"/>\n   <frame tileid=\"2862\" duration=\"100\"/>\n   <frame tileid=\"2870\" duration=\"100\"/>\n   <frame tileid=\"2878\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2823\" duration=\"100\"/>\n   <frame tileid=\"2831\" duration=\"100\"/>\n   <frame tileid=\"2839\" duration=\"100\"/>\n   <frame tileid=\"2847\" duration=\"100\"/>\n   <frame tileid=\"2855\" duration=\"100\"/>\n   <frame tileid=\"2863\" duration=\"100\"/>\n   <frame tileid=\"2871\" duration=\"100\"/>\n   <frame tileid=\"2879\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2880\" duration=\"100\"/>\n   <frame tileid=\"2888\" duration=\"100\"/>\n   <frame tileid=\"2896\" duration=\"100\"/>\n   <frame tileid=\"2904\" duration=\"100\"/>\n   <frame tileid=\"2912\" duration=\"100\"/>\n   <frame tileid=\"2920\" duration=\"100\"/>\n   <frame tileid=\"2928\" duration=\"100\"/>\n   <frame tileid=\"2936\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2881\" duration=\"100\"/>\n   <frame tileid=\"2889\" duration=\"100\"/>\n   <frame tileid=\"2897\" duration=\"100\"/>\n   <frame tileid=\"2905\" duration=\"100\"/>\n   <frame tileid=\"2913\" duration=\"100\"/>\n   <frame tileid=\"2921\" duration=\"100\"/>\n   <frame tileid=\"2929\" duration=\"100\"/>\n   <frame tileid=\"2937\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2882\" duration=\"100\"/>\n   <frame tileid=\"2890\" duration=\"100\"/>\n   <frame tileid=\"2898\" duration=\"100\"/>\n   <frame tileid=\"2906\" duration=\"100\"/>\n   <frame tileid=\"2914\" duration=\"100\"/>\n   <frame tileid=\"2922\" duration=\"100\"/>\n   <frame tileid=\"2930\" duration=\"100\"/>\n   <frame tileid=\"2938\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2883\" duration=\"100\"/>\n   <frame tileid=\"2891\" duration=\"100\"/>\n   <frame tileid=\"2899\" duration=\"100\"/>\n   <frame tileid=\"2907\" duration=\"100\"/>\n   <frame tileid=\"2915\" duration=\"100\"/>\n   <frame tileid=\"2923\" duration=\"100\"/>\n   <frame tileid=\"2931\" duration=\"100\"/>\n   <frame tileid=\"2939\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2884\" duration=\"100\"/>\n   <frame tileid=\"2892\" duration=\"100\"/>\n   <frame tileid=\"2900\" duration=\"100\"/>\n   <frame tileid=\"2908\" duration=\"100\"/>\n   <frame tileid=\"2916\" duration=\"100\"/>\n   <frame tileid=\"2924\" duration=\"100\"/>\n   <frame tileid=\"2932\" duration=\"100\"/>\n   <frame tileid=\"2940\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2885\" duration=\"100\"/>\n   <frame tileid=\"2893\" duration=\"100\"/>\n   <frame tileid=\"2901\" duration=\"100\"/>\n   <frame tileid=\"2909\" duration=\"100\"/>\n   <frame tileid=\"2917\" duration=\"100\"/>\n   <frame tileid=\"2925\" duration=\"100\"/>\n   <frame tileid=\"2933\" duration=\"100\"/>\n   <frame tileid=\"2941\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2886\" duration=\"100\"/>\n   <frame tileid=\"2894\" duration=\"100\"/>\n   <frame tileid=\"2902\" duration=\"100\"/>\n   <frame tileid=\"2910\" duration=\"100\"/>\n   <frame tileid=\"2918\" duration=\"100\"/>\n   <frame tileid=\"2926\" duration=\"100\"/>\n   <frame tileid=\"2934\" duration=\"100\"/>\n   <frame tileid=\"2942\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2887\" duration=\"100\"/>\n   <frame tileid=\"2895\" duration=\"100\"/>\n   <frame tileid=\"2903\" duration=\"100\"/>\n   <frame tileid=\"2911\" duration=\"100\"/>\n   <frame tileid=\"2919\" duration=\"100\"/>\n   <frame tileid=\"2927\" duration=\"100\"/>\n   <frame tileid=\"2935\" duration=\"100\"/>\n   <frame tileid=\"2943\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2944\" duration=\"100\"/>\n   <frame tileid=\"2952\" duration=\"100\"/>\n   <frame tileid=\"2960\" duration=\"100\"/>\n   <frame tileid=\"2968\" duration=\"100\"/>\n   <frame tileid=\"2976\" duration=\"100\"/>\n   <frame tileid=\"2984\" duration=\"100\"/>\n   <frame tileid=\"2992\" duration=\"100\"/>\n   <frame tileid=\"3000\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2945\" duration=\"100\"/>\n   <frame tileid=\"2953\" duration=\"100\"/>\n   <frame tileid=\"2961\" duration=\"100\"/>\n   <frame tileid=\"2969\" duration=\"100\"/>\n   <frame tileid=\"2977\" duration=\"100\"/>\n   <frame tileid=\"2985\" duration=\"100\"/>\n   <frame tileid=\"2993\" duration=\"100\"/>\n   <frame tileid=\"3001\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2946\" duration=\"100\"/>\n   <frame tileid=\"2954\" duration=\"100\"/>\n   <frame tileid=\"2962\" duration=\"100\"/>\n   <frame tileid=\"2970\" duration=\"100\"/>\n   <frame tileid=\"2978\" duration=\"100\"/>\n   <frame tileid=\"2986\" duration=\"100\"/>\n   <frame tileid=\"2994\" duration=\"100\"/>\n   <frame tileid=\"3002\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2947\" duration=\"100\"/>\n   <frame tileid=\"2955\" duration=\"100\"/>\n   <frame tileid=\"2963\" duration=\"100\"/>\n   <frame tileid=\"2971\" duration=\"100\"/>\n   <frame tileid=\"2979\" duration=\"100\"/>\n   <frame tileid=\"2987\" duration=\"100\"/>\n   <frame tileid=\"2995\" duration=\"100\"/>\n   <frame tileid=\"3003\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2948\" duration=\"100\"/>\n   <frame tileid=\"2956\" duration=\"100\"/>\n   <frame tileid=\"2964\" duration=\"100\"/>\n   <frame tileid=\"2972\" duration=\"100\"/>\n   <frame tileid=\"2980\" duration=\"100\"/>\n   <frame tileid=\"2988\" duration=\"100\"/>\n   <frame tileid=\"2996\" duration=\"100\"/>\n   <frame tileid=\"3004\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2949\" duration=\"100\"/>\n   <frame tileid=\"2957\" duration=\"100\"/>\n   <frame tileid=\"2965\" duration=\"100\"/>\n   <frame tileid=\"2973\" duration=\"100\"/>\n   <frame tileid=\"2981\" duration=\"100\"/>\n   <frame tileid=\"2989\" duration=\"100\"/>\n   <frame tileid=\"2997\" duration=\"100\"/>\n   <frame tileid=\"3005\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2950\" duration=\"100\"/>\n   <frame tileid=\"2958\" duration=\"100\"/>\n   <frame tileid=\"2966\" duration=\"100\"/>\n   <frame tileid=\"2974\" duration=\"100\"/>\n   <frame tileid=\"2982\" duration=\"100\"/>\n   <frame tileid=\"2990\" duration=\"100\"/>\n   <frame tileid=\"2998\" duration=\"100\"/>\n   <frame tileid=\"3006\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"2951\" duration=\"100\"/>\n   <frame tileid=\"2959\" duration=\"100\"/>\n   <frame tileid=\"2967\" duration=\"100\"/>\n   <frame tileid=\"2975\" duration=\"100\"/>\n   <frame tileid=\"2983\" duration=\"100\"/>\n   <frame tileid=\"2991\" duration=\"100\"/>\n   <frame tileid=\"2999\" duration=\"100\"/>\n   <frame tileid=\"3007\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"2952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"2999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3000\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3001\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3002\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3003\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3004\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3005\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3006\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3007\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3008\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3008\" duration=\"100\"/>\n   <frame tileid=\"3016\" duration=\"100\"/>\n   <frame tileid=\"3024\" duration=\"100\"/>\n   <frame tileid=\"3032\" duration=\"100\"/>\n   <frame tileid=\"3040\" duration=\"100\"/>\n   <frame tileid=\"3048\" duration=\"100\"/>\n   <frame tileid=\"3056\" duration=\"100\"/>\n   <frame tileid=\"3064\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3009\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3009\" duration=\"100\"/>\n   <frame tileid=\"3017\" duration=\"100\"/>\n   <frame tileid=\"3025\" duration=\"100\"/>\n   <frame tileid=\"3033\" duration=\"100\"/>\n   <frame tileid=\"3041\" duration=\"100\"/>\n   <frame tileid=\"3049\" duration=\"100\"/>\n   <frame tileid=\"3057\" duration=\"100\"/>\n   <frame tileid=\"3065\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3010\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3010\" duration=\"100\"/>\n   <frame tileid=\"3018\" duration=\"100\"/>\n   <frame tileid=\"3026\" duration=\"100\"/>\n   <frame tileid=\"3034\" duration=\"100\"/>\n   <frame tileid=\"3042\" duration=\"100\"/>\n   <frame tileid=\"3050\" duration=\"100\"/>\n   <frame tileid=\"3058\" duration=\"100\"/>\n   <frame tileid=\"3066\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3011\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3011\" duration=\"100\"/>\n   <frame tileid=\"3019\" duration=\"100\"/>\n   <frame tileid=\"3027\" duration=\"100\"/>\n   <frame tileid=\"3035\" duration=\"100\"/>\n   <frame tileid=\"3043\" duration=\"100\"/>\n   <frame tileid=\"3051\" duration=\"100\"/>\n   <frame tileid=\"3059\" duration=\"100\"/>\n   <frame tileid=\"3067\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3012\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3012\" duration=\"100\"/>\n   <frame tileid=\"3020\" duration=\"100\"/>\n   <frame tileid=\"3028\" duration=\"100\"/>\n   <frame tileid=\"3036\" duration=\"100\"/>\n   <frame tileid=\"3044\" duration=\"100\"/>\n   <frame tileid=\"3052\" duration=\"100\"/>\n   <frame tileid=\"3060\" duration=\"100\"/>\n   <frame tileid=\"3068\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3013\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3013\" duration=\"100\"/>\n   <frame tileid=\"3021\" duration=\"100\"/>\n   <frame tileid=\"3029\" duration=\"100\"/>\n   <frame tileid=\"3037\" duration=\"100\"/>\n   <frame tileid=\"3045\" duration=\"100\"/>\n   <frame tileid=\"3053\" duration=\"100\"/>\n   <frame tileid=\"3061\" duration=\"100\"/>\n   <frame tileid=\"3069\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3014\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3014\" duration=\"100\"/>\n   <frame tileid=\"3022\" duration=\"100\"/>\n   <frame tileid=\"3030\" duration=\"100\"/>\n   <frame tileid=\"3038\" duration=\"100\"/>\n   <frame tileid=\"3046\" duration=\"100\"/>\n   <frame tileid=\"3054\" duration=\"100\"/>\n   <frame tileid=\"3062\" duration=\"100\"/>\n   <frame tileid=\"3070\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3015\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <animation>\n   <frame tileid=\"3015\" duration=\"100\"/>\n   <frame tileid=\"3023\" duration=\"100\"/>\n   <frame tileid=\"3031\" duration=\"100\"/>\n   <frame tileid=\"3039\" duration=\"100\"/>\n   <frame tileid=\"3047\" duration=\"100\"/>\n   <frame tileid=\"3055\" duration=\"100\"/>\n   <frame tileid=\"3063\" duration=\"100\"/>\n   <frame tileid=\"3071\" duration=\"100\"/>\n  </animation>\n </tile>\n <tile id=\"3016\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3017\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3018\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3019\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3020\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3021\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3022\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3023\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3024\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3025\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3026\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3027\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3028\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3029\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3030\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3031\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3032\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3033\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3034\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3035\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3036\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3037\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3038\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3039\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3040\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3041\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3042\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3043\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3044\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3045\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3046\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3047\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3048\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3049\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3050\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3051\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3052\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3053\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3054\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3055\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3056\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3057\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3058\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3059\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3060\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3061\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3062\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3063\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3064\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3065\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3066\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3067\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3068\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3069\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3070\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"3071\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <wangsets>\n  <wangset name=\"Autotile\" type=\"mixed\" tile=\"0\">\n   <wangcolor name=\"\" color=\"#71c138\" tile=\"0\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#a533b6\" tile=\"384\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#65c07c\" tile=\"768\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#bda392\" tile=\"1152\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#6bbbaa\" tile=\"1536\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#7a0610\" tile=\"1920\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#d737fa\" tile=\"2304\" probability=\"1\"/>\n   <wangcolor name=\"\" color=\"#3feb30\" tile=\"2688\" probability=\"1\"/>\n   <wangtile tileid=\"1\" wangid=\"0,0,1,0,0,0,0,0\"/>\n   <wangtile tileid=\"2\" wangid=\"0,0,1,0,0,0,1,0\"/>\n   <wangtile tileid=\"3\" wangid=\"0,0,0,0,0,0,1,0\"/>\n   <wangtile tileid=\"4\" wangid=\"0,0,0,0,1,0,0,0\"/>\n   <wangtile tileid=\"5\" wangid=\"0,0,1,1,1,0,0,0\"/>\n   <wangtile tileid=\"6\" wangid=\"0,0,1,1,1,1,1,0\"/>\n   <wangtile tileid=\"7\" wangid=\"0,0,0,0,1,1,1,0\"/>\n   <wangtile tileid=\"64\" wangid=\"0,0,1,0,1,0,0,0\"/>\n   <wangtile tileid=\"65\" wangid=\"0,0,0,0,1,0,1,0\"/>\n   <wangtile tileid=\"66\" wangid=\"1,0,1,0,1,0,0,0\"/>\n   <wangtile tileid=\"67\" wangid=\"0,0,1,0,1,0,1,0\"/>\n   <wangtile tileid=\"68\" wangid=\"1,0,0,0,1,0,0,0\"/>\n   <wangtile tileid=\"69\" wangid=\"1,1,1,1,1,0,0,0\"/>\n   <wangtile tileid=\"70\" wangid=\"1,1,1,1,1,1,1,1\"/>\n   <wangtile tileid=\"71\" wangid=\"1,0,0,0,1,1,1,1\"/>\n   <wangtile tileid=\"128\" wangid=\"1,0,1,0,0,0,0,0\"/>\n   <wangtile tileid=\"129\" wangid=\"1,0,0,0,0,0,1,0\"/>\n   <wangtile tileid=\"130\" wangid=\"1,0,1,0,0,0,1,0\"/>\n   <wangtile tileid=\"131\" wangid=\"1,0,0,0,1,0,1,0\"/>\n   <wangtile tileid=\"132\" wangid=\"1,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"133\" wangid=\"1,1,1,0,0,0,0,0\"/>\n   <wangtile tileid=\"134\" wangid=\"1,1,1,0,0,0,1,1\"/>\n   <wangtile tileid=\"135\" wangid=\"1,0,0,0,0,0,1,1\"/>\n   <wangtile tileid=\"192\" wangid=\"1,1,1,0,1,0,0,0\"/>\n   <wangtile tileid=\"193\" wangid=\"1,0,0,0,1,0,1,1\"/>\n   <wangtile tileid=\"194\" wangid=\"0,0,1,0,1,1,1,0\"/>\n   <wangtile tileid=\"195\" wangid=\"0,0,1,1,1,0,1,0\"/>\n   <wangtile tileid=\"196\" wangid=\"1,1,1,0,1,1,1,1\"/>\n   <wangtile tileid=\"197\" wangid=\"1,1,1,1,1,0,1,1\"/>\n   <wangtile tileid=\"198\" wangid=\"1,0,1,0,1,0,1,1\"/>\n   <wangtile tileid=\"199\" wangid=\"1,1,1,0,1,0,1,0\"/>\n   <wangtile tileid=\"256\" wangid=\"1,0,1,1,1,0,0,0\"/>\n   <wangtile tileid=\"257\" wangid=\"1,0,0,0,1,1,1,0\"/>\n   <wangtile tileid=\"258\" wangid=\"1,0,1,0,0,0,1,1\"/>\n   <wangtile tileid=\"259\" wangid=\"1,1,1,0,0,0,1,0\"/>\n   <wangtile tileid=\"260\" wangid=\"1,0,1,1,1,1,1,1\"/>\n   <wangtile tileid=\"261\" wangid=\"1,1,1,1,1,1,1,0\"/>\n   <wangtile tileid=\"262\" wangid=\"1,0,1,0,1,1,1,0\"/>\n   <wangtile tileid=\"263\" wangid=\"1,0,1,1,1,0,1,0\"/>\n   <wangtile tileid=\"320\" wangid=\"1,0,1,1,1,1,1,0\"/>\n   <wangtile tileid=\"321\" wangid=\"1,1,1,0,1,0,1,1\"/>\n   <wangtile tileid=\"322\" wangid=\"1,0,1,0,1,1,1,1\"/>\n   <wangtile tileid=\"323\" wangid=\"1,1,1,1,1,0,1,0\"/>\n   <wangtile tileid=\"324\" wangid=\"1,0,1,1,1,0,1,1\"/>\n   <wangtile tileid=\"325\" wangid=\"1,1,1,0,1,1,1,0\"/>\n   <wangtile tileid=\"326\" wangid=\"1,0,1,0,1,0,1,0\"/>\n   <wangtile tileid=\"385\" wangid=\"0,0,2,0,0,0,0,0\"/>\n   <wangtile tileid=\"386\" wangid=\"0,0,2,0,0,0,2,0\"/>\n   <wangtile tileid=\"387\" wangid=\"0,0,0,0,0,0,2,0\"/>\n   <wangtile tileid=\"388\" wangid=\"0,0,0,0,2,0,0,0\"/>\n   <wangtile tileid=\"389\" wangid=\"0,0,2,2,2,0,0,0\"/>\n   <wangtile tileid=\"390\" wangid=\"0,0,2,2,2,2,2,0\"/>\n   <wangtile tileid=\"391\" wangid=\"0,0,0,0,2,2,2,0\"/>\n   <wangtile tileid=\"448\" wangid=\"0,0,2,0,2,0,0,0\"/>\n   <wangtile tileid=\"449\" wangid=\"0,0,0,0,2,0,2,0\"/>\n   <wangtile tileid=\"450\" wangid=\"2,0,2,0,2,0,0,0\"/>\n   <wangtile tileid=\"451\" wangid=\"0,0,2,0,2,0,2,0\"/>\n   <wangtile tileid=\"452\" wangid=\"2,0,0,0,2,0,0,0\"/>\n   <wangtile tileid=\"453\" wangid=\"2,2,2,2,2,0,0,0\"/>\n   <wangtile tileid=\"454\" wangid=\"2,2,2,2,2,2,2,2\"/>\n   <wangtile tileid=\"455\" wangid=\"2,0,0,0,2,2,2,2\"/>\n   <wangtile tileid=\"512\" wangid=\"2,0,2,0,0,0,0,0\"/>\n   <wangtile tileid=\"513\" wangid=\"2,0,0,0,0,0,2,0\"/>\n   <wangtile tileid=\"514\" wangid=\"2,0,2,0,0,0,2,0\"/>\n   <wangtile tileid=\"515\" wangid=\"2,0,0,0,2,0,2,0\"/>\n   <wangtile tileid=\"516\" wangid=\"2,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"517\" wangid=\"2,2,2,0,0,0,0,0\"/>\n   <wangtile tileid=\"518\" wangid=\"2,2,2,0,0,0,2,2\"/>\n   <wangtile tileid=\"519\" wangid=\"2,0,0,0,0,0,2,2\"/>\n   <wangtile tileid=\"576\" wangid=\"2,2,2,0,2,0,0,0\"/>\n   <wangtile tileid=\"577\" wangid=\"2,0,0,0,2,0,2,2\"/>\n   <wangtile tileid=\"578\" wangid=\"0,0,2,0,2,2,2,0\"/>\n   <wangtile tileid=\"579\" wangid=\"0,0,2,2,2,0,2,0\"/>\n   <wangtile tileid=\"580\" wangid=\"2,2,2,0,2,2,2,2\"/>\n   <wangtile tileid=\"581\" wangid=\"2,2,2,2,2,0,2,2\"/>\n   <wangtile tileid=\"582\" wangid=\"2,0,2,0,2,0,2,2\"/>\n   <wangtile tileid=\"583\" wangid=\"2,2,2,0,2,0,2,0\"/>\n   <wangtile tileid=\"640\" wangid=\"2,0,2,2,2,0,0,0\"/>\n   <wangtile tileid=\"641\" wangid=\"2,0,0,0,2,2,2,0\"/>\n   <wangtile tileid=\"642\" wangid=\"2,0,2,0,0,0,2,2\"/>\n   <wangtile tileid=\"643\" wangid=\"2,2,2,0,0,0,2,0\"/>\n   <wangtile tileid=\"644\" wangid=\"2,0,2,2,2,2,2,2\"/>\n   <wangtile tileid=\"645\" wangid=\"2,2,2,2,2,2,2,0\"/>\n   <wangtile tileid=\"646\" wangid=\"2,0,2,0,2,2,2,0\"/>\n   <wangtile tileid=\"647\" wangid=\"2,0,2,2,2,0,2,0\"/>\n   <wangtile tileid=\"704\" wangid=\"2,0,2,2,2,2,2,0\"/>\n   <wangtile tileid=\"705\" wangid=\"2,2,2,0,2,0,2,2\"/>\n   <wangtile tileid=\"706\" wangid=\"2,0,2,0,2,2,2,2\"/>\n   <wangtile tileid=\"707\" wangid=\"2,2,2,2,2,0,2,0\"/>\n   <wangtile tileid=\"708\" wangid=\"2,0,2,2,2,0,2,2\"/>\n   <wangtile tileid=\"709\" wangid=\"2,2,2,0,2,2,2,0\"/>\n   <wangtile tileid=\"710\" wangid=\"2,0,2,0,2,0,2,0\"/>\n   <wangtile tileid=\"769\" wangid=\"0,0,3,0,0,0,0,0\"/>\n   <wangtile tileid=\"770\" wangid=\"0,0,3,0,0,0,3,0\"/>\n   <wangtile tileid=\"771\" wangid=\"0,0,0,0,0,0,3,0\"/>\n   <wangtile tileid=\"772\" wangid=\"0,0,0,0,3,0,0,0\"/>\n   <wangtile tileid=\"773\" wangid=\"0,0,3,3,3,0,0,0\"/>\n   <wangtile tileid=\"774\" wangid=\"0,0,3,3,3,3,3,0\"/>\n   <wangtile tileid=\"775\" wangid=\"0,0,0,0,3,3,3,0\"/>\n   <wangtile tileid=\"832\" wangid=\"0,0,3,0,3,0,0,0\"/>\n   <wangtile tileid=\"833\" wangid=\"0,0,0,0,3,0,3,0\"/>\n   <wangtile tileid=\"834\" wangid=\"3,0,3,0,3,0,0,0\"/>\n   <wangtile tileid=\"835\" wangid=\"0,0,3,0,3,0,3,0\"/>\n   <wangtile tileid=\"836\" wangid=\"3,0,0,0,3,0,0,0\"/>\n   <wangtile tileid=\"837\" wangid=\"3,3,3,3,3,0,0,0\"/>\n   <wangtile tileid=\"838\" wangid=\"3,3,3,3,3,3,3,3\"/>\n   <wangtile tileid=\"839\" wangid=\"3,0,0,0,3,3,3,3\"/>\n   <wangtile tileid=\"896\" wangid=\"3,0,3,0,0,0,0,0\"/>\n   <wangtile tileid=\"897\" wangid=\"3,0,0,0,0,0,3,0\"/>\n   <wangtile tileid=\"898\" wangid=\"3,0,3,0,0,0,3,0\"/>\n   <wangtile tileid=\"899\" wangid=\"3,0,0,0,3,0,3,0\"/>\n   <wangtile tileid=\"900\" wangid=\"3,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"901\" wangid=\"3,3,3,0,0,0,0,0\"/>\n   <wangtile tileid=\"902\" wangid=\"3,3,3,0,0,0,3,3\"/>\n   <wangtile tileid=\"903\" wangid=\"3,0,0,0,0,0,3,3\"/>\n   <wangtile tileid=\"960\" wangid=\"3,3,3,0,3,0,0,0\"/>\n   <wangtile tileid=\"961\" wangid=\"3,0,0,0,3,0,3,3\"/>\n   <wangtile tileid=\"962\" wangid=\"0,0,3,0,3,3,3,0\"/>\n   <wangtile tileid=\"963\" wangid=\"0,0,3,3,3,0,3,0\"/>\n   <wangtile tileid=\"964\" wangid=\"3,3,3,0,3,3,3,3\"/>\n   <wangtile tileid=\"965\" wangid=\"3,3,3,3,3,0,3,3\"/>\n   <wangtile tileid=\"966\" wangid=\"3,0,3,0,3,0,3,3\"/>\n   <wangtile tileid=\"967\" wangid=\"3,3,3,0,3,0,3,0\"/>\n   <wangtile tileid=\"1024\" wangid=\"3,0,3,3,3,0,0,0\"/>\n   <wangtile tileid=\"1025\" wangid=\"3,0,0,0,3,3,3,0\"/>\n   <wangtile tileid=\"1026\" wangid=\"3,0,3,0,0,0,3,3\"/>\n   <wangtile tileid=\"1027\" wangid=\"3,3,3,0,0,0,3,0\"/>\n   <wangtile tileid=\"1028\" wangid=\"3,0,3,3,3,3,3,3\"/>\n   <wangtile tileid=\"1029\" wangid=\"3,3,3,3,3,3,3,0\"/>\n   <wangtile tileid=\"1030\" wangid=\"3,0,3,0,3,3,3,0\"/>\n   <wangtile tileid=\"1031\" wangid=\"3,0,3,3,3,0,3,0\"/>\n   <wangtile tileid=\"1088\" wangid=\"3,0,3,3,3,3,3,0\"/>\n   <wangtile tileid=\"1089\" wangid=\"3,3,3,0,3,0,3,3\"/>\n   <wangtile tileid=\"1090\" wangid=\"3,0,3,0,3,3,3,3\"/>\n   <wangtile tileid=\"1091\" wangid=\"3,3,3,3,3,0,3,0\"/>\n   <wangtile tileid=\"1092\" wangid=\"3,0,3,3,3,0,3,3\"/>\n   <wangtile tileid=\"1093\" wangid=\"3,3,3,0,3,3,3,0\"/>\n   <wangtile tileid=\"1094\" wangid=\"3,0,3,0,3,0,3,0\"/>\n   <wangtile tileid=\"1153\" wangid=\"0,0,4,0,0,0,0,0\"/>\n   <wangtile tileid=\"1154\" wangid=\"0,0,4,0,0,0,4,0\"/>\n   <wangtile tileid=\"1155\" wangid=\"0,0,0,0,0,0,4,0\"/>\n   <wangtile tileid=\"1156\" wangid=\"0,0,0,0,4,0,0,0\"/>\n   <wangtile tileid=\"1157\" wangid=\"0,0,4,4,4,0,0,0\"/>\n   <wangtile tileid=\"1158\" wangid=\"0,0,4,4,4,4,4,0\"/>\n   <wangtile tileid=\"1159\" wangid=\"0,0,0,0,4,4,4,0\"/>\n   <wangtile tileid=\"1216\" wangid=\"0,0,4,0,4,0,0,0\"/>\n   <wangtile tileid=\"1217\" wangid=\"0,0,0,0,4,0,4,0\"/>\n   <wangtile tileid=\"1218\" wangid=\"4,0,4,0,4,0,0,0\"/>\n   <wangtile tileid=\"1219\" wangid=\"0,0,4,0,4,0,4,0\"/>\n   <wangtile tileid=\"1220\" wangid=\"4,0,0,0,4,0,0,0\"/>\n   <wangtile tileid=\"1221\" wangid=\"4,4,4,4,4,0,0,0\"/>\n   <wangtile tileid=\"1222\" wangid=\"4,4,4,4,4,4,4,4\"/>\n   <wangtile tileid=\"1223\" wangid=\"4,0,0,0,4,4,4,4\"/>\n   <wangtile tileid=\"1280\" wangid=\"4,0,4,0,0,0,0,0\"/>\n   <wangtile tileid=\"1281\" wangid=\"4,0,0,0,0,0,4,0\"/>\n   <wangtile tileid=\"1282\" wangid=\"4,0,4,0,0,0,4,0\"/>\n   <wangtile tileid=\"1283\" wangid=\"4,0,0,0,4,0,4,0\"/>\n   <wangtile tileid=\"1284\" wangid=\"4,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"1285\" wangid=\"4,4,4,0,0,0,0,0\"/>\n   <wangtile tileid=\"1286\" wangid=\"4,4,4,0,0,0,4,4\"/>\n   <wangtile tileid=\"1287\" wangid=\"4,0,0,0,0,0,4,4\"/>\n   <wangtile tileid=\"1344\" wangid=\"4,4,4,0,4,0,0,0\"/>\n   <wangtile tileid=\"1345\" wangid=\"4,0,0,0,4,0,4,4\"/>\n   <wangtile tileid=\"1346\" wangid=\"0,0,4,0,4,4,4,0\"/>\n   <wangtile tileid=\"1347\" wangid=\"0,0,4,4,4,0,4,0\"/>\n   <wangtile tileid=\"1348\" wangid=\"4,4,4,0,4,4,4,4\"/>\n   <wangtile tileid=\"1349\" wangid=\"4,4,4,4,4,0,4,4\"/>\n   <wangtile tileid=\"1350\" wangid=\"4,0,4,0,4,0,4,4\"/>\n   <wangtile tileid=\"1351\" wangid=\"4,4,4,0,4,0,4,0\"/>\n   <wangtile tileid=\"1408\" wangid=\"4,0,4,4,4,0,0,0\"/>\n   <wangtile tileid=\"1409\" wangid=\"4,0,0,0,4,4,4,0\"/>\n   <wangtile tileid=\"1410\" wangid=\"4,0,4,0,0,0,4,4\"/>\n   <wangtile tileid=\"1411\" wangid=\"4,4,4,0,0,0,4,0\"/>\n   <wangtile tileid=\"1412\" wangid=\"4,0,4,4,4,4,4,4\"/>\n   <wangtile tileid=\"1413\" wangid=\"4,4,4,4,4,4,4,0\"/>\n   <wangtile tileid=\"1414\" wangid=\"4,0,4,0,4,4,4,0\"/>\n   <wangtile tileid=\"1415\" wangid=\"4,0,4,4,4,0,4,0\"/>\n   <wangtile tileid=\"1472\" wangid=\"4,0,4,4,4,4,4,0\"/>\n   <wangtile tileid=\"1473\" wangid=\"4,4,4,0,4,0,4,4\"/>\n   <wangtile tileid=\"1474\" wangid=\"4,0,4,0,4,4,4,4\"/>\n   <wangtile tileid=\"1475\" wangid=\"4,4,4,4,4,0,4,0\"/>\n   <wangtile tileid=\"1476\" wangid=\"4,0,4,4,4,0,4,4\"/>\n   <wangtile tileid=\"1477\" wangid=\"4,4,4,0,4,4,4,0\"/>\n   <wangtile tileid=\"1478\" wangid=\"4,0,4,0,4,0,4,0\"/>\n   <wangtile tileid=\"1537\" wangid=\"0,0,5,0,0,0,0,0\"/>\n   <wangtile tileid=\"1538\" wangid=\"0,0,5,0,0,0,5,0\"/>\n   <wangtile tileid=\"1539\" wangid=\"0,0,0,0,0,0,5,0\"/>\n   <wangtile tileid=\"1540\" wangid=\"0,0,0,0,5,0,0,0\"/>\n   <wangtile tileid=\"1541\" wangid=\"0,0,5,5,5,0,0,0\"/>\n   <wangtile tileid=\"1542\" wangid=\"0,0,5,5,5,5,5,0\"/>\n   <wangtile tileid=\"1543\" wangid=\"0,0,0,0,5,5,5,0\"/>\n   <wangtile tileid=\"1600\" wangid=\"0,0,5,0,5,0,0,0\"/>\n   <wangtile tileid=\"1601\" wangid=\"0,0,0,0,5,0,5,0\"/>\n   <wangtile tileid=\"1602\" wangid=\"5,0,5,0,5,0,0,0\"/>\n   <wangtile tileid=\"1603\" wangid=\"0,0,5,0,5,0,5,0\"/>\n   <wangtile tileid=\"1604\" wangid=\"5,0,0,0,5,0,0,0\"/>\n   <wangtile tileid=\"1605\" wangid=\"5,5,5,5,5,0,0,0\"/>\n   <wangtile tileid=\"1606\" wangid=\"5,5,5,5,5,5,5,5\"/>\n   <wangtile tileid=\"1607\" wangid=\"5,0,0,0,5,5,5,5\"/>\n   <wangtile tileid=\"1664\" wangid=\"5,0,5,0,0,0,0,0\"/>\n   <wangtile tileid=\"1665\" wangid=\"5,0,0,0,0,0,5,0\"/>\n   <wangtile tileid=\"1666\" wangid=\"5,0,5,0,0,0,5,0\"/>\n   <wangtile tileid=\"1667\" wangid=\"5,0,0,0,5,0,5,0\"/>\n   <wangtile tileid=\"1668\" wangid=\"5,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"1669\" wangid=\"5,5,5,0,0,0,0,0\"/>\n   <wangtile tileid=\"1670\" wangid=\"5,5,5,0,0,0,5,5\"/>\n   <wangtile tileid=\"1671\" wangid=\"5,0,0,0,0,0,5,5\"/>\n   <wangtile tileid=\"1728\" wangid=\"5,5,5,0,5,0,0,0\"/>\n   <wangtile tileid=\"1729\" wangid=\"5,0,0,0,5,0,5,5\"/>\n   <wangtile tileid=\"1730\" wangid=\"0,0,5,0,5,5,5,0\"/>\n   <wangtile tileid=\"1731\" wangid=\"0,0,5,5,5,0,5,0\"/>\n   <wangtile tileid=\"1732\" wangid=\"5,5,5,0,5,5,5,5\"/>\n   <wangtile tileid=\"1733\" wangid=\"5,5,5,5,5,0,5,5\"/>\n   <wangtile tileid=\"1734\" wangid=\"5,0,5,0,5,0,5,5\"/>\n   <wangtile tileid=\"1735\" wangid=\"5,5,5,0,5,0,5,0\"/>\n   <wangtile tileid=\"1792\" wangid=\"5,0,5,5,5,0,0,0\"/>\n   <wangtile tileid=\"1793\" wangid=\"5,0,0,0,5,5,5,0\"/>\n   <wangtile tileid=\"1794\" wangid=\"5,0,5,0,0,0,5,5\"/>\n   <wangtile tileid=\"1795\" wangid=\"5,5,5,0,0,0,5,0\"/>\n   <wangtile tileid=\"1796\" wangid=\"5,0,5,5,5,5,5,5\"/>\n   <wangtile tileid=\"1797\" wangid=\"5,5,5,5,5,5,5,0\"/>\n   <wangtile tileid=\"1798\" wangid=\"5,0,5,0,5,5,5,0\"/>\n   <wangtile tileid=\"1799\" wangid=\"5,0,5,5,5,0,5,0\"/>\n   <wangtile tileid=\"1856\" wangid=\"5,0,5,5,5,5,5,0\"/>\n   <wangtile tileid=\"1857\" wangid=\"5,5,5,0,5,0,5,5\"/>\n   <wangtile tileid=\"1858\" wangid=\"5,0,5,0,5,5,5,5\"/>\n   <wangtile tileid=\"1859\" wangid=\"5,5,5,5,5,0,5,0\"/>\n   <wangtile tileid=\"1860\" wangid=\"5,0,5,5,5,0,5,5\"/>\n   <wangtile tileid=\"1861\" wangid=\"5,5,5,0,5,5,5,0\"/>\n   <wangtile tileid=\"1862\" wangid=\"5,0,5,0,5,0,5,0\"/>\n   <wangtile tileid=\"1921\" wangid=\"0,0,6,0,0,0,0,0\"/>\n   <wangtile tileid=\"1922\" wangid=\"0,0,6,0,0,0,6,0\"/>\n   <wangtile tileid=\"1923\" wangid=\"0,0,0,0,0,0,6,0\"/>\n   <wangtile tileid=\"1924\" wangid=\"0,0,0,0,6,0,0,0\"/>\n   <wangtile tileid=\"1925\" wangid=\"0,0,6,6,6,0,0,0\"/>\n   <wangtile tileid=\"1926\" wangid=\"0,0,6,6,6,6,6,0\"/>\n   <wangtile tileid=\"1927\" wangid=\"0,0,0,0,6,6,6,0\"/>\n   <wangtile tileid=\"1984\" wangid=\"0,0,6,0,6,0,0,0\"/>\n   <wangtile tileid=\"1985\" wangid=\"0,0,0,0,6,0,6,0\"/>\n   <wangtile tileid=\"1986\" wangid=\"6,0,6,0,6,0,0,0\"/>\n   <wangtile tileid=\"1987\" wangid=\"0,0,6,0,6,0,6,0\"/>\n   <wangtile tileid=\"1988\" wangid=\"6,0,0,0,6,0,0,0\"/>\n   <wangtile tileid=\"1989\" wangid=\"6,6,6,6,6,0,0,0\"/>\n   <wangtile tileid=\"1990\" wangid=\"6,6,6,6,6,6,6,6\"/>\n   <wangtile tileid=\"1991\" wangid=\"6,0,0,0,6,6,6,6\"/>\n   <wangtile tileid=\"2048\" wangid=\"6,0,6,0,0,0,0,0\"/>\n   <wangtile tileid=\"2049\" wangid=\"6,0,0,0,0,0,6,0\"/>\n   <wangtile tileid=\"2050\" wangid=\"6,0,6,0,0,0,6,0\"/>\n   <wangtile tileid=\"2051\" wangid=\"6,0,0,0,6,0,6,0\"/>\n   <wangtile tileid=\"2052\" wangid=\"6,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"2053\" wangid=\"6,6,6,0,0,0,0,0\"/>\n   <wangtile tileid=\"2054\" wangid=\"6,6,6,0,0,0,6,6\"/>\n   <wangtile tileid=\"2055\" wangid=\"6,0,0,0,0,0,6,6\"/>\n   <wangtile tileid=\"2112\" wangid=\"6,6,6,0,6,0,0,0\"/>\n   <wangtile tileid=\"2113\" wangid=\"6,0,0,0,6,0,6,6\"/>\n   <wangtile tileid=\"2114\" wangid=\"0,0,6,0,6,6,6,0\"/>\n   <wangtile tileid=\"2115\" wangid=\"0,0,6,6,6,0,6,0\"/>\n   <wangtile tileid=\"2116\" wangid=\"6,6,6,0,6,6,6,6\"/>\n   <wangtile tileid=\"2117\" wangid=\"6,6,6,6,6,0,6,6\"/>\n   <wangtile tileid=\"2118\" wangid=\"6,0,6,0,6,0,6,6\"/>\n   <wangtile tileid=\"2119\" wangid=\"6,6,6,0,6,0,6,0\"/>\n   <wangtile tileid=\"2176\" wangid=\"6,0,6,6,6,0,0,0\"/>\n   <wangtile tileid=\"2177\" wangid=\"6,0,0,0,6,6,6,0\"/>\n   <wangtile tileid=\"2178\" wangid=\"6,0,6,0,0,0,6,6\"/>\n   <wangtile tileid=\"2179\" wangid=\"6,6,6,0,0,0,6,0\"/>\n   <wangtile tileid=\"2180\" wangid=\"6,0,6,6,6,6,6,6\"/>\n   <wangtile tileid=\"2181\" wangid=\"6,6,6,6,6,6,6,0\"/>\n   <wangtile tileid=\"2182\" wangid=\"6,0,6,0,6,6,6,0\"/>\n   <wangtile tileid=\"2183\" wangid=\"6,0,6,6,6,0,6,0\"/>\n   <wangtile tileid=\"2240\" wangid=\"6,0,6,6,6,6,6,0\"/>\n   <wangtile tileid=\"2241\" wangid=\"6,6,6,0,6,0,6,6\"/>\n   <wangtile tileid=\"2242\" wangid=\"6,0,6,0,6,6,6,6\"/>\n   <wangtile tileid=\"2243\" wangid=\"6,6,6,6,6,0,6,0\"/>\n   <wangtile tileid=\"2244\" wangid=\"6,0,6,6,6,0,6,6\"/>\n   <wangtile tileid=\"2245\" wangid=\"6,6,6,0,6,6,6,0\"/>\n   <wangtile tileid=\"2246\" wangid=\"6,0,6,0,6,0,6,0\"/>\n   <wangtile tileid=\"2305\" wangid=\"0,0,7,0,0,0,0,0\"/>\n   <wangtile tileid=\"2306\" wangid=\"0,0,7,0,0,0,7,0\"/>\n   <wangtile tileid=\"2307\" wangid=\"0,0,0,0,0,0,7,0\"/>\n   <wangtile tileid=\"2308\" wangid=\"0,0,0,0,7,0,0,0\"/>\n   <wangtile tileid=\"2309\" wangid=\"0,0,7,7,7,0,0,0\"/>\n   <wangtile tileid=\"2310\" wangid=\"0,0,7,7,7,7,7,0\"/>\n   <wangtile tileid=\"2311\" wangid=\"0,0,0,0,7,7,7,0\"/>\n   <wangtile tileid=\"2368\" wangid=\"0,0,7,0,7,0,0,0\"/>\n   <wangtile tileid=\"2369\" wangid=\"0,0,0,0,7,0,7,0\"/>\n   <wangtile tileid=\"2370\" wangid=\"7,0,7,0,7,0,0,0\"/>\n   <wangtile tileid=\"2371\" wangid=\"0,0,7,0,7,0,7,0\"/>\n   <wangtile tileid=\"2372\" wangid=\"7,0,0,0,7,0,0,0\"/>\n   <wangtile tileid=\"2373\" wangid=\"7,7,7,7,7,0,0,0\"/>\n   <wangtile tileid=\"2374\" wangid=\"7,7,7,7,7,7,7,7\"/>\n   <wangtile tileid=\"2375\" wangid=\"7,0,0,0,7,7,7,7\"/>\n   <wangtile tileid=\"2432\" wangid=\"7,0,7,0,0,0,0,0\"/>\n   <wangtile tileid=\"2433\" wangid=\"7,0,0,0,0,0,7,0\"/>\n   <wangtile tileid=\"2434\" wangid=\"7,0,7,0,0,0,7,0\"/>\n   <wangtile tileid=\"2435\" wangid=\"7,0,0,0,7,0,7,0\"/>\n   <wangtile tileid=\"2436\" wangid=\"7,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"2437\" wangid=\"7,7,7,0,0,0,0,0\"/>\n   <wangtile tileid=\"2438\" wangid=\"7,7,7,0,0,0,7,7\"/>\n   <wangtile tileid=\"2439\" wangid=\"7,0,0,0,0,0,7,7\"/>\n   <wangtile tileid=\"2496\" wangid=\"7,7,7,0,7,0,0,0\"/>\n   <wangtile tileid=\"2497\" wangid=\"7,0,0,0,7,0,7,7\"/>\n   <wangtile tileid=\"2498\" wangid=\"0,0,7,0,7,7,7,0\"/>\n   <wangtile tileid=\"2499\" wangid=\"0,0,7,7,7,0,7,0\"/>\n   <wangtile tileid=\"2500\" wangid=\"7,7,7,0,7,7,7,7\"/>\n   <wangtile tileid=\"2501\" wangid=\"7,7,7,7,7,0,7,7\"/>\n   <wangtile tileid=\"2502\" wangid=\"7,0,7,0,7,0,7,7\"/>\n   <wangtile tileid=\"2503\" wangid=\"7,7,7,0,7,0,7,0\"/>\n   <wangtile tileid=\"2560\" wangid=\"7,0,7,7,7,0,0,0\"/>\n   <wangtile tileid=\"2561\" wangid=\"7,0,0,0,7,7,7,0\"/>\n   <wangtile tileid=\"2562\" wangid=\"7,0,7,0,0,0,7,7\"/>\n   <wangtile tileid=\"2563\" wangid=\"7,7,7,0,0,0,7,0\"/>\n   <wangtile tileid=\"2564\" wangid=\"7,0,7,7,7,7,7,7\"/>\n   <wangtile tileid=\"2565\" wangid=\"7,7,7,7,7,7,7,0\"/>\n   <wangtile tileid=\"2566\" wangid=\"7,0,7,0,7,7,7,0\"/>\n   <wangtile tileid=\"2567\" wangid=\"7,0,7,7,7,0,7,0\"/>\n   <wangtile tileid=\"2624\" wangid=\"7,0,7,7,7,7,7,0\"/>\n   <wangtile tileid=\"2625\" wangid=\"7,7,7,0,7,0,7,7\"/>\n   <wangtile tileid=\"2626\" wangid=\"7,0,7,0,7,7,7,7\"/>\n   <wangtile tileid=\"2627\" wangid=\"7,7,7,7,7,0,7,0\"/>\n   <wangtile tileid=\"2628\" wangid=\"7,0,7,7,7,0,7,7\"/>\n   <wangtile tileid=\"2629\" wangid=\"7,7,7,0,7,7,7,0\"/>\n   <wangtile tileid=\"2630\" wangid=\"7,0,7,0,7,0,7,0\"/>\n   <wangtile tileid=\"2689\" wangid=\"0,0,8,0,0,0,0,0\"/>\n   <wangtile tileid=\"2690\" wangid=\"0,0,8,0,0,0,8,0\"/>\n   <wangtile tileid=\"2691\" wangid=\"0,0,0,0,0,0,8,0\"/>\n   <wangtile tileid=\"2692\" wangid=\"0,0,0,0,8,0,0,0\"/>\n   <wangtile tileid=\"2693\" wangid=\"0,0,8,8,8,0,0,0\"/>\n   <wangtile tileid=\"2694\" wangid=\"0,0,8,8,8,8,8,0\"/>\n   <wangtile tileid=\"2695\" wangid=\"0,0,0,0,8,8,8,0\"/>\n   <wangtile tileid=\"2752\" wangid=\"0,0,8,0,8,0,0,0\"/>\n   <wangtile tileid=\"2753\" wangid=\"0,0,0,0,8,0,8,0\"/>\n   <wangtile tileid=\"2754\" wangid=\"8,0,8,0,8,0,0,0\"/>\n   <wangtile tileid=\"2755\" wangid=\"0,0,8,0,8,0,8,0\"/>\n   <wangtile tileid=\"2756\" wangid=\"8,0,0,0,8,0,0,0\"/>\n   <wangtile tileid=\"2757\" wangid=\"8,8,8,8,8,0,0,0\"/>\n   <wangtile tileid=\"2758\" wangid=\"8,8,8,8,8,8,8,8\"/>\n   <wangtile tileid=\"2759\" wangid=\"8,0,0,0,8,8,8,8\"/>\n   <wangtile tileid=\"2816\" wangid=\"8,0,8,0,0,0,0,0\"/>\n   <wangtile tileid=\"2817\" wangid=\"8,0,0,0,0,0,8,0\"/>\n   <wangtile tileid=\"2818\" wangid=\"8,0,8,0,0,0,8,0\"/>\n   <wangtile tileid=\"2819\" wangid=\"8,0,0,0,8,0,8,0\"/>\n   <wangtile tileid=\"2820\" wangid=\"8,0,0,0,0,0,0,0\"/>\n   <wangtile tileid=\"2821\" wangid=\"8,8,8,0,0,0,0,0\"/>\n   <wangtile tileid=\"2822\" wangid=\"8,8,8,0,0,0,8,8\"/>\n   <wangtile tileid=\"2823\" wangid=\"8,0,0,0,0,0,8,8\"/>\n   <wangtile tileid=\"2880\" wangid=\"8,8,8,0,8,0,0,0\"/>\n   <wangtile tileid=\"2881\" wangid=\"8,0,0,0,8,0,8,8\"/>\n   <wangtile tileid=\"2882\" wangid=\"0,0,8,0,8,8,8,0\"/>\n   <wangtile tileid=\"2883\" wangid=\"0,0,8,8,8,0,8,0\"/>\n   <wangtile tileid=\"2884\" wangid=\"8,8,8,0,8,8,8,8\"/>\n   <wangtile tileid=\"2885\" wangid=\"8,8,8,8,8,0,8,8\"/>\n   <wangtile tileid=\"2886\" wangid=\"8,0,8,0,8,0,8,8\"/>\n   <wangtile tileid=\"2887\" wangid=\"8,8,8,0,8,0,8,0\"/>\n   <wangtile tileid=\"2944\" wangid=\"8,0,8,8,8,0,0,0\"/>\n   <wangtile tileid=\"2945\" wangid=\"8,0,0,0,8,8,8,0\"/>\n   <wangtile tileid=\"2946\" wangid=\"8,0,8,0,0,0,8,8\"/>\n   <wangtile tileid=\"2947\" wangid=\"8,8,8,0,0,0,8,0\"/>\n   <wangtile tileid=\"2948\" wangid=\"8,0,8,8,8,8,8,8\"/>\n   <wangtile tileid=\"2949\" wangid=\"8,8,8,8,8,8,8,0\"/>\n   <wangtile tileid=\"2950\" wangid=\"8,0,8,0,8,8,8,0\"/>\n   <wangtile tileid=\"2951\" wangid=\"8,0,8,8,8,0,8,0\"/>\n   <wangtile tileid=\"3008\" wangid=\"8,0,8,8,8,8,8,0\"/>\n   <wangtile tileid=\"3009\" wangid=\"8,8,8,0,8,0,8,8\"/>\n   <wangtile tileid=\"3010\" wangid=\"8,0,8,0,8,8,8,8\"/>\n   <wangtile tileid=\"3011\" wangid=\"8,8,8,8,8,0,8,0\"/>\n   <wangtile tileid=\"3012\" wangid=\"8,0,8,8,8,0,8,8\"/>\n   <wangtile tileid=\"3013\" wangid=\"8,8,8,0,8,8,8,0\"/>\n   <wangtile tileid=\"3014\" wangid=\"8,0,8,0,8,0,8,0\"/>\n  </wangset>\n </wangsets>\n</tileset>\n"
  },
  {
    "path": "docs/public/[Base]BaseChip_pipo.tsx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[Base]BaseChip_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"1000\" columns=\"8\">\n <image source=\"[Base]BaseChip_pipo.png\" width=\"256\" height=\"4000\"/>\n <tile id=\"0\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"1\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"2\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"3\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"4\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"5\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"6\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"7\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"8\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"9\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"10\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"11\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"12\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"13\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"14\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"15\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"16\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"16.9835\" y=\"14.9844\" width=\"15\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"17\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"1.66533e-16\" y=\"15.4545\" width=\"17\" height=\"16.5455\"/>\n  </objectgroup>\n </tile>\n <tile id=\"18\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"19\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"20\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"21\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"22\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"23\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"24\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"25\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"26\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"27\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"28\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"29\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"30\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"31\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"32\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"33\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"34\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"35\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"36\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"37\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"38\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"39\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"40\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"9.52174\" width=\"31.9565\" height=\"20.4783\"/>\n  </objectgroup>\n </tile>\n <tile id=\"41\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"11.3913\" width=\"32\" height=\"18.913\"/>\n  </objectgroup>\n </tile>\n <tile id=\"42\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"11.4348\" width=\"31.8261\" height=\"18.4348\"/>\n  </objectgroup>\n </tile>\n <tile id=\"43\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.69565\" y=\"19.2174\" width=\"27.2174\" height=\"10.6957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"44\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"45\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"46\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"47\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"48\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"49\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"50\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"51\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"52\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"53\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"54\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"55\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"56\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"57\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"58\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"59\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"60\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"61\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"62\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"63\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"64\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"65\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"66\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"67\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"68\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"69\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"70\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"71\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"72\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"73\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"-0.0869565\" y=\"0.0434783\" width=\"32.087\" height=\"1.86957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"74\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.0434783\">\n    <polygon points=\"0,0 17.7826,0.0869565 31.8261,13.6957 32.1304,31.9565 29.913,31.913 29.5652,14.3913 16.9565,2.04348 -0.0434783,2.04348\"/>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"75\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"76\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"77\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"78\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"79\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"80\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"81\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"82\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"83\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"84\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"85\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"86\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"87\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"88\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"89\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"90\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"91\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"92\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"93\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"94\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"95\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"96\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"97\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"98\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"99\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"121\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"141\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.75\" y=\"-0.25\" width=\"24.5\" height=\"16\"/>\n  </objectgroup>\n </tile>\n <tile id=\"160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.78261\" y=\"0.0434783\" width=\"18.1304\" height=\"13.2174\"/>\n  </objectgroup>\n </tile>\n <tile id=\"164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.5\" y=\"0.75\" width=\"26.25\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.75\" y=\"0.5\" width=\"24.5\" height=\"16.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.25\" y=\"-0.25\" width=\"23.25\" height=\"15.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8.25\" y=\"-0.25\" width=\"14\" height=\"32\"/>\n  </objectgroup>\n </tile>\n <tile id=\"177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.5\" y=\"3.5\" width=\"12\" height=\"28.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.75\" y=\"12.25\" width=\"22\" height=\"19.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"20.75\" height=\"20\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12.5\" width=\"31.5\" height=\"19.75\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"31.5\" height=\"18\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.25\" y=\"0\" width=\"12.5\" height=\"28.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.25\" width=\"19\" height=\"27.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.25\" y=\"11.25\" width=\"20\" height=\"16.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.5\" y=\"0.25\" width=\"19.25\" height=\"31.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"13.8261\" width=\"20\" height=\"6.17391\"/>\n   <object id=\"2\" x=\"10.3478\" y=\"0.130435\" width=\"10.2174\" height=\"31.7391\"/>\n  </objectgroup>\n </tile>\n <tile id=\"191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.9565\" y=\"4.43478\" width=\"8\" height=\"24.0435\"/>\n  </objectgroup>\n </tile>\n <tile id=\"192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.75\" y=\"10.75\" width=\"17.25\" height=\"19\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"4.18182\" y=\"17.4545\" width=\"23.8182\" height=\"14\"/>\n  </objectgroup>\n </tile>\n <tile id=\"237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.8696\" y=\"20.3913\" width=\"6.21739\" height=\"9.56522\"/>\n  </objectgroup>\n </tile>\n <tile id=\"238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.17391\" y=\"18.9565\" width=\"28.7391\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"19.5217\" width=\"28.9565\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"14.0435\" width=\"31.913\" height=\"12.1739\"/>\n  </objectgroup>\n </tile>\n <tile id=\"266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.0435\" y=\"16.2609\" width=\"7.43478\" height=\"15.8696\">\n    <properties>\n     <property name=\"overlay\" type=\"bool\" value=\"true\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"4\">\n   <object id=\"4\" x=\"14.5272\" y=\"16.125\" width=\"6.28261\" height=\"16.0734\"/>\n  </objectgroup>\n </tile>\n <tile id=\"270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"15\" y=\"0.0869565\" width=\"2.04348\" height=\"31.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"14.8261\" y=\"0.0434783\" width=\"2.26087\" height=\"31.8696\"/>\n  </objectgroup>\n </tile>\n <tile id=\"278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"14.1304\" width=\"31.7826\" height=\"12.6087\"/>\n  </objectgroup>\n </tile>\n <tile id=\"282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.2609\" y=\"0.173913\" width=\"9.21739\" height=\"23.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.4348\" y=\"0.0434783\" width=\"9.17391\" height=\"23.5217\"/>\n  </objectgroup>\n </tile>\n <tile id=\"286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0\" width=\"8.75\" height=\"30.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"21\" y=\"0.5\" width=\"9.5\" height=\"29.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8\" y=\"11.2727\" width=\"15.4545\" height=\"18.7273\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.1818\" y=\"12.9091\" width=\"12\" height=\"15.6364\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n</tileset>\n"
  },
  {
    "path": "docs/public/grammar.pegjs",
    "content": "{\n  function generateError(message, location) {\n    const { start, end } = location;\n    const errorMessage = `${message}\\n` +\n      `at line ${start.line}, column ${start.column} to line ${end.line}, column ${end.column}`;\n    throw new Error(errorMessage);\n  }\n\n  /*——— Custom error handler for syntax errors ———*/\n  function parseError(error) {\n    // error.expected : array of { type, description }\n    // error.found    : string | null\n    // error.location : { start, end }\n    const { expected, found, location } = error;\n\n    // Group expected items by description to avoid duplicates\n    const uniqueExpected = [...new Set(expected.map(e => e.description))];\n    \n    // Format the expected values in a more readable way\n    const expectedDesc = uniqueExpected\n      .map(desc => `'${desc}'`)\n      .join(' or ');\n\n    const foundDesc = found === null ? 'end of input' : `'${found}'`;\n\n    generateError(\n      `Syntax error: expected ${expectedDesc} but found ${foundDesc}`,\n      location\n    );\n  }\n\n  // List of standard HTML DOM elements\n  const domElements = new Set([\n    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 'samp', 's', 'script', 'section', 'select', 'slot', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr'\n  ]);\n\n  // Framework components that should NOT be transformed to DOM elements\n  const frameworkComponents = new Set([\n    'Canvas', 'Container', 'Sprite', 'Text', 'DOMElement', 'Svg', 'Button'\n  ]);\n\n  const voidElements = new Set([\n    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta',\n    'param', 'source', 'track', 'wbr'\n  ]);\n\n  const eventAttributes = new Set([\n    'click', 'tap', 'pointertap', 'pointerdown', 'pointerup', 'pointermove',\n    'pointerover', 'pointerout', 'pointerupoutside', 'mousedown', 'mouseup',\n    'mousemove', 'mouseover', 'mouseout', 'touchstart', 'touchend', 'touchmove',\n    'touchcancel', 'rightclick', 'keydown', 'keyup', 'keypress'\n  ]);\n\n  // DisplayObject special attributes that should not be in attrs\n  const displayObjectAttributes = new Set([\n    'x', 'y', 'scale', 'anchor', 'skew', 'tint', 'rotation', 'angle', \n    'zIndex', 'roundPixels', 'cursor', 'visible', 'alpha', 'pivot', 'filters', 'maskOf', \n    'blendMode', 'filterArea', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', \n    'aspectRatio', 'flexGrow', 'flexShrink', 'flexBasis', 'rowGap', 'columnGap', \n    'positionType', 'top', 'right', 'bottom', 'left', 'objectFit', 'objectPosition', \n    'transformOrigin', 'flexDirection', 'justifyContent', 'alignItems', 'alignContent', \n    'alignSelf', 'margin', 'padding', 'border', 'gap', 'blur', 'shadow'\n  ]);\n\n  function isDOMElement(tagName) {\n    // Don't transform framework components to DOM elements\n    if (frameworkComponents.has(tagName)) {\n      return false;\n    }\n    return domElements.has(tagName.toLowerCase());\n  }\n\n  function isVoidElement(tagName) {\n    return voidElements.has(tagName.toLowerCase());\n  }\n\n  function formatAttributes(attributes) {\n    if (attributes.length === 0) {\n      return null;\n    }\n  \n    // Check if there's exactly one attribute and it's a spread attribute\n    if (attributes.length === 1 && attributes[0].startsWith('...')) {\n      // Return the identifier directly, removing the '...'\n      return attributes[0].substring(3);\n    }\n  \n    // Otherwise, format as an object literal\n    const formattedAttrs = attributes.map(attr => {\n      // If it's a spread attribute, keep it as is\n      if (attr.startsWith('...')) {\n        return attr;\n      }\n      // If it's a standalone attribute (doesn't contain ':'), format as shorthand property 'name'\n      if (!attr.includes(':')) {\n        return attr; // JS object literal shorthand\n      }\n      // Otherwise (key: value), keep it as is\n      return attr;\n    });\n  \n    return `{ ${formattedAttrs.join(', ')} }`;\n  }\n\n  function formatDOMElement(tagName, attributes) {\n    if (attributes.length === 0) {\n      return `h(DOMElement, { element: \"${tagName}\" })`;\n    }\n\n    const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n    // Build the result\n    const parts = [`element: \"${tagName}\"`];\n    \n    if (domAttrs.length > 0) {\n      parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n    }\n    \n    if (displayObjectAttrs.length > 0) {\n      parts.push(...displayObjectAttrs);\n    }\n\n    return `h(DOMElement, { ${parts.join(', ')} })`;\n  }\n\n  function splitAttributes(attributes) {\n    const domAttrs = [];\n    const displayObjectAttrs = [];\n    const classValues = [];\n    let classInsertIndex = null;\n\n    attributes.forEach(attr => {\n      // Handle spread attributes\n      if (attr.startsWith('...')) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      // Extract attribute name and value (if present)\n      let attrName;\n      let attrValue;\n      if (attr.includes(':')) {\n        const colonIndex = attr.indexOf(':');\n        attrName = attr.slice(0, colonIndex).trim().replace(/['\"]/g, '');\n        attrValue = attr.slice(colonIndex + 1).trim();\n      } else {\n        // Standalone attribute\n        attrName = attr.replace(/['\"]/g, '');\n      }\n\n      // Check if it's a DisplayObject attribute\n      if (displayObjectAttributes.has(attrName)) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      if (attrName === 'class' && attrValue !== undefined) {\n        classValues.push(attrValue);\n        if (classInsertIndex === null) {\n          classInsertIndex = domAttrs.length;\n        }\n        return;\n      }\n\n      domAttrs.push(attr);\n    });\n\n    if (classValues.length > 0) {\n      const mergedClass = classValues.length === 1\n        ? `class: ${classValues[0]}`\n        : `class: [${classValues.join(', ')}]`;\n      if (classInsertIndex === null) {\n        domAttrs.push(mergedClass);\n      } else {\n        domAttrs.splice(classInsertIndex, 0, mergedClass);\n      }\n    }\n\n    return { domAttrs, displayObjectAttrs };\n  }\n\n  function formatDOMContainerAttributes(attributes) {\n    if (attributes.length === 0) {\n      return null;\n    }\n\n    const propsEntries = [];\n    const domAttrs = [];\n    const classValues = [];\n    let classInsertIndex = null;\n    let attrsInsertIndex = null;\n    let attrsIndex = null;\n    let attrsValue = null;\n\n    attributes.forEach(attr => {\n      if (attr.startsWith('...')) {\n        propsEntries.push(attr);\n        return;\n      }\n\n      let attrName;\n      let attrValue;\n      if (attr.includes(':')) {\n        const colonIndex = attr.indexOf(':');\n        attrName = attr.slice(0, colonIndex).trim().replace(/['\"]/g, '');\n        attrValue = attr.slice(colonIndex + 1).trim();\n      } else {\n        attrName = attr.replace(/['\"]/g, '');\n      }\n\n      if (attrName === 'class' && attrValue !== undefined) {\n        classValues.push(attrValue);\n        if (classInsertIndex === null) {\n          classInsertIndex = domAttrs.length;\n        }\n        if (attrsInsertIndex === null) {\n          attrsInsertIndex = propsEntries.length;\n        }\n        return;\n      }\n\n      if (attrName === 'style') {\n        domAttrs.push(attr);\n        if (attrsInsertIndex === null) {\n          attrsInsertIndex = propsEntries.length;\n        }\n        return;\n      }\n\n      if (attrName === 'attrs' && attrValue !== undefined) {\n        attrsValue = attrValue;\n        attrsIndex = propsEntries.length;\n        propsEntries.push(null);\n        return;\n      }\n\n      propsEntries.push(attr);\n    });\n\n    if (classValues.length > 0) {\n      const mergedClass = classValues.length === 1\n        ? `class: ${classValues[0]}`\n        : `class: [${classValues.join(', ')}]`;\n      if (classInsertIndex === null) {\n        domAttrs.push(mergedClass);\n      } else {\n        domAttrs.splice(classInsertIndex, 0, mergedClass);\n      }\n    }\n\n    let attrsEntry = null;\n    if (attrsValue && domAttrs.length > 0) {\n      attrsEntry = `attrs: { ...${attrsValue}, ${domAttrs.join(', ')} }`;\n    } else if (attrsValue) {\n      attrsEntry = `attrs: ${attrsValue}`;\n    } else if (domAttrs.length > 0) {\n      attrsEntry = `attrs: { ${domAttrs.join(', ')} }`;\n    }\n\n    if (attrsEntry) {\n      if (attrsIndex !== null) {\n        propsEntries[attrsIndex] = attrsEntry;\n      } else if (attrsInsertIndex !== null) {\n        propsEntries.splice(attrsInsertIndex, 0, attrsEntry);\n      } else {\n        propsEntries.unshift(attrsEntry);\n      }\n    }\n\n    const filteredEntries = propsEntries.filter(entry => entry !== null);\n    if (filteredEntries.length === 0) {\n      return null;\n    }\n\n    if (filteredEntries.length === 1 && filteredEntries[0].startsWith('...')) {\n      return filteredEntries[0].substring(3);\n    }\n\n    return `{ ${filteredEntries.join(', ')} }`;\n  }\n\n  function hasFunctionCall(value) {\n    return /[a-zA-Z_][a-zA-Z0-9_]*\\s*\\(/.test(value);\n  }\n\n  function hasIdentifier(value) {\n    return /[a-zA-Z_]/.test(value);\n  }\n\n  function isSimpleAccessor(value) {\n    return /^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(value.trim());\n  }\n\n  function formatObjectLiteralSpacing(value) {\n    const trimmed = value.trim();\n    if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n      return value;\n    }\n    const inner = trimmed.slice(1, -1).trim();\n    return `{ ${inner} }`;\n  }\n\n  function collectMemberRoots(value) {\n    const roots = new Set();\n    const memberRegex = /\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\./g;\n    let match;\n\n    while ((match = memberRegex.exec(value)) !== null) {\n      roots.add(match[1]);\n    }\n\n    return roots;\n  }\n\n  function transformBareIdentifiersToSignals(value) {\n    const memberRoots = collectMemberRoots(value);\n\n    return value.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match, name, offset) => {\n      if (['true', 'false', 'null'].includes(name)) {\n        return match;\n      }\n\n      const beforeMatch = value.substring(0, offset);\n      const singleQuotesBefore = (beforeMatch.match(/'/g) || []).length;\n      const doubleQuotesBefore = (beforeMatch.match(/\"/g) || []).length;\n      if (singleQuotesBefore % 2 === 1 || doubleQuotesBefore % 2 === 1) {\n        return match;\n      }\n\n      const charBefore = offset > 0 ? value[offset - 1] : '';\n      const charAfter = offset + match.length < value.length ? value[offset + match.length] : '';\n\n      if (charBefore === '.' || charAfter === '.') {\n        return match;\n      }\n\n      if (memberRoots.has(name)) {\n        return match;\n      }\n\n      const afterSlice = value.slice(offset + match.length);\n      if (/^\\s*\\(/.test(afterSlice)) {\n        return match;\n      }\n\n      return `${name}()`;\n    });\n  }\n}\n\nstart\n  = _ elements:(element)* _ {\n    if (elements.length === 1) {\n      return elements[0];\n    }\n    return `[${elements.join(',')}]`;\n  }\n\nelement \"component or control structure\"\n  = forLoop\n  / ifCondition\n  / svgElement\n  / domElementWithText\n  / domElementWithMixedContent\n  / selfClosingElement\n  / voidElement\n  / openCloseElement\n  / openUnclosedTag\n  / comment\n\nselfClosingElement \"self-closing component tag\"\n  = _ \"<\" _ tagName:tagName _ attributes:attributes _ \"/>\" _ {\n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        return formatDOMElement(tagName, attributes);\n      }\n      if (tagName === 'DOMContainer') {\n        const attrsString = formatDOMContainerAttributes(attributes);\n        return attrsString ? `h(DOMContainer, ${attrsString})` : `h(DOMContainer)`;\n      }\n      // Otherwise, treat as regular component\n      const attrsString = formatAttributes(attributes);\n      return attrsString ? `h(${tagName}, ${attrsString})` : `h(${tagName})`;\n    }\n\nvoidElement \"void DOM element tag\"\n  = _ \"<\" _ tagName:tagName &{ return isVoidElement(tagName); } _ attributes:attributes _ \">\" _ {\n      return formatDOMElement(tagName, attributes);\n    }\n\ndomElementWithText \"DOM element with text content\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ text:simpleTextContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      if (isDOMElement(tagName)) {\n        if (attributes.length === 0) {\n          return `h(DOMElement, { element: \"${tagName}\", textContent: ${text} })`;\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        parts.push(`textContent: ${text}`);\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n      \n      // If not a DOM element, fall back to regular parsing\n      return null;\n    }\n\ndomElementWithMixedContent \"DOM element with mixed content\"\n  = \"<\" _ tagName:tagName &{ return isDOMElement(tagName) && !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ children:domContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n\n      const childrenContent = children ? children : null;\n\n      if (attributes.length === 0) {\n        if (childrenContent) {\n          return `h(DOMElement, { element: \"${tagName}\" }, ${childrenContent})`;\n        } else {\n          return `h(DOMElement, { element: \"${tagName}\" })`;\n        }\n      }\n\n      const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n      // Build the result\n      const parts = [`element: \"${tagName}\"`];\n      \n      if (domAttrs.length > 0) {\n        parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n      }\n      \n      if (displayObjectAttrs.length > 0) {\n        parts.push(...displayObjectAttrs);\n      }\n\n      if (childrenContent) {\n        return `h(DOMElement, { ${parts.join(', ')} }, ${childrenContent})`;\n      } else {\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n    }\n\nsimpleTextContent \"simple text content\"\n  = parts:(simpleDynamicPart / simpleTextPart)+ {\n      const validParts = parts.filter(p => p !== null);\n      if (validParts.length === 0) return null;\n      if (validParts.length === 1) return validParts[0];\n      \n      // Multiple parts - need to concatenate\n      const normalizedParts = validParts.map(part => {\n        if (typeof part === 'string' && part.startsWith('computed(() => ') && part.endsWith(')')) {\n          return part.slice('computed(() => '.length, -1);\n        }\n        return part;\n      });\n      const hasSignals = normalizedParts.some(part => part && part.includes && part.includes('()'));\n      if (hasSignals) {\n        return `computed(() => ${normalizedParts.join(' + ')})`;\n      }\n      return normalizedParts.join(' + ');\n    }\n\nsimpleTextPart \"simple text part\"\n  = !(\"@for\" / \"@if\") text:$([^<{@]+) {\n      const trimmed = text.trim();\n      if (!trimmed) return null;\n      const escaped = text\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/'/g, \"\\\\'\")\n        .replace(/\\r/g, '\\\\r')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\t/g, '\\\\t');\n      return `'${escaped}'`;\n    }\n\nsimpleDynamicPart \"simple dynamic part\"\n  = \"{{\" _ expr:attributeValue _ \"}}\" {\n      const trimmedExpr = expr.trim();\n      if (!trimmedExpr) {\n        return trimmedExpr;\n      }\n      if (hasFunctionCall(trimmedExpr)) {\n        return `computed(() => ${trimmedExpr})`;\n      }\n      return trimmedExpr;\n    }\n  / \"{\" _ expr:attributeValue _ \"}\" {\n      const trimmedExpr = expr.trim();\n      if (!trimmedExpr) {\n        return trimmedExpr;\n      }\n      if (hasFunctionCall(trimmedExpr)) {\n        return `computed(() => ${trimmedExpr})`;\n      }\n      return trimmedExpr;\n    }\n\nopenCloseElement \"component with content\"\n  = \"<\" _ tagName:tagName _ attributes:attributes _ \">\" _ content:content _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      const children = content ? content : null;\n\n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        if (attributes.length === 0) {\n          if (children) {\n            return `h(DOMElement, { element: \"${tagName}\" }, ${children})`;\n          } else {\n            return `h(DOMElement, { element: \"${tagName}\" })`;\n          }\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        if (children) {\n          return `h(DOMElement, { ${parts.join(', ')} }, ${children})`;\n        } else {\n          return `h(DOMElement, { ${parts.join(', ')} })`;\n        }\n      }\n      \n      // Otherwise, treat as regular component\n      if (tagName === 'DOMContainer') {\n        const attrsString = formatDOMContainerAttributes(attributes);\n        if (attrsString && children) {\n          return `h(DOMContainer, ${attrsString}, ${children})`;\n        } else if (attrsString) {\n          return `h(DOMContainer, ${attrsString})`;\n        } else if (children) {\n          return `h(DOMContainer, null, ${children})`;\n        } else {\n          return `h(DOMContainer)`;\n        }\n      }\n\n      const attrsString = formatAttributes(attributes);\n      if (attrsString && children) {\n        return `h(${tagName}, ${attrsString}, ${children})`;\n      } else if (attrsString) {\n        return `h(${tagName}, ${attrsString})`;\n      } else if (children) {\n        return `h(${tagName}, null, ${children})`;\n      } else {\n        return `h(${tagName})`;\n      }\n    }\n\nattributes \"component attributes\"\n  = attrs:(attribute (_ attribute)*)? {\n      return attrs\n        ? [attrs[0]].concat(attrs[1].map(a => a[1]))\n        : [];\n    }\n\nattribute \"attribute\"\n  = staticAttribute\n  / dynamicAttribute\n  / eventHandler\n  / spreadAttribute\n  / unclosedQuote\n  / unclosedBrace\n\nspreadAttribute \"spread attribute\"\n  = \"...\" expr:(functionCallExpr / dotNotation) {\n      return \"...\" + expr;\n    }\n\nfunctionCallExpr \"function call\"\n  = name:dotNotation \"(\" args:functionArgs? \")\" {\n      return `${name}(${args || ''})`;\n    }\n\ndotNotation \"property access\"\n  = first:identifier rest:(\".\" identifier)* {\n      return text();\n    }\n\neventHandler \"event handler\"\n  = \"@\" eventName:identifier _ \"=\" _ \"{\" _ handlerName:attributeValue _ \"}\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      const formattedName = needsQuotes ? `'${eventName}'` : eventName;\n      return `${formattedName}: ${handlerName}`;\n    }\n     / \"@\" eventName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      return needsQuotes ? `'${eventName}'` : eventName;\n    }\n\ndynamicAttribute \"dynamic attribute\"\n  = attributeName:attributeName _ \"=\" _ \"{\" _ attributeValue:attributeValue _ \"}\" {\n      // Check if attributeName needs to be quoted (contains dash or other invalid JS identifier chars)\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      \n        if (eventAttributes.has(attributeName)) {\n          return `${formattedName}: ${attributeValue}`;\n        }\n      \n        // If it's a complex object with strings, preserve it as is\n        if (attributeValue.trim().startsWith('{') && attributeValue.trim().endsWith('}') && \n            (attributeValue.includes('\"') || attributeValue.includes(\"'\"))) {\n          return `${formattedName}: ${attributeValue}`;\n        }\n        \n        // If it's a template string, keep it as-is\n      if (attributeValue.trim().startsWith('`') && attributeValue.trim().endsWith('`')) {\n        return formattedName + ': ' + attributeValue;\n      }\n      \n      // Handle other types of values\n      if (attributeValue.startsWith('h(') || attributeValue.includes('=>')) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const trimmedValue = attributeValue.trim();\n      if (trimmedValue.match(/^[a-zA-Z_]\\w*$/)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (/^\\d+(\\.\\d+)?$/.test(trimmedValue) || ['true', 'false', 'null'].includes(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (isSimpleAccessor(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const isObjectLiteral = trimmedValue.startsWith('{') && trimmedValue.endsWith('}');\n      const isArrayLiteral = trimmedValue.startsWith('[') && trimmedValue.endsWith(']');\n      const isTernaryExpression = trimmedValue.includes('?') && trimmedValue.includes(':');\n      if (isObjectLiteral) {\n        const formattedObject = formatObjectLiteralSpacing(attributeValue);\n        if (hasFunctionCall(trimmedValue)) {\n          return `${formattedName}: computed(() => (${formattedObject}))`;\n        }\n        return `${formattedName}: ${formattedObject}`;\n      }\n      if (isArrayLiteral) {\n        if (hasFunctionCall(trimmedValue)) {\n          return `${formattedName}: computed(() => ${attributeValue})`;\n        }\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (isTernaryExpression) {\n        return `${formattedName}: computed(() => ${attributeValue})`;\n      }\n\n      if (hasFunctionCall(trimmedValue)) {\n        return `${formattedName}: computed(() => ${attributeValue})`;\n      }\n\n      if (!hasIdentifier(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const computedValue = transformBareIdentifiersToSignals(attributeValue);\n      return `${formattedName}: computed(() => ${computedValue})`;\n    }\n  / attributeName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      return needsQuotes ? `'${attributeName}'` : attributeName;\n    }\n\nattributeValue \"attribute value\"\n  = element\n  / functionWithElement\n  / objectLiteral\n  / $([^{}]* (\"{\" [^{}]* \"}\" [^{}]*)*) {\n    return text().trim()\n  }\n\nobjectLiteral \"object literal\"\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nobjectContent\n  = prop:objectProperty rest:(_ \",\" _ objectProperty)* {\n    return [prop].concat(rest.map(r => r[3])).join(', ');\n  }\n  / \"\" { return \"\"; }\n\nobjectProperty\n  = key:identifier _ \":\" _ value:propertyValue {\n    return `${key}: ${value}`;\n  }\n  / key:identifier {\n    return key;\n  }\n\npropertyValue\n  = nestedObject\n  / element\n  / functionWithElement\n  / stringLiteral\n  / number\n  / identifier\n\nnestedObject\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nstringLiteral\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\nfunctionWithElement \"function expression\"\n  = \"(\" _ params:functionParams? _ \")\" _ \"=>\" _ elem:element {\n      return `${params ? `(${params}) =>` : '() =>'} ${elem}`;\n    }\n\nfunctionParams\n  = destructuredParams\n  / simpleParams\n\ndestructuredParams\n  = \"{\" _ param:identifier rest:(_ \",\" _ identifier)* _ \"}\" {\n      return `{${[param].concat(rest.map(r => r[3])).join(', ')}}`;\n    }\n\nsimpleParams\n  = param:identifier rest:(_ \",\" _ identifier)* {\n      return [param].concat(rest.map(r => r[3])).join(', ');\n    }\n\nstaticAttribute \"static attribute\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" attributeValue:staticValue \"\\\"\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      return `${formattedName}: ${attributeValue}`;\n    }\n\neventAttribute\n  = \"(\" _ eventName:eventName _ \")\" _ \"=\" _ \"\\\"\" eventAction:eventAction \"\\\"\" {\n      return `${eventName}: () => { ${eventAction} }`;\n    }\n\nstaticValue\n  = [^\"]+ {\n      var val = text();\n      return `'${val}'`\n    }\n\ncontent \"component content\"\n  = elements:(element)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContent \"DOM content\"\n  = elements:(domContentPart)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContentPart\n  = element\n  / simpleTextContent\n\n\n\ntextNode\n  = text:$([^<]+) {\n      const trimmed = text.trim();\n      return trimmed ? `'${trimmed}'` : null;\n    }\n\ntextElement\n  = text:[^<>]+ {\n      const trimmed = text.join('').trim();\n      return trimmed ? JSON.stringify(trimmed) : null;\n    }\n\nforLoop \"for loop\"\n  = _ \"@for\" _ \"(\" _ variableName:(tupleDestructuring / identifier) _ \"of\" _ iterable:iterable _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return `loop(${iterable}, ${variableName} => ${content})`;\n    }\n\ntupleDestructuring \"destructuring pattern\"\n  = \"(\" _ first:identifier _ \",\" _ second:identifier _ \")\" {\n      return `(${first}, ${second})`;\n    }\n\nifCondition \"if condition\"\n  = _ \"@if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ elseIfs:elseIfClause* elseClause:elseClause? _ {\n      let result = `cond(${condition}, () => ${content}`;\n      \n      // Add else if clauses\n      elseIfs.forEach(elseIf => {\n        result += `, [${elseIf.condition}, () => ${elseIf.content}]`;\n      });\n      \n      // Add else clause if present\n      if (elseClause) {\n        result += `, () => ${elseClause}`;\n      }\n      \n      result += ')';\n      return result;\n    }\n\nelseIfClause \"else if clause\"\n  = _ \"@else\" _ \"if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return { condition, content };\n    }\n\nelseClause \"else clause\"\n  = _ \"@else\" _ \"{\" _ content:content _ \"}\" _ {\n      return content;\n    }\n\ntagName \"tag name\"\n  = tagExpression\n\ntagExpression \"tag expression\"\n  = first:tagPart rest:(\".\" tagPart)* {\n      return text();\n    }\n\ntagPart \"tag part\"\n  = name:[a-zA-Z][a-zA-Z0-9]* args:(\"(\" functionArgs? \")\")? {\n      return text();\n    }\n\nattributeName \"attribute name\"\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\neventName\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\nvariableName\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\niterable \"iterable expression\"\n  = id:identifier \"(\" _ args:functionArgs? _ \")\" { // Direct function call\n      return `${id}(${args || ''})`;\n    }\n  / first:identifier \".\" rest:dotFunctionChain { // Dot notation possibly with function call\n      return `${first}.${rest}`;\n    }\n  / id:identifier { return id; }\n\ndotFunctionChain\n  = segment:identifier \"(\" _ args:functionArgs? _ \")\" rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}(${args || ''})${restStr}`;\n    }\n  / segment:identifier rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}${restStr}`;\n    }\n\ncondition \"condition expression\"\n  = text:$(conditionChunk*) {\n      const originalText = text.trim();\n      if (!originalText) {\n        return originalText;\n      }\n\n      const hasOperator = /[!<>=&|]/.test(originalText);\n      if (hasOperator) {\n        return `computed(() => ${originalText})`;\n      }\n\n      return originalText;\n  }\n\nconditionChunk\n  = \"(\" conditionChunk* \")\"\n  / [^()]\n\nfunctionCall \"function call\"\n  = name:identifier \"(\" args:functionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionCallWithArgs \"function call with complex args\"\n  = name:identifier \"(\" args:complexFunctionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionArgs\n  = arg:functionArg rest:(\",\" _ functionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\ncomplexFunctionArgs\n  = arg:complexFunctionArg rest:(\",\" _ complexFunctionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\nfunctionArg\n  = _ value:(identifier / number / string) _ {\n    return value;\n  }\n\ncomplexFunctionArg \"complex function argument\"\n  = _ value:complexArgExpression _ {\n    return value.trim();\n  }\n\ncomplexArgExpression \"complex argument expression\"\n  = $([^,)]* (\"(\" [^)]* \")\" [^,)]*)*) {\n    return text().trim();\n  }\n\nnumber\n  = [0-9]+ (\".\" [0-9]+)? { return text(); }\n\nstring\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\neventAction\n  = [^\"]* { return text(); }\n\n_ 'whitespace'\n  = [ \\t\\n\\r]* \n\nidentifier\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\ncomment\n  = singleComment+ {\n    return null\n  }\n\nsingleComment\n  = \"<!--\" _ content:((!(\"-->\") .)* \"-->\") _ {\n      return null;\n    }\n\n// Add a special error detection rule for unclosed tags\nopenUnclosedTag \"unclosed tag\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ content:content _ !(\"</\" _ closingTagName:tagName _ \">\") {\n      generateError(\n        `Unclosed tag: <${tagName}> is missing its closing tag`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed quotes in static attributes\nunclosedQuote \"unclosed string\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" [^\"]* !(\"\\\"\") {\n      generateError(\n        `Missing closing quote in attribute '${attributeName}'`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed braces in dynamic attributes\nunclosedBrace \"unclosed brace\"\n  = attributeName:attributeName _ \"=\" _ \"{\" !(\"}\" / _ \"}\") [^{}]* {\n      generateError(\n        `Missing closing brace in dynamic attribute '${attributeName}'`,\n        location()\n      );\n    }\n\nsvgElement \"SVG element\"\n  = \"<svg\" attrs:([^>]*) \">\" content:svgInnerContent \"</svg>\" _ {\n      const attributes = attrs.join('').trim();\n      // Clean up the content by removing extra whitespace and newlines\n      const cleanContent = content.replace(/\\s+/g, ' ').trim();\n      const rawContent = `<svg${attributes ? ' ' + attributes : ''}>${cleanContent}</svg>`;\n      return `h(Svg, { content: \\`${rawContent}\\` })`;\n    }\n\nsvgInnerContent \"SVG inner content\"\n  = content:$((!(\"</svg>\") .)*) {\n      return content;\n    }\n"
  },
  {
    "path": "docs/public/map.tmx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.9\" tiledversion=\"1.9.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"40\" height=\"40\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"11\" nextobjectid=\"33\">\n <tileset firstgid=\"1\" source=\"tileset.tsx\"/>\n <layer id=\"8\" name=\"Tile Layer 1\" width=\"40\" height=\"40\">\n  <data encoding=\"base64\">\n   AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n  </data>\n </layer>\n <layer id=\"10\" name=\"Tile Layer 2\" width=\"40\" height=\"40\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAACgAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAoAAAAAAAAAEQAAABIAAAARAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAEQAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAkAAAAKAAAACQAAAAoAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAABEAAAASAAAAAAAAAAAAAAARAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <objectgroup id=\"9\" name=\"Object Layer 1\">\n  <object id=\"30\" name=\"start\" x=\"156\" y=\"220\">\n   <point/>\n  </object>\n  <object id=\"31\" name=\"EV-1\" x=\"571\" y=\"417\">\n   <point/>\n  </object>\n  <object id=\"32\" name=\"EV-2\" x=\"500\" y=\"351\">\n   <point/>\n  </object>\n </objectgroup>\n</map>\n"
  },
  {
    "path": "docs/public/simplemap.tmx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.9\" tiledversion=\"1.9.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"25\" height=\"20\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"14\">\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <tileset firstgid=\"1001\" source=\"[A]Water_pipo.tsx\"/>\n <tileset firstgid=\"4073\" source=\"[A]Dirt_pipo.tsx\"/>\n <tileset firstgid=\"4409\" source=\"[A]Flower_pipo.tsx\"/>\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"25\" height=\"20\">\n  <data encoding=\"base64\">\n   AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAA=\n  </data>\n </layer>\n <objectgroup id=\"3\" name=\"Object Layer 1\" offsetx=\"1\" offsety=\"0\">\n  <object id=\"1\" name=\"start\" class=\"start\" x=\"375.943\" y=\"217.028\">\n   <point/>\n  </object>\n  <object id=\"12\" name=\"EV-1\" x=\"290.284\" y=\"371.638\">\n   <point/>\n  </object>\n </objectgroup>\n <layer id=\"2\" name=\"Tile Layer 2\" width=\"25\" height=\"20\">\n  <data encoding=\"base64\">\n   rwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAAAtBgAA7wUAAO8FAADvBQAA7wUAAC4GAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAC0GAADvBQAA8AUAAG4RAABvEQAAbxEAAHARAADuBQAA7wUAAC4GAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAC0GAADvBQAA7wUAAO8FAADwBQAAbhEAAG8RAACOEQAAdxEAAHcRAACNEQAAbxEAAHARAADuBQAA7wUAAO8FAADvBQAALgYAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACwBQAAbhEAAG8RAABvEQAAbxEAAI4RAAB3EQAAdxEAAHcRAAB3EQAAdxEAAHcRAACNEQAAbxEAAG8RAABwEQAAAAAAAO4FAADvBQAA7wUAAC4GAACvBQAArwUAAK8FAACvBQAAsAUAAHYRAAB3EQAAdxEAAHcRAAB3EQAAdxEAAIURAAB/EQAAfxEAAIYRAAB3EQAAdxEAAHcRAAB3EQAAeBEAAAAAAAApAAAAAAAAAAAAAACuBQAArwUAAK8FAACvBQAALQYAAPAFAAB2EQAAdxEAAHcRAACFEQAACQAAAAoAAACAEQAAAAAAAAAAAAB+EQAAfxEAAH8RAAB/EQAAfxEAAIARAAAAAAAAAAAAAAkAAAAKAAAArgUAAK8FAACvBQAArwUAALAFAABuEQAAjhEAAHcRAAB3EQAAeBEAABEAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAwAAAARAAAAEgAAAO4FAAAuBgAArwUAAK8FAACwBQAAdhEAAHcRAAB3EQAAdxEAAHgRAAAAAAAAAAAAAK4QAACvEAAAsBAAAAAAAAAAAAAANwAAAAAAAAAAAAAAAAAAABMAAAAUAAAAAAAAAAAAAAAAAAAArgUAAK8FAACvBQAAsAUAAH4RAAB/EQAAfxEAAH8RAACAEQAAAAAAAK4QAADOEAAAtxAAALgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAK4FAACvBQAArwUAALAFAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAC2EAAAtxAAALcQAAC4EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAAAAAA1AAAAAAAAAAAAAACuBQAArwUAAK8FAABtBgAAcAUAAAAAAAARAAAAEgAAAAAAAAAAAAAAthAAALcQAAC3EAAAuBAAAAAAAAAAAAAANQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAoAAAAAAAAArgUAAK8FAACvBQAArwUAALAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAALYQAAC3EAAAtxAAALgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3AAAAAAAAABEAAAASAAAAAAAAAK4FAACvBQAA7wUAAO8FAADwBQAAAAAAAAAAAAAAAAAArhAAAK8QAADOEAAAtxAAALcQAAC4EAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADuBQAALgYAAEoAAABLAAAAAAAAAAkAAAAKAAAAAAAAALYQAAC3EAAAtxAAALcQAADFEAAAwBAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAAAAAAJAAAACgAAAAAAAAAAAAAAAAAAAK4FAAAAAAAAUwAAAAAAAAARAAAAEgAAAAAAAAC2EAAAtxAAAMUQAAC/EAAAwBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAABIAAAA3AAAAAAAAAAAAAACuBQAAAAAAAFMAAAAAAAAAAAAAAAAAAAAAAAAAthAAALcQAADNEAAAsBAAAAAAAAAAAAAANQAAAAAAAAAAAAAACQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuBQAAbgYAAAAAAABbAAAAAAAAAAAAAAAAAAAArhAAAM4QAAC3EAAAtxAAALgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6AAAArgUAAK8FAAAAAAAAYwAAAAAAAAAAAAAArhAAAM4QAAC3EAAAtxAAAMUQAADAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAMAAAAAAAAAK4FAACvBQAAUwAAAGsAAAAAAAAAAAAAALYQAAC3EAAAtxAAAMUQAADAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuBQAAbwUAAG8FAABvBQAAbwUAAHAFAAATAAAAFAAAAAAAAACuBQAArwUAAFMAAAAAAAAAAAAAAAAAAAC2EAAAtxAAALcQAAC4EAAAAAAAAAAAAAAAAAAAAAAAAG4FAABvBQAAbgYAAK8FAACvBQAArwUAAK8FAABtBgAAbwUAAG8FAABvBQAAbgYAAK8FAAA=\n  </data>\n </layer>\n <layer id=\"4\" name=\"Tile Layer 3\" width=\"25\" height=\"20\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n  </data>\n </layer>\n</map>\n"
  },
  {
    "path": "docs/public/simplemap2.tmx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"20\" height=\"20\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"4\" nextobjectid=\"1\">\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <tileset firstgid=\"1001\" source=\"[A]Water_pipo.tsx\"/>\n <tileset firstgid=\"4073\" source=\"[A]Dirt_pipo.tsx\"/>\n <tileset firstgid=\"4409\" source=\"[A]Flower_pipo.tsx\"/>\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"20\" height=\"20\">\n  <data encoding=\"base64\">\n   AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n  </data>\n </layer>\n <layer id=\"2\" name=\"Tile Layer 2\" width=\"20\" height=\"20\">\n  <data encoding=\"base64\">\n   AAAAAEIAAAAAAAAAAAAAAFoAAABBAAAAWgAAAFsAAAAAAAAAAAAAAK4QAADOEAAAtxAAALcQAAC4EAAAAAAAAAAAAAA3AAAAAAAAAK4FAABaAAAAWgAAAEIAAABbAAAAYwAAAGIAAABiAAAAYwAAAAAAAACuEAAAzhAAALcQAAC3EAAAxRAAAMAQAAAAAAAAAAAAAAAAAABuBQAAbgYAAGIAAABiAAAAYgAAAGMAAABqAAAAagAAAGoAAABrAAAArhAAAM4QAAC3EAAAtxAAAMUQAADAEAAAAAAAAAkAAAAKAAAAAAAAAK4FAACvBQAAagAAAGoAAABqAAAAawAAAAkAAAAKAAAAQgAAAAAAAAC2EAAAtxAAALcQAADFEAAAwBAAAAAAAAAAAAAAEQAAABIAAABuBQAAbgYAAK8FAABwBQAAKQAAAAAAAAAAAAAAEQAAABIAAAAAAAAAAAAAALYQAAC3EAAAtxAAALgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK4FAACvBQAArwUAALAFAAAAAAAACQAAAAoAAAA2AAAANQAAAAAAAAAAAAAAthAAALcQAAC3EAAAuBAAAAAAAAAAAAAAQQAAAAAAAAA2AAAArgUAAK8FAACvBQAAsAUAAAAAAAARAAAAEgAAAD4RAAA/EQAAQBEAAAAAAAC+EAAAxhAAALcQAADNEAAAsBAAAAAAAAAAAAAAAAAAAAAAAADuBQAALgYAAK8FAACwBQAAAAAAADYAAAAAAAAAThEAAE8RAABlEQAAQBEAAAAAAAC2EAAAtxAAALcQAAC4EAAAAAAAADUAAAAAAAAAAAAAAAAAAACuBQAArwUAAG0GAABwBQAAAAAAAAAAAAAAAAAANwAAAE4RAABQEQAAAAAAAL4QAADGEAAAtxAAALgQAAAAAAAAAAAAAAkAAAAKAAAAAAAAAK4FAACvBQAArwUAAG0GAABwBQAACQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL4QAAC/EAAAwBAAAAAAAAAAAAAAEQAAABIAAAAAAAAArgUAAK8FAACvBQAArwUAALAFAAARAAAAEgAAAAAAAAALAAAADAAAAAAAAABBAAAAAAAAAAAAAAAJAAAACgAAAAAAAAAAAAAACQAAAAoAAACuBQAArwUAAK8FAACvBQAAsAUAAAAAAAAAAAAAAAAAABMAAAAUAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAARAAAAEgAAAO4FAAAuBgAArwUAAK8FAACwBQAAAAAAAAkAAAAKAAAAAAAAAAAAAAAAAAAACwAAAAwAAAAAAAAAAAAAAAAAAAAJAAAACgAAAAAAAAAAAAAAAAAAAK4FAACvBQAALQYAAPAFAAAAAAAAEQAAABIAAAAJAAAACgAAAAAAAAATAAAAFAAAAAAAAAALAAAADAAAABEAAAASAAAAAAAAAAAAAABuBQAAbgYAAK8FAACwBQAACQAAAAoAAAA1AAAAAAAAABEAAAASAAAAAAAAAAkAAAAKAAAAAAAAABMAAAAUAAAAAAAAAAAAAAAuAAAAAAAAAK4FAACvBQAArwUAALAFAAARAAAAEgAAAAAAAAA1AAAAAAAAAAAAAAAAAAAAEQAAABIAAAAJAAAACgAAAAAAAAAJAAAACgAAAAAAAAAAAAAArgUAAK8FAACvBQAAsAUAAAAAAAAAAAAAAAAAAG4FAABvBQAAbwUAAHAFAAAAAAAAAAAAABEAAAASAAAAAAAAABEAAAASAAAAAAAAAAAAAACuBQAArwUAAK8FAACwBQAAAAAAAG4FAABvBQAAbgYAAK8FAACvBQAAsAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG4FAABvBQAAbwUAAG4GAACvBQAArwUAAG0GAABvBQAAbgYAAK8FAACvBQAArwUAAK8FAABtBgAAbwUAAG8FAABvBQAAbwUAAG8FAABvBQAAbgYAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAK8FAACvBQAArwUAAA==\n  </data>\n </layer>\n <layer id=\"3\" name=\"Tile Layer 3\" width=\"20\" height=\"20\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACQAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n</map>\n"
  },
  {
    "path": "docs/public/tileset.tsx",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tileset version=\"1.9\" tiledversion=\"1.9.2\" name=\"[Base]BaseChip_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"1000\" columns=\"8\">\n <image source=\"base.png\" width=\"256\" height=\"4000\"/>\n <tile id=\"0\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"1\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"2\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"3\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"4\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"5\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"6\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"7\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"8\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"9\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"10\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"11\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"12\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"13\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"14\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"15\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"16\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"16.9835\" y=\"14.9844\" width=\"15\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"17\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"1.66533e-16\" y=\"15.4545\" width=\"17\" height=\"16.5455\"/>\n  </objectgroup>\n </tile>\n <tile id=\"18\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"19\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"20\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"21\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"22\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"23\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"24\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"25\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"26\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"27\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"28\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"29\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"30\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"31\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"32\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"33\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"34\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"35\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"36\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"37\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"38\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"39\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"40\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"9.52174\" width=\"31.9565\" height=\"20.4783\"/>\n  </objectgroup>\n </tile>\n <tile id=\"41\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"11.3913\" width=\"32\" height=\"18.913\"/>\n  </objectgroup>\n </tile>\n <tile id=\"42\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"11.4348\" width=\"31.8261\" height=\"18.4348\"/>\n  </objectgroup>\n </tile>\n <tile id=\"43\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.69565\" y=\"19.2174\" width=\"27.2174\" height=\"10.6957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"44\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"45\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"46\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"47\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"48\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"49\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"50\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"51\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"52\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"53\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"54\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"55\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"56\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"57\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"58\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"59\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"60\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"61\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"62\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"63\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"64\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"65\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"66\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"67\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"68\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"69\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"70\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"71\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"72\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"73\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"-0.0869565\" y=\"0.0434783\" width=\"32.087\" height=\"1.86957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"74\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.0434783\">\n    <polygon points=\"0,0 17.7826,0.0869565 31.8261,13.6957 32.1304,31.9565 29.913,31.913 29.5652,14.3913 16.9565,2.04348 -0.0434783,2.04348\"/>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"75\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"76\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"77\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"78\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"79\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"80\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"81\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"82\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"83\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"84\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"85\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"86\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"87\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"88\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"89\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"90\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"91\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"92\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"93\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"94\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"95\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"96\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"97\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"98\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"99\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"121\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"141\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.75\" y=\"-0.25\" width=\"24.5\" height=\"16\"/>\n  </objectgroup>\n </tile>\n <tile id=\"160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.78261\" y=\"0.0434783\" width=\"18.1304\" height=\"13.2174\"/>\n  </objectgroup>\n </tile>\n <tile id=\"164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.5\" y=\"0.75\" width=\"26.25\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.75\" y=\"0.5\" width=\"24.5\" height=\"16.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.25\" y=\"-0.25\" width=\"23.25\" height=\"15.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8.25\" y=\"-0.25\" width=\"14\" height=\"32\"/>\n  </objectgroup>\n </tile>\n <tile id=\"177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.5\" y=\"3.5\" width=\"12\" height=\"28.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.75\" y=\"12.25\" width=\"22\" height=\"19.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"20.75\" height=\"20\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12.5\" width=\"31.5\" height=\"19.75\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"31.5\" height=\"18\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.25\" y=\"0\" width=\"12.5\" height=\"28.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.25\" width=\"19\" height=\"27.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.25\" y=\"11.25\" width=\"20\" height=\"16.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.5\" y=\"0.25\" width=\"19.25\" height=\"31.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"13.8261\" width=\"20\" height=\"6.17391\"/>\n   <object id=\"2\" x=\"10.3478\" y=\"0.130435\" width=\"10.2174\" height=\"31.7391\"/>\n  </objectgroup>\n </tile>\n <tile id=\"191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.9565\" y=\"4.43478\" width=\"8\" height=\"24.0435\"/>\n  </objectgroup>\n </tile>\n <tile id=\"192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.75\" y=\"10.75\" width=\"17.25\" height=\"19\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"4.18182\" y=\"17.4545\" width=\"23.8182\" height=\"14\"/>\n  </objectgroup>\n </tile>\n <tile id=\"237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.8696\" y=\"20.3913\" width=\"6.21739\" height=\"9.56522\"/>\n  </objectgroup>\n </tile>\n <tile id=\"238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.17391\" y=\"18.9565\" width=\"28.7391\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"19.5217\" width=\"28.9565\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"14.0435\" width=\"31.913\" height=\"12.1739\"/>\n  </objectgroup>\n </tile>\n <tile id=\"266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.0435\" y=\"16.2609\" width=\"7.43478\" height=\"15.8696\">\n    <properties>\n     <property name=\"overlay\" type=\"bool\" value=\"true\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"4\">\n   <object id=\"4\" x=\"14.5272\" y=\"16.125\" width=\"6.28261\" height=\"16.0734\"/>\n  </objectgroup>\n </tile>\n <tile id=\"270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"15\" y=\"0.0869565\" width=\"2.04348\" height=\"31.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"14.8261\" y=\"0.0434783\" width=\"2.26087\" height=\"31.8696\"/>\n  </objectgroup>\n </tile>\n <tile id=\"278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"14.1304\" width=\"31.7826\" height=\"12.6087\"/>\n  </objectgroup>\n </tile>\n <tile id=\"282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.2609\" y=\"0.173913\" width=\"9.21739\" height=\"23.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.4348\" y=\"0.0434783\" width=\"9.17391\" height=\"23.5217\"/>\n  </objectgroup>\n </tile>\n <tile id=\"286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0\" width=\"8.75\" height=\"30.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"21\" y=\"0.5\" width=\"9.5\" height=\"29.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8\" y=\"11.2727\" width=\"15.4545\" height=\"18.7273\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.1818\" y=\"12.9091\" width=\"12\" height=\"15.6364\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n</tileset>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"canvasengine-project\",\n  \"description\": \"A reactive HTML5 Canvas management library built on top of PixiJS\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev:sample\": \"cd sample && npm run dev\",\n    \"dev\": \"pnpm -r --filter=./packages/** --parallel run dev\",\n    \"build\": \"pnpm -r --filter=./packages/** run build\",\n    \"test\": \"vitest run\",\n    \"coverage\": \"vitest --coverage\",\n    \"release\": \"bumpp package.json packages/*/package.json --all\",\n    \"changeset\": \"changeset\",\n    \"publish:packages\": \"changeset publish\",\n    \"version:packages\": \"changeset version\",\n    \"preinstall\": \"cd docs && npm install\"\n  },\n  \"dependencies\": {\n    \"@changesets/cli\": \"^2.31.0\",\n    \"bumpp\": \"^11.0.1\",\n    \"howler\": \"^2.2.4\",\n    \"pixi.js\": \"^8.18.1\",\n    \"rollup-plugin-node-polyfills\": \"^0.2.1\",\n    \"tsup\": \"^8.5.1\",\n    \"typescript\": \"^6.0.3\"\n  },\n  \"devDependencies\": {\n    \"@vitest/coverage-v8\": \"^4.1.5\",\n    \"dedent\": \"^1.7.2\",\n    \"eslint\": \"^10.2.1\",\n    \"jsdom\": \"^29.1.0\",\n    \"lightningcss\": \"^1.32.0\",\n    \"vite\": \"^8.0.10\",\n    \"vitest\": \"^4.1.5\",\n    \"vitest-webgl-canvas-mock\": \"^1.1.0\"\n  },\n  \"author\": \"Samuel Ronce\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://canvasengine.net\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/RSamaium/CanvasEngine.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/RSamaium/CanvasEngine/issues\"\n  },\n  \"keywords\": [\n    \"canvas\",\n    \"pixijs\",\n    \"reactive\",\n    \"html5\"\n  ],\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler/grammar.pegjs",
    "content": "{\n  function generateError(message, location) {\n    const { start, end } = location;\n    const errorMessage = `${message}\\n` +\n      `at line ${start.line}, column ${start.column} to line ${end.line}, column ${end.column}`;\n    throw new Error(errorMessage);\n  }\n\n  /*——— Custom error handler for syntax errors ———*/\n  function parseError(error) {\n    // error.expected : array of { type, description }\n    // error.found    : string | null\n    // error.location : { start, end }\n    const { expected, found, location } = error;\n\n    // Group expected items by description to avoid duplicates\n    const uniqueExpected = [...new Set(expected.map(e => e.description))];\n    \n    // Format the expected values in a more readable way\n    const expectedDesc = uniqueExpected\n      .map(desc => `'${desc}'`)\n      .join(' or ');\n\n    const foundDesc = found === null ? 'end of input' : `'${found}'`;\n\n    generateError(\n      `Syntax error: expected ${expectedDesc} but found ${foundDesc}`,\n      location\n    );\n  }\n\n  // List of standard HTML DOM elements\n  const domElements = new Set([\n    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 'samp', 's', 'script', 'section', 'select', 'slot', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr'\n  ]);\n\n  // Framework components that should NOT be transformed to DOM elements\n  const frameworkComponents = new Set([\n    'Canvas', 'Container', 'Sprite', 'Text', 'DOMElement', 'Svg', 'Button'\n  ]);\n\n  const voidElements = new Set([\n    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta',\n    'param', 'source', 'track', 'wbr'\n  ]);\n\n  // DisplayObject special attributes that should not be in attrs\n  const displayObjectAttributes = new Set([\n    'x', 'y', 'scale', 'anchor', 'skew', 'tint', 'rotation', 'angle', \n    'zIndex', 'roundPixels', 'cursor', 'visible', 'alpha', 'pivot', 'filters', 'maskOf', \n    'blendMode', 'filterArea', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', \n    'aspectRatio', 'flexGrow', 'flexShrink', 'flexBasis', 'rowGap', 'columnGap', \n    'positionType', 'top', 'right', 'bottom', 'left', 'objectFit', 'objectPosition', \n    'transformOrigin', 'flexDirection', 'justifyContent', 'alignItems', 'alignContent', \n    'alignSelf', 'margin', 'padding', 'border', 'gap', 'blur', 'shadow'\n  ]);\n\n  function isDOMElement(tagName) {\n    // Don't transform framework components to DOM elements\n    if (frameworkComponents.has(tagName)) {\n      return false;\n    }\n    return domElements.has(tagName.toLowerCase());\n  }\n\n  function isVoidElement(tagName) {\n    return voidElements.has(tagName.toLowerCase());\n  }\n\n  function formatAttributes(attributes) {\n    if (attributes.length === 0) {\n      return null;\n    }\n  \n    // Check if there's exactly one attribute and it's a spread attribute\n    if (attributes.length === 1 && attributes[0].startsWith('...')) {\n      // Return the identifier directly, removing the '...'\n      return attributes[0].substring(3);\n    }\n  \n    // Otherwise, format as an object literal\n    const formattedAttrs = attributes.map(attr => {\n      // If it's a spread attribute, keep it as is\n      if (attr.startsWith('...')) {\n        return attr;\n      }\n      // If it's a standalone attribute (doesn't contain ':'), format as shorthand property 'name'\n      if (!attr.includes(':')) {\n        return attr; // JS object literal shorthand\n      }\n      // Otherwise (key: value), keep it as is\n      return attr;\n    });\n  \n    return `{ ${formattedAttrs.join(', ')} }`;\n  }\n\n  function formatDOMElement(tagName, attributes) {\n    if (attributes.length === 0) {\n      return `h(DOMElement, { element: \"${tagName}\" })`;\n    }\n\n    const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n    // Build the result\n    const parts = [`element: \"${tagName}\"`];\n    \n    if (domAttrs.length > 0) {\n      parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n    }\n    \n    if (displayObjectAttrs.length > 0) {\n      parts.push(...displayObjectAttrs);\n    }\n\n    return `h(DOMElement, { ${parts.join(', ')} })`;\n  }\n\n  function splitAttributes(attributes) {\n    const domAttrs = [];\n    const displayObjectAttrs = [];\n    const classValues = [];\n    let classInsertIndex = null;\n\n    attributes.forEach(attr => {\n      // Handle spread attributes\n      if (attr.startsWith('...')) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      // Extract attribute name and value (if present)\n      let attrName;\n      let attrValue;\n      if (attr.includes(':')) {\n        const colonIndex = attr.indexOf(':');\n        attrName = attr.slice(0, colonIndex).trim().replace(/['\"]/g, '');\n        attrValue = attr.slice(colonIndex + 1).trim();\n      } else {\n        // Standalone attribute\n        attrName = attr.replace(/['\"]/g, '');\n      }\n\n      // Check if it's a DisplayObject attribute\n      if (displayObjectAttributes.has(attrName)) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      if (attrName === 'class' && attrValue !== undefined) {\n        classValues.push(attrValue);\n        if (classInsertIndex === null) {\n          classInsertIndex = domAttrs.length;\n        }\n        return;\n      }\n\n      domAttrs.push(attr);\n    });\n\n    if (classValues.length > 0) {\n      const mergedClass = classValues.length === 1\n        ? `class: ${classValues[0]}`\n        : `class: [${classValues.join(', ')}]`;\n      if (classInsertIndex === null) {\n        domAttrs.push(mergedClass);\n      } else {\n        domAttrs.splice(classInsertIndex, 0, mergedClass);\n      }\n    }\n\n    return { domAttrs, displayObjectAttrs };\n  }\n}\n\nstart\n  = _ elements:(element)* _ {\n    if (elements.length === 1) {\n      return elements[0];\n    }\n    return `[${elements.join(',')}]`;\n  }\n\nelement \"component or control structure\"\n  = forLoop\n  / ifCondition\n  / svgElement\n  / domElementWithText\n  / domElementWithMixedContent\n  / selfClosingElement\n  / voidElement\n  / openCloseElement\n  / openUnclosedTag\n  / comment\n\nselfClosingElement \"self-closing component tag\"\n  = _ \"<\" _ tagName:tagName _ attributes:attributes _ \"/>\" _ {\n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        return formatDOMElement(tagName, attributes);\n      }\n      // Otherwise, treat as regular component\n      const attrsString = formatAttributes(attributes);\n      return attrsString ? `h(${tagName}, ${attrsString})` : `h(${tagName})`;\n    }\n\nvoidElement \"void DOM element tag\"\n  = _ \"<\" _ tagName:tagName &{ return isVoidElement(tagName); } _ attributes:attributes _ \">\" _ {\n      return formatDOMElement(tagName, attributes);\n    }\n\ndomElementWithText \"DOM element with text content\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ text:simpleTextContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      if (isDOMElement(tagName)) {\n        if (attributes.length === 0) {\n          return `h(DOMElement, { element: \"${tagName}\", textContent: ${text} })`;\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        parts.push(`textContent: ${text}`);\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n      \n      // If not a DOM element, fall back to regular parsing\n      return null;\n    }\n\ndomElementWithMixedContent \"DOM element with mixed content\"\n  = \"<\" _ tagName:tagName &{ return isDOMElement(tagName) && !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ children:domContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n\n      const childrenContent = children ? children : null;\n\n      if (attributes.length === 0) {\n        if (childrenContent) {\n          return `h(DOMElement, { element: \"${tagName}\" }, ${childrenContent})`;\n        } else {\n          return `h(DOMElement, { element: \"${tagName}\" })`;\n        }\n      }\n\n      const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n      // Build the result\n      const parts = [`element: \"${tagName}\"`];\n      \n      if (domAttrs.length > 0) {\n        parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n      }\n      \n      if (displayObjectAttrs.length > 0) {\n        parts.push(...displayObjectAttrs);\n      }\n\n      if (childrenContent) {\n        return `h(DOMElement, { ${parts.join(', ')} }, ${childrenContent})`;\n      } else {\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n    }\n\nsimpleTextContent \"simple text content\"\n  = parts:(simpleDynamicPart / simpleTextPart)+ {\n      const validParts = parts.filter(p => p !== null);\n      if (validParts.length === 0) return null;\n      if (validParts.length === 1) return validParts[0];\n      \n      // Multiple parts - need to concatenate\n      const normalizedParts = validParts.map(part => {\n        if (typeof part === 'string' && part.startsWith('computed(() => ') && part.endsWith(')')) {\n          return part.slice('computed(() => '.length, -1);\n        }\n        return part;\n      });\n      const hasSignals = normalizedParts.some(part => part && part.includes && part.includes('()'));\n      if (hasSignals) {\n        return `computed(() => ${normalizedParts.join(' + ')})`;\n      }\n      return normalizedParts.join(' + ');\n    }\n\nsimpleTextPart \"simple text part\"\n  = !(\"@for\" / \"@if\") text:$([^<{@]+) {\n      const trimmed = text.trim();\n      if (!trimmed) return null;\n      const escaped = text\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/'/g, \"\\\\'\")\n        .replace(/\\r/g, '\\\\r')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\t/g, '\\\\t');\n      return `'${escaped}'`;\n    }\n\nsimpleDynamicPart \"simple dynamic part\"\n  = \"{{\" _ expr:attributeValue _ \"}}\" {\n      // Handle double brace expressions like {{ object.x }} or {{ @object.x }} or {{ @object.@x }}\n      if (expr.trim().match(/^(@?[a-zA-Z_][a-zA-Z0-9_]*)(\\.@?[a-zA-Z_][a-zA-Z0-9_]*)*$/)) {\n        let foundSignal = false;\n        let hasLiterals = false;\n        \n        // Split by dots to handle each part separately\n        const parts = expr.split('.');\n        const allLiterals = parts.every(part => part.trim().startsWith('@'));\n        \n        let computedValue;\n        \n        if (allLiterals) {\n          // All parts are literals, just remove @ prefixes\n          computedValue = parts.map(part => part.replace('@', '')).join('.');\n          hasLiterals = true;\n        } else {\n          // Transform each part individually\n          computedValue = parts.map(part => {\n            const trimmedPart = part.trim();\n            if (trimmedPart.startsWith('@')) {\n              hasLiterals = true;\n              return trimmedPart.substring(1); // Remove @ prefix for literals\n            } else {\n              // Don't transform keywords\n              if (['true', 'false', 'null'].includes(trimmedPart)) {\n                return trimmedPart;\n              }\n              foundSignal = true;\n              return `${trimmedPart}()`;\n            }\n          }).join('.');\n        }\n        \n        if (foundSignal && !allLiterals) {\n          return `computed(() => ${computedValue})`;\n        }\n        return computedValue;\n      }\n      return expr;\n    }\n  / \"{\" _ expr:attributeValue _ \"}\" {\n      // Handle single brace expressions like {item.name} or {@text}\n      if (expr.trim().match(/^(@?[a-zA-Z_][a-zA-Z0-9_]*)(\\.@?[a-zA-Z_][a-zA-Z0-9_]*)*$/)) {\n        let foundSignal = false;\n        const computedValue = expr.replace(/@?([a-zA-Z_][a-zA-Z0-9_]*)\\b(?!\\s*:)/g, (match, p1) => {\n          if (match.startsWith('@')) {\n            return p1;\n          }\n          foundSignal = true;\n          return `${p1}()`;\n        });\n        if (foundSignal) {\n          return `computed(() => ${computedValue})`;\n        }\n        return computedValue;\n      }\n      return expr;\n    }\n\nopenCloseElement \"component with content\"\n  = \"<\" _ tagName:tagName _ attributes:attributes _ \">\" _ content:content _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        const children = content ? content : null;\n        \n        if (attributes.length === 0) {\n          if (children) {\n            return `h(DOMElement, { element: \"${tagName}\" }, ${children})`;\n          } else {\n            return `h(DOMElement, { element: \"${tagName}\" })`;\n          }\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        if (children) {\n          return `h(DOMElement, { ${parts.join(', ')} }, ${children})`;\n        } else {\n          return `h(DOMElement, { ${parts.join(', ')} })`;\n        }\n      }\n      \n      // Otherwise, treat as regular component\n      const attrsString = formatAttributes(attributes);\n      const children = content ? content : null;\n      if (attrsString && children) {\n        return `h(${tagName}, ${attrsString}, ${children})`;\n      } else if (attrsString) {\n        return `h(${tagName}, ${attrsString})`;\n      } else if (children) {\n        return `h(${tagName}, null, ${children})`;\n      } else {\n        return `h(${tagName})`;\n      }\n    }\n\nattributes \"component attributes\"\n  = attrs:(attribute (_ attribute)*)? {\n      return attrs\n        ? [attrs[0]].concat(attrs[1].map(a => a[1]))\n        : [];\n    }\n\nattribute \"attribute\"\n  = staticAttribute\n  / dynamicAttribute\n  / eventHandler\n  / spreadAttribute\n  / unclosedQuote\n  / unclosedBrace\n\nspreadAttribute \"spread attribute\"\n  = \"...\" expr:(functionCallExpr / dotNotation) {\n      return \"...\" + expr;\n    }\n\nfunctionCallExpr \"function call\"\n  = name:dotNotation \"(\" args:functionArgs? \")\" {\n      return `${name}(${args || ''})`;\n    }\n\ndotNotation \"property access\"\n  = first:identifier rest:(\".\" identifier)* {\n      return text();\n    }\n\neventHandler \"event handler\"\n  = \"@\" eventName:identifier _ \"=\" _ \"{\" _ handlerName:attributeValue _ \"}\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      const formattedName = needsQuotes ? `'${eventName}'` : eventName;\n      return `${formattedName}: ${handlerName}`;\n    }\n     / \"@\" eventName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      return needsQuotes ? `'${eventName}'` : eventName;\n    }\n\ndynamicAttribute \"dynamic attribute\"\n  = attributeName:attributeName _ \"=\" _ \"{\" _ attributeValue:attributeValue _ \"}\" {\n      // Check if attributeName needs to be quoted (contains dash or other invalid JS identifier chars)\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      \n      \n        // If it's a complex object with strings, preserve it as is\n        if (attributeValue.trim().startsWith('{') && attributeValue.trim().endsWith('}') && \n            (attributeValue.includes('\"') || attributeValue.includes(\"'\"))) {\n          return `${formattedName}: ${attributeValue}`;\n        }\n        \n        // If it's a template string, transform expressions inside ${}\n      if (attributeValue.trim().startsWith('`') && attributeValue.trim().endsWith('`')) {\n        // Transform expressions inside ${} in template strings\n        let transformedTemplate = attributeValue;\n        \n        // Find and replace ${expression} patterns\n        let startIndex = 0;\n        while (true) {\n          const dollarIndex = transformedTemplate.indexOf('${', startIndex);\n          if (dollarIndex === -1) break;\n          \n          const braceIndex = transformedTemplate.indexOf('}', dollarIndex);\n          if (braceIndex === -1) break;\n          \n          const expr = transformedTemplate.substring(dollarIndex + 2, braceIndex);\n          const trimmedExpr = expr.trim();\n          \n          let replacement;\n          if (trimmedExpr.startsWith('@')) {\n            // Remove @ prefix for literals\n            replacement = '${' + trimmedExpr.substring(1) + '}';\n          } else if (trimmedExpr.match(/^[a-zA-Z_][a-zA-Z0-9_.]*$/)) {\n            // Transform identifiers to signals\n            replacement = '${' + trimmedExpr + '()}';\n          } else {\n            // Keep as is for complex expressions\n            replacement = '${' + expr + '}';\n          }\n          \n          transformedTemplate = transformedTemplate.substring(0, dollarIndex) + \n                               replacement + \n                               transformedTemplate.substring(braceIndex + 1);\n          \n          startIndex = dollarIndex + replacement.length;\n        }\n        \n        return formattedName + ': ' + transformedTemplate;\n      }\n      \n      // Handle other types of values\n      if (attributeValue.startsWith('h(') || attributeValue.includes('=>')) {\n        return `${formattedName}: ${attributeValue}`;\n      } else if (attributeValue.trim().match(/^[a-zA-Z_]\\w*$/)) {\n        return `${formattedName}: ${attributeValue}`;\n      } else {\n        // Check if this is an object or array literal\n        const isObjectLiteral = attributeValue.trim().startsWith('{ ') && attributeValue.trim().endsWith(' }');\n        const isArrayLiteral = attributeValue.trim().startsWith('[') && attributeValue.trim().endsWith(']');\n        \n        let foundSignal = false;\n        let hasLiterals = false;\n        let computedValue = attributeValue;\n        \n        // For simple object and array literals (like {x: x, y: 20} or [x, 20]), \n        // don't use computed() at all and don't transform identifiers\n        if ((isObjectLiteral || isArrayLiteral) && !attributeValue.includes('()')) {\n          // Don't transform anything, return as is\n          foundSignal = false;\n          computedValue = attributeValue;\n        } else {\n          // Apply signal transformation for other values\n          computedValue = attributeValue.replace(/@?([a-zA-Z_][a-zA-Z0-9_]*)\\b(?!\\s*:)/g, (match, p1, offset) => {\n            // Don't transform keywords, numbers, or if we're inside quotes\n            if (['true', 'false', 'null'].includes(p1) || /^\\d+(\\.\\d+)?$/.test(p1)) {\n              return match;\n            }\n            \n            // Check if we're inside a string literal\n            const beforeMatch = attributeValue.substring(0, offset);\n            const singleQuotesBefore = (beforeMatch.match(/'/g) || []).length;\n            const doubleQuotesBefore = (beforeMatch.match(/\"/g) || []).length;\n            \n            // If we're inside quotes, don't transform\n            if (singleQuotesBefore % 2 === 1 || doubleQuotesBefore % 2 === 1) {\n              return match;\n            }\n            \n            if (match.startsWith('@')) {\n              hasLiterals = true;\n              return p1; // Remove @ prefix\n            }\n            foundSignal = true;\n            return `${p1}()`;\n          });\n          \n          // Check if any values already contain signals (ending with ())\n          if (attributeValue.includes('()')) {\n            foundSignal = true;\n          }\n        }\n        \n        if (foundSignal) {\n          // For objects, wrap in parentheses\n          if (attributeValue.trim().startsWith('{') && attributeValue.trim().endsWith('}')) {\n            // Remove spaces for objects in parentheses\n            const cleanedObject = computedValue.replace(/{ /g, '{').replace(/ }/g, '}');\n            return `${formattedName}: computed(() => (${cleanedObject}))`;\n          }\n          return `${formattedName}: computed(() => ${computedValue})`;\n        }\n        \n        // If only literals (all @), don't use computed\n        if (hasLiterals && !foundSignal) {\n          return `${formattedName}: ${computedValue}`;\n        }\n        \n        // For static objects and arrays, return as is without parentheses\n        return `${formattedName}: ${computedValue}`;\n      }\n    }\n  / attributeName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      return needsQuotes ? `'${attributeName}'` : attributeName;\n    }\n\nattributeValue \"attribute value\"\n  = element\n  / functionWithElement\n  / objectLiteral\n  / $([^{}]* (\"{\" [^{}]* \"}\" [^{}]*)*) {\n    return text().trim()\n  }\n\nobjectLiteral \"object literal\"\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nobjectContent\n  = prop:objectProperty rest:(_ \",\" _ objectProperty)* {\n    return [prop].concat(rest.map(r => r[3])).join(', ');\n  }\n  / \"\" { return \"\"; }\n\nobjectProperty\n  = key:identifier _ \":\" _ value:propertyValue {\n    return `${key}: ${value}`;\n  }\n  / key:identifier {\n    return key;\n  }\n\npropertyValue\n  = nestedObject\n  / element\n  / functionWithElement\n  / stringLiteral\n  / number\n  / identifier\n\nnestedObject\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nstringLiteral\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\nfunctionWithElement \"function expression\"\n  = \"(\" _ params:functionParams? _ \")\" _ \"=>\" _ elem:element {\n      return `${params ? `(${params}) =>` : '() =>'} ${elem}`;\n    }\n\nfunctionParams\n  = destructuredParams\n  / simpleParams\n\ndestructuredParams\n  = \"{\" _ param:identifier rest:(_ \",\" _ identifier)* _ \"}\" {\n      return `{${[param].concat(rest.map(r => r[3])).join(', ')}}`;\n    }\n\nsimpleParams\n  = param:identifier rest:(_ \",\" _ identifier)* {\n      return [param].concat(rest.map(r => r[3])).join(', ');\n    }\n\nstaticAttribute \"static attribute\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" attributeValue:staticValue \"\\\"\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      return `${formattedName}: ${attributeValue}`;\n    }\n\neventAttribute\n  = \"(\" _ eventName:eventName _ \")\" _ \"=\" _ \"\\\"\" eventAction:eventAction \"\\\"\" {\n      return `${eventName}: () => { ${eventAction} }`;\n    }\n\nstaticValue\n  = [^\"]+ {\n      var val = text();\n      return `'${val}'`\n    }\n\ncontent \"component content\"\n  = elements:(element)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContent \"DOM content\"\n  = elements:(domContentPart)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContentPart\n  = element\n  / simpleTextContent\n\n\n\ntextNode\n  = text:$([^<]+) {\n      const trimmed = text.trim();\n      return trimmed ? `'${trimmed}'` : null;\n    }\n\ntextElement\n  = text:[^<>]+ {\n      const trimmed = text.join('').trim();\n      return trimmed ? JSON.stringify(trimmed) : null;\n    }\n\nforLoop \"for loop\"\n  = _ \"@for\" _ \"(\" _ variableName:(tupleDestructuring / identifier) _ \"of\" _ iterable:iterable _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return `loop(${iterable}, ${variableName} => ${content})`;\n    }\n\ntupleDestructuring \"destructuring pattern\"\n  = \"(\" _ first:identifier _ \",\" _ second:identifier _ \")\" {\n      return `(${first}, ${second})`;\n    }\n\nifCondition \"if condition\"\n  = _ \"@if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ elseIfs:elseIfClause* elseClause:elseClause? _ {\n      let result = `cond(${condition}, () => ${content}`;\n      \n      // Add else if clauses\n      elseIfs.forEach(elseIf => {\n        result += `, [${elseIf.condition}, () => ${elseIf.content}]`;\n      });\n      \n      // Add else clause if present\n      if (elseClause) {\n        result += `, () => ${elseClause}`;\n      }\n      \n      result += ')';\n      return result;\n    }\n\nelseIfClause \"else if clause\"\n  = _ \"@else\" _ \"if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return { condition, content };\n    }\n\nelseClause \"else clause\"\n  = _ \"@else\" _ \"{\" _ content:content _ \"}\" _ {\n      return content;\n    }\n\ntagName \"tag name\"\n  = tagExpression\n\ntagExpression \"tag expression\"\n  = first:tagPart rest:(\".\" tagPart)* {\n      return text();\n    }\n\ntagPart \"tag part\"\n  = name:[a-zA-Z][a-zA-Z0-9]* args:(\"(\" functionArgs? \")\")? {\n      return text();\n    }\n\nattributeName \"attribute name\"\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\neventName\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\nvariableName\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\niterable \"iterable expression\"\n  = id:identifier \"(\" _ args:functionArgs? _ \")\" { // Direct function call\n      return `${id}(${args || ''})`;\n    }\n  / first:identifier \".\" rest:dotFunctionChain { // Dot notation possibly with function call\n      return `${first}.${rest}`;\n    }\n  / id:identifier { return id; }\n\ndotFunctionChain\n  = segment:identifier \"(\" _ args:functionArgs? _ \")\" rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}(${args || ''})${restStr}`;\n    }\n  / segment:identifier rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}${restStr}`;\n    }\n\ncondition \"condition expression\"\n  = functionCall\n  / functionCallWithArgs\n  / text_condition:$([^)]*) {\n      const originalText = text_condition.trim();\n\n      // Handle expressions with @ literals (like @item.@id)\n      // First, process dot notation expressions with @ literals\n      let processedText = originalText;\n      const dotNotationReplacements = new Map();\n      let replacementCounter = 0;\n      \n      // Process dot notation expressions like @item.@id, @item.id, item.@id\n      // Only process expressions that contain at least one @\n      processedText = processedText.replace(/(@[a-zA-Z_][a-zA-Z0-9_]*)(\\.@?[a-zA-Z_][a-zA-Z0-9_]*)+|([a-zA-Z_][a-zA-Z0-9_]*)(\\.@[a-zA-Z_][a-zA-Z0-9_]*)+/g, (match) => {\n        // Split by dots to handle each part separately\n        const parts = match.split('.');\n        const allLiterals = parts.every(part => part.trim().startsWith('@'));\n        \n        let replacement;\n        if (allLiterals) {\n          // All parts are literals, just remove @ prefixes (no signal transformation)\n          replacement = parts.map(part => part.trim().replace('@', '')).join('.');\n        } else {\n          // Transform each part individually\n          // Note: In conditions with operators, even @ literals in the first part\n          // should be transformed to signals for comparison\n          replacement = parts.map((part, index) => {\n            const trimmedPart = part.trim();\n            if (trimmedPart.startsWith('@')) {\n              // For the first part in conditions with operators, we still want to transform to signal\n              // For later parts, keep as literal\n              if (index === 0) {\n                // First part: remove @ but will be transformed to signal later\n                return trimmedPart.substring(1);\n              } else {\n                // Later parts: remove @ and keep as literal (no signal)\n                return trimmedPart.substring(1);\n              }\n            } else {\n              // Don't transform keywords\n              if (['true', 'false', 'null'].includes(trimmedPart)) {\n                return trimmedPart;\n              }\n              // Check if already a function call\n              if (trimmedPart.includes('(')) {\n                return trimmedPart;\n              }\n              // Transform to signal\n              return `${trimmedPart}()`;\n            }\n          }).join('.');\n        }\n        \n        // Store replacement and use a temporary marker\n        const marker = `__DOT_NOTATION_${replacementCounter++}__`;\n        dotNotationReplacements.set(marker, replacement);\n        return marker;\n      });\n      \n      // Now handle standalone @ identifiers (not in dot notation)\n      processedText = processedText.replace(/@([a-zA-Z_][a-zA-Z0-9_]*)\\b(?!\\s*\\.)/g, (match, p1) => {\n        return p1; // Remove @ prefix for standalone literals\n      });\n\n      // Transform simple identifiers to function calls like \"foo\" to \"foo()\"\n      // This regex matches identifiers not followed by an opening parenthesis.\n      // This transformation should only apply if we are wrapping in 'computed'.\n      if (processedText.includes('!') || processedText.includes('&&') || processedText.includes('||') || \n          processedText.includes('>=') || processedText.includes('<=') || processedText.includes('===') || \n          processedText.includes('!==') || processedText.includes('==') || processedText.includes('!=') ||\n          processedText.includes('>') || processedText.includes('<')) {\n          // Replace dot notation markers with their processed values BEFORE transforming identifiers\n          // This way, expressions like @item.id become item.id() and then item() is transformed\n          let textWithReplacements = processedText;\n          dotNotationReplacements.forEach((value, marker) => {\n            textWithReplacements = textWithReplacements.replace(new RegExp(marker.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), value);\n          });\n          \n          const transformedText = textWithReplacements.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b(?!\\s*\\()/g, (match, p1, offset) => {\n              // Do not transform keywords (true, false, null) or numeric literals\n              if (['true', 'false', 'null'].includes(match) || /^\\d+(\\.\\d+)?$/.test(match)) {\n                  return match;\n              }\n              \n              // Check if this is a marker (starts with __DOT_NOTATION_)\n              if (match.startsWith('__DOT_NOTATION_')) {\n                return match; // Don't transform markers\n              }\n              \n              // Check if the match is inside quotes\n              const beforeMatch = processedText.substring(0, offset);\n              const afterMatch = processedText.substring(offset + match.length);\n              const singleQuotesBefore = (beforeMatch.match(/'/g) || []).length;\n              const doubleQuotesBefore = (beforeMatch.match(/\"/g) || []).length;\n              \n              // If we're inside quotes, don't transform\n              if (singleQuotesBefore % 2 === 1 || doubleQuotesBefore % 2 === 1) {\n                  return match;\n              }\n              \n              // Check if this identifier is part of a dot notation expression\n              const charBefore = offset > 0 ? textWithReplacements[offset - 1] : '';\n              const charAfter = offset + match.length < textWithReplacements.length ? textWithReplacements[offset + match.length] : '';\n              \n              // If there's a dot before or after, this is part of dot notation\n              if (charBefore === '.' || charAfter === '.') {\n                // Check if this dot notation expression was a marker (had @ in original)\n                const beforeContext = originalText.substring(Math.max(0, offset - 20), offset);\n                const afterContext = originalText.substring(offset, Math.min(originalText.length, offset + match.length + 20));\n                const fullContext = beforeContext + afterContext;\n                \n                // Check if this identifier had @ in the original\n                const hadAt = fullContext.includes('@' + match) || fullContext.match(new RegExp('@' + match.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') + '\\\\b'));\n                \n                if (hadAt) {\n                  // Check if ALL parts of the dot notation had @ (all literals)\n                  // Find the full dot notation expression in the original\n                  const dotExprMatch = originalText.match(/(@?[a-zA-Z_][a-zA-Z0-9_]*)(\\.@?[a-zA-Z_][a-zA-Z0-9_]*)+/);\n                  if (dotExprMatch) {\n                    const dotExpr = dotExprMatch[0];\n                    const allPartsHadAt = dotExpr.split('.').every(part => part.trim().startsWith('@'));\n                    if (allPartsHadAt) {\n                      // All parts were literals (@item.@id), don't transform\n                      return match;\n                    }\n                  }\n                  \n                  // Only some parts had @ (@item.id or item.@id)\n                  if (charAfter === '.') {\n                    // First part: transform to signal even if it had @\n                    return `${match}()`;\n                  } else if (charBefore === '.') {\n                    // Later part: already processed in marker, don't retransform\n                    return match;\n                  }\n                }\n                \n                // In conditions with operators, transform dot notation expressions to signals\n                // (e.g., user.role becomes user().role())\n                // This applies to regular dot notation, not markers (which are already processed)\n                return `${match}()`;\n              }\n              \n              return `${match}()`;\n          });\n          \n          return `computed(() => ${transformedText})`;\n      }\n      // For simple conditions (no !, &&, ||), return the processed text as is.\n      // Cases like `myFunction()` are handled by the `functionCallWithArgs` rule.\n      \n      // Replace dot notation markers with their processed values\n      let finalText = processedText;\n      dotNotationReplacements.forEach((value, marker) => {\n        finalText = finalText.replace(new RegExp(marker.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'g'), value);\n      });\n      \n      return finalText;\n  }\n\nfunctionCall \"function call\"\n  = name:identifier \"(\" args:functionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionCallWithArgs \"function call with complex args\"\n  = name:identifier \"(\" args:complexFunctionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionArgs\n  = arg:functionArg rest:(\",\" _ functionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\ncomplexFunctionArgs\n  = arg:complexFunctionArg rest:(\",\" _ complexFunctionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\nfunctionArg\n  = _ value:(identifier / number / string) _ {\n    return value;\n  }\n\ncomplexFunctionArg \"complex function argument\"\n  = _ value:complexArgExpression _ {\n    // Process @ literals and transform identifiers to signals\n    // Handle dot notation with @ literals like @item.@id, @item.id, item.@id\n    // Similar logic to simpleDynamicPart but for function arguments\n    \n    let processed = value.trim();\n    const original = processed;\n    \n    // Check if it's a dot notation expression\n    if (processed.match(/^(@?[a-zA-Z_][a-zA-Z0-9_]*)(\\.@?[a-zA-Z_][a-zA-Z0-9_]*)*$/)) {\n      // Split by dots to handle each part separately\n      const parts = processed.split('.');\n      const allLiterals = parts.every(part => part.trim().startsWith('@'));\n      \n      let computedValue;\n      \n      if (allLiterals) {\n        // All parts are literals, just remove @ prefixes\n        computedValue = parts.map(part => part.trim().replace('@', '')).join('.');\n      } else {\n        // Transform each part individually\n        computedValue = parts.map(part => {\n          const trimmedPart = part.trim();\n          if (trimmedPart.startsWith('@')) {\n            return trimmedPart.substring(1); // Remove @ prefix for literals\n          } else {\n            // Don't transform keywords\n            if (['true', 'false', 'null'].includes(trimmedPart)) {\n              return trimmedPart;\n            }\n            // Check if it's already a function call\n            if (trimmedPart.includes('(')) {\n              return trimmedPart;\n            }\n            // Transform to signal\n            return `${trimmedPart}()`;\n          }\n        }).join('.');\n      }\n      \n      return computedValue;\n    }\n    \n    // Handle standalone identifiers (not dot notation)\n    // If it starts with @, remove @ prefix (literal)\n    if (processed.startsWith('@')) {\n      return processed.substring(1);\n    }\n    \n    // Don't transform keywords or numbers\n    if (['true', 'false', 'null'].includes(processed) || /^\\d+(\\.\\d+)?$/.test(processed)) {\n      return processed;\n    }\n    \n    // Check if it's already a function call\n    if (processed.includes('(')) {\n      return processed;\n    }\n    \n    // Transform identifier to signal\n    return `${processed}()`;\n  }\n\ncomplexArgExpression \"complex argument expression\"\n  = $([^,)]* (\"(\" [^)]* \")\" [^,)]*)*) {\n    return text().trim();\n  }\n\nnumber\n  = [0-9]+ (\".\" [0-9]+)? { return text(); }\n\nstring\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\neventAction\n  = [^\"]* { return text(); }\n\n_ 'whitespace'\n  = [ \\t\\n\\r]* \n\nidentifier\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\ncomment\n  = singleComment+ {\n    return null\n  }\n\nsingleComment\n  = \"<!--\" _ content:((!(\"-->\") .)* \"-->\") _ {\n      return null;\n    }\n\n// Add a special error detection rule for unclosed tags\nopenUnclosedTag \"unclosed tag\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ content:content _ !(\"</\" _ closingTagName:tagName _ \">\") {\n      generateError(\n        `Unclosed tag: <${tagName}> is missing its closing tag`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed quotes in static attributes\nunclosedQuote \"unclosed string\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" [^\"]* !(\"\\\"\") {\n      generateError(\n        `Missing closing quote in attribute '${attributeName}'`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed braces in dynamic attributes\nunclosedBrace \"unclosed brace\"\n  = attributeName:attributeName _ \"=\" _ \"{\" !(\"}\" / _ \"}\") [^{}]* {\n      generateError(\n        `Missing closing brace in dynamic attribute '${attributeName}'`,\n        location()\n      );\n    }\n\nsvgElement \"SVG element\"\n  = \"<svg\" attrs:([^>]*) \">\" content:svgInnerContent \"</svg>\" _ {\n      const attributes = attrs.join('').trim();\n      // Clean up the content by removing extra whitespace and newlines\n      const cleanContent = content.replace(/\\s+/g, ' ').trim();\n      const rawContent = `<svg${attributes ? ' ' + attributes : ''}>${cleanContent}</svg>`;\n      return `h(Svg, { content: \\`${rawContent}\\` })`;\n    }\n\nsvgInnerContent \"SVG inner content\"\n  = content:$((!(\"</svg>\") .)*) {\n      return content;\n    }\n"
  },
  {
    "path": "packages/compiler/grammar2.pegjs",
    "content": "{\n  function generateError(message, location) {\n    const { start, end } = location;\n    const errorMessage = `${message}\\n` +\n      `at line ${start.line}, column ${start.column} to line ${end.line}, column ${end.column}`;\n    throw new Error(errorMessage);\n  }\n\n  /*——— Custom error handler for syntax errors ———*/\n  function parseError(error) {\n    // error.expected : array of { type, description }\n    // error.found    : string | null\n    // error.location : { start, end }\n    const { expected, found, location } = error;\n\n    // Group expected items by description to avoid duplicates\n    const uniqueExpected = [...new Set(expected.map(e => e.description))];\n    \n    // Format the expected values in a more readable way\n    const expectedDesc = uniqueExpected\n      .map(desc => `'${desc}'`)\n      .join(' or ');\n\n    const foundDesc = found === null ? 'end of input' : `'${found}'`;\n\n    generateError(\n      `Syntax error: expected ${expectedDesc} but found ${foundDesc}`,\n      location\n    );\n  }\n\n  // List of standard HTML DOM elements\n  const domElements = new Set([\n    'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 'samp', 's', 'script', 'section', 'select', 'slot', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr'\n  ]);\n\n  // Framework components that should NOT be transformed to DOM elements\n  const frameworkComponents = new Set([\n    'Canvas', 'Container', 'Sprite', 'Text', 'DOMElement', 'Svg', 'Button'\n  ]);\n\n  const voidElements = new Set([\n    'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta',\n    'param', 'source', 'track', 'wbr'\n  ]);\n\n  const eventAttributes = new Set([\n    'click', 'tap', 'pointertap', 'pointerdown', 'pointerup', 'pointermove',\n    'pointerover', 'pointerout', 'pointerupoutside', 'mousedown', 'mouseup',\n    'mousemove', 'mouseover', 'mouseout', 'touchstart', 'touchend', 'touchmove',\n    'touchcancel', 'rightclick', 'keydown', 'keyup', 'keypress'\n  ]);\n\n  // DisplayObject special attributes that should not be in attrs\n  const displayObjectAttributes = new Set([\n    'x', 'y', 'scale', 'anchor', 'skew', 'tint', 'rotation', 'angle', \n    'zIndex', 'roundPixels', 'cursor', 'visible', 'alpha', 'pivot', 'filters', 'maskOf', \n    'blendMode', 'filterArea', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight', \n    'aspectRatio', 'flexGrow', 'flexShrink', 'flexBasis', 'rowGap', 'columnGap', \n    'positionType', 'top', 'right', 'bottom', 'left', 'objectFit', 'objectPosition', \n    'transformOrigin', 'flexDirection', 'justifyContent', 'alignItems', 'alignContent', \n    'alignSelf', 'margin', 'padding', 'border', 'gap', 'blur', 'shadow'\n  ]);\n\n  function isDOMElement(tagName) {\n    // Don't transform framework components to DOM elements\n    if (frameworkComponents.has(tagName)) {\n      return false;\n    }\n    return domElements.has(tagName.toLowerCase());\n  }\n\n  function isVoidElement(tagName) {\n    return voidElements.has(tagName.toLowerCase());\n  }\n\n  function formatAttributes(attributes) {\n    if (attributes.length === 0) {\n      return null;\n    }\n  \n    // Check if there's exactly one attribute and it's a spread attribute\n    if (attributes.length === 1 && attributes[0].startsWith('...')) {\n      // Return the identifier directly, removing the '...'\n      return attributes[0].substring(3);\n    }\n  \n    // Otherwise, format as an object literal\n    const formattedAttrs = attributes.map(attr => {\n      // If it's a spread attribute, keep it as is\n      if (attr.startsWith('...')) {\n        return attr;\n      }\n      // If it's a standalone attribute (doesn't contain ':'), format as shorthand property 'name'\n      if (!attr.includes(':')) {\n        return attr; // JS object literal shorthand\n      }\n      // Otherwise (key: value), keep it as is\n      return attr;\n    });\n  \n    return `{ ${formattedAttrs.join(', ')} }`;\n  }\n\n  function formatDOMElement(tagName, attributes) {\n    if (attributes.length === 0) {\n      return `h(DOMElement, { element: \"${tagName}\" })`;\n    }\n\n    const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n    // Build the result\n    const parts = [`element: \"${tagName}\"`];\n    \n    if (domAttrs.length > 0) {\n      parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n    }\n    \n    if (displayObjectAttrs.length > 0) {\n      parts.push(...displayObjectAttrs);\n    }\n\n    return `h(DOMElement, { ${parts.join(', ')} })`;\n  }\n\n  function splitAttributes(attributes) {\n    const domAttrs = [];\n    const displayObjectAttrs = [];\n    const classValues = [];\n    let classInsertIndex = null;\n\n    attributes.forEach(attr => {\n      // Handle spread attributes\n      if (attr.startsWith('...')) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      // Extract attribute name and value (if present)\n      let attrName;\n      let attrValue;\n      if (attr.includes(':')) {\n        const colonIndex = attr.indexOf(':');\n        attrName = attr.slice(0, colonIndex).trim().replace(/['\"]/g, '');\n        attrValue = attr.slice(colonIndex + 1).trim();\n      } else {\n        // Standalone attribute\n        attrName = attr.replace(/['\"]/g, '');\n      }\n\n      // Check if it's a DisplayObject attribute\n      if (displayObjectAttributes.has(attrName)) {\n        displayObjectAttrs.push(attr);\n        return;\n      }\n\n      if (attrName === 'class' && attrValue !== undefined) {\n        classValues.push(attrValue);\n        if (classInsertIndex === null) {\n          classInsertIndex = domAttrs.length;\n        }\n        return;\n      }\n\n      domAttrs.push(attr);\n    });\n\n    if (classValues.length > 0) {\n      const mergedClass = classValues.length === 1\n        ? `class: ${classValues[0]}`\n        : `class: [${classValues.join(', ')}]`;\n      if (classInsertIndex === null) {\n        domAttrs.push(mergedClass);\n      } else {\n        domAttrs.splice(classInsertIndex, 0, mergedClass);\n      }\n    }\n\n    return { domAttrs, displayObjectAttrs };\n  }\n\n  function formatDOMContainerAttributes(attributes) {\n    if (attributes.length === 0) {\n      return null;\n    }\n\n    const propsEntries = [];\n    const domAttrs = [];\n    const classValues = [];\n    let classInsertIndex = null;\n    let attrsInsertIndex = null;\n    let attrsIndex = null;\n    let attrsValue = null;\n\n    attributes.forEach(attr => {\n      if (attr.startsWith('...')) {\n        propsEntries.push(attr);\n        return;\n      }\n\n      let attrName;\n      let attrValue;\n      if (attr.includes(':')) {\n        const colonIndex = attr.indexOf(':');\n        attrName = attr.slice(0, colonIndex).trim().replace(/['\"]/g, '');\n        attrValue = attr.slice(colonIndex + 1).trim();\n      } else {\n        attrName = attr.replace(/['\"]/g, '');\n      }\n\n      if (attrName === 'class' && attrValue !== undefined) {\n        classValues.push(attrValue);\n        if (classInsertIndex === null) {\n          classInsertIndex = domAttrs.length;\n        }\n        if (attrsInsertIndex === null) {\n          attrsInsertIndex = propsEntries.length;\n        }\n        return;\n      }\n\n      if (attrName === 'style') {\n        domAttrs.push(attr);\n        if (attrsInsertIndex === null) {\n          attrsInsertIndex = propsEntries.length;\n        }\n        return;\n      }\n\n      if (attrName === 'attrs' && attrValue !== undefined) {\n        attrsValue = attrValue;\n        attrsIndex = propsEntries.length;\n        propsEntries.push(null);\n        return;\n      }\n\n      propsEntries.push(attr);\n    });\n\n    if (classValues.length > 0) {\n      const mergedClass = classValues.length === 1\n        ? `class: ${classValues[0]}`\n        : `class: [${classValues.join(', ')}]`;\n      if (classInsertIndex === null) {\n        domAttrs.push(mergedClass);\n      } else {\n        domAttrs.splice(classInsertIndex, 0, mergedClass);\n      }\n    }\n\n    let attrsEntry = null;\n    if (attrsValue && domAttrs.length > 0) {\n      attrsEntry = `attrs: { ...${attrsValue}, ${domAttrs.join(', ')} }`;\n    } else if (attrsValue) {\n      attrsEntry = `attrs: ${attrsValue}`;\n    } else if (domAttrs.length > 0) {\n      attrsEntry = `attrs: { ${domAttrs.join(', ')} }`;\n    }\n\n    if (attrsEntry) {\n      if (attrsIndex !== null) {\n        propsEntries[attrsIndex] = attrsEntry;\n      } else if (attrsInsertIndex !== null) {\n        propsEntries.splice(attrsInsertIndex, 0, attrsEntry);\n      } else {\n        propsEntries.unshift(attrsEntry);\n      }\n    }\n\n    const filteredEntries = propsEntries.filter(entry => entry !== null);\n    if (filteredEntries.length === 0) {\n      return null;\n    }\n\n    if (filteredEntries.length === 1 && filteredEntries[0].startsWith('...')) {\n      return filteredEntries[0].substring(3);\n    }\n\n    return `{ ${filteredEntries.join(', ')} }`;\n  }\n\n  function hasFunctionCall(value) {\n    return /[a-zA-Z_][a-zA-Z0-9_]*\\s*\\(/.test(value);\n  }\n\n  function hasIdentifier(value) {\n    return /[a-zA-Z_]/.test(value);\n  }\n\n  function isSimpleAccessor(value) {\n    return /^[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*$/.test(value.trim());\n  }\n\n  function formatObjectLiteralSpacing(value) {\n    const trimmed = value.trim();\n    if (!trimmed.startsWith('{') || !trimmed.endsWith('}')) {\n      return value;\n    }\n    const inner = trimmed.slice(1, -1).trim();\n    return `{ ${inner} }`;\n  }\n\n  function collectMemberRoots(value) {\n    const roots = new Set();\n    const memberRegex = /\\b([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\./g;\n    let match;\n\n    while ((match = memberRegex.exec(value)) !== null) {\n      roots.add(match[1]);\n    }\n\n    return roots;\n  }\n\n  function transformBareIdentifiersToSignals(value) {\n    const memberRoots = collectMemberRoots(value);\n\n    return value.replace(/\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b/g, (match, name, offset) => {\n      if (['true', 'false', 'null'].includes(name)) {\n        return match;\n      }\n\n      const beforeMatch = value.substring(0, offset);\n      const singleQuotesBefore = (beforeMatch.match(/'/g) || []).length;\n      const doubleQuotesBefore = (beforeMatch.match(/\"/g) || []).length;\n      if (singleQuotesBefore % 2 === 1 || doubleQuotesBefore % 2 === 1) {\n        return match;\n      }\n\n      const charBefore = offset > 0 ? value[offset - 1] : '';\n      const charAfter = offset + match.length < value.length ? value[offset + match.length] : '';\n\n      if (charBefore === '.' || charAfter === '.') {\n        return match;\n      }\n\n      if (memberRoots.has(name)) {\n        return match;\n      }\n\n      const afterSlice = value.slice(offset + match.length);\n      if (/^\\s*\\(/.test(afterSlice)) {\n        return match;\n      }\n\n      return `${name}()`;\n    });\n  }\n}\n\nstart\n  = _ elements:(element)* _ {\n    if (elements.length === 1) {\n      return elements[0];\n    }\n    return `[${elements.join(',')}]`;\n  }\n\nelement \"component or control structure\"\n  = forLoop\n  / ifCondition\n  / svgElement\n  / domElementWithText\n  / domElementWithMixedContent\n  / selfClosingElement\n  / voidElement\n  / openCloseElement\n  / openUnclosedTag\n  / comment\n\nselfClosingElement \"self-closing component tag\"\n  = _ \"<\" _ tagName:tagName _ attributes:attributes _ \"/>\" _ {\n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        return formatDOMElement(tagName, attributes);\n      }\n      if (tagName === 'DOMContainer') {\n        const attrsString = formatDOMContainerAttributes(attributes);\n        return attrsString ? `h(DOMContainer, ${attrsString})` : `h(DOMContainer)`;\n      }\n      // Otherwise, treat as regular component\n      const attrsString = formatAttributes(attributes);\n      return attrsString ? `h(${tagName}, ${attrsString})` : `h(${tagName})`;\n    }\n\nvoidElement \"void DOM element tag\"\n  = _ \"<\" _ tagName:tagName &{ return isVoidElement(tagName); } _ attributes:attributes _ \">\" _ {\n      return formatDOMElement(tagName, attributes);\n    }\n\ndomElementWithText \"DOM element with text content\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ text:simpleTextContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      if (isDOMElement(tagName)) {\n        if (attributes.length === 0) {\n          return `h(DOMElement, { element: \"${tagName}\", textContent: ${text} })`;\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        parts.push(`textContent: ${text}`);\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n      \n      // If not a DOM element, fall back to regular parsing\n      return null;\n    }\n\ndomElementWithMixedContent \"DOM element with mixed content\"\n  = \"<\" _ tagName:tagName &{ return isDOMElement(tagName) && !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ children:domContent _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n\n      const childrenContent = children ? children : null;\n\n      if (attributes.length === 0) {\n        if (childrenContent) {\n          return `h(DOMElement, { element: \"${tagName}\" }, ${childrenContent})`;\n        } else {\n          return `h(DOMElement, { element: \"${tagName}\" })`;\n        }\n      }\n\n      const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n      // Build the result\n      const parts = [`element: \"${tagName}\"`];\n      \n      if (domAttrs.length > 0) {\n        parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n      }\n      \n      if (displayObjectAttrs.length > 0) {\n        parts.push(...displayObjectAttrs);\n      }\n\n      if (childrenContent) {\n        return `h(DOMElement, { ${parts.join(', ')} }, ${childrenContent})`;\n      } else {\n        return `h(DOMElement, { ${parts.join(', ')} })`;\n      }\n    }\n\nsimpleTextContent \"simple text content\"\n  = parts:(simpleDynamicPart / simpleTextPart)+ {\n      const validParts = parts.filter(p => p !== null);\n      if (validParts.length === 0) return null;\n      if (validParts.length === 1) return validParts[0];\n      \n      // Multiple parts - need to concatenate\n      const normalizedParts = validParts.map(part => {\n        if (typeof part === 'string' && part.startsWith('computed(() => ') && part.endsWith(')')) {\n          return part.slice('computed(() => '.length, -1);\n        }\n        return part;\n      });\n      const hasSignals = normalizedParts.some(part => part && part.includes && part.includes('()'));\n      if (hasSignals) {\n        return `computed(() => ${normalizedParts.join(' + ')})`;\n      }\n      return normalizedParts.join(' + ');\n    }\n\nsimpleTextPart \"simple text part\"\n  = !(\"@for\" / \"@if\") text:$([^<{@]+) {\n      const trimmed = text.trim();\n      if (!trimmed) return null;\n      const escaped = text\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/'/g, \"\\\\'\")\n        .replace(/\\r/g, '\\\\r')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\t/g, '\\\\t');\n      return `'${escaped}'`;\n    }\n\nsimpleDynamicPart \"simple dynamic part\"\n  = \"{{\" _ expr:attributeValue _ \"}}\" {\n      const trimmedExpr = expr.trim();\n      if (!trimmedExpr) {\n        return trimmedExpr;\n      }\n      if (hasFunctionCall(trimmedExpr)) {\n        return `computed(() => ${trimmedExpr})`;\n      }\n      return trimmedExpr;\n    }\n  / \"{\" _ expr:attributeValue _ \"}\" {\n      const trimmedExpr = expr.trim();\n      if (!trimmedExpr) {\n        return trimmedExpr;\n      }\n      if (hasFunctionCall(trimmedExpr)) {\n        return `computed(() => ${trimmedExpr})`;\n      }\n      return trimmedExpr;\n    }\n\nopenCloseElement \"component with content\"\n  = \"<\" _ tagName:tagName _ attributes:attributes _ \">\" _ content:content _ \"</\" _ closingTagName:tagName _ \">\" _ {\n      if (tagName !== closingTagName) {\n        generateError(\n          `Mismatched tag: opened <${tagName}> but closed </${closingTagName}>`,\n          location()\n        );\n      }\n      \n      const children = content ? content : null;\n\n      // Check if it's a DOM element\n      if (isDOMElement(tagName)) {\n        if (attributes.length === 0) {\n          if (children) {\n            return `h(DOMElement, { element: \"${tagName}\" }, ${children})`;\n          } else {\n            return `h(DOMElement, { element: \"${tagName}\" })`;\n          }\n        }\n\n        const { domAttrs, displayObjectAttrs } = splitAttributes(attributes);\n\n        // Build the result\n        const parts = [`element: \"${tagName}\"`];\n        \n        if (domAttrs.length > 0) {\n          parts.push(`attrs: { ${domAttrs.join(', ')} }`);\n        }\n        \n        if (displayObjectAttrs.length > 0) {\n          parts.push(...displayObjectAttrs);\n        }\n\n        if (children) {\n          return `h(DOMElement, { ${parts.join(', ')} }, ${children})`;\n        } else {\n          return `h(DOMElement, { ${parts.join(', ')} })`;\n        }\n      }\n      \n      // Otherwise, treat as regular component\n      if (tagName === 'DOMContainer') {\n        const attrsString = formatDOMContainerAttributes(attributes);\n        if (attrsString && children) {\n          return `h(DOMContainer, ${attrsString}, ${children})`;\n        } else if (attrsString) {\n          return `h(DOMContainer, ${attrsString})`;\n        } else if (children) {\n          return `h(DOMContainer, null, ${children})`;\n        } else {\n          return `h(DOMContainer)`;\n        }\n      }\n\n      const attrsString = formatAttributes(attributes);\n      if (attrsString && children) {\n        return `h(${tagName}, ${attrsString}, ${children})`;\n      } else if (attrsString) {\n        return `h(${tagName}, ${attrsString})`;\n      } else if (children) {\n        return `h(${tagName}, null, ${children})`;\n      } else {\n        return `h(${tagName})`;\n      }\n    }\n\nattributes \"component attributes\"\n  = attrs:(attribute (_ attribute)*)? {\n      return attrs\n        ? [attrs[0]].concat(attrs[1].map(a => a[1]))\n        : [];\n    }\n\nattribute \"attribute\"\n  = staticAttribute\n  / dynamicAttribute\n  / eventHandler\n  / spreadAttribute\n  / unclosedQuote\n  / unclosedBrace\n\nspreadAttribute \"spread attribute\"\n  = \"...\" expr:(functionCallExpr / dotNotation) {\n      return \"...\" + expr;\n    }\n\nfunctionCallExpr \"function call\"\n  = name:dotNotation \"(\" args:functionArgs? \")\" {\n      return `${name}(${args || ''})`;\n    }\n\ndotNotation \"property access\"\n  = first:identifier rest:(\".\" identifier)* {\n      return text();\n    }\n\neventHandler \"event handler\"\n  = \"@\" eventName:identifier _ \"=\" _ \"{\" _ handlerName:attributeValue _ \"}\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      const formattedName = needsQuotes ? `'${eventName}'` : eventName;\n      return `${formattedName}: ${handlerName}`;\n    }\n     / \"@\" eventName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(eventName);\n      return needsQuotes ? `'${eventName}'` : eventName;\n    }\n\ndynamicAttribute \"dynamic attribute\"\n  = attributeName:attributeName _ \"=\" _ \"{\" _ attributeValue:attributeValue _ \"}\" {\n      // Check if attributeName needs to be quoted (contains dash or other invalid JS identifier chars)\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      \n        if (eventAttributes.has(attributeName)) {\n          return `${formattedName}: ${attributeValue}`;\n        }\n      \n        // If it's a complex object with strings, preserve it as is\n        if (attributeValue.trim().startsWith('{') && attributeValue.trim().endsWith('}') && \n            (attributeValue.includes('\"') || attributeValue.includes(\"'\"))) {\n          return `${formattedName}: ${attributeValue}`;\n        }\n        \n        // If it's a template string, keep it as-is\n      if (attributeValue.trim().startsWith('`') && attributeValue.trim().endsWith('`')) {\n        return formattedName + ': ' + attributeValue;\n      }\n      \n      // Handle other types of values\n      if (attributeValue.startsWith('h(') || attributeValue.includes('=>')) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const trimmedValue = attributeValue.trim();\n      if (trimmedValue.match(/^[a-zA-Z_]\\w*$/)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (/^\\d+(\\.\\d+)?$/.test(trimmedValue) || ['true', 'false', 'null'].includes(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (isSimpleAccessor(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const isObjectLiteral = trimmedValue.startsWith('{') && trimmedValue.endsWith('}');\n      const isArrayLiteral = trimmedValue.startsWith('[') && trimmedValue.endsWith(']');\n      const isTernaryExpression = trimmedValue.includes('?') && trimmedValue.includes(':');\n      if (isObjectLiteral) {\n        const formattedObject = formatObjectLiteralSpacing(attributeValue);\n        if (hasFunctionCall(trimmedValue)) {\n          return `${formattedName}: computed(() => (${formattedObject}))`;\n        }\n        return `${formattedName}: ${formattedObject}`;\n      }\n      if (isArrayLiteral) {\n        if (hasFunctionCall(trimmedValue)) {\n          return `${formattedName}: computed(() => ${attributeValue})`;\n        }\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      if (isTernaryExpression) {\n        return `${formattedName}: computed(() => ${attributeValue})`;\n      }\n\n      if (hasFunctionCall(trimmedValue)) {\n        return `${formattedName}: computed(() => ${attributeValue})`;\n      }\n\n      if (!hasIdentifier(trimmedValue)) {\n        return `${formattedName}: ${attributeValue}`;\n      }\n\n      const computedValue = transformBareIdentifiersToSignals(attributeValue);\n      return `${formattedName}: computed(() => ${computedValue})`;\n    }\n  / attributeName:attributeName _ {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      return needsQuotes ? `'${attributeName}'` : attributeName;\n    }\n\nattributeValue \"attribute value\"\n  = element\n  / functionWithElement\n  / objectLiteral\n  / $([^{}]* (\"{\" [^{}]* \"}\" [^{}]*)*) {\n    return text().trim()\n  }\n\nobjectLiteral \"object literal\"\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nobjectContent\n  = prop:objectProperty rest:(_ \",\" _ objectProperty)* {\n    return [prop].concat(rest.map(r => r[3])).join(', ');\n  }\n  / \"\" { return \"\"; }\n\nobjectProperty\n  = key:identifier _ \":\" _ value:propertyValue {\n    return `${key}: ${value}`;\n  }\n  / key:identifier {\n    return key;\n  }\n\npropertyValue\n  = nestedObject\n  / element\n  / functionWithElement\n  / stringLiteral\n  / number\n  / identifier\n\nnestedObject\n  = \"{\" _ objContent:objectContent _ \"}\" {\n    return `{ ${objContent} }`;\n  }\n\nstringLiteral\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\nfunctionWithElement \"function expression\"\n  = \"(\" _ params:functionParams? _ \")\" _ \"=>\" _ elem:element {\n      return `${params ? `(${params}) =>` : '() =>'} ${elem}`;\n    }\n\nfunctionParams\n  = destructuredParams\n  / simpleParams\n\ndestructuredParams\n  = \"{\" _ param:identifier rest:(_ \",\" _ identifier)* _ \"}\" {\n      return `{${[param].concat(rest.map(r => r[3])).join(', ')}}`;\n    }\n\nsimpleParams\n  = param:identifier rest:(_ \",\" _ identifier)* {\n      return [param].concat(rest.map(r => r[3])).join(', ');\n    }\n\nstaticAttribute \"static attribute\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" attributeValue:staticValue \"\\\"\" {\n      const needsQuotes = /[^a-zA-Z0-9_$]/.test(attributeName);\n      const formattedName = needsQuotes ? `'${attributeName}'` : attributeName;\n      return `${formattedName}: ${attributeValue}`;\n    }\n\neventAttribute\n  = \"(\" _ eventName:eventName _ \")\" _ \"=\" _ \"\\\"\" eventAction:eventAction \"\\\"\" {\n      return `${eventName}: () => { ${eventAction} }`;\n    }\n\nstaticValue\n  = [^\"]+ {\n      var val = text();\n      return `'${val}'`\n    }\n\ncontent \"component content\"\n  = elements:(element)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContent \"DOM content\"\n  = elements:(domContentPart)* {\n      const filteredElements = elements.filter(el => el !== null);\n      if (filteredElements.length === 0) return null;\n      if (filteredElements.length === 1) return filteredElements[0];\n      return `[${filteredElements.join(', ')}]`;\n    }\n\ndomContentPart\n  = element\n  / simpleTextContent\n\n\n\ntextNode\n  = text:$([^<]+) {\n      const trimmed = text.trim();\n      return trimmed ? `'${trimmed}'` : null;\n    }\n\ntextElement\n  = text:[^<>]+ {\n      const trimmed = text.join('').trim();\n      return trimmed ? JSON.stringify(trimmed) : null;\n    }\n\nforLoop \"for loop\"\n  = _ \"@for\" _ \"(\" _ variableName:(tupleDestructuring / identifier) _ \"of\" _ iterable:iterable _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return `loop(${iterable}, ${variableName} => ${content})`;\n    }\n\ntupleDestructuring \"destructuring pattern\"\n  = \"(\" _ first:identifier _ \",\" _ second:identifier _ \")\" {\n      return `(${first}, ${second})`;\n    }\n\nifCondition \"if condition\"\n  = _ \"@if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ elseIfs:elseIfClause* elseClause:elseClause? _ {\n      let result = `cond(${condition}, () => ${content}`;\n      \n      // Add else if clauses\n      elseIfs.forEach(elseIf => {\n        result += `, [${elseIf.condition}, () => ${elseIf.content}]`;\n      });\n      \n      // Add else clause if present\n      if (elseClause) {\n        result += `, () => ${elseClause}`;\n      }\n      \n      result += ')';\n      return result;\n    }\n\nelseIfClause \"else if clause\"\n  = _ \"@else\" _ \"if\" _ \"(\" _ condition:condition _ \")\" _ \"{\" _ content:content _ \"}\" _ {\n      return { condition, content };\n    }\n\nelseClause \"else clause\"\n  = _ \"@else\" _ \"{\" _ content:content _ \"}\" _ {\n      return content;\n    }\n\ntagName \"tag name\"\n  = tagExpression\n\ntagExpression \"tag expression\"\n  = first:tagPart rest:(\".\" tagPart)* {\n      return text();\n    }\n\ntagPart \"tag part\"\n  = name:[a-zA-Z][a-zA-Z0-9]* args:(\"(\" functionArgs? \")\")? {\n      return text();\n    }\n\nattributeName \"attribute name\"\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\neventName\n  = [a-zA-Z][a-zA-Z0-9-]* { return text(); }\n\nvariableName\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\niterable \"iterable expression\"\n  = id:identifier \"(\" _ args:functionArgs? _ \")\" { // Direct function call\n      return `${id}(${args || ''})`;\n    }\n  / first:identifier \".\" rest:dotFunctionChain { // Dot notation possibly with function call\n      return `${first}.${rest}`;\n    }\n  / id:identifier { return id; }\n\ndotFunctionChain\n  = segment:identifier \"(\" _ args:functionArgs? _ \")\" rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}(${args || ''})${restStr}`;\n    }\n  / segment:identifier rest:(\".\" dotFunctionChain)? {\n      const restStr = rest ? `.${rest[1]}` : '';\n      return `${segment}${restStr}`;\n    }\n\ncondition \"condition expression\"\n  = text:$(conditionChunk*) {\n      const originalText = text.trim();\n      if (!originalText) {\n        return originalText;\n      }\n\n      const hasOperator = /[!<>=&|]/.test(originalText);\n      if (hasOperator) {\n        return `computed(() => ${originalText})`;\n      }\n\n      return originalText;\n  }\n\nconditionChunk\n  = \"(\" conditionChunk* \")\"\n  / [^()]\n\nfunctionCall \"function call\"\n  = name:identifier \"(\" args:functionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionCallWithArgs \"function call with complex args\"\n  = name:identifier \"(\" args:complexFunctionArgs? \")\" {\n    return `${name}(${args || ''})`;\n  }\n\nfunctionArgs\n  = arg:functionArg rest:(\",\" _ functionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\ncomplexFunctionArgs\n  = arg:complexFunctionArg rest:(\",\" _ complexFunctionArg)* {\n    return [arg].concat(rest.map(r => r[2])).join(', ');\n  }\n\nfunctionArg\n  = _ value:(identifier / number / string) _ {\n    return value;\n  }\n\ncomplexFunctionArg \"complex function argument\"\n  = _ value:complexArgExpression _ {\n    return value.trim();\n  }\n\ncomplexArgExpression \"complex argument expression\"\n  = $([^,)]* (\"(\" [^)]* \")\" [^,)]*)*) {\n    return text().trim();\n  }\n\nnumber\n  = [0-9]+ (\".\" [0-9]+)? { return text(); }\n\nstring\n  = '\"' chars:[^\"]* '\"' { return text(); }\n  / \"'\" chars:[^']* \"'\" { return text(); }\n\neventAction\n  = [^\"]* { return text(); }\n\n_ 'whitespace'\n  = [ \\t\\n\\r]* \n\nidentifier\n  = [a-zA-Z_][a-zA-Z0-9_]* { return text(); }\n\ncomment\n  = singleComment+ {\n    return null\n  }\n\nsingleComment\n  = \"<!--\" _ content:((!(\"-->\") .)* \"-->\") _ {\n      return null;\n    }\n\n// Add a special error detection rule for unclosed tags\nopenUnclosedTag \"unclosed tag\"\n  = \"<\" _ tagName:tagName &{ return !isVoidElement(tagName); } _ attributes:attributes _ \">\" _ content:content _ !(\"</\" _ closingTagName:tagName _ \">\") {\n      generateError(\n        `Unclosed tag: <${tagName}> is missing its closing tag`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed quotes in static attributes\nunclosedQuote \"unclosed string\"\n  = attributeName:attributeName _ \"=\" _ \"\\\"\" [^\"]* !(\"\\\"\") {\n      generateError(\n        `Missing closing quote in attribute '${attributeName}'`,\n        location()\n      );\n    }\n\n// Add error detection for unclosed braces in dynamic attributes\nunclosedBrace \"unclosed brace\"\n  = attributeName:attributeName _ \"=\" _ \"{\" !(\"}\" / _ \"}\") [^{}]* {\n      generateError(\n        `Missing closing brace in dynamic attribute '${attributeName}'`,\n        location()\n      );\n    }\n\nsvgElement \"SVG element\"\n  = \"<svg\" attrs:([^>]*) \">\" content:svgInnerContent \"</svg>\" _ {\n      const attributes = attrs.join('').trim();\n      // Clean up the content by removing extra whitespace and newlines\n      const cleanContent = content.replace(/\\s+/g, ' ').trim();\n      const rawContent = `<svg${attributes ? ' ' + attributes : ''}>${cleanContent}</svg>`;\n      return `h(Svg, { content: \\`${rawContent}\\` })`;\n    }\n\nsvgInnerContent \"SVG inner content\"\n  = content:$((!(\"</svg>\") .)*) {\n      return content;\n    }\n"
  },
  {
    "path": "packages/compiler/index.ts",
    "content": "import { createFilter } from \"vite\";\nimport { parse } from \"acorn\";\nimport fs from \"fs\";\nimport pkg from \"peggy\";\nimport path from \"path\";\nimport * as ts from \"typescript\";\nimport { fileURLToPath } from 'url';\n\nconst { generate } = pkg;\n\nconst DEV_SRC = \"../../src\"\n\n/**\n * Generates a short hash (8 characters, letters only) from a string\n * \n * @param {string} str - The string to hash\n * @returns {string} - An 8-character hash containing only lowercase letters (a-z)\n */\nfunction generateHash(str: string): string {\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 32-bit integer\n  }\n  // Convert to positive number and map to letters only (a-z)\n  // Use modulo to map to 26 letters, then convert to character\n  const positiveHash = Math.abs(hash);\n  let result = '';\n  for (let i = 0; i < 8; i++) {\n    const letterIndex = (positiveHash + i * 31) % 26; // 31 is a prime to spread values\n    result += String.fromCharCode(97 + letterIndex); // 97 is 'a'\n  }\n  return result;\n}\n\n/**\n * Formats a syntax error message with visual pointer to the error location\n * \n * @param {string} template - The template content that failed to parse\n * @param {object} error - The error object with location information\n * @returns {string} - Formatted error message with a visual pointer\n * \n * @example\n * ```\n * const errorMessage = showErrorMessage(\"<Canvas>test(d)</Canvas>\", syntaxError);\n * // Returns a formatted error message with an arrow pointing to 'd'\n * ```\n */\nfunction showErrorMessage(template: string, error: any): string {\n  if (!error.location) {\n    return `Syntax error: ${error.message}`;\n  }\n\n  const lines = template.split('\\n');\n  const { line, column } = error.location.start;\n  const errorLine = lines[line - 1] || '';\n  \n  // Create a visual pointer with an arrow\n  const pointer = ' '.repeat(column - 1) + '^';\n  \n  return `Syntax error at line ${line}, column ${column}: ${error.message}\\n\\n` +\n         `${errorLine}\\n${pointer}\\n`;\n}\n\n/**\n * Scopes CSS selectors by prefixing them with a class selector\n * \n * This function prefixes all CSS rule selectors (not @rules) with a class\n * selector to scope the styles to a specific component instance.\n * \n * @param {string} css - The CSS content to scope\n * @param {string} scopeClass - The unique scope class to use (without the dot)\n * @returns {string} - The scoped CSS content\n * \n * @example\n * ```\n * const scoped = scopeCSS('.my-class { color: red; }', 'ce-scope-abc123');\n * // Returns: '.ce-scope-abc123 .my-class { color: red; }'\n * ```\n */\nfunction scopeCSS(css: string, scopeClass: string): string {\n  const scopeSelector = `.${scopeClass}`;\n  \n  // Process CSS by finding rule blocks while skipping @rules\n  let result = '';\n  let i = 0;\n  let depth = 0;\n  let inRule = false;\n  let selectorBuffer = '';\n  \n  while (i < css.length) {\n    const char = css[i];\n    \n    if (char === '@' && !inRule && selectorBuffer === '') {\n      // Found @rule - copy it as-is until matching closing brace\n      const atRuleStart = i;\n      i++; // Skip '@'\n      \n      // Find the opening brace\n      while (i < css.length && css[i] !== '{') {\n        i++;\n      }\n      \n      if (i < css.length) {\n        // Found opening brace, now find matching closing brace\n        depth = 1;\n        i++; // Skip '{'\n        \n        while (i < css.length && depth > 0) {\n          if (css[i] === '{') depth++;\n          else if (css[i] === '}') depth--;\n          i++;\n        }\n        \n        // Copy entire @rule as-is\n        result += css.substring(atRuleStart, i);\n      }\n      continue;\n    }\n    \n    if (char === '{' && !inRule) {\n      // Start of a rule block - scope the selector we just collected\n      const selectorText = selectorBuffer.trim();\n      \n      if (selectorText) {\n        // Split selectors by comma and scope each one\n        const scopedSelectors = selectorText\n          .split(',')\n          .map(sel => {\n            const trimmed = sel.trim();\n            return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n          })\n          .join(', ');\n        \n        result += scopedSelectors;\n      }\n      result += ' {';\n      inRule = true;\n      depth = 1;\n      selectorBuffer = '';\n    } else if (char === '{' && inRule) {\n      // Nested brace\n      result += char;\n      depth++;\n    } else if (char === '}' && inRule) {\n      result += char;\n      depth--;\n      if (depth === 0) {\n        inRule = false;\n      }\n    } else if (!inRule) {\n      // Collecting selector\n      selectorBuffer += char;\n    } else {\n      // Inside rule block\n      result += char;\n      if (char === '{') depth++;\n    }\n    \n    i++;\n  }\n  \n  // Add any remaining selector (shouldn't happen in valid CSS, but handle it)\n  if (selectorBuffer.trim()) {\n    const scopedSelectors = selectorBuffer.trim()\n      .split(',')\n      .map(sel => {\n        const trimmed = sel.trim();\n        return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n      })\n      .join(', ');\n    result += scopedSelectors;\n  }\n  \n  return result;\n}\n\nfunction splitCallArguments(argsText: string): string[] {\n  const args: string[] = [];\n  let current = \"\";\n  let depth = 0;\n  let inSingle = false;\n  let inDouble = false;\n  let inTemplate = false;\n  let escaped = false;\n\n  for (let i = 0; i < argsText.length; i++) {\n    const char = argsText[i];\n\n    if (escaped) {\n      current += char;\n      escaped = false;\n      continue;\n    }\n\n    if (char === \"\\\\\") {\n      current += char;\n      escaped = true;\n      continue;\n    }\n\n    if (inSingle) {\n      current += char;\n      if (char === \"'\") inSingle = false;\n      continue;\n    }\n\n    if (inDouble) {\n      current += char;\n      if (char === '\"') inDouble = false;\n      continue;\n    }\n\n    if (inTemplate) {\n      current += char;\n      if (char === \"`\") inTemplate = false;\n      continue;\n    }\n\n    if (char === \"'\") {\n      inSingle = true;\n      current += char;\n      continue;\n    }\n\n    if (char === '\"') {\n      inDouble = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"`\") {\n      inTemplate = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"(\" || char === \"{\" || char === \"[\") {\n      depth++;\n      current += char;\n      continue;\n    }\n\n    if (char === \")\" || char === \"}\" || char === \"]\") {\n      depth--;\n      current += char;\n      continue;\n    }\n\n    if (char === \",\" && depth === 0) {\n      args.push(current.trim());\n      current = \"\";\n      continue;\n    }\n\n    current += char;\n  }\n\n  if (current.trim()) {\n    args.push(current.trim());\n  }\n\n  return args;\n}\n\nfunction addScopeClassToDOMContainer(parsedTemplate: string, scopeClass: string): string {\n  let result = \"\";\n  let cursor = 0;\n\n  while (cursor < parsedTemplate.length) {\n    const start = parsedTemplate.indexOf(\"h(DOMContainer\", cursor);\n    if (start === -1) {\n      result += parsedTemplate.slice(cursor);\n      break;\n    }\n\n    result += parsedTemplate.slice(cursor, start);\n    const openParen = parsedTemplate.indexOf(\"(\", start);\n    if (openParen === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    let depth = 0;\n    let inSingle = false;\n    let inDouble = false;\n    let inTemplate = false;\n    let escaped = false;\n    let end = -1;\n\n    for (let i = openParen; i < parsedTemplate.length; i++) {\n      const char = parsedTemplate[i];\n\n      if (escaped) {\n        escaped = false;\n        continue;\n      }\n\n      if (char === \"\\\\\") {\n        escaped = true;\n        continue;\n      }\n\n      if (inSingle) {\n        if (char === \"'\") inSingle = false;\n        continue;\n      }\n\n      if (inDouble) {\n        if (char === '\"') inDouble = false;\n        continue;\n      }\n\n      if (inTemplate) {\n        if (char === \"`\") inTemplate = false;\n        continue;\n      }\n\n      if (char === \"'\") {\n        inSingle = true;\n        continue;\n      }\n\n      if (char === '\"') {\n        inDouble = true;\n        continue;\n      }\n\n      if (char === \"`\") {\n        inTemplate = true;\n        continue;\n      }\n\n      if (char === \"(\") depth++;\n      if (char === \")\") depth--;\n\n      if (depth === 0) {\n        end = i + 1;\n        break;\n      }\n    }\n\n    if (end === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    const callText = parsedTemplate.slice(start, end);\n    const argsText = parsedTemplate.slice(openParen + 1, end - 1);\n    const args = splitCallArguments(argsText);\n\n    if (args[0]?.trim() !== \"DOMContainer\") {\n      result += callText;\n      cursor = end;\n      continue;\n    }\n\n    if (args.length === 1) {\n      args.push(`{ _scopeClass: '${scopeClass}' }`);\n    } else {\n      const props = args[1].trim();\n      if (props === \"null\" || props === \"undefined\") {\n        args[1] = `{ _scopeClass: '${scopeClass}' }`;\n      } else if (props.startsWith(\"{\")) {\n        args[1] = props.replace(/^\\{\\s*/, `{ _scopeClass: '${scopeClass}', `);\n      } else {\n        args[1] = `{ _scopeClass: '${scopeClass}', ...${props} }`;\n      }\n    }\n\n    result += `h(${args.join(\", \")})`;\n    cursor = end;\n  }\n\n  return result;\n}\n\n/**\n * Vite plugin to load shader files (.frag, .vert, .wgsl) as text strings\n * \n * This plugin allows importing shader files directly as string literals in your code.\n * It supports fragment shaders (.frag), vertex shaders (.vert), and WebGPU shaders (.wgsl).\n * The content is loaded as a raw string and can be used directly with graphics APIs.\n * \n * @returns {object} - Vite plugin configuration object\n * \n * @example\n * ```typescript\n * // In your vite.config.ts\n * import { shaderLoader } from './path/to/compiler'\n * \n * export default defineConfig({\n *   plugins: [shaderLoader()]\n * })\n * \n * // In your code\n * import fragmentShader from './shader.frag'\n * import vertexShader from './shader.vert'\n * import computeShader from './shader.wgsl'\n * \n * console.log(fragmentShader) // Raw shader code as string\n * ```\n */\nexport function shaderLoader() {\n  const filter = createFilter(/\\.(frag|vert|wgsl)$/);\n\n  return {\n    name: \"vite-plugin-shader-loader\",\n    transform(code: string, id: string) {\n      if (!filter(id)) return;\n\n      // Escape the shader code to be safely embedded in a JavaScript string\n      const escapedCode = code\n        .replace(/\\\\/g, '\\\\\\\\')  // Escape backslashes\n        .replace(/`/g, '\\\\`')    // Escape backticks\n        .replace(/\\$/g, '\\\\$');  // Escape dollar signs\n\n      // Return the shader content as a default export string\n      return {\n        code: `export default \\`${escapedCode}\\`;`,\n        map: null,\n      };\n    },\n  };\n}\n\nexport default function canvasengine() {\n  const filter = createFilter(\"**/*.ce\");\n  const useLegacyGrammar = process.env.CANVASENGINE_COMPILER_V1 === \"1\";\n\n  // Convert import.meta.url to a file path\n  const __filename = fileURLToPath(import.meta.url);\n  const __dirname = path.dirname(__filename);\n\n  const grammarFile = useLegacyGrammar ? \"grammar.pegjs\" : \"grammar2.pegjs\";\n  const grammar = fs.readFileSync(\n    path.join(__dirname, grammarFile),\n    \"utf8\"\n  );\n  const parser = generate(grammar);\n  const isDev = process.env.NODE_ENV === \"dev\";\n  const FLAG_COMMENT = \"/*--[TPL]--*/\";\n  let warnedAboutGrammar = false;\n\n  const PRIMITIVE_COMPONENTS = [\n    \"Canvas\",\n    \"Sprite\",\n    \"Text\",\n    \"Viewport\",\n    \"Graphics\",\n    \"Container\",\n    \"Navigation\",\n    \"ImageMap\",\n    \"NineSliceSprite\",\n    \"Rect\",\n    \"Circle\",\n    \"Ellipse\",\n    \"Triangle\",\n    \"TilingSprite\",\n    \"svg\",\n    \"Video\",\n    \"Mesh\",\n    \"Svg\",\n    \"DOMContainer\",\n    \"DOMElement\",\n    \"DOMSprite\",\n    \"Button\",\n    \"Joystick\"\n  ];\n\n  return {\n    name: \"vite-plugin-ce\",\n    transform(code: string, id: string) {\n      if (!filter(id)) return null;\n      if (!warnedAboutGrammar) {\n        warnedAboutGrammar = true;\n        const legacyNote = \"Set CANVASENGINE_COMPILER_V1=1 to compile with the legacy grammar (v1).\";\n        if (useLegacyGrammar) {\n          console.warn(`[canvasengine] Using legacy grammar v1. ${legacyNote}`);\n        } else {\n          console.warn(`[canvasengine] Breaking change: compiler grammar v2 is now the default. ${legacyNote}`);\n        }\n      }\n\n      // Extract the script content\n      const scriptMatch = code.match(/<script>([\\s\\S]*?)<\\/script>/);\n      let scriptContent = scriptMatch ? scriptMatch[1].trim() : \"\";\n      \n      // Extract the style tag with attributes and content\n      const styleTagMatch = code.match(/<style([^>]*)>([\\s\\S]*?)<\\/style>/);\n      let styleContent = \"\";\n      let isScoped = false;\n      \n      if (styleTagMatch) {\n        const styleAttributes = styleTagMatch[1].trim();\n        styleContent = styleTagMatch[2].trim();\n        \n        // Check if scoped attribute is present\n        isScoped = /scoped(?:\\s|>|$)/.test(styleAttributes);\n      }\n      \n      // Remove script and style tags from template before parsing\n      let template = code\n        .replace(/<script>[\\s\\S]*?<\\/script>/, \"\")\n        .replace(/<style[^>]*>[\\s\\S]*?<\\/style>/, \"\")\n        .replace(/^\\s+|\\s+$/g, '');\n\n      let parsedTemplate;\n      try {\n        parsedTemplate = parser.parse(template);\n      } catch (error) {\n        const errorMsg = showErrorMessage(template, error);\n        throw new Error(`Error parsing template in file ${id}:\\n${errorMsg}`);\n      }\n\n      // trick to avoid typescript remove imports in scriptContent\n      scriptContent += FLAG_COMMENT + parsedTemplate\n\n      let transpiledCode = ts.transpileModule(scriptContent, {\n        compilerOptions: {\n          module: ts.ModuleKind.Preserve,\n        },\n      }).outputText;\n\n      // remove code after /*---*/\n      transpiledCode = transpiledCode.split(FLAG_COMMENT)[0]\n\n      // Use Acorn to parse the script content\n      const parsed = parse(transpiledCode, {\n        sourceType: \"module\",\n        ecmaVersion: 2020,\n      });\n\n      // Extract imports\n      const imports = parsed.body.filter(\n        (node) => node.type === \"ImportDeclaration\"\n      );\n\n      // Extract non-import statements from scriptContent\n      const nonImportCode = parsed.body\n        .filter((node) => node.type !== \"ImportDeclaration\")\n        .map((node) => transpiledCode.slice(node.start, node.end))\n        .join(\"\\n\");\n\n      let importsCode = imports\n        .map((imp) => {\n          let importCode = transpiledCode.slice(imp.start, imp.end);\n          if (isDev && importCode.includes(\"from 'canvasengine'\")) {\n            importCode = importCode.replace(\n              \"from 'canvasengine'\",\n              `from '${DEV_SRC}'`\n            );\n          }\n          return importCode;\n        })\n        .join(\"\\n\");\n\n      // Define an array for required imports\n      const requiredImports = [\"h\", \"computed\", \"cond\", \"loop\"];\n\n      // Check for missing imports\n      const missingImports = requiredImports.filter(\n        (importName) =>\n          !imports.some(\n            (imp) =>\n              imp.specifiers &&\n              imp.specifiers.some(\n                (spec) =>\n                  spec.type === \"ImportSpecifier\" &&\n                  spec.imported && \n                  'name' in spec.imported &&\n                  spec.imported.name === importName\n              )\n          )\n      );\n\n      // Add missing imports\n      if (missingImports.length > 0) {\n        const additionalImportCode = `import { ${missingImports.join(\n          \", \"\n        )} } from ${isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"};`;\n        importsCode = `${additionalImportCode}\\n${importsCode}`;\n      }\n\n      // Check for primitive components in parsedTemplate\n      const primitiveImports = PRIMITIVE_COMPONENTS.filter((component) =>\n        parsedTemplate.includes(`h(${component}`)\n      );\n\n      // Add missing imports for primitive components\n      primitiveImports.forEach((component) => {\n        const importStatement = `import { ${component} } from ${\n          isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"\n        };`;\n        if (!importsCode.includes(importStatement)) {\n          importsCode = `${importStatement}\\n${importsCode}`;\n        }\n      });\n\n      // Process CSS: scope it if scoped attribute is present\n      let processedStyleContent = styleContent;\n      let scopeClass = '';\n      \n      if (isScoped && styleContent) {\n        // Generate short hash (8 characters) based on file path\n        const fileHash = generateHash(id);\n        scopeClass = fileHash;\n        processedStyleContent = scopeCSS(styleContent, scopeClass);\n        \n        // Add _scopeClass prop to all DOMContainer in the template\n        parsedTemplate = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n      }\n      \n      // Escape style content for safe embedding in JavaScript string (using single quotes)\n      // We need to escape: backslashes, single quotes, and line breaks\n      const escapedStyleContent = processedStyleContent\n        .replace(/\\\\/g, '\\\\\\\\')  // Escape backslashes first\n        .replace(/'/g, \"\\\\'\")    // Escape single quotes\n        .replace(/\\n/g, '\\\\n')   // Escape newlines\n        .replace(/\\r/g, '\\\\r');  // Escape carriage returns\n\n      // Generate unique ID for style element based on file path\n      const styleId = `ce-style-${id.replace(/[^a-zA-Z0-9]/g, '-')}`;\n\n      // Generate CSS injection code if style content exists\n      // Use single quotes to avoid escaping issues with backticks\n      const styleInjectionCode = styleContent ? \n        '// Inject CSS styles into the document head\\n' +\n        `if (typeof document !== 'undefined' && !document.getElementById('${styleId}')) {\\n` +\n        '  const styleElement = document.createElement(\\'style\\');\\n' +\n        `  styleElement.id = '${styleId}';\\n` +\n        `  styleElement.textContent = '${escapedStyleContent}';\\n` +\n        '  document.head.appendChild(styleElement);\\n' +\n        '}\\n'\n        : '';\n      \n\n      // Generate the output\n      const output = String.raw`\n      ${importsCode}\n      import { useProps, useDefineProps } from ${isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"}\n      ${styleInjectionCode}\n      export default function component($$props) {\n        const $props = useProps($$props)\n        const defineProps = useDefineProps($$props)\n        ${nonImportCode}\n        let $this = ${parsedTemplate}\n        return $this\n      }\n      `;\n\n      return {\n        code: output,\n        map: null,\n      };\n    },\n  };\n}\n"
  },
  {
    "path": "packages/compiler/package.json",
    "content": "{\n  \"name\": \"@canvasengine/compiler\",\n  \"version\": \"2.0.0-beta.58\",\n  \"description\": \"\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsup && cp grammar2.pegjs ../../docs/public/grammar.pegjs\",\n    \"dev\": \"tsup --watch\"\n  },\n  \"type\": \"module\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"keywords\": [],\n  \"author\": \"Samuel Ronce\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"acorn\": \"^8.16.0\",\n    \"peggy\": \"^5.1.0\",\n    \"typescript\": \"^6.0.3\",\n    \"vite\": \"^8.0.10\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^25.6.0\",\n    \"tsup\": \"^8.5.1\"\n  }\n}\n"
  },
  {
    "path": "packages/compiler/tests/compiler.spec.ts",
    "content": "import pkg from \"peggy\";\nimport fs from \"fs\";\nimport { beforeAll, describe, test, expect } from \"vitest\";\n\nconst { generate } = pkg;\nlet parser: any;\n\nbeforeAll(() => {\n  const grammar = fs.readFileSync(\"packages/compiler/grammar.pegjs\", \"utf8\");\n  parser = generate(grammar);\n});\n\n// Helper functions to test scoping logic directly\nfunction generateHash(str: string): string {\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 32-bit integer\n  }\n  // Convert to positive number and map to letters only (a-z)\n  // Use modulo to map to 26 letters, then convert to character\n  const positiveHash = Math.abs(hash);\n  let result = '';\n  for (let i = 0; i < 8; i++) {\n    const letterIndex = (positiveHash + i * 31) % 26; // 31 is a prime to spread values\n    result += String.fromCharCode(97 + letterIndex); // 97 is 'a'\n  }\n  return result;\n}\n\nfunction scopeCSS(css: string, scopeClass: string): string {\n  const scopeSelector = `.${scopeClass}`;\n\n  // Process CSS by finding rule blocks while skipping @rules\n  let result = '';\n  let i = 0;\n  let depth = 0;\n  let inRule = false;\n  let selectorBuffer = '';\n\n  while (i < css.length) {\n    const char = css[i];\n\n    if (char === '@' && !inRule && selectorBuffer === '') {\n      // Found @rule - copy it as-is until matching closing brace\n      const atRuleStart = i;\n      i++; // Skip '@'\n\n      // Find the opening brace\n      while (i < css.length && css[i] !== '{') {\n        i++;\n      }\n\n      if (i < css.length) {\n        // Found opening brace, now find matching closing brace\n        depth = 1;\n        i++; // Skip '{'\n\n        while (i < css.length && depth > 0) {\n          if (css[i] === '{') depth++;\n          else if (css[i] === '}') depth--;\n          i++;\n        }\n\n        // Copy entire @rule as-is\n        result += css.substring(atRuleStart, i);\n      }\n      continue;\n    }\n\n    if (char === '{' && !inRule) {\n      // Start of a rule block - scope the selector we just collected\n      const selectorText = selectorBuffer.trim();\n\n      if (selectorText) {\n        // Split selectors by comma and scope each one\n        const scopedSelectors = selectorText\n          .split(',')\n          .map(sel => {\n            const trimmed = sel.trim();\n            return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n          })\n          .join(', ');\n\n        result += scopedSelectors;\n      }\n      result += ' {';\n      inRule = true;\n      depth = 1;\n      selectorBuffer = '';\n    } else if (char === '{' && inRule) {\n      // Nested brace\n      result += char;\n      depth++;\n    } else if (char === '}' && inRule) {\n      result += char;\n      depth--;\n      if (depth === 0) {\n        inRule = false;\n      }\n    } else if (!inRule) {\n      // Collecting selector\n      selectorBuffer += char;\n    } else {\n      // Inside rule block\n      result += char;\n      if (char === '{') depth++;\n    }\n\n    i++;\n  }\n\n  // Add any remaining selector (shouldn't happen in valid CSS, but handle it)\n  if (selectorBuffer.trim()) {\n    const scopedSelectors = selectorBuffer.trim()\n      .split(',')\n      .map(sel => {\n        const trimmed = sel.trim();\n        return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n      })\n      .join(', ');\n    result += scopedSelectors;\n  }\n\n  return result;\n}\n\nfunction splitCallArguments(argsText: string): string[] {\n  const args: string[] = [];\n  let current = \"\";\n  let depth = 0;\n  let inSingle = false;\n  let inDouble = false;\n  let inTemplate = false;\n  let escaped = false;\n\n  for (let i = 0; i < argsText.length; i++) {\n    const char = argsText[i];\n\n    if (escaped) {\n      current += char;\n      escaped = false;\n      continue;\n    }\n\n    if (char === \"\\\\\") {\n      current += char;\n      escaped = true;\n      continue;\n    }\n\n    if (inSingle) {\n      current += char;\n      if (char === \"'\") inSingle = false;\n      continue;\n    }\n\n    if (inDouble) {\n      current += char;\n      if (char === '\"') inDouble = false;\n      continue;\n    }\n\n    if (inTemplate) {\n      current += char;\n      if (char === \"`\") inTemplate = false;\n      continue;\n    }\n\n    if (char === \"'\") {\n      inSingle = true;\n      current += char;\n      continue;\n    }\n\n    if (char === '\"') {\n      inDouble = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"`\") {\n      inTemplate = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"(\" || char === \"{\" || char === \"[\") {\n      depth++;\n      current += char;\n      continue;\n    }\n\n    if (char === \")\" || char === \"}\" || char === \"]\") {\n      depth--;\n      current += char;\n      continue;\n    }\n\n    if (char === \",\" && depth === 0) {\n      args.push(current.trim());\n      current = \"\";\n      continue;\n    }\n\n    current += char;\n  }\n\n  if (current.trim()) {\n    args.push(current.trim());\n  }\n\n  return args;\n}\n\nfunction addScopeClassToDOMContainer(parsedTemplate: string, scopeClass: string): string {\n  let result = \"\";\n  let cursor = 0;\n\n  while (cursor < parsedTemplate.length) {\n    const start = parsedTemplate.indexOf(\"h(DOMContainer\", cursor);\n    if (start === -1) {\n      result += parsedTemplate.slice(cursor);\n      break;\n    }\n\n    result += parsedTemplate.slice(cursor, start);\n    const openParen = parsedTemplate.indexOf(\"(\", start);\n    if (openParen === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    let depth = 0;\n    let inSingle = false;\n    let inDouble = false;\n    let inTemplate = false;\n    let escaped = false;\n    let end = -1;\n\n    for (let i = openParen; i < parsedTemplate.length; i++) {\n      const char = parsedTemplate[i];\n\n      if (escaped) {\n        escaped = false;\n        continue;\n      }\n\n      if (char === \"\\\\\") {\n        escaped = true;\n        continue;\n      }\n\n      if (inSingle) {\n        if (char === \"'\") inSingle = false;\n        continue;\n      }\n\n      if (inDouble) {\n        if (char === '\"') inDouble = false;\n        continue;\n      }\n\n      if (inTemplate) {\n        if (char === \"`\") inTemplate = false;\n        continue;\n      }\n\n      if (char === \"'\") {\n        inSingle = true;\n        continue;\n      }\n\n      if (char === '\"') {\n        inDouble = true;\n        continue;\n      }\n\n      if (char === \"`\") {\n        inTemplate = true;\n        continue;\n      }\n\n      if (char === \"(\") depth++;\n      if (char === \")\") depth--;\n\n      if (depth === 0) {\n        end = i + 1;\n        break;\n      }\n    }\n\n    if (end === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    const callText = parsedTemplate.slice(start, end);\n    const argsText = parsedTemplate.slice(openParen + 1, end - 1);\n    const args = splitCallArguments(argsText);\n\n    if (args[0]?.trim() !== \"DOMContainer\") {\n      result += callText;\n      cursor = end;\n      continue;\n    }\n\n    if (args.length === 1) {\n      args.push(`{ _scopeClass: '${scopeClass}' }`);\n    } else {\n      const props = args[1].trim();\n      if (props === \"null\" || props === \"undefined\") {\n        args[1] = `{ _scopeClass: '${scopeClass}' }`;\n      } else if (props.startsWith(\"{\")) {\n        args[1] = props.replace(/^\\{\\s*/, `{ _scopeClass: '${scopeClass}', `);\n      } else {\n        args[1] = `{ _scopeClass: '${scopeClass}', ...${props} }`;\n      }\n    }\n\n    result += `h(${args.join(\", \")})`;\n    cursor = end;\n  }\n\n  return result;\n}\n\ndescribe(\"Compiler\", () => {\n  test(\"should compile comment\", () => {\n    const input = `\n      <Canvas>\n        <!-- Comment -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile multiple comment\", () => {\n    const input = `\n      <Canvas>\n        <!-- Comment -->\n        <!-- Comment -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile multiple line comment\", () => {\n    const input = `\n      <Canvas>\n        <!--\n          Comment\n          Comment\n        -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile simple component\", () => {\n    const input = `<Canvas />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  describe(\"Dot notation\", () => {\n    test(\"should compile component with dot notation\", () => {\n      const input = `<MyComp.test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp.test)`);\n    });\n\n    test(\"object function call\", () => {\n      const input = `<MyComp.test() />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp.test())`);\n    });\n\n    test(\"function call with return object\", () => {\n      const input = `<MyComp().test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp().test)`);\n    });\n\n    test(\"function call with return object and params\", () => {\n      const input = `<MyComp().test(x, y) />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp().test(x, y))`);\n    });\n\n    test(\"function call and params with return object and\", () => {\n      const input = `<MyComp(x, y).test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp(x, y).test)`);\n    });\n\n    test(\"function call\", () => {\n      const input = `<MyComp() />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp())`);\n    });\n\n    test(\"function call and params\", () => {\n      const input = `<MyComp(x, y) />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp(x, y))`);\n    });\n  })\n\n  test(\"should compile component with dynamic attribute\", () => {\n    const input = `<Canvas width={x} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: x })`);\n  });\n\n  test(\"should compile component with spread operator\", () => {\n    const input = `<Canvas ...obj />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, obj)`);\n  });\n\n  test(\"should compile component with spread operator object\", () => {\n    const input = `<Canvas ...obj.prop />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, obj.prop)`);\n  });\n\n  test(\"should compile component with spread operator function\", () => {\n    const input = `<Canvas ...fn() />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, fn())`);\n  });\n\n  test(\"should compile component with spread operator function and params\", () => {\n    const input = `<Canvas ...fn(x, y) />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, fn(x, y))`);\n  });\n\n  test(\"should compile component with dynamic attribute but is not a signal\", () => {\n    const input = `<Canvas width={20} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: 20 })`);\n  });\n\n  test(\"should compile if/else condition\", () => {\n    const input = `\n            @if (sprite) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"No sprite\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite, () => h(Sprite), () => h(Text, { text: 'No sprite' }))`);\n  });\n\n  test(\"should compile if/else if condition\", () => {\n    const input = `\n            @if (score >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score >= 80) {\n                <Text text=\"A\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })])`);\n  });\n\n  test(\"should compile if/else if/else condition\", () => {\n    const input = `\n            @if (score >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score >= 80) {\n                <Text text=\"A\" />\n            }\n            @else {\n                <Text text=\"F\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })], () => h(Text, { text: 'F' }))`);\n  });\n\n  test(\"should compile if/else if/else condition within canvas\", () => {\n    const input = `<Canvas>\n  <Container>\n    @if (score >= 90) {\n        <Text text=\"Grade: A+\" x={100} y={100} color=\"gold\" size={24} />\n        <Text text=\"Excellent work!\" x={100} y={130} color=\"gold\" size={16} />\n    }\n  </Container>\n</Canvas>\n        `;\n\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, null, h(Container, null, cond(computed(() => score() >= 90), () => [h(Text, { text: 'Grade: A+', x: 100, y: 100, color: 'gold', size: 24 }), h(Text, { text: 'Excellent work!', x: 100, y: 130, color: 'gold', size: 16 })])))`);\n  });\n\n  test(\"should compile multiple else if conditions\", () => {\n    const input = `\n            @if (score >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score >= 80) {\n                <Text text=\"A\" />\n            }\n            @else if (score >= 70) {\n                <Text text=\"B\" />\n            }\n            @else if (score >= 60) {\n                <Text text=\"C\" />\n            }\n            @else {\n                <Text text=\"F\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })], [computed(() => score() >= 70), () => h(Text, { text: 'B' })], [computed(() => score() >= 60), () => h(Text, { text: 'C' })], () => h(Text, { text: 'F' }))`);\n  });\n\n  test(\"should compile if/else with multiple elements\", () => {\n    const input = `\n            @if (user.role === 'admin') {\n                <Text text=\"Admin Panel\" />\n                <Text text=\"Settings\" />\n            }\n            @else {\n                <Text text=\"Please log in\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => user().role() === 'admin'), () => [h(Text, { text: 'Admin Panel' }), h(Text, { text: 'Settings' })], () => h(Text, { text: 'Please log in' }))`);\n  });\n\n  test(\"should compile nested if/else conditions\", () => {\n    const input = `\n            @if (user) {\n                @if (user.isActive) {\n                    <Text text=\"Active user\" />\n                }\n                @else {\n                    <Text text=\"Inactive user\" />\n                }\n            }\n            @else {\n                <Text text=\"No user\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(user, () => cond(user.isActive, () => h(Text, { text: 'Active user' }), () => h(Text, { text: 'Inactive user' })), () => h(Text, { text: 'No user' }))`);\n  });\n\n  test(\"should compile if/else if with simple conditions\", () => {\n    const input = `\n            @if (theme === 'dark') {\n                <Text text=\"Dark mode\" />\n            }\n            @else if (theme === 'light') {\n                <Text text=\"Light mode\" />\n            }\n            @else {\n                <Text text=\"Auto mode\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => theme() === 'dark'), () => h(Text, { text: 'Dark mode' }), [computed(() => theme() === 'light'), () => h(Text, { text: 'Light mode' })], () => h(Text, { text: 'Auto mode' }))`);\n  });\n\n  test(\"should compile if/else with function conditions\", () => {\n    const input = `\n            @if (isVisible()) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"Hidden\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isVisible(), () => h(Sprite), () => h(Text, { text: 'Hidden' }))`);\n  });\n\n  test(\"should compile if/else if with object property conditions\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n            }\n            @else if (sprite.loading) {\n                <Text text=\"Loading...\" />\n            }\n            @else {\n                <Text text=\"Not available\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite.visible, () => h(Sprite), [sprite.loading, () => h(Text, { text: 'Loading...' })], () => h(Text, { text: 'Not available' }))`);\n  });\n\n  test(\"should compile condition with function call and @ literal argument\", () => {\n    const input = `\n            @if (isSelected(@item.@id)) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with function call and @ literal in dot notation\", () => {\n    const input = `\n            @if (isSelected(@item.@id)) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"Not selected\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id), () => h(Sprite), () => h(Text, { text: 'Not selected' }))`);\n  });\n\n  test(\"should compile condition with function call and mixed @ literal and signal\", () => {\n    const input = `\n            @if (isSelected(@item.id)) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with function call and @ literal property\", () => {\n    const input = `\n            @if (check(@value)) {\n                <Text text=\"Checked\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(check(value), () => h(Text, { text: 'Checked' }))`);\n  });\n\n  test(\"should compile condition with function call and multiple @ literal arguments\", () => {\n    const input = `\n            @if (compare(@item.@id, @other.@id)) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(compare(item.id, other.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and @ literal dot notation\", () => {\n    const input = `\n            @if (isSelected == @item.@id) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and mixed @ literal and signal\", () => {\n    const input = `\n            @if (isSelected == @item.id) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item().id()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and signal and @ literal\", () => {\n    const input = `\n            @if (isSelected == item.@id) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item().id), () => h(Sprite))`);\n  });\n\n  test(\"should compile component with templating string\", () => {\n    const input = `<Canvas width={\\`direction: \\${direction}\\`} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: \\`direction: \\${direction()}\\` })`);\n  });\n\n  test(\"should compile component with templating string with @ (literal)\", () => {\n    const input = `<Canvas width={\\`direction: \\${@direction}\\`} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: \\`direction: \\${direction}\\` })`);\n  });\n\n  test(\"should compile component with object attribute\", () => {\n    const input = `<Canvas width={ {x: 10, y: 20} } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: { x: 10, y: 20 } })`);\n  });\n\n  test(\"should compile component with complex object attribute\", () => {\n    const input = `<Sprite \n        sheet={{\n            definition,\n            playing: \"stand\",\n            params: {\n                direction: \"right\"\n            },\n            onFinish\n        }}\n    />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { sheet: { definition, playing: \"stand\", params: { direction: \"right\" }, onFinish } })`);\n  });\n\n  test(\"should compile component with deep object attribute\", () => {\n    const input = `<Canvas width={deep.value} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => deep().value()) })`);\n  });\n\n  test('should compile component with deep object attribute', () => {\n    const input = `<Button \n      style={{\n        backgroundColor: {\n          normal: \"#6c757d\",\n          hover: \"#5a6268\",\n          pressed: \"#545b62\"\n        },\n        text: {\n          fontSize: 16,\n          color: \"#ffffff\"\n        }\n      }}\n    />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Button, { style: { backgroundColor: { normal: \"#6c757d\", hover: \"#5a6268\", pressed: \"#545b62\" }, text: { fontSize: 16, color: \"#ffffff\" } } })`);\n  });\n\n  test('should compile component with deep object attribute and shorthand', () => {\n    const input = `<Canvas>\n  <Container>\n    <Sprite x y sheet={{\n      definition,\n      playing: animationPlaying,\n      params: {\n          direction\n      }\n    }}\n    controls />\n  </Container>\n</Canvas>\n`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, null, h(Container, null, h(Sprite, { x, y, sheet: { definition, playing: animationPlaying, params: { direction } }, controls })))`);\n  });\n\n  test(\"should compile component with deep object attribute but not transform to signal\", () => {\n    const input = `<Canvas width={@deep.value} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => deep.value()) })`);\n  });\n\n  test(\"should compile component with deep object attribute but not all transform to signal\", () => {\n    const input = `<Canvas width={@deep.@value} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: deep.value })`);\n  });\n\n  test(\"should compile component with dynamic object attribute\", () => {\n    const input = `<Canvas width={ {x: x, y: 20} } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: { x: x, y: 20 } })`);\n  });\n\n  test(\"should compile component with array attribute\", () => {\n    const input = `<Canvas width={ [10, 20] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: [10, 20] })`);\n  });\n\n  test(\"should compile component with dynamic array attribute\", () => {\n    const input = `<Canvas width={ [x, 20] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: [x, 20] })`);\n  });\n\n  test(\"should compile component with standalone dynamic attribute\", () => {\n    const input = `<Canvas width />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width })`);\n  });\n\n  test(\"should compile component with computed dynamic attribute\", () => {\n    const input = `<Canvas width={x * 2} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => x() * 2) })`);\n  });\n\n  test(\"should compile component with multiple computed dynamic attributes\", () => {\n    const input = `<Canvas width={x * 2 * y} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => x() * 2 * y()) })`);\n  });\n\n  test(\"should compile component with static string attribute\", () => {\n    const input = `<Canvas width=\"val\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: 'val' })`);\n  });\n\n  test(\"should compile component with static string attribute with dash\", () => {\n    const input = `<Canvas max-width=\"val\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { 'max-width': 'val' })`);\n  });\n\n  test(\"should compile component with static attribute (with number)\", () => {\n    const input = `<Canvas width=\"10\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: '10' })`);\n  });\n\n  test(\"should compile component with children\", () => {\n    const input = `\n            <Canvas>\n                <Sprite />\n                <Text />\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,[h(Sprite),h(Text)])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with multiple children\", () => {\n    const input = `<Container>\n        <Container></Container>\n        <Container></Container>\n    </Container>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Container,null,[h(Container),h(Container)])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with multi children\", () => {\n    const input = `\n           <Sprite />\n           <Sprite />\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `[h(Sprite),h(Sprite)]`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with event handler\", () => {\n    const input = `<Sprite click={fn} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: fn })`);\n  });\n\n  test(\"should compile component with standalone event handler\", () => {\n    const input = `<Sprite click />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click })`);\n  });\n\n  test('should compile component with inline event handler', () => {\n    const input = `<Sprite click={() => console.log('click')} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: () => console.log('click') })`);\n  });\n\n  test(\"should compile component with component attribute\", () => {\n    const input = `<Canvas child={<Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: h(Sprite) })`);\n  });\n\n  test(\"should compile component with function returns component attribute\", () => {\n    const input = `<Canvas child={() => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Sprite) })`);\n  });\n\n  test(\"should compile component with function (with params) returns component attribute\", () => {\n    const input = `<Canvas child={(x, y) => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: (x, y) => h(Sprite) })`);\n  });\n\n  test(\"should compile component with destructuring function (with params)\", () => {\n    const input = `<Canvas child={({ x, y }) => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: ({x, y}) => h(Sprite) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and data\", () => {\n    const input = `<Canvas child={() => <Text text=\"Hello\" />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Text, { text: 'Hello' }) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and child\", () => {\n    const input = `<Canvas child={() => <Container>\n        <Text text=\"Hello\" />\n    </Container>} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Container, null, h(Text, { text: 'Hello' })) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and children\", () => {\n    const input = `<Canvas child={() => <Container>\n        <Text text=\"Hello 1\" />\n        <Text text=\"Hello 2\" />\n    </Container>} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Container, null, [h(Text, { text: 'Hello 1' }), h(Text, { text: 'Hello 2' })]) })`);\n  });\n\n  test(\"should compile component with dynamic text content and multiple @ literals\", () => {\n    const input = `<button tabindex={@item.@id}>{@item.@label}</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"button\", attrs: { tabindex: item.id }, textContent: item.label })`);\n  });\n\n  test(\"should compile component with dynamic signal text content\", () => {\n    const input = `<button>{item.label}</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"button\", textContent: computed(() => item().label()) })`);\n  });\n\n  test(\"should compile mixed text with signal without nested computed\", () => {\n    const input = `<p>Gold: {gold}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"p\", textContent: computed(() => 'Gold: ' + gold()) })`);\n  });\n\n  test(\"should compile mixed text and void element content\", () => {\n    const input = `<p>{gold} <br> G</p>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"p\" }, [computed(() => gold()), h(DOMElement, { element: \"br\" }), ' G'])`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe(\"Loop\", () => {\n  test(\"loop in canvas\", () => {\n    const input = `\n        <Canvas>\n            @for (sprite of sprites) {\n                <Sprite />\n            }\n        </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>h(Sprite)))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop\", () => {\n    const input = `\n        @for (sprite of sprites) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with object\", () => {\n    const input = `\n        @for (sprite of sprites.items) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with deep object\", () => {\n    const input = `\n        @for (sprite of sprites.items.items) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items.items,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with function\", () => {\n    const input = `\n        @for (sprite of sprites()) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites(),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with function and params\", () => {\n    const input = `\n        @for (sprite of sprites(x, y)) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites(x,y),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with object and function and params\", () => {\n    const input = `\n        @for (sprite of sprites.items(x, y)) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items(x,y),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with destructuring\", () => {\n    const input = `\n        @for ((sprite, index) of sprites) {\n            <Sprite key={index} />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,(sprite,index)=>h(Sprite, { key: index }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile nestedloop\", () => {\n    const input = `\n        @for (sprite of sprites) {\n            @for (other of others) {\n                <Sprite />\n            }\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,sprite=>loop(others,other=>h(Sprite)))`.replace(\n        /\\s+/g,\n        \"\"\n      )\n    );\n  });\n});\n\ndescribe(\"Condition\", () => {\n  test(\"should compile condition\", () => {\n    const input = `\n            @if (sprite) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite, () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition\", () => {\n    const input = `\n            @if (!sprite) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite()), () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition with multiple condition\", () => {\n    const input = `\n            @if (!sprite && other) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite() && other()), () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition with multiple condition (or)\", () => {\n    const input = `\n            @if (!sprite || other) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite() || other()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite.visible, () => h(Sprite))`);\n  });\n\n  test(\"should compile condition when function value\", () => {\n    const input = `\n            @if (val()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(val(), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition for multiple sprites\", () => {\n    const input = `\n            @if (sprite) {\n              <Sprite />\n            }\n            @if (other) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `[cond(sprite, () => h(Sprite)),cond(other, () => h(Sprite))]`\n    );\n  });\n\n  test(\"should compile nested condition when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n               @if (deep) {\n                    <Sprite />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => cond(deep, () => h(Sprite)))`\n    );\n  });\n\n  test(\"should compile condition with nested sprite when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n                @if (deep) {\n                    <Sprite />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => [h(Sprite), cond(deep, () => h(Sprite))])`\n    );\n  });\n\n  test(\"should compile condition with multiple sprites when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n                @if (deep) {\n                    <Sprite />\n                }\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => [h(Sprite), cond(deep, () => h(Sprite)), h(Sprite)])`\n    );\n  });\n\n  test(\"should compile if/else within canvas\", () => {\n    const input = `\n            <Canvas>\n                @if (showSprite) {\n                    <Sprite />\n                }\n                @else {\n                    <Text text=\"No sprite\" />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `h(Canvas, null, cond(showSprite, () => h(Sprite), () => h(Text, { text: 'No sprite' })))`\n    );\n  });\n\n  test(\"should compile if/else if/else within loop\", () => {\n    const input = `\n            @for (item of items) {\n                @if (item.type === 'sprite') {\n                    <Sprite />\n                }\n                @else if (item.type === 'text') {\n                    <Text />\n                }\n                @else {\n                    <Container />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(items,item=>cond(computed(()=>item().type()==='sprite'),()=>h(Sprite),[computed(()=>item().type()==='text'),()=>h(Text)],()=>h(Container)))`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe(\"Condition in Loops\", () => {\n  test(\"should compile condition within a loop\", () => { // New test for condition in a loop\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    @if (sprite.visible) {\n                        <Sprite />\n                    }\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>cond(sprite.visible,()=>h(Sprite))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile elements within a loop\", () => { // New test for elements in a loop\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    <Sprite />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>h(Sprite)))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile multiple loops at the same level\", () => { // New test for multiple loops\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    <Sprite />\n                }\n                @for (other of others) {\n                    <Sprite />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,[loop(sprites,sprite=>h(Sprite)),loop(others,other=>h(Sprite))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n});\n\ndescribe('Svg', () => {\n  test('should compile svg', () => {\n    const input = `<svg>\n      <path d=\"M 100 350 l 150 -300\" stroke=\"red\" stroke-width=\"4\"/>\n    </svg>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Svg, { content: `<svg><path d=\"M 100 350 l 150 -300\" stroke=\"red\" stroke-width=\"4\"/></svg>` })');\n  });\n\n  test('should compile svg with canvas', () => {\n    const input = `<Canvas antialias={true}>\n    <svg height=\"400\" width=\"450\" xmlns=\"http://www.w3.org/2000/svg\"></svg></Canvas>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Canvas, { antialias: true }, h(Svg, { content: `<svg height=\"400\" width=\"450\" xmlns=\"http://www.w3.org/2000/svg\"></svg>` }))');\n  });\n});\n\ndescribe('DOM', () => {\n  test('should compile input DOM', () => {\n    const input = `<input type=\"text\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"input\", attrs: { type: \\'text\\' } })');\n  });\n\n  test('should compile div DOM', () => {\n    const input = `<div class=\"container\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: \\'container\\' } })');\n  });\n\n  test('should merge static and dynamic class attributes', () => {\n    const input = `<div class=\"container\" class={className} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: [\\'container\\', className] } })');\n  });\n\n  test('should merge static and object class attributes', () => {\n    const input = `<div class=\"container\" class={{ active: true }} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: [\\'container\\', { active: true }] } })');\n  });\n\n  test('should compile button DOM', () => {\n    const input = `<button type=\"submit\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { type: \\'submit\\' } })');\n  });\n\n  test('should compile button DOM', () => {\n    const input = `<button>Text</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", textContent: \\'Text\\' })');\n  });\n\n  test('should compile textarea DOM with dynamic attributes', () => {\n    const input = `<textarea rows={rows} cols={cols} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"textarea\", attrs: { rows: rows, cols: cols } })');\n  });\n\n  test('should not transform Canvas to DOM', () => {\n    const input = `<Canvas width={800} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Canvas, { width: 800 })');\n  });\n\n  test('should not transform Sprite to DOM', () => {\n    const input = `<Sprite image=\"test.png\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Sprite, { image: \\'test.png\\' })');\n  });\n\n  // Tests avec imbrications DOM\n  test('should compile nested DOM elements', () => {\n    const input = `<div class=\"container\">\n      <p>Hello World</p>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: \\'container\\' } }, h(DOMElement, { element: \"p\", textContent: \\'Hello World\\' }))');\n  });\n\n  test('should compile deeply nested DOM elements', () => {\n    const input = `<div class=\"wrapper\">\n      <section>\n        <h1>Title</h1>\n        <p>Content</p>\n      </section>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'wrapper' } }, h(DOMElement, { element: \"section\" }, [h(DOMElement, { element: \"h1\", textContent: 'Title' }), h(DOMElement, { element: \"p\", textContent: 'Content' })]))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile DOM with multiple children', () => {\n    const input = `<ul>\n      <li>Item 1</li>\n      <li>Item 2</li>\n      <li>Item 3</li>\n    </ul>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"ul\" }, [h(DOMElement, { element: \"li\", textContent: 'Item 1' }), h(DOMElement, { element: \"li\", textContent: 'Item 2' }), h(DOMElement, { element: \"li\", textContent: 'Item 3' })])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile mixed DOM and framework components', () => {\n    const input = `<div class=\"game-container\">\n      <Canvas width={800} height={600} />\n      <div class=\"ui\">\n        <button>Start Game</button>\n      </div>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'game-container' } }, [h(Canvas, { width: 800, height: 600 }), h(DOMElement, { element: \"div\", attrs: { class: 'ui' } }, h(DOMElement, { element: \"button\", textContent: 'Start Game' }))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile DOM with attributes and text content', () => {\n    const input = `<button class=\"btn primary\" type=\"submit\">Submit Form</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { class: \\'btn primary\\', type: \\'submit\\' }, textContent: \\'Submit Form\\' })');\n  });\n});\n\ndescribe('DOM with special attributes', () => {\n  test('should compile DOM with special attributes', () => {\n    const input = `<input type=\"password\" x={100} y={100} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"input\", attrs: { type: \\'password\\' }, x: 100, y: 100 })');\n  });\n\n  test('should compile DOM with text object', () => {\n    const input = `<p>{{ object.x }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: computed(() => object().x()) })');\n  });\n\n  test('should compile DOM with text object with @', () => {\n    const input = `<p>{{ @object.x }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: computed(() => object.x()) })');\n  });\n\n  test('should compile DOM with text object with literal ', () => {\n    const input = `<p>{{ @object.@x }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: object.x })');\n  });\n});\n\ndescribe('DOM with Control Structures', () => {\n  test('should compile @for loop with DOM elements', () => {\n    const input = `\n      @for (item of items) {\n        <li>{item.name}</li>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(items, item => h(DOMElement, { element: \"li\", textContent: computed(() => item().name()) }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('Use literal text content', () => {\n    const input = `\n      <p>{@text}</p>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"p\", textContent: text })`.replace(/\\s+/g, \"\")\n    );\n  })\n\n  test('should compile @for loop with nested DOM structure', () => {\n    const input = `\n      <ul class=\"menu\">\n        @for (item of menuItems) {\n          <li class=\"menu-item\">\n            <a href={item.url}>{item.title}</a>\n          </li>\n        }\n      </ul>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"ul\", attrs: { class: 'menu' } }, loop(menuItems, item => h(DOMElement, { element: \"li\", attrs: { class: 'menu-item' } }, h(DOMElement, { element: \"a\", attrs: { href: computed(() => item().url()) }, textContent: computed(() => item().title()) }))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if condition with DOM elements', () => {\n    const input = `\n      @if (showMessage) {\n        <div class=\"alert\">\n          <p>Important message!</p>\n        </div>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `cond(showMessage, () => h(DOMElement, { element: \"div\", attrs: { class: 'alert' } }, h(DOMElement, { element: \"p\", textContent: 'Important message!' })))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if condition with simple DOM element', () => {\n    const input = `\n      @if (isVisible) {\n        <button>Click me</button>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `cond(isVisible, () => h(DOMElement, { element: \"button\", textContent: 'Click me' }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile nested @for and @if with DOM', () => {\n    const input = `\n      <div class=\"container\">\n        @for (section of sections) {\n          @if (section.visible) {\n            <section class=\"content\">\n              <h2>{section.title}</h2>\n              <div class=\"items\">\n                @for (item of section.items) {\n                  <div class=\"item\">{item.name}</div>\n                }\n              </div>\n            </section>\n          }\n        }\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'container' } }, loop(sections, section => cond(section.visible, () => h(DOMElement, { element: \"section\", attrs: { class: 'content' } }, [h(DOMElement, { element: \"h2\", textContent: computed(() => section().title()) }), h(DOMElement, { element: \"div\", attrs: { class: 'items' } }, loop(section.items, item => h(DOMElement, { element: \"div\", attrs: { class: 'item' }, textContent: computed(() => item().name()) })))]))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @for with DOM table structure', () => {\n    const input = `\n      <table>\n        <thead>\n          <tr>\n            <th>Name</th>\n            <th>Age</th>\n          </tr>\n        </thead>\n        <tbody>\n          @for (user of users) {\n            <tr>\n              <td>{user.name}</td>\n              <td>{user.age}</td>\n            </tr>\n          }\n        </tbody>\n      </table>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"table\" }, [h(DOMElement, { element: \"thead\" }, h(DOMElement, { element: \"tr\" }, [h(DOMElement, { element: \"th\", textContent: 'Name' }), h(DOMElement, { element: \"th\", textContent: 'Age' })])), h(DOMElement, { element: \"tbody\" }, loop(users, user => h(DOMElement, { element: \"tr\" }, [h(DOMElement, { element: \"td\", textContent: computed(() => user().name()) }), h(DOMElement, { element: \"td\", textContent: computed(() => user().age()) })])))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if with multiple DOM conditions', () => {\n    const input = `\n      <div class=\"status\">\n        @if (isLoading) {\n          <div class=\"spinner\">Loading...</div>\n        }\n        @if (hasError) {\n          <div class=\"error\">Error occurred!</div>\n        }\n        @if (isSuccess) {\n          <div class=\"success\">Success!</div>\n        }\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'status' } }, [cond(isLoading, () => h(DOMElement, { element: \"div\", attrs: { class: 'spinner' }, textContent: 'Loading...' })), cond(hasError, () => h(DOMElement, { element: \"div\", attrs: { class: 'error' }, textContent: 'Error occurred!' })), cond(isSuccess, () => h(DOMElement, { element: \"div\", attrs: { class: 'success' }, textContent: 'Success!' }))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile mixed Canvas and DOM with control structures', () => {\n    const input = `\n      <div class=\"game-wrapper\">\n        <Canvas width={800} height={600}>\n          @for (sprite of sprites) {\n            <Sprite x={sprite.x} y={sprite.y} />\n          }\n        </Canvas>\n        <div class=\"ui-overlay\">\n          @if (showScore) {\n            <div class=\"score\">Score: {score}</div>\n          }\n          @if (showMenu) {\n            <div class=\"menu\">\n              @for (option of menuOptions) {\n                <button class=\"menu-btn\">{option.label}</button>\n              }\n            </div>\n          }\n        </div>\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'game-wrapper' } }, [h(Canvas, { width: 800, height: 600 }, loop(sprites, sprite => h(Sprite, { x: computed(() => sprite().x()), y: computed(() => sprite().y()) }))), h(DOMElement, { element: \"div\", attrs: { class: 'ui-overlay' } }, [cond(showScore, () => h(DOMElement, { element: \"div\", attrs: { class: 'score' }, textContent: computed(() => 'Score: ' + score()) })), cond(showMenu, () => h(DOMElement, { element: \"div\", attrs: { class: 'menu' } }, loop(menuOptions, option => h(DOMElement, { element: \"button\", attrs: { class: 'menu-btn' }, textContent: computed(() => option().label()) }))))])])`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe('Style scoping', () => {\n  test('should scope CSS selectors correctly', () => {\n    const css = `button {\n  color: red;\n}\ndiv {\n  padding: 10px;\n}`;\n\n    const scopeClass = 'abc12345';\n    const scoped = scopeCSS(css, scopeClass);\n\n    // Should prefix selectors with scope class\n    expect(scoped).toContain(`.${scopeClass} button`);\n    expect(scoped).toContain(`.${scopeClass} div`);\n    expect(scoped).toContain('color: red');\n    expect(scoped).toContain('padding: 10px');\n  });\n\n  test('should preserve @rules in scoped CSS', () => {\n    const css = `@media (max-width: 600px) {\n  button {\n    font-size: 14px;\n  }\n}\nbutton {\n  color: red;\n}`;\n\n    const scopeClass = 'abc12345';\n    const scoped = scopeCSS(css, scopeClass);\n\n    // @media should not be scoped\n    expect(scoped).toContain('@media');\n    // button inside @media should not be scoped\n    expect(scoped).toMatch(/@media[^{]*\\{[^}]*button[^}]*\\{/);\n    // Regular button should be scoped\n    expect(scoped).toContain(`.${scopeClass} button`);\n  });\n\n  test('should add _scopeClass to DOMContainer in parsed template', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toMatch(/h\\(DOMContainer,\\s*\\{\\s*_scopeClass:\\s*'abc12345'/);\n  });\n\n  test('should add _scopeClass to DOMContainer with existing props', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, { class: \"my-class\", x: 100 }))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toContain('class: \"my-class\"');\n    expect(result).toContain('x: 100');\n    // _scopeClass should be first in the props object\n    expect(result).toMatch(/\\{\\s*_scopeClass:\\s*'abc12345',\\s*class:/);\n  });\n\n  test('should add _scopeClass to DOMContainer with attrs object', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, { attrs: { class: \"container\" } }))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toContain('attrs: { class: \"container\" }');\n    expect(result).toMatch(/\\{\\s*_scopeClass:\\s*'abc12345',\\s*attrs:/);\n  });\n\n  test('should add _scopeClass to DOMContainer with null props', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, null, h(Text)))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toMatch(/h\\(DOMContainer,\\s*\\{\\s*_scopeClass:\\s*'abc12345'\\s*\\},\\s*h\\(Text\\)/);\n  });\n\n  test('should handle multiple DOMContainer with same scope class', () => {\n    const parsedTemplate = 'h(Canvas, null, [h(DOMContainer), h(DOMContainer, { class: \"test\" })])';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    // Both should have _scopeClass\n    const matches = result.match(/_scopeClass/g);\n    expect(matches?.length).toBe(2);\n    // Both should have the same scope class value\n    expect(result.match(/_scopeClass:\\s*'abc12345'/g)?.length).toBe(2);\n  });\n\n  test('should generate 8-character hash with letters only', () => {\n    const hash1 = generateHash('/test/my-component.ce');\n    const hash2 = generateHash('/test/another-component.ce');\n\n    // Should be exactly 8 characters\n    expect(hash1.length).toBe(8);\n    expect(hash2.length).toBe(8);\n\n    // Should be letters only (lowercase a-z)\n    expect(hash1).toMatch(/^[a-z]{8}$/);\n    expect(hash2).toMatch(/^[a-z]{8}$/);\n\n    // Different files should produce different hashes (most of the time)\n    // Note: hash collisions are possible but unlikely for different paths\n    expect(hash1).not.toBe(hash2);\n  });\n\n  test('should generate consistent hash for same file', () => {\n    const filePath = '/test/my-component.ce';\n    const hash1 = generateHash(filePath);\n    const hash2 = generateHash(filePath);\n\n    // Same file should produce same hash\n    expect(hash1).toBe(hash2);\n  });\n});\n"
  },
  {
    "path": "packages/compiler/tests/compiler2.spec.ts",
    "content": "import pkg from \"peggy\";\nimport fs from \"fs\";\nimport { beforeAll, describe, test, expect } from \"vitest\";\n\nconst { generate } = pkg;\nlet parser: any;\n\nbeforeAll(() => {\n  const grammar = fs.readFileSync(\"packages/compiler/grammar2.pegjs\", \"utf8\");\n  parser = generate(grammar);\n});\n\n// Helper functions to test scoping logic directly\nfunction generateHash(str: string): string {\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 32-bit integer\n  }\n  // Convert to positive number and map to letters only (a-z)\n  // Use modulo to map to 26 letters, then convert to character\n  const positiveHash = Math.abs(hash);\n  let result = '';\n  for (let i = 0; i < 8; i++) {\n    const letterIndex = (positiveHash + i * 31) % 26; // 31 is a prime to spread values\n    result += String.fromCharCode(97 + letterIndex); // 97 is 'a'\n  }\n  return result;\n}\n\nfunction scopeCSS(css: string, scopeClass: string): string {\n  const scopeSelector = `.${scopeClass}`;\n\n  // Process CSS by finding rule blocks while skipping @rules\n  let result = '';\n  let i = 0;\n  let depth = 0;\n  let inRule = false;\n  let selectorBuffer = '';\n\n  while (i < css.length) {\n    const char = css[i];\n\n    if (char === '@' && !inRule && selectorBuffer === '') {\n      // Found @rule - copy it as-is until matching closing brace\n      const atRuleStart = i;\n      i++; // Skip '@'\n\n      // Find the opening brace\n      while (i < css.length && css[i] !== '{') {\n        i++;\n      }\n\n      if (i < css.length) {\n        // Found opening brace, now find matching closing brace\n        depth = 1;\n        i++; // Skip '{'\n\n        while (i < css.length && depth > 0) {\n          if (css[i] === '{') depth++;\n          else if (css[i] === '}') depth--;\n          i++;\n        }\n\n        // Copy entire @rule as-is\n        result += css.substring(atRuleStart, i);\n      }\n      continue;\n    }\n\n    if (char === '{' && !inRule) {\n      // Start of a rule block - scope the selector we just collected\n      const selectorText = selectorBuffer.trim();\n\n      if (selectorText) {\n        // Split selectors by comma and scope each one\n        const scopedSelectors = selectorText\n          .split(',')\n          .map(sel => {\n            const trimmed = sel.trim();\n            return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n          })\n          .join(', ');\n\n        result += scopedSelectors;\n      }\n      result += ' {';\n      inRule = true;\n      depth = 1;\n      selectorBuffer = '';\n    } else if (char === '{' && inRule) {\n      // Nested brace\n      result += char;\n      depth++;\n    } else if (char === '}' && inRule) {\n      result += char;\n      depth--;\n      if (depth === 0) {\n        inRule = false;\n      }\n    } else if (!inRule) {\n      // Collecting selector\n      selectorBuffer += char;\n    } else {\n      // Inside rule block\n      result += char;\n      if (char === '{') depth++;\n    }\n\n    i++;\n  }\n\n  // Add any remaining selector (shouldn't happen in valid CSS, but handle it)\n  if (selectorBuffer.trim()) {\n    const scopedSelectors = selectorBuffer.trim()\n      .split(',')\n      .map(sel => {\n        const trimmed = sel.trim();\n        return trimmed ? `${scopeSelector} ${trimmed}` : trimmed;\n      })\n      .join(', ');\n    result += scopedSelectors;\n  }\n\n  return result;\n}\n\nfunction splitCallArguments(argsText: string): string[] {\n  const args: string[] = [];\n  let current = \"\";\n  let depth = 0;\n  let inSingle = false;\n  let inDouble = false;\n  let inTemplate = false;\n  let escaped = false;\n\n  for (let i = 0; i < argsText.length; i++) {\n    const char = argsText[i];\n\n    if (escaped) {\n      current += char;\n      escaped = false;\n      continue;\n    }\n\n    if (char === \"\\\\\") {\n      current += char;\n      escaped = true;\n      continue;\n    }\n\n    if (inSingle) {\n      current += char;\n      if (char === \"'\") inSingle = false;\n      continue;\n    }\n\n    if (inDouble) {\n      current += char;\n      if (char === '\"') inDouble = false;\n      continue;\n    }\n\n    if (inTemplate) {\n      current += char;\n      if (char === \"`\") inTemplate = false;\n      continue;\n    }\n\n    if (char === \"'\") {\n      inSingle = true;\n      current += char;\n      continue;\n    }\n\n    if (char === '\"') {\n      inDouble = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"`\") {\n      inTemplate = true;\n      current += char;\n      continue;\n    }\n\n    if (char === \"(\" || char === \"{\" || char === \"[\") {\n      depth++;\n      current += char;\n      continue;\n    }\n\n    if (char === \")\" || char === \"}\" || char === \"]\") {\n      depth--;\n      current += char;\n      continue;\n    }\n\n    if (char === \",\" && depth === 0) {\n      args.push(current.trim());\n      current = \"\";\n      continue;\n    }\n\n    current += char;\n  }\n\n  if (current.trim()) {\n    args.push(current.trim());\n  }\n\n  return args;\n}\n\nfunction addScopeClassToDOMContainer(parsedTemplate: string, scopeClass: string): string {\n  let result = \"\";\n  let cursor = 0;\n\n  while (cursor < parsedTemplate.length) {\n    const start = parsedTemplate.indexOf(\"h(DOMContainer\", cursor);\n    if (start === -1) {\n      result += parsedTemplate.slice(cursor);\n      break;\n    }\n\n    result += parsedTemplate.slice(cursor, start);\n    const openParen = parsedTemplate.indexOf(\"(\", start);\n    if (openParen === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    let depth = 0;\n    let inSingle = false;\n    let inDouble = false;\n    let inTemplate = false;\n    let escaped = false;\n    let end = -1;\n\n    for (let i = openParen; i < parsedTemplate.length; i++) {\n      const char = parsedTemplate[i];\n\n      if (escaped) {\n        escaped = false;\n        continue;\n      }\n\n      if (char === \"\\\\\") {\n        escaped = true;\n        continue;\n      }\n\n      if (inSingle) {\n        if (char === \"'\") inSingle = false;\n        continue;\n      }\n\n      if (inDouble) {\n        if (char === '\"') inDouble = false;\n        continue;\n      }\n\n      if (inTemplate) {\n        if (char === \"`\") inTemplate = false;\n        continue;\n      }\n\n      if (char === \"'\") {\n        inSingle = true;\n        continue;\n      }\n\n      if (char === '\"') {\n        inDouble = true;\n        continue;\n      }\n\n      if (char === \"`\") {\n        inTemplate = true;\n        continue;\n      }\n\n      if (char === \"(\") depth++;\n      if (char === \")\") depth--;\n\n      if (depth === 0) {\n        end = i + 1;\n        break;\n      }\n    }\n\n    if (end === -1) {\n      result += parsedTemplate.slice(start);\n      break;\n    }\n\n    const callText = parsedTemplate.slice(start, end);\n    const argsText = parsedTemplate.slice(openParen + 1, end - 1);\n    const args = splitCallArguments(argsText);\n\n    if (args[0]?.trim() !== \"DOMContainer\") {\n      result += callText;\n      cursor = end;\n      continue;\n    }\n\n    if (args.length === 1) {\n      args.push(`{ _scopeClass: '${scopeClass}' }`);\n    } else {\n      const props = args[1].trim();\n      if (props === \"null\" || props === \"undefined\") {\n        args[1] = `{ _scopeClass: '${scopeClass}' }`;\n      } else if (props.startsWith(\"{\")) {\n        args[1] = props.replace(/^\\{\\s*/, `{ _scopeClass: '${scopeClass}', `);\n      } else {\n        args[1] = `{ _scopeClass: '${scopeClass}', ...${props} }`;\n      }\n    }\n\n    result += `h(${args.join(\", \")})`;\n    cursor = end;\n  }\n\n  return result;\n}\n\ndescribe(\"Compiler\", () => {\n  test(\"should compile comment\", () => {\n    const input = `\n      <Canvas>\n        <!-- Comment -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile multiple comment\", () => {\n    const input = `\n      <Canvas>\n        <!-- Comment -->\n        <!-- Comment -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile multiple line comment\", () => {\n    const input = `\n      <Canvas>\n        <!--\n          Comment\n          Comment\n        -->\n      </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  test(\"should compile simple component\", () => {\n    const input = `<Canvas />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas)`);\n  });\n\n  describe(\"Dot notation\", () => {\n    test(\"should compile component with dot notation\", () => {\n      const input = `<MyComp.test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp.test)`);\n    });\n\n    test(\"object function call\", () => {\n      const input = `<MyComp.test() />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp.test())`);\n    });\n\n    test(\"function call with return object\", () => {\n      const input = `<MyComp().test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp().test)`);\n    });\n\n    test(\"function call with return object and params\", () => {\n      const input = `<MyComp().test(x, y) />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp().test(x, y))`);\n    });\n\n    test(\"function call and params with return object and\", () => {\n      const input = `<MyComp(x, y).test />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp(x, y).test)`);\n    });\n\n    test(\"function call\", () => {\n      const input = `<MyComp() />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp())`);\n    });\n\n    test(\"function call and params\", () => {\n      const input = `<MyComp(x, y) />`;\n      const output = parser.parse(input);\n      expect(output).toBe(`h(MyComp(x, y))`);\n    });\n  })\n\n  test(\"should compile component with dynamic attribute\", () => {\n    const input = `<Canvas width={x} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: x })`);\n  });\n\n  test(\"should compile component with spread operator\", () => {\n    const input = `<Canvas ...obj />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, obj)`);\n  });\n\n  test(\"should compile component with spread operator object\", () => {\n    const input = `<Canvas ...obj.prop />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, obj.prop)`);\n  });\n\n  test(\"should compile component with spread operator function\", () => {\n    const input = `<Canvas ...fn() />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, fn())`);\n  });\n\n  test(\"should compile component with spread operator function and params\", () => {\n    const input = `<Canvas ...fn(x, y) />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, fn(x, y))`);\n  });\n\n  test(\"should compile component with dynamic attribute but is not a signal\", () => {\n    const input = `<Canvas width={20} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: 20 })`);\n  });\n\n  test(\"should compile if/else condition\", () => {\n    const input = `\n            @if (sprite) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"No sprite\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite, () => h(Sprite), () => h(Text, { text: 'No sprite' }))`);\n  });\n\n  test(\"should compile if/else if condition\", () => {\n    const input = `\n            @if (score() >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score() >= 80) {\n                <Text text=\"A\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })])`);\n  });\n\n  test(\"should compile if/else if/else condition\", () => {\n    const input = `\n            @if (score() >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score() >= 80) {\n                <Text text=\"A\" />\n            }\n            @else {\n                <Text text=\"F\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })], () => h(Text, { text: 'F' }))`);\n  });\n\n  test(\"should compile if/else if/else condition within canvas\", () => {\n    const input = `<Canvas>\n  <Container>\n    @if (score() >= 90) {\n        <Text text=\"Grade: A+\" x={100} y={100} color=\"gold\" size={24} />\n        <Text text=\"Excellent work!\" x={100} y={130} color=\"gold\" size={16} />\n    }\n  </Container>\n</Canvas>\n        `;\n\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, null, h(Container, null, cond(computed(() => score() >= 90), () => [h(Text, { text: 'Grade: A+', x: 100, y: 100, color: 'gold', size: 24 }), h(Text, { text: 'Excellent work!', x: 100, y: 130, color: 'gold', size: 16 })])))`);\n  });\n\n  test(\"should compile multiple else if conditions\", () => {\n    const input = `\n            @if (score() >= 90) {\n                <Text text=\"A+\" />\n            }\n            @else if (score() >= 80) {\n                <Text text=\"A\" />\n            }\n            @else if (score() >= 70) {\n                <Text text=\"B\" />\n            }\n            @else if (score() >= 60) {\n                <Text text=\"C\" />\n            }\n            @else {\n                <Text text=\"F\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => score() >= 90), () => h(Text, { text: 'A+' }), [computed(() => score() >= 80), () => h(Text, { text: 'A' })], [computed(() => score() >= 70), () => h(Text, { text: 'B' })], [computed(() => score() >= 60), () => h(Text, { text: 'C' })], () => h(Text, { text: 'F' }))`);\n  });\n\n  test(\"should compile if/else with multiple elements\", () => {\n    const input = `\n            @if (user().role() === 'admin') {\n                <Text text=\"Admin Panel\" />\n                <Text text=\"Settings\" />\n            }\n            @else {\n                <Text text=\"Please log in\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => user().role() === 'admin'), () => [h(Text, { text: 'Admin Panel' }), h(Text, { text: 'Settings' })], () => h(Text, { text: 'Please log in' }))`);\n  });\n\n  test(\"should compile nested if/else conditions\", () => {\n    const input = `\n            @if (user) {\n                @if (user.isActive) {\n                    <Text text=\"Active user\" />\n                }\n                @else {\n                    <Text text=\"Inactive user\" />\n                }\n            }\n            @else {\n                <Text text=\"No user\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(user, () => cond(user.isActive, () => h(Text, { text: 'Active user' }), () => h(Text, { text: 'Inactive user' })), () => h(Text, { text: 'No user' }))`);\n  });\n\n  test(\"should compile if/else if with simple conditions\", () => {\n    const input = `\n            @if (theme() === 'dark') {\n                <Text text=\"Dark mode\" />\n            }\n            @else if (theme() === 'light') {\n                <Text text=\"Light mode\" />\n            }\n            @else {\n                <Text text=\"Auto mode\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => theme() === 'dark'), () => h(Text, { text: 'Dark mode' }), [computed(() => theme() === 'light'), () => h(Text, { text: 'Light mode' })], () => h(Text, { text: 'Auto mode' }))`);\n  });\n\n  test(\"should compile if/else with function conditions\", () => {\n    const input = `\n            @if (isVisible()) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"Hidden\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isVisible(), () => h(Sprite), () => h(Text, { text: 'Hidden' }))`);\n  });\n\n  test(\"should compile if/else if with object property conditions\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n            }\n            @else if (sprite.loading) {\n                <Text text=\"Loading...\" />\n            }\n            @else {\n                <Text text=\"Not available\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite.visible, () => h(Sprite), [sprite.loading, () => h(Text, { text: 'Loading...' })], () => h(Text, { text: 'Not available' }))`);\n  });\n\n  test(\"should compile condition with function call and @ literal argument\", () => {\n    const input = `\n            @if (isSelected(item.id)) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with function call and @ literal in dot notation\", () => {\n    const input = `\n            @if (isSelected(item.id)) {\n                <Sprite />\n            }\n            @else {\n                <Text text=\"Not selected\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id), () => h(Sprite), () => h(Text, { text: 'Not selected' }))`);\n  });\n\n  test(\"should compile condition with function call and mixed @ literal and signal\", () => {\n    const input = `\n            @if (isSelected(item.id())) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isSelected(item.id()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with function call and @ literal property\", () => {\n    const input = `\n            @if (check(value)) {\n                <Text text=\"Checked\" />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(check(value), () => h(Text, { text: 'Checked' }))`);\n  });\n\n  test(\"should compile condition with function call and multiple @ literal arguments\", () => {\n    const input = `\n            @if (compare(item.id, other.id)) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(compare(item.id, other.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and @ literal dot notation\", () => {\n    const input = `\n            @if (isSelected() == item.id) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item.id), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and mixed @ literal and signal\", () => {\n    const input = `\n            @if (isSelected() == item().id()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item().id()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with comparison and signal and @ literal\", () => {\n    const input = `\n            @if (isSelected() == item().id) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => isSelected() == item().id), () => h(Sprite))`);\n  });\n\n  test(\"should compile component with templating string\", () => {\n    const input = `<Canvas width={\\`direction: \\${direction()}\\`} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: \\`direction: \\${direction()}\\` })`);\n  });\n\n  test(\"should compile component with templating string with @ (literal)\", () => {\n    const input = `<Canvas width={\\`direction: \\${direction}\\`} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: \\`direction: \\${direction}\\` })`);\n  });\n\n  test(\"should compile template string without transforming identifiers\", () => {\n    const input = `<Canvas width={\\`hello \\${name}\\`} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: \\`hello \\${name}\\` })`);\n  });\n\n  test(\"should compile component with object attribute\", () => {\n    const input = `<Canvas width={ {x: 10, y: 20} } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: { x: 10, y: 20 } })`);\n  });\n\n  test(\"should format compact object attribute spacing\", () => {\n    const input = `<Canvas width={{x:10,y:20}} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: { x: 10, y: 20 } })`);\n  });\n\n  test('should compile component with object attribute', () => {\n    const input = `\n    <Container obj={{positive: stat.delta > 0, negative: stat.delta < 0}}></Container>\n    `;\n    const output = parser.parse(input);\n   expect(output).toBe(`h(Container, { obj: { positive: stat.delta > 0, negative: stat.delta < 0 } })`);\n  });\n\n  test('should compile component with object attribute', () => {\n    const input = `\n    <Container obj={{positive: positive(), negative: stat.delta < 0}}></Container>\n    `;\n    const output = parser.parse(input);\n   expect(output).toBe(`h(Container, { obj: computed(() => ({ positive: positive(), negative: stat.delta < 0 })) })`);\n  });\n\n  test('should compile object attribute with function and nested value', () => {\n    const input = `<Container obj={{ foo: bar(), nested: baz }} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Container, { obj: computed(() => ({ foo: bar(), nested: baz })) })`);\n  });\n\n  test('should compile object attribute with spread and function', () => {\n    const input = `<Container obj={{ ...base, count: total() }} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Container, { obj: computed(() => ({ ...base, count: total() })) })`);\n  });\n\n  test(\"should compile component with complex object attribute\", () => {\n    const input = `<Sprite \n        sheet={{\n            definition,\n            playing: \"stand\",\n            params: {\n                direction: \"right\"\n            },\n            onFinish\n        }}\n    />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { sheet: { definition, playing: \"stand\", params: { direction: \"right\" }, onFinish } })`);\n  });\n\n  test(\"should compile component with deep object attribute\", () => {\n    const input = `<Canvas width={deep().value()} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => deep().value()) })`);\n  });\n\n  test('should compile component with deep object attribute', () => {\n    const input = `<Button \n      style={{\n        backgroundColor: {\n          normal: \"#6c757d\",\n          hover: \"#5a6268\",\n          pressed: \"#545b62\"\n        },\n        text: {\n          fontSize: 16,\n          color: \"#ffffff\"\n        }\n      }}\n    />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Button, { style: { backgroundColor: { normal: \"#6c757d\", hover: \"#5a6268\", pressed: \"#545b62\" }, text: { fontSize: 16, color: \"#ffffff\" } } })`);\n  });\n\n  test('should compile component with deep object attribute and shorthand', () => {\n    const input = `<Canvas>\n  <Container>\n    <Sprite x y sheet={{\n      definition,\n      playing: animationPlaying,\n      params: {\n          direction\n      }\n    }}\n    controls />\n  </Container>\n</Canvas>\n`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, null, h(Container, null, h(Sprite, { x, y, sheet: { definition, playing: animationPlaying, params: { direction } }, controls })))`);\n  });\n\n  test(\"should compile component with deep object attribute but not transform to signal\", () => {\n    const input = `<Canvas width={deep.value()} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => deep.value()) })`);\n  });\n\n  test(\"should compile component with deep object attribute but not all transform to signal\", () => {\n    const input = `<Canvas width={deep.value} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: deep.value })`);\n  });\n\n  test(\"should compile component with dynamic object attribute\", () => {\n    const input = `<Canvas width={ {x: x, y: 20} } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: { x: x, y: 20 } })`);\n  });\n\n  test(\"should compile component with array attribute\", () => {\n    const input = `<Canvas width={ [10, 20] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: [10, 20] })`);\n  });\n\n  test(\"should compile component with dynamic array attribute\", () => {\n    const input = `<Canvas width={ [x, 20] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: [x, 20] })`);\n  });\n\n  test(\"should compile component with array attribute containing function\", () => {\n    const input = `<Canvas width={ [x(), 20] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => [x(), 20]) })`);\n  });\n\n  test(\"should compile component with array attribute containing expression without computed\", () => {\n    const input = `<Canvas width={ [x + 1, y] } />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: [x + 1, y] })`);\n  });\n\n  test(\"should compile component with standalone dynamic attribute\", () => {\n    const input = `<Canvas width />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width })`);\n  });\n\n  test(\"should compile component with computed dynamic attribute\", () => {\n    const input = `<Canvas width={x * 2} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => x() * 2) })`);\n  });\n\n  test(\"should compile component with multiple computed dynamic attributes\", () => {\n    const input = `<Canvas width={x * 2 * y} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: computed(() => x() * 2 * y()) })`);\n  });\n\n  test(\"should compile component with static string attribute\", () => {\n    const input = `<Canvas width=\"val\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: 'val' })`);\n  });\n\n  test(\"should compile component with static string attribute with dash\", () => {\n    const input = `<Canvas max-width=\"val\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { 'max-width': 'val' })`);\n  });\n\n  test(\"should compile component with static attribute (with number)\", () => {\n    const input = `<Canvas width=\"10\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { width: '10' })`);\n  });\n\n  test(\"should compile component with children\", () => {\n    const input = `\n            <Canvas>\n                <Sprite />\n                <Text />\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,[h(Sprite),h(Text)])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with multiple children\", () => {\n    const input = `<Container>\n        <Container></Container>\n        <Container></Container>\n    </Container>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Container,null,[h(Container),h(Container)])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with multi children\", () => {\n    const input = `\n           <Sprite />\n           <Sprite />\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `[h(Sprite),h(Sprite)]`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile component with event handler\", () => {\n    const input = `<Sprite click={fn} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: fn })`);\n  });\n\n  test(\"should compile component with standalone event handler\", () => {\n    const input = `<Sprite click />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click })`);\n  });\n\n  test('should compile component with inline event handler', () => {\n    const input = `<Sprite click={() => console.log('click')} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: () => console.log('click') })`);\n  });\n\n  test('should compile component with event handler function call without computed', () => {\n    const input = `<Sprite click={selected()} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: selected() })`);\n  });\n\n  test('should compile component with complex event handler expression without computed', () => {\n    const input = `<Sprite click={selected() ? onA : onB} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Sprite, { click: selected() ? onA : onB })`);\n  });\n\n  test(\"should compile component with component attribute\", () => {\n    const input = `<Canvas child={<Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: h(Sprite) })`);\n  });\n\n  test(\"should compile component with function returns component attribute\", () => {\n    const input = `<Canvas child={() => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Sprite) })`);\n  });\n\n  test(\"should compile component with function (with params) returns component attribute\", () => {\n    const input = `<Canvas child={(x, y) => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: (x, y) => h(Sprite) })`);\n  });\n\n  test(\"should compile component with destructuring function (with params)\", () => {\n    const input = `<Canvas child={({ x, y }) => <Sprite />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: ({x, y}) => h(Sprite) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and data\", () => {\n    const input = `<Canvas child={() => <Text text=\"Hello\" />} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Text, { text: 'Hello' }) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and child\", () => {\n    const input = `<Canvas child={() => <Container>\n        <Text text=\"Hello\" />\n    </Container>} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Container, null, h(Text, { text: 'Hello' })) })`);\n  });\n\n  test(\"should compile component with function returns component attribute and children\", () => {\n    const input = `<Canvas child={() => <Container>\n        <Text text=\"Hello 1\" />\n        <Text text=\"Hello 2\" />\n    </Container>} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(Canvas, { child: () => h(Container, null, [h(Text, { text: 'Hello 1' }), h(Text, { text: 'Hello 2' })]) })`);\n  });\n\n  test(\"should compile component with dynamic text content and multiple literals\", () => {\n    const input = `<button tabindex={item.id}>{item.label}</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"button\", attrs: { tabindex: item.id }, textContent: item.label })`);\n  });\n\n  test(\"should compile component with dynamic signal text content\", () => {\n    const input = `<button>{item().label()}</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"button\", textContent: computed(() => item().label()) })`);\n  });\n\n  test(\"should compile text content with mixed expression and function\", () => {\n    const input = `<p>{a + b()}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"p\", textContent: computed(() => a + b()) })`);\n  });\n\n  test(\"should compile text content with multiple function calls\", () => {\n    const input = `<p>{a() + b()}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"p\", textContent: computed(() => a() + b()) })`);\n  });\n\n  test(\"should compile text content with dot notation without computed\", () => {\n    const input = `<p>{user.name}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"p\", textContent: user.name })`);\n  });\n\n  test(\"should compile mixed text with signal without nested computed\", () => {\n    const input = `<p>Gold: {gold()}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe(`h(DOMElement, { element: \"p\", textContent: computed(() => 'Gold: ' + gold()) })`);\n  });\n\n  test(\"should compile mixed text and void element content\", () => {\n    const input = `<p>{gold()} <br> G</p>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"p\" }, [computed(() => gold()), h(DOMElement, { element: \"br\" }), ' G'])`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe(\"Loop\", () => {\n  test(\"loop in canvas\", () => {\n    const input = `\n        <Canvas>\n            @for (sprite of sprites) {\n                <Sprite />\n            }\n        </Canvas>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>h(Sprite)))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop\", () => {\n    const input = `\n        @for (sprite of sprites) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with object\", () => {\n    const input = `\n        @for (sprite of sprites.items) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with deep object\", () => {\n    const input = `\n        @for (sprite of sprites.items.items) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items.items,sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with function\", () => {\n    const input = `\n        @for (sprite of sprites()) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites(),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with function and params\", () => {\n    const input = `\n        @for (sprite of sprites(x, y)) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites(x,y),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with object and function and params\", () => {\n    const input = `\n        @for (sprite of sprites.items(x, y)) {\n            <Sprite />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites.items(x,y),sprite=>h(Sprite))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile loop with destructuring\", () => {\n    const input = `\n        @for ((sprite, index) of sprites) {\n            <Sprite key={index} />\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,(sprite,index)=>h(Sprite, { key: index }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile nestedloop\", () => {\n    const input = `\n        @for (sprite of sprites) {\n            @for (other of others) {\n                <Sprite />\n            }\n        }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(sprites,sprite=>loop(others,other=>h(Sprite)))`.replace(\n        /\\s+/g,\n        \"\"\n      )\n    );\n  });\n});\n\ndescribe(\"Condition\", () => {\n  test(\"should compile condition\", () => {\n    const input = `\n            @if (sprite) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite, () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition\", () => {\n    const input = `\n            @if (!sprite()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite()), () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition with multiple condition\", () => {\n    const input = `\n            @if (!sprite() && other()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite() && other()), () => h(Sprite))`);\n  });\n\n  test(\"should compile negative condition with multiple condition (or)\", () => {\n    const input = `\n            @if (!sprite() || other()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => !sprite() || other()), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with nested parentheses\", () => {\n    const input = `\n            @if ((a && b()) || c) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(computed(() => (a && b()) || c), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(sprite.visible, () => h(Sprite))`);\n  });\n\n  test(\"should compile condition when function value\", () => {\n    const input = `\n            @if (val()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(val(), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition with function call without computed\", () => {\n    const input = `\n            @if (isVisible()) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(`cond(isVisible(), () => h(Sprite))`);\n  });\n\n  test(\"should compile condition for multiple sprites\", () => {\n    const input = `\n            @if (sprite) {\n              <Sprite />\n            }\n            @if (other) {\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `[cond(sprite, () => h(Sprite)),cond(other, () => h(Sprite))]`\n    );\n  });\n\n  test(\"should compile nested condition when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n               @if (deep) {\n                    <Sprite />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => cond(deep, () => h(Sprite)))`\n    );\n  });\n\n  test(\"should compile condition with nested sprite when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n                @if (deep) {\n                    <Sprite />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => [h(Sprite), cond(deep, () => h(Sprite))])`\n    );\n  });\n\n  test(\"should compile condition with multiple sprites when sprite is visible\", () => {\n    const input = `\n            @if (sprite.visible) {\n                <Sprite />\n                @if (deep) {\n                    <Sprite />\n                }\n                <Sprite />\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `cond(sprite.visible, () => [h(Sprite), cond(deep, () => h(Sprite)), h(Sprite)])`\n    );\n  });\n\n  test(\"should compile if/else within canvas\", () => {\n    const input = `\n            <Canvas>\n                @if (showSprite) {\n                    <Sprite />\n                }\n                @else {\n                    <Text text=\"No sprite\" />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      `h(Canvas, null, cond(showSprite, () => h(Sprite), () => h(Text, { text: 'No sprite' })))`\n    );\n  });\n\n  test(\"should compile if/else if/else within loop\", () => {\n    const input = `\n            @for (item of items) {\n                @if (item().type() === 'sprite') {\n                    <Sprite />\n                }\n                @else if (item().type() === 'text') {\n                    <Text />\n                }\n                @else {\n                    <Container />\n                }\n            }\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(items,item=>cond(computed(()=>item().type()==='sprite'),()=>h(Sprite),[computed(()=>item().type()==='text'),()=>h(Text)],()=>h(Container)))`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe(\"Condition in Loops\", () => {\n  test(\"should compile condition within a loop\", () => { // New test for condition in a loop\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    @if (sprite.visible) {\n                        <Sprite />\n                    }\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>cond(sprite.visible,()=>h(Sprite))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile elements within a loop\", () => { // New test for elements in a loop\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    <Sprite />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,loop(sprites,sprite=>h(Sprite)))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test(\"should compile multiple loops at the same level\", () => { // New test for multiple loops\n    const input = `\n            <Canvas>\n                @for (sprite of sprites) {\n                    <Sprite />\n                }\n                @for (other of others) {\n                    <Sprite />\n                }\n            </Canvas>\n        `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(Canvas,null,[loop(sprites,sprite=>h(Sprite)),loop(others,other=>h(Sprite))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n});\n\ndescribe('Svg', () => {\n  test('should compile svg', () => {\n    const input = `<svg>\n      <path d=\"M 100 350 l 150 -300\" stroke=\"red\" stroke-width=\"4\"/>\n    </svg>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Svg, { content: `<svg><path d=\"M 100 350 l 150 -300\" stroke=\"red\" stroke-width=\"4\"/></svg>` })');\n  });\n\n  test('should compile svg with canvas', () => {\n    const input = `<Canvas antialias={true}>\n    <svg height=\"400\" width=\"450\" xmlns=\"http://www.w3.org/2000/svg\"></svg></Canvas>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Canvas, { antialias: true }, h(Svg, { content: `<svg height=\"400\" width=\"450\" xmlns=\"http://www.w3.org/2000/svg\"></svg>` }))');\n  });\n});\n\ndescribe('DOM', () => {\n  test('should compile input DOM', () => {\n    const input = `<input type=\"text\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"input\", attrs: { type: \\'text\\' } })');\n  });\n\n  test('should compile div DOM', () => {\n    const input = `<div class=\"container\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: \\'container\\' } })');\n  });\n\n  test('should merge static and dynamic class attributes', () => {\n    const input = `<div class=\"container\" class={className} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: [\\'container\\', className] } })');\n  });\n\n  test('should merge static and object class attributes', () => {\n    const input = `<div class=\"container\" class={{ active: true }} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: [\\'container\\', { active: true }] } })');\n  });\n\n  test('reactive class attributes', () => {\n    const input = `<div class={{ active: active() }} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: computed(() => ({ active: active() })) } })');\n  });\n\n  test('should compile button DOM', () => {\n    const input = `<button type=\"submit\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { type: \\'submit\\' } })');\n  });\n\n  test('should compile button DOM', () => {\n    const input = `<button>Text</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", textContent: \\'Text\\' })');\n  });\n\n  test('should compile textarea DOM with dynamic attributes', () => {\n    const input = `<textarea rows={rows} cols={cols} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"textarea\", attrs: { rows: rows, cols: cols } })');\n  });\n\n  test('should compile DOM with data-disabled expression', () => {\n    const input = `<button data-disabled={!skill || !skill.usable} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { \\'data-disabled\\': computed(() => !skill || !skill.usable) } })');\n  });\n\n  test('should compile DOM with conditional tabindex and click attributes', () => {\n    const input = `<button tabindex={skill ? index : -1} click={skill ? onSelectSkill(index) : undefined} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { tabindex: computed(() => skill ? index : -1), click: skill ? onSelectSkill(index) : undefined } })');\n  });\n\n  test('should not transform Canvas to DOM', () => {\n    const input = `<Canvas width={800} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Canvas, { width: 800 })');\n  });\n\n  test('should not transform Sprite to DOM', () => {\n    const input = `<Sprite image=\"test.png\" />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(Sprite, { image: \\'test.png\\' })');\n  });\n\n  test('should compile DOMContainer with class and style attributes', () => {\n    const input = `<DOMContainer class=\"panel\" style=\"color: red;\" x={10} />`;\n    const output = parser.parse(input);\n    expect(output).toBe(\n      'h(DOMContainer, { attrs: { class: \\'panel\\', style: \\'color: red;\\' }, x: 10 })'\n    );\n  });\n\n  // Tests avec imbrications DOM\n  test('should compile nested DOM elements', () => {\n    const input = `<div class=\"container\">\n      <p>Hello World</p>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"div\", attrs: { class: \\'container\\' } }, h(DOMElement, { element: \"p\", textContent: \\'Hello World\\' }))');\n  });\n\n  test('should compile deeply nested DOM elements', () => {\n    const input = `<div class=\"wrapper\">\n      <section>\n        <h1>Title</h1>\n        <p>Content</p>\n      </section>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'wrapper' } }, h(DOMElement, { element: \"section\" }, [h(DOMElement, { element: \"h1\", textContent: 'Title' }), h(DOMElement, { element: \"p\", textContent: 'Content' })]))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile DOM with multiple children', () => {\n    const input = `<ul>\n      <li>Item 1</li>\n      <li>Item 2</li>\n      <li>Item 3</li>\n    </ul>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"ul\" }, [h(DOMElement, { element: \"li\", textContent: 'Item 1' }), h(DOMElement, { element: \"li\", textContent: 'Item 2' }), h(DOMElement, { element: \"li\", textContent: 'Item 3' })])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile mixed DOM and framework components', () => {\n    const input = `<div class=\"game-container\">\n      <Canvas width={800} height={600} />\n      <div class=\"ui\">\n        <button>Start Game</button>\n      </div>\n    </div>`;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'game-container' } }, [h(Canvas, { width: 800, height: 600 }), h(DOMElement, { element: \"div\", attrs: { class: 'ui' } }, h(DOMElement, { element: \"button\", textContent: 'Start Game' }))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile DOM with attributes and text content', () => {\n    const input = `<button class=\"btn primary\" type=\"submit\">Submit Form</button>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"button\", attrs: { class: \\'btn primary\\', type: \\'submit\\' }, textContent: \\'Submit Form\\' })');\n  });\n});\n\ndescribe('DOM with special attributes', () => {\n  test('should compile DOM with special attributes', () => {\n    const input = `<input type=\"password\" x={100} y={100} />`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"input\", attrs: { type: \\'password\\' }, x: 100, y: 100 })');\n  });\n\n  test('should compile DOM with text object', () => {\n    const input = `<p>{{ object().x() }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: computed(() => object().x()) })');\n  });\n\n  test('should compile DOM with text object with method call', () => {\n    const input = `<p>{{ object.x() }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: computed(() => object.x()) })');\n  });\n\n  test('should compile DOM with text object with literal ', () => {\n    const input = `<p>{{ object.x }}</p>`;\n    const output = parser.parse(input);\n    expect(output).toBe('h(DOMElement, { element: \"p\", textContent: object.x })');\n  });\n});\n\ndescribe('DOM with Control Structures', () => {\n  test('should compile @for loop with DOM elements', () => {\n    const input = `\n      @for (item of items) {\n        <li>{item().name()}</li>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `loop(items, item => h(DOMElement, { element: \"li\", textContent: computed(() => item().name()) }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('Use literal text content', () => {\n    const input = `\n      <p>{text}</p>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"p\", textContent: text })`.replace(/\\s+/g, \"\")\n    );\n  })\n\n  test('should compile @for loop with nested DOM structure', () => {\n    const input = `\n      <ul class=\"menu\">\n        @for (item of menuItems) {\n          <li class=\"menu-item\">\n            <a href={item().url()}>{item().title()}</a>\n          </li>\n        }\n      </ul>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"ul\", attrs: { class: 'menu' } }, loop(menuItems, item => h(DOMElement, { element: \"li\", attrs: { class: 'menu-item' } }, h(DOMElement, { element: \"a\", attrs: { href: computed(() => item().url()) }, textContent: computed(() => item().title()) }))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if condition with DOM elements', () => {\n    const input = `\n      @if (showMessage) {\n        <div class=\"alert\">\n          <p>Important message!</p>\n        </div>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `cond(showMessage, () => h(DOMElement, { element: \"div\", attrs: { class: 'alert' } }, h(DOMElement, { element: \"p\", textContent: 'Important message!' })))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if condition with simple DOM element', () => {\n    const input = `\n      @if (isVisible) {\n        <button>Click me</button>\n      }\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `cond(isVisible, () => h(DOMElement, { element: \"button\", textContent: 'Click me' }))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile nested @for and @if with DOM', () => {\n    const input = `\n      <div class=\"container\">\n        @for (section of sections) {\n          @if (section.visible) {\n            <section class=\"content\">\n              <h2>{section().title()}</h2>\n              <div class=\"items\">\n                @for (item of section.items) {\n                  <div class=\"item\">{item().name()}</div>\n                }\n              </div>\n            </section>\n          }\n        }\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'container' } }, loop(sections, section => cond(section.visible, () => h(DOMElement, { element: \"section\", attrs: { class: 'content' } }, [h(DOMElement, { element: \"h2\", textContent: computed(() => section().title()) }), h(DOMElement, { element: \"div\", attrs: { class: 'items' } }, loop(section.items, item => h(DOMElement, { element: \"div\", attrs: { class: 'item' }, textContent: computed(() => item().name()) })))]))))`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @for with DOM table structure', () => {\n    const input = `\n      <table>\n        <thead>\n          <tr>\n            <th>Name</th>\n            <th>Age</th>\n          </tr>\n        </thead>\n        <tbody>\n          @for (user of users) {\n            <tr>\n              <td>{user().name()}</td>\n              <td>{user().age()}</td>\n            </tr>\n          }\n        </tbody>\n      </table>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"table\" }, [h(DOMElement, { element: \"thead\" }, h(DOMElement, { element: \"tr\" }, [h(DOMElement, { element: \"th\", textContent: 'Name' }), h(DOMElement, { element: \"th\", textContent: 'Age' })])), h(DOMElement, { element: \"tbody\" }, loop(users, user => h(DOMElement, { element: \"tr\" }, [h(DOMElement, { element: \"td\", textContent: computed(() => user().name()) }), h(DOMElement, { element: \"td\", textContent: computed(() => user().age()) })])))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile @if with multiple DOM conditions', () => {\n    const input = `\n      <div class=\"status\">\n        @if (isLoading) {\n          <div class=\"spinner\">Loading...</div>\n        }\n        @if (hasError) {\n          <div class=\"error\">Error occurred!</div>\n        }\n        @if (isSuccess) {\n          <div class=\"success\">Success!</div>\n        }\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'status' } }, [cond(isLoading, () => h(DOMElement, { element: \"div\", attrs: { class: 'spinner' }, textContent: 'Loading...' })), cond(hasError, () => h(DOMElement, { element: \"div\", attrs: { class: 'error' }, textContent: 'Error occurred!' })), cond(isSuccess, () => h(DOMElement, { element: \"div\", attrs: { class: 'success' }, textContent: 'Success!' }))])`.replace(/\\s+/g, \"\")\n    );\n  });\n\n  test('should compile mixed Canvas and DOM with control structures', () => {\n    const input = `\n      <div class=\"game-wrapper\">\n        <Canvas width={800} height={600}>\n          @for (sprite of sprites) {\n            <Sprite x={sprite().x()} y={sprite().y()} />\n          }\n        </Canvas>\n        <div class=\"ui-overlay\">\n          @if (showScore) {\n            <div class=\"score\">Score: {score()}</div>\n          }\n          @if (showMenu) {\n            <div class=\"menu\">\n              @for (option of menuOptions) {\n                <button class=\"menu-btn\">{option().label()}</button>\n              }\n            </div>\n          }\n        </div>\n      </div>\n    `;\n    const output = parser.parse(input);\n    expect(output.replace(/\\s+/g, \"\")).toBe(\n      `h(DOMElement, { element: \"div\", attrs: { class: 'game-wrapper' } }, [h(Canvas, { width: 800, height: 600 }, loop(sprites, sprite => h(Sprite, { x: computed(() => sprite().x()), y: computed(() => sprite().y()) }))), h(DOMElement, { element: \"div\", attrs: { class: 'ui-overlay' } }, [cond(showScore, () => h(DOMElement, { element: \"div\", attrs: { class: 'score' }, textContent: computed(() => 'Score: ' + score()) })), cond(showMenu, () => h(DOMElement, { element: \"div\", attrs: { class: 'menu' } }, loop(menuOptions, option => h(DOMElement, { element: \"button\", attrs: { class: 'menu-btn' }, textContent: computed(() => option().label()) }))))])])`.replace(/\\s+/g, \"\")\n    );\n  });\n});\n\ndescribe('Style scoping', () => {\n  test('should scope CSS selectors correctly', () => {\n    const css = `button {\n  color: red;\n}\ndiv {\n  padding: 10px;\n}`;\n\n    const scopeClass = 'abc12345';\n    const scoped = scopeCSS(css, scopeClass);\n\n    // Should prefix selectors with scope class\n    expect(scoped).toContain(`.${scopeClass} button`);\n    expect(scoped).toContain(`.${scopeClass} div`);\n    expect(scoped).toContain('color: red');\n    expect(scoped).toContain('padding: 10px');\n  });\n\n  test('should preserve @rules in scoped CSS', () => {\n    const css = `@media (max-width: 600px) {\n  button {\n    font-size: 14px;\n  }\n}\nbutton {\n  color: red;\n}`;\n\n    const scopeClass = 'abc12345';\n    const scoped = scopeCSS(css, scopeClass);\n\n    // @media should not be scoped\n    expect(scoped).toContain('@media');\n    // button inside @media should not be scoped\n    expect(scoped).toMatch(/@media[^{]*\\{[^}]*button[^}]*\\{/);\n    // Regular button should be scoped\n    expect(scoped).toContain(`.${scopeClass} button`);\n  });\n\n  test('should add _scopeClass to DOMContainer in parsed template', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toMatch(/h\\(DOMContainer,\\s*\\{\\s*_scopeClass:\\s*'abc12345'/);\n  });\n\n  test('should add _scopeClass to DOMContainer with existing props', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, { class: \"my-class\", x: 100 }))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toContain('class: \"my-class\"');\n    expect(result).toContain('x: 100');\n    // _scopeClass should be first in the props object\n    expect(result).toMatch(/\\{\\s*_scopeClass:\\s*'abc12345',\\s*class:/);\n  });\n\n  test('should add _scopeClass to DOMContainer with attrs object', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, { attrs: { class: \"container\" } }))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toContain('attrs: { class: \"container\" }');\n    expect(result).toMatch(/\\{\\s*_scopeClass:\\s*'abc12345',\\s*attrs:/);\n  });\n\n  test('should add _scopeClass to DOMContainer with null props', () => {\n    const parsedTemplate = 'h(Canvas, null, h(DOMContainer, null, h(Text)))';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    expect(result).toContain('_scopeClass');\n    expect(result).toMatch(/h\\(DOMContainer,\\s*\\{\\s*_scopeClass:\\s*'abc12345'\\s*\\},\\s*h\\(Text\\)/);\n  });\n\n  test('should handle multiple DOMContainer with same scope class', () => {\n    const parsedTemplate = 'h(Canvas, null, [h(DOMContainer), h(DOMContainer, { class: \"test\" })])';\n    const scopeClass = 'abc12345';\n    const result = addScopeClassToDOMContainer(parsedTemplate, scopeClass);\n\n    // Both should have _scopeClass\n    const matches = result.match(/_scopeClass/g);\n    expect(matches?.length).toBe(2);\n    // Both should have the same scope class value\n    expect(result.match(/_scopeClass:\\s*'abc12345'/g)?.length).toBe(2);\n  });\n\n  test('should generate 8-character hash with letters only', () => {\n    const hash1 = generateHash('/test/my-component.ce');\n    const hash2 = generateHash('/test/another-component.ce');\n\n    // Should be exactly 8 characters\n    expect(hash1.length).toBe(8);\n    expect(hash2.length).toBe(8);\n\n    // Should be letters only (lowercase a-z)\n    expect(hash1).toMatch(/^[a-z]{8}$/);\n    expect(hash2).toMatch(/^[a-z]{8}$/);\n\n    // Different files should produce different hashes (most of the time)\n    // Note: hash collisions are possible but unlikely for different paths\n    expect(hash1).not.toBe(hash2);\n  });\n\n  test('should generate consistent hash for same file', () => {\n    const filePath = '/test/my-component.ce';\n    const hash1 = generateHash(filePath);\n    const hash2 = generateHash(filePath);\n\n    // Same file should produce same hash\n    expect(hash1).toBe(hash2);\n  });\n\n  \n});\n"
  },
  {
    "path": "packages/compiler/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n      \"target\": \"ES2020\",\n      \"module\": \"ES2020\",\n      \"outDir\": \"./dist\",\n      \"rootDir\": \".\",\n      \"strict\": true,\n      \"sourceMap\": true,\n      \"strictNullChecks\": true,\n      \"strictPropertyInitialization\": false,\n      \"moduleResolution\": \"bundler\",\n      \"ignoreDeprecations\": \"6.0\",\n      \"esModuleInterop\": true,\n      \"removeComments\": false,\n      \"noUnusedParameters\": false,\n      \"noUnusedLocals\": false,\n      \"noImplicitThis\": false,\n      \"noImplicitAny\": false,\n      \"noImplicitReturns\": false,\n      \"declaration\": true,\n      \"experimentalDecorators\": true, \n      \"emitDecoratorMetadata\": true,\n      \"stripInternal\": true,\n      \"skipLibCheck\": true,\n      \"types\": [\"node\"]\n    },\n    \"include\": [\n        \".\"\n    ]\n  }\n"
  },
  {
    "path": "packages/compiler/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\nimport { copyFileSync } from 'fs'\nimport { join } from 'path'\n\nexport default  defineConfig({\n    format: ['esm'],\n    target: 'node20',\n    splitting: true,\n    clean: true,\n    shims: false,\n    dts: true,\n    sourcemap: true,\n    entry: ['index.ts'],\n    outDir: 'dist',\n    external: ['vite', 'acorn', 'peggy', 'typescript'],\n    onSuccess: async () => {\n        // Copy grammar.pegjs to dist directory\n        copyFileSync(\n            join(process.cwd(), 'grammar.pegjs'),\n            join(process.cwd(), 'dist', 'grammar.pegjs')\n        )\n        copyFileSync(\n            join(process.cwd(), 'grammar2.pegjs'),\n            join(process.cwd(), 'dist', 'grammar2.pegjs')\n        )\n    },\n})\n"
  },
  {
    "path": "packages/core/index.d.ts",
    "content": "declare module '*.ce' {\n    const content: import(\"./dist/index\").ComponentFunction;\n    export default content;\n}"
  },
  {
    "path": "packages/core/package.json",
    "content": "{\n  \"name\": \"canvasengine\",\n  \"version\": \"2.0.0-beta.58\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"dev\": \"vite build --watch\"\n  },\n  \"peerDependencies\": {\n    \"pixi.js\": \"^8.9.2\"\n  },\n  \"dependencies\": {\n    \"@barvynkoa/particle-emitter\": \"^0.0.1\",\n    \"@pixi/layout\": \"^3.2.0\",\n    \"@signe/reactive\": \"^2.9.0\",\n    \"howler\": \"^2.2.4\",\n    \"joypad.js\": \"^2.3.5\",\n    \"pixi-filters\": \"^6.1.5\",\n    \"pixi-viewport\": \"^6.0.3\",\n    \"popmotion\": \"^11.0.5\",\n    \"rxjs\": \"^7.8.2\",\n    \"yoga-layout\": \"^3.2.1\"\n  },\n  \"devDependencies\": {\n    \"@types/howler\": \"^2.2.12\",\n    \"vite\": \"^8.0.10\",\n    \"vite-plugin-dts\": \"^4.5.4\"\n  },\n  \"author\": \"Samuel Ronce\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://canvasengine.net\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/RSamaium/CanvasEngine.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/RSamaium/CanvasEngine/issues\"\n  },\n  \"keywords\": [\n    \"canvas\",\n    \"pixijs\",\n    \"reactive\",\n    \"html5\"\n  ],\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/core/src/components/Button.ts",
    "content": "import { effect, signal, computed, isSignal, Signal } from \"@signe/reactive\";\nimport { FederatedPointerEvent } from \"pixi.js\";\nimport { h } from \"../engine/signal\";\nimport { useDefineProps } from \"../hooks/useProps\";\nimport { Container } from \"./Container\";\nimport { Rect, Circle, Ellipse } from \"./Graphic\";\nimport { Text } from \"./Text\";\nimport { ControlsDirective } from \"../directives/Controls\";\nimport { JoystickControls } from \"../directives/JoystickControls\";\nimport { Element } from \"../engine/reactive\";\n\n/**\n * Button states for visual feedback\n */\nexport enum ButtonState {\n  Normal = \"normal\",\n  Hover = \"hover\",\n  Pressed = \"pressed\",\n  Disabled = \"disabled\"\n}\n\n/**\n * Button style configuration for different visual approaches\n */\nexport interface ButtonStyle {\n  /** Background color for each state */\n  backgroundColor?: {\n    [ButtonState.Normal]?: string;\n    [ButtonState.Hover]?: string;\n    [ButtonState.Pressed]?: string;\n    [ButtonState.Disabled]?: string;\n  };\n  /** Border configuration */\n  border?: {\n    color?: string;\n    width?: number;\n    radius?: number;\n  };\n  /** Text styling */\n  text?: {\n    color?: string;\n    fontSize?: number;\n    fontFamily?: string;\n  };\n  /** Sprite textures for each state (alternative to backgroundColor) */\n  textures?: {\n    [ButtonState.Normal]?: string;\n    [ButtonState.Hover]?: string;\n    [ButtonState.Pressed]?: string;\n    [ButtonState.Disabled]?: string;\n  };\n}\n\n/**\n * Properties for the Button component\n */\nexport interface ButtonProps {\n  /** Button text content */\n  text?: string;\n  /** Button disabled state */\n  disabled?: boolean;\n  /** Click event handler */\n  click?: (event: FederatedPointerEvent) => void;\n  /** Hover enter event handler */\n  hoverEnter?: (event: FederatedPointerEvent) => void;\n  /** Hover leave event handler */\n  hoverLeave?: (event: FederatedPointerEvent) => void;\n  /** Press down event handler */\n  pressDown?: (event: FederatedPointerEvent) => void;\n  /** Press up event handler */\n  pressUp?: (event: FederatedPointerEvent) => void;\n  /** Visual style configuration */\n  style?: ButtonStyle;\n  /** Button width */\n  width?: number;\n  /** Button height */\n  height?: number;\n  /** Button position X */\n  x?: number;\n  /** Button position Y */\n  y?: number;\n  /** Button alpha/opacity */\n  alpha?: number;\n  /** Button visibility */\n  visible?: boolean;\n  /** Button cursor */\n  cursor?: string;\n  /** Controls instance to automatically apply button events to (e.g., ControlsDirective or JoystickControls) */\n  controls?: ControlsDirective | JoystickControls | any;\n  /** Name of the control to trigger with applyControl when button is clicked */\n  controlName?: string;\n  /** Shape of the button background: 'rect', 'circle', or 'ellipse' */\n  shape?: 'rect' | 'circle' | 'ellipse';\n  /** Custom background component or element (replaces default background if provided) */\n  background?: Element | any;\n  /** Custom children components for button content (takes priority over text if provided) */\n  children?: Element[];\n  /** Focus index for the button */\n  tabindex?: number | Signal<number>;\n}\n\n/**\n * Creates a Button component with interactive states and customizable styling.\n * \n * This component provides a fully interactive button with visual feedback\n * for different states (normal, hover, pressed, disabled). It supports both\n * sprite-based and graphics-based rendering approaches.\n * \n * The button is built using a Container with background and text elements,\n * providing reactive state management and event handling.\n * \n * ## Features\n * \n * - **Controls Integration**: Automatically trigger controls via `applyControl` when clicked\n * - **Multiple Shapes**: Support for rect, circle, and ellipse shapes\n * - **Custom Content**: Use children components for custom button content\n * - **Custom Background**: Provide a custom background component\n * \n * @param props - Button configuration including text, styling, controls, shape, and event handlers\n * @returns A reactive Button component\n * @example\n * ```typescript\n * // Simple button with text and click handler\n * const simpleButton = Button({\n *   text: \"Click Me\",\n *   click: () => console.log(\"Button clicked!\"),\n *   width: 150,\n *   height: 50\n * });\n * \n * // Button with controls integration\n * const jumpButton = Button({\n *   text: \"Jump\",\n *   controls: controlsInstance,\n *   controlName: \"jump\",\n *   width: 120,\n *   height: 40\n * });\n * \n * // Circular button\n * const circleButton = Button({\n *   text: \"Action\",\n *   shape: \"circle\",\n *   width: 100,\n *   height: 100\n * });\n * \n * // Button with custom content (children)\n * const customButton = Button({\n *   shape: \"circle\",\n *   width: 80,\n *   height: 80,\n *   children: [\n *     h(Sprite, { image: \"icon.png\", width: 50, height: 50 })\n *   ]\n * });\n * \n * // Styled button with custom colors\n * const styledButton = Button({\n *   text: \"Styled Button\",\n *   style: {\n *     backgroundColor: {\n *       normal: \"#28a745\",\n *       hover: \"#218838\",\n *       pressed: \"#1e7e34\",\n *       disabled: \"#6c757d\"\n *     },\n *     border: {\n *       radius: 8,\n *       width: 2,\n *       color: \"#ffffff\"\n *     },\n *     text: {\n *       fontSize: 18,\n *       color: \"#ffffff\"\n *     }\n *   }\n * });\n * \n * // Sprite-based button\n * const spriteButton = Button({\n *   text: \"Play Game\",\n *   style: {\n *     textures: {\n *       normal: \"/assets/button-normal.png\",\n *       hover: \"/assets/button-hover.png\",\n *       pressed: \"/assets/button-pressed.png\"\n *     }\n *   }\n * });\n * ```\n */\nexport function Button(props: ButtonProps) {\n  // Internal state signals\n  const currentState = signal(ButtonState.Normal);\n  const isPressed = signal(false);\n  const isHovered = signal(false);\n\n  // Define reactive props with defaults\n  const defineProps = useDefineProps(props);\n  const { text, disabled, width, height, style, shape, controlName } = defineProps({\n    text: {\n      type: String,\n      default: \"\"\n    },\n    disabled: {\n      type: Boolean,\n      default: false\n    },\n    width: {\n      type: Number,\n      default: 120\n    },\n    height: {\n      type: Number,\n      default: 40\n    },\n    style: {\n      type: Object,\n      default: () => ({})\n    },\n    shape: {\n      type: String,\n      default: \"rect\"\n    },\n    controlName: {\n      type: String,\n      default: undefined\n    }\n  });\n\n  // Helper function to get controls instance (handles signals like Joystick)\n  const getControls = () => {\n    if (!props.controls) return null;\n    if (isSignal(props.controls)) {\n      return props.controls();\n    }\n    return props.controls;\n  };\n\n  // Update button state based on disabled and interaction states\n  effect(() => {\n    const isDisabled = disabled();\n    const pressed = isPressed();\n    const hovered = isHovered();\n\n    if (isDisabled) {\n      currentState.set(ButtonState.Disabled);\n    } else if (pressed) {\n      currentState.set(ButtonState.Pressed);\n    } else if (hovered) {\n      currentState.set(ButtonState.Hover);\n    } else {\n      currentState.set(ButtonState.Normal);\n    }\n  });\n\n  // Event handlers\n  const eventHandlers = {\n    pointerenter: (event: FederatedPointerEvent) => {\n      if (!disabled()) {\n        isHovered.set(true);\n        props.hoverEnter?.(event);\n      }\n    },\n    pointerleave: (event: FederatedPointerEvent) => {\n      isHovered.set(false);\n      isPressed.set(false);\n      props.hoverLeave?.(event);\n    },\n    pointerdown: async (event: FederatedPointerEvent) => {\n      if (!disabled()) {\n        isPressed.set(true);\n        props.pressDown?.(event);\n\n        // Apply control if controls and controlName are provided\n        const controls = getControls();\n        const name = controlName();\n        if (controls && name && controls.applyControl) {\n          await controls.applyControl(name, true);\n        }\n      }\n    },\n    pointerup: async (event: FederatedPointerEvent) => {\n      if (!disabled() && isPressed()) {\n        isPressed.set(false);\n        props.pressUp?.(event);\n\n        // Apply control release if controls and controlName are provided\n        const controls = getControls();\n        const name = controlName();\n        if (controls && name && controls.applyControl) {\n          await controls.applyControl(name, false);\n        }\n      }\n    },\n    pointertap: async (event: FederatedPointerEvent) => {\n      if (!disabled()) {\n        props.click?.(event);\n\n        // Apply control if controls and controlName are provided (press and release)\n        const controls = getControls();\n        const name = controlName();\n        if (controls && name && controls.applyControl) {\n          await controls.applyControl(name);\n        }\n      }\n    }\n  };\n\n  // Generate background element\n  const getBackgroundElement = () => {\n    // If custom background is provided, use it\n    if (props.background) {\n      return props.background;\n    }\n\n    // Otherwise, use shape-based background\n    const currentShape = shape();\n    const bgColor = computed(() => {\n      const currentStyle = style();\n      const backgroundColor = currentStyle.backgroundColor || {\n        [ButtonState.Normal]: \"#007bff\",\n        [ButtonState.Hover]: \"#0056b3\",\n        [ButtonState.Pressed]: \"#004085\",\n        [ButtonState.Disabled]: \"#6c757d\"\n      };\n      const state = currentState();\n      return backgroundColor[state] || backgroundColor[ButtonState.Normal];\n    });\n\n    if (currentShape === 'circle') {\n      // For circle, use the smaller dimension as radius\n      const radius = computed(() => Math.min(width(), height()) / 2);\n      return h(Circle, {\n        radius: radius,\n        x: computed(() => width() / 2),\n        y: computed(() => height() / 2),\n        color: bgColor\n      });\n    } else if (currentShape === 'ellipse') {\n      return h(Ellipse, {\n        width: width,\n        height: height,\n        color: bgColor\n      });\n    } else {\n      // Default: rect\n      return h(Rect, {\n        width: width,\n        height: height,\n        color: bgColor\n      });\n    }\n  };\n\n  // Generate content element(s)\n  const getContentElements = () => {\n    // If children are provided, use them (priority over text)\n    if (props.children && props.children.length > 0) {\n      return props.children;\n    }\n\n    // Otherwise, use text\n    return [\n      h(Text, {\n        text: text,\n        x: computed(() => width() / 2),\n        y: computed(() => height() / 2),\n        anchor: { x: 0.5, y: 0.5 },\n        style: computed(() => {\n          const currentStyle = style();\n          const textStyle = currentStyle.text || {};\n          return {\n            fontSize: textStyle.fontSize || 16,\n            fontFamily: textStyle.fontFamily || \"Arial\",\n            fill: textStyle.color || \"#ffffff\"\n          };\n        })()\n      })\n    ];\n  };\n\n  // Return Container with h() children\n  return h(Container, {\n    x: props.x,\n    y: props.y,\n    width: props.width,\n    height: props.height,\n    alpha: props.alpha,\n    visible: props.visible,\n    cursor: props.cursor || \"pointer\",\n    tabindex: props.tabindex,\n    ...eventHandlers\n  }, [\n    getBackgroundElement(),\n    ...getContentElements()\n  ]);\n}\n"
  },
  {
    "path": "packages/core/src/components/Canvas.ts",
    "content": "import { effect, Signal, signal } from \"@signe/reactive\";\nimport { Application, Container } from \"pixi.js\";\nimport {\n  Props,\n  createComponent,\n  registerComponent,\n  Element,\n} from \"../engine/reactive\";\nimport { useProps } from \"../hooks/useProps\";\nimport { ComponentInstance, DisplayObject } from \"./DisplayObject\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { SignalOrPrimitive } from \"./types\";\nimport { Size } from \"./types/DisplayObject\";\nimport { Scheduler, Tick } from \"../directives/Scheduler\";\nimport { GlobalAssetLoader } from \"../utils/GlobalAssetLoader\";\n\ninterface CanvasElement extends Element<ComponentInstance> {\n  render: (rootElement: HTMLElement, app?: Application) => void;\n  directives: {\n    tick: Scheduler;\n  };\n  propObservables: {\n    tick: Signal<Tick>;\n  };\n}\n\nregisterComponent(\"Canvas\", class Canvas extends DisplayObject(Container) { });\n\nexport interface CanvasProps extends Props {\n  cursorStyles?: () => any;\n  width?: SignalOrPrimitive<Size>;\n  height?: SignalOrPrimitive<Size>;\n  canvasEl?: HTMLElement;\n  selector?: string;\n  isRoot?: boolean;\n  tick?: any;\n  class?: SignalOrPrimitive<string>;\n  background?: string;\n}\n\nexport const Canvas: ComponentFunction<CanvasProps> = async (props = {}) => {\n  let { cursorStyles, width, height, class: className } = useProps(props);\n\n  if (!props.width) width = signal<Size>(800);\n  if (!props.height) height = signal<Size>(600);\n\n  const canvasSize = signal({\n    width: 0,\n    height: 0,\n  });\n\n  props.isRoot = true;\n  const globalLoader = new GlobalAssetLoader();\n  const options: CanvasProps = {\n    ...props,\n    context: {\n      canvasSize,\n      app: signal(null),\n      globalLoader,\n    },\n    width: width?.(),\n    height: height?.(),\n  };\n\n  if (!props.tick) {\n    options.context!.tick = options.tick = signal({\n      timestamp: 0,\n      deltaTime: 0,\n      frame: 0,\n      deltaRatio: 1,\n    });\n  } else {\n    options.context!.tick = props.tick;\n  }\n\n  // Register the tick signal globally so animatedSignal can use it by default\n  (globalThis as any).__CANVAS_ENGINE_TICK__ = options.context!.tick;\n\n  const canvasElement = createComponent(\"Canvas\", options) as CanvasElement;\n\n  canvasElement.render = (rootElement: HTMLElement, app?: Application) => {\n    if (!app) {\n      return;\n    }\n\n    const renderer = app.renderer;\n    const canvasEl = renderer.view.canvas as HTMLCanvasElement;\n\n    (globalThis as any).__PIXI_STAGE__ = canvasElement.componentInstance;\n    (globalThis as any).__PIXI_RENDERER__ = renderer;\n\n    if (props.tickStart !== false) canvasElement.directives.tick.start()\n\n    effect(() => {\n      canvasElement.propObservables!.tick();\n      renderer.render(canvasElement.componentInstance as any);\n    });\n\n    app.stage = canvasElement.componentInstance as any;\n\n    app.stage.layout = {\n      width: app.screen.width,\n      height: app.screen.height,\n      justifyContent: props.justifyContent,\n      alignItems: props.alignItems,\n    };\n\n    canvasSize.set({ width: app.screen.width, height: app.screen.height })\n\n    app.renderer.on('resize', (width: number, height: number) => {\n      canvasSize.set({ width, height });\n\n      if (app.stage.layout) {\n        app.stage.layout = {\n          width,\n          height\n        }\n      }\n    });\n\n    if (props.tickStart !== false) canvasElement.directives.tick.start();\n\n    app.ticker.add(() => {\n      canvasElement.propObservables!.tick();\n    });\n\n    if (cursorStyles) {\n      effect(() => {\n        renderer.events.cursorStyles = cursorStyles();\n      });\n    }\n\n    if (className) {\n      effect(() => {\n        canvasEl.classList.add(className());\n      });\n    }\n\n    const existingCanvas = rootElement.querySelector(\"canvas\");\n    if (existingCanvas) {\n      rootElement.replaceChild(canvasEl, existingCanvas);\n    } else {\n      rootElement.appendChild(canvasEl);\n    }\n\n    options.context!.app.set(app)\n  };\n\n  return canvasElement;\n};\n"
  },
  {
    "path": "packages/core/src/components/Container.ts",
    "content": "import { Container as PixiContainer } from \"pixi.js\";\nimport { createComponent, registerComponent } from \"../engine/reactive\";\nimport { DisplayObject } from \"./DisplayObject\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { setObservablePoint } from \"../engine/utils\";\nimport { isPercent } from \"../utils/functions\";\n\ninterface ContainerProps extends DisplayObjectProps {\n  sortableChildren?: boolean;\n}\n\nexport class CanvasContainer extends DisplayObject(PixiContainer) {\n  isCustomAnchor = true;\n  \n  onUpdate(props) {\n    if (props.anchor) {\n      setObservablePoint(this._anchorPoints, props.anchor);\n      props.pivot = [\n        this.getWidth() * this._anchorPoints.x,\n        this.getHeight() * this._anchorPoints.y\n      ]\n    }\n    super.onUpdate(props);\n    if (props.sortableChildren != undefined) {\n      this.sortableChildren = props.sortableChildren;\n    }\n  }\n  async onMount(args) {\n    await super.onMount(args);\n    const { componentInstance, props } = args;\n    const { pixiChildren } = props;\n    if (pixiChildren) {\n      pixiChildren.forEach((child) => {\n        componentInstance.addChild(child);\n      });\n    }\n\n    // Listen to layout events to update displayWidth and displayHeight with computed values\n    const isWidthPercentage = isPercent(props.width);\n    const isHeightPercentage = isPercent(props.height);\n\n    if (isWidthPercentage || isHeightPercentage) {\n      this.on('layout', (event) => {\n        const layoutBox = event.computedLayout;\n        if (isWidthPercentage && layoutBox.width !== undefined) {\n          this.displayWidth.set(layoutBox.width);\n        }\n        if (isHeightPercentage && layoutBox.height !== undefined) {\n          this.displayHeight.set(layoutBox.height);\n        }\n      });\n    }\n  }\n}\n\nexport interface CanvasContainer extends DisplayObjectProps {}\n\nregisterComponent(\"Container\", CanvasContainer);\n\nexport const Container: ComponentFunction<ContainerProps> = (props) => {\n  // Ensure component is registered (useful in tests if module cache differs)\n  registerComponent(\"Container\", CanvasContainer);\n  return createComponent(\"Container\", props);\n};\n"
  },
  {
    "path": "packages/core/src/components/DOMContainer.ts",
    "content": "import { DOMContainer as PixiDOMContainer } from \"pixi.js\";\nimport { effect } from \"@signe/reactive\";\nimport {\n  createComponent,\n  Element,\n  isElement,\n  registerComponent,\n} from \"../engine/reactive\";\nimport { ComponentInstance, DisplayObject } from \"./DisplayObject\";\nimport { ComponentFunction, h } from \"../engine/signal\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { CanvasDOMElement, DOMElement } from \"./DOMElement\";\nimport { isPercent } from \"../utils/functions\";\n\n\n/**\n * DOMContainer class for managing DOM elements within the canvas engine\n *\n * This class extends the DisplayObject functionality to handle DOM elements using\n * PixiJS's native DOMContainer. It provides a bridge between the canvas rendering\n * system and traditional DOM manipulation with proper transform hierarchy and visibility.\n *\n * The DOMContainer is especially useful for rendering standard DOM elements that handle\n * user input, such as `<input>` or `<textarea>`. This is often simpler and more flexible\n * than trying to implement text input directly in PixiJS.\n *\n * @example\n * ```typescript\n * // Basic usage with input element\n * const element = document.createElement('input');\n * element.type = 'text';\n * element.placeholder = 'Enter text...';\n *\n * const domContainer = new DOMContainer({\n *   element,\n *   x: 100,\n *   y: 50,\n *   anchor: { x: 0.5, y: 0.5 }\n * });\n *\n * // Using different class and style formats\n * const containerWithClasses = new DOMContainer({\n *   element: 'div',\n *   attrs: {\n *     // String format: space-separated classes\n *     class: 'container primary-theme',\n *\n *     // Array format: array of class names\n *     // class: ['container', 'primary-theme'],\n *\n *     // Object format: conditional classes\n *     // class: {\n *     //   'container': true,\n *     //   'primary-theme': true,\n *     //   'disabled': false\n *     // }\n *\n *     // String format: CSS style string\n *     style: 'background-color: red; padding: 10px;',\n *\n *     // Object format: style properties\n *     // style: {\n *     //   backgroundColor: 'red',\n *     //   padding: '10px',\n *     //   fontSize: 16\n *     // }\n *   }\n * });\n * ```\n */\nconst EVENTS = [\n  \"click\",\n  \"mouseover\",\n  \"mouseout\",\n  \"mouseenter\",\n  \"mouseleave\",\n  \"mousemove\",\n  \"mouseup\",\n  \"mousedown\",\n  \"touchstart\",\n  \"touchend\",\n  \"touchmove\",\n  \"touchcancel\",\n  \"wheel\",\n  \"scroll\",\n  \"resize\",\n  \"focus\",\n  \"blur\",\n  \"change\",\n  \"input\",\n  \"submit\",\n  \"reset\",\n  \"keydown\",\n  \"keyup\",\n  \"keypress\",\n  \"contextmenu\",\n  \"drag\",\n  \"dragend\",\n  \"dragenter\",\n  \"dragleave\",\n  \"dragover\",\n  \"drop\",\n  \"dragstart\",\n  \"select\",\n  \"selectstart\",\n  \"selectend\",\n  \"selectall\",\n  \"selectnone\",\n];\n\nexport class CanvasDOMContainer extends DisplayObject(PixiDOMContainer) {\n  disableLayout = true;\n  private canvasSizeEffect: any = null;\n  private static readonly DOM_ROUTING_MAP: Record<string, string> = {\n    Sprite: \"DOMSprite\",\n  };\n  private static readonly DOM_ALLOWED_TAGS = new Set([\n    \"DOMContainer\",\n    \"DOMElement\",\n    \"DOMSprite\",\n  ]);\n  private static readonly DOM_UNSUPPORTED_TAGS = new Set([\n    \"Canvas\",\n    \"Container\",\n    \"Graphics\",\n    \"Rect\",\n    \"Circle\",\n    \"Ellipse\",\n    \"Triangle\",\n    \"Svg\",\n    \"Mesh\",\n    \"Scene\",\n    \"ParticlesEmitter\",\n    \"Sprite\",\n    \"Video\",\n    \"Text\",\n    \"TilingSprite\",\n    \"Viewport\",\n    \"NineSliceSprite\",\n    \"Button\",\n    \"Joystick\",\n    \"FocusContainer\",\n  ]);\n\n  private hasDomContainerAncestor(): boolean {\n    const element = this.getElement();\n    let parent = element?.parent;\n    while (parent) {\n      if (parent.tag === \"DOMContainer\") return true;\n      parent = parent.parent;\n    }\n    return false;\n  }\n\n  private getPercentRatio(value: string): number | null {\n    const parsed = parseFloat(value);\n    if (Number.isNaN(parsed)) return null;\n    return parsed / 100;\n  }\n\n  private getCanvasSize() {\n    const canvasSize = this.fullProps?.context?.canvasSize;\n    return typeof canvasSize === \"function\" ? canvasSize() : canvasSize;\n  }\n\n  private shouldUseCanvasPercent(): boolean {\n    const widthProp = this.fullProps?.width;\n    const heightProp = this.fullProps?.height;\n    if (!isPercent(widthProp) && !isPercent(heightProp)) return false;\n    return !this.hasDomContainerAncestor();\n  }\n\n  private syncCanvasSizeEffect() {\n    const shouldTrack = this.shouldUseCanvasPercent();\n    if (shouldTrack && !this.canvasSizeEffect) {\n      const canvasSize = this.fullProps?.context?.canvasSize;\n      if (typeof canvasSize === \"function\") {\n        this.canvasSizeEffect = effect(() => {\n          canvasSize();\n          this.applyElementSize();\n        });\n      }\n    } else if (!shouldTrack && this.canvasSizeEffect) {\n      this.canvasSizeEffect.subscription?.unsubscribe();\n      this.canvasSizeEffect = null;\n    }\n  }\n\n  private applyElementSize() {\n    if (!this.element) return;\n    const widthProp = this.fullProps?.width;\n    const heightProp = this.fullProps?.height;\n    const useCanvasSize = this.shouldUseCanvasPercent();\n    const canvasSize = useCanvasSize ? this.getCanvasSize() : null;\n\n    if (widthProp !== undefined) {\n      if (isPercent(widthProp)) {\n        if (useCanvasSize) {\n          const ratio = this.getPercentRatio(widthProp);\n          if (ratio !== null) {\n            const baseWidth = (canvasSize?.width !== undefined)\n              ? canvasSize.width\n              : this.getWidth();\n            this.element.style.width = `${baseWidth * ratio}px`;\n          }\n        } else {\n          this.element.style.width = widthProp;\n        }\n      } else if (typeof widthProp === \"number\") {\n        this.element.style.width = `${widthProp}px`;\n      } else if (typeof widthProp === \"string\") {\n        this.element.style.width = widthProp;\n      }\n    }\n\n    if (heightProp !== undefined) {\n      if (isPercent(heightProp)) {\n        if (useCanvasSize) {\n          const ratio = this.getPercentRatio(heightProp);\n          if (ratio !== null) {\n            const baseHeight = (canvasSize?.height !== undefined)\n              ? canvasSize.height\n              : this.getHeight();\n            this.element.style.height = `${baseHeight * ratio}px`;\n          }\n        } else {\n          this.element.style.height = heightProp;\n        }\n      } else if (typeof heightProp === \"number\") {\n        this.element.style.height = `${heightProp}px`;\n      } else if (typeof heightProp === \"string\") {\n        this.element.style.height = heightProp;\n      }\n    }\n  }\n\n  private routeDomChildren(children: any): any {\n    if (!children) return children;\n    if (Array.isArray(children)) {\n      return children.map((child) => this.routeDomChildren(child));\n    }\n    if (isElement(children)) {\n      if (CanvasDOMContainer.DOM_ALLOWED_TAGS.has(children.tag)) {\n        return children;\n      }\n      const routedTag = CanvasDOMContainer.DOM_ROUTING_MAP[children.tag];\n      if (routedTag) {\n        children.propSubscriptions?.forEach((sub) => sub.unsubscribe());\n        children.effectSubscriptions?.forEach((sub) => sub.unsubscribe());\n        children.effectUnmounts?.forEach((fn) => fn?.());\n        const routedProps = children.propObservables ?? children.props;\n        return createComponent(routedTag, routedProps);\n      }\n      if (CanvasDOMContainer.DOM_UNSUPPORTED_TAGS.has(children.tag)) {\n        throw new Error(\n          `Component ${children.tag} is not implemented for DOMContainer context yet. Only Sprite is supported.`\n        );\n      }\n      if (children.props?.children) {\n        children.props.children = this.routeDomChildren(children.props.children);\n      }\n      return children;\n    }\n    return children;\n  }\n\n  onInit(props: any) {\n    // Handle internal _scopeClass prop for scoped CSS\n    const scopeClass = props._scopeClass;\n    let divProps: any = { element: \"div\" };\n    const divAttrs = { ...(props.attrs || {}) };\n\n    const mergeScopeClass = (classValue: any) => {\n      if (!scopeClass) return classValue;\n      if (classValue == null) return scopeClass;\n      if (typeof classValue === \"string\") {\n        return `${scopeClass} ${classValue}`;\n      }\n      if (Array.isArray(classValue)) {\n        return [scopeClass, ...classValue];\n      }\n      if (typeof classValue === \"object\") {\n        if (\"items\" in classValue) {\n          const itemsValue = (classValue as any).items;\n          return { ...classValue, items: [scopeClass, itemsValue] };\n        }\n        if (\"value\" in classValue) {\n          const valueValue = (classValue as any).value;\n          return { ...classValue, value: [scopeClass, valueValue] };\n        }\n        return { [scopeClass]: true, ...classValue };\n      }\n      return [scopeClass, classValue];\n    };\n\n    if (props.class !== undefined) {\n      if (divAttrs.class) {\n        divAttrs.class = [props.class, divAttrs.class];\n      } else {\n        divAttrs.class = props.class;\n      }\n    }\n\n    if (props.style !== undefined) {\n      if (\n        typeof divAttrs.style === \"object\"\n        && divAttrs.style !== null\n        && typeof props.style === \"object\"\n        && props.style !== null\n      ) {\n        divAttrs.style = { ...divAttrs.style, ...props.style };\n      } else if (divAttrs.style === undefined) {\n        divAttrs.style = props.style;\n      } else if (typeof divAttrs.style === \"string\" && typeof props.style === \"string\") {\n        divAttrs.style = `${divAttrs.style}; ${props.style}`;\n      } else {\n        divAttrs.style = props.style;\n      }\n    }\n\n    if (props.zIndex !== undefined) {\n      if (typeof divAttrs.style === \"object\" && divAttrs.style !== null) {\n        divAttrs.style = { ...divAttrs.style, zIndex: props.zIndex };\n      } else if (typeof divAttrs.style === \"string\") {\n        divAttrs.style = `${divAttrs.style}; z-index: ${props.zIndex}`;\n      } else {\n        divAttrs.style = { zIndex: props.zIndex };\n      }\n    }\n\n    if (scopeClass) {\n      // Merge scope class with existing attrs.class\n      divProps.attrs = { ...divAttrs };\n      divProps.attrs.class = mergeScopeClass(divProps.attrs.class);\n    } else if (Object.keys(divAttrs).length > 0) {\n      divProps.attrs = divAttrs;\n    }\n\n    const routedChildren = this.routeDomChildren(props.children);\n    props.children = routedChildren;\n    const div = h(DOMElement, divProps, routedChildren) as unknown as Element<CanvasDOMElement>;\n    this.element = div.componentInstance.element;\n  }\n\n  async onMount(element: Element<any>, index?: number) {\n    await super.onMount(element, index);\n    this.syncCanvasSizeEffect();\n    this.applyElementSize();\n  }\n\n  onUpdate(props: any) {\n    super.onUpdate(props);\n    this.syncCanvasSizeEffect();\n    this.applyElementSize();\n  }\n\n  onLayoutComputed() {\n    this.applyElementSize();\n  }\n\n  async onDestroy(parent: Element<any>, afterDestroy?: () => void) {\n    const _afterDestroy = () => {\n      if (this.canvasSizeEffect) {\n        this.canvasSizeEffect.subscription?.unsubscribe();\n        this.canvasSizeEffect = null;\n      }\n      if (afterDestroy) afterDestroy();\n    };\n    await super.onDestroy(parent, _afterDestroy);\n  }\n}\n\nexport interface CanvasDOMContainer extends DisplayObjectProps { }\n\nregisterComponent(\"DOMContainer\", CanvasDOMContainer);\n\nexport const DOMContainer: ComponentFunction<any> = (props) => {\n  return createComponent(\"DOMContainer\", props);\n};\n"
  },
  {
    "path": "packages/core/src/components/DOMElement.ts",
    "content": "import { DOMContainer as PixiDOMContainer } from \"pixi.js\";\nimport {\n  createComponent,\n  Element,\n  registerComponent,\n} from \"../engine/reactive\";\nimport { ComponentInstance, DisplayObject, OnHook } from \"./DisplayObject\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { isObservable } from \"../engine/utils\";\nimport { isSignal } from \"@signe/reactive\";\n\nexport interface DOMElementProps extends DisplayObjectProps {\n  element?:\n  | string\n  | {\n    value: HTMLElement;\n  };\n  textContent?: string;\n  attrs?: Record<string, any> & {\n    class?:\n    | string\n    | string[]\n    | Record<string, boolean>\n    | { items?: string[] }\n    | { value?: string | string[] | Record<string, boolean> };\n    style?:\n    | string\n    | Record<string, string | number>\n    | { value?: string | Record<string, string | number> };\n  };\n  onBeforeDestroy?: OnHook;\n}\n\nexport interface DOMContainerProps extends DOMElementProps {\n  element:\n  | string\n  | {\n    value: HTMLElement;\n  };\n}\n\n/**\n * DOMContainer class for managing DOM elements within the canvas engine\n *\n * This class extends the DisplayObject functionality to handle DOM elements using\n * PixiJS's native DOMContainer. It provides a bridge between the canvas rendering\n * system and traditional DOM manipulation with proper transform hierarchy and visibility.\n *\n * The DOMContainer is especially useful for rendering standard DOM elements that handle\n * user input, such as `<input>` or `<textarea>`. This is often simpler and more flexible\n * than trying to implement text input directly in PixiJS.\n *\n * ## Form Elements with Reactive Signals\n *\n * For form elements (`input`, `textarea`, `select`), the component supports reactive\n * two-way data binding using signals. When the `value` attribute is a signal, the\n * component automatically:\n * - Sets the initial value from the signal\n * - Listens for `input` events and updates the signal with the new value\n * - Updates the DOM element when the signal value changes programmatically\n *\n * ## Form Submission Handling\n *\n * When a `form` element has a `submit` event handler, the component automatically:\n * - Prevents the default form submission behavior (stops propagation)\n * - Collects all form data from input elements within the form\n * - Passes both the event and the collected form data as parameters to the submit handler\n * - Handles multiple values for the same field name (e.g., checkboxes with same name)\n *\n * @example\n * ```typescript\n * import { signal } from '@signe/reactive';\n *\n * // Basic usage with input element\n * const element = document.createElement('input');\n * element.type = 'text';\n * element.placeholder = 'Enter text...';\n *\n * const domContainer = new DOMContainer({\n *   element,\n *   x: 100,\n *   y: 50,\n *   anchor: { x: 0.5, y: 0.5 }\n * });\n *\n * // Reactive form input with signal\n * const inputValue = signal('');\n *\n * const reactiveInput = new DOMContainer({\n *   element: 'input',\n *   attrs: {\n *     type: 'text',\n *     placeholder: 'Type something...',\n *     value: inputValue // Signal for two-way binding\n *   }\n * });\n *\n * // The signal will automatically update when user types\n * inputValue.subscribe(value => {\n *   console.log('Input value changed:', value);\n * });\n *\n * // You can also update the input programmatically\n * inputValue.set('New value');\n *\n * // Form submission with automatic data collection\n * const loginForm = new DOMContainer({\n *   element: 'form',\n *   attrs: {\n *     submit: (event, formData) => {\n *       // event: the submit event (already prevented)\n *       // formData: object containing all form field values\n *       console.log('Form submitted with data:', formData);\n *       // Example formData: { username: 'john', password: 'secret', remember: 'on' }\n *     }\n *   },\n *   children: [\n *     new DOMContainer({\n *       element: 'input',\n *       attrs: { name: 'username', type: 'text', placeholder: 'Username' }\n *     }),\n *     new DOMContainer({\n *       element: 'input',\n *       attrs: { name: 'password', type: 'password', placeholder: 'Password' }\n *     }),\n *     new DOMContainer({\n *       element: 'input',\n *       attrs: { name: 'remember', type: 'checkbox', value: 'on' }\n *     }),\n *     new DOMContainer({\n *       element: 'button',\n *       attrs: { type: 'submit' },\n *       textContent: 'Login'\n *     })\n *   ]\n * });\n *\n * // Using different class and style formats\n * const containerWithClasses = new DOMContainer({\n *   element: 'div',\n *   attrs: {\n *     // String format: space-separated classes\n *     class: 'container primary-theme',\n *\n *     // Array format: array of class names\n *     // class: ['container', 'primary-theme'],\n *\n *     // Object format: conditional classes\n *     // class: {\n *     //   'container': true,\n *     //   'primary-theme': true,\n *     //   'disabled': false\n *     // }\n *\n *     // String format: CSS style string\n *     style: 'background-color: red; padding: 10px;',\n *\n *     // Object format: style properties\n *     // style: {\n *     //   backgroundColor: 'red',\n *     //   padding: '10px',\n *     //   fontSize: 16\n *     // }\n *   }\n * });\n * ```\n */\nconst EVENTS = [\n  \"click\",\n  \"mouseover\",\n  \"mouseout\",\n  \"mouseenter\",\n  \"mouseleave\",\n  \"mousemove\",\n  \"mouseup\",\n  \"mousedown\",\n  \"touchstart\",\n  \"touchend\",\n  \"touchmove\",\n  \"touchcancel\",\n  \"wheel\",\n  \"scroll\",\n  \"resize\",\n  \"focus\",\n  \"blur\",\n  \"change\",\n  \"input\",\n  \"submit\",\n  \"reset\",\n  \"keydown\",\n  \"keyup\",\n  \"keypress\",\n  \"contextmenu\",\n  \"drag\",\n  \"dragend\",\n  \"dragenter\",\n  \"dragleave\",\n  \"dragover\",\n  \"drop\",\n  \"dragstart\",\n  \"select\",\n  \"selectstart\",\n  \"selectend\",\n  \"selectall\",\n  \"selectnone\",\n];\n\nexport class CanvasDOMElement {\n  public element: HTMLElement;\n  private eventListeners: Map<string, (e: Event) => void> = new Map();\n  private onBeforeDestroy: OnHook | null = null;\n  private valueSignal: any = null;\n  private isFormElementType: boolean = false;\n  private classSubscriptions: Array<{ unsubscribe: () => void }> = [];\n  private childTextSubscriptions: Array<{ unsubscribe: () => void }> = [];\n\n  /**\n   * Checks if the element is a form element that supports the value attribute\n   * @param elementType - The element type string from props\n   * @returns true if the element is a form element with value support\n   */\n  private isFormElement(elementType: string): boolean {\n    const formElements = [\"input\", \"textarea\", \"select\"];\n    return formElements.includes(elementType.toLowerCase());\n  }\n\n  private collectClassTokens(value: any, tokens: string[]) {\n    if (!value) return;\n    if (isSignal(value)) {\n      this.collectClassTokens(value(), tokens);\n      return;\n    }\n    if (typeof value === \"string\") {\n      value.split(/\\s+/).filter(Boolean).forEach((token) => tokens.push(token));\n      return;\n    }\n    if (Array.isArray(value)) {\n      value.forEach((item) => this.collectClassTokens(item, tokens));\n      return;\n    }\n    if (typeof value === \"object\") {\n      for (const [className, shouldAdd] of Object.entries(value)) {\n        const resolved = isSignal(shouldAdd as any) ? (shouldAdd as any)() : shouldAdd;\n        if (resolved) {\n          tokens.push(className);\n        }\n      }\n    }\n  }\n\n  private collectClassSignals(value: any, signals: Set<any>) {\n    if (!value) return;\n    if (isSignal(value)) {\n      signals.add(value);\n      return;\n    }\n    if (Array.isArray(value)) {\n      value.forEach((item) => this.collectClassSignals(item, signals));\n      return;\n    }\n    if (typeof value === \"object\") {\n      Object.values(value).forEach((item) =>\n        this.collectClassSignals(item, signals)\n      );\n    }\n  }\n\n  private applyClassList(classList: any) {\n    // Clear existing classes first\n    this.element.className = \"\";\n\n    if (typeof classList === \"string\") {\n      // String: space-separated class names\n      this.element.className = classList;\n      return;\n    }\n\n    const tokens: string[] = [];\n    this.collectClassTokens(classList, tokens);\n    if (tokens.length > 0) {\n      this.element.classList.add(...tokens);\n    }\n  }\n\n  private syncClassSubscriptions(classList: any) {\n    for (const sub of this.classSubscriptions) {\n      sub.unsubscribe();\n    }\n    this.classSubscriptions = [];\n\n    const signals = new Set<any>();\n    this.collectClassSignals(classList, signals);\n    if (signals.size === 0) return;\n\n    signals.forEach((signal) => {\n      if (!signal?.observable?.subscribe) return;\n      const sub = signal.observable.subscribe(() => {\n        this.applyClassList(classList);\n      });\n      this.classSubscriptions.push(sub);\n    });\n  }\n\n  private appendChildElement(child: any) {\n    if (child === null || child === undefined || child === false) return;\n\n    if (typeof child === \"string\" || typeof child === \"number\") {\n      this.element.appendChild(document.createTextNode(String(child)));\n      return;\n    }\n\n    if (isSignal(child)) {\n      const textNode = document.createTextNode(\n        child() == null ? \"\" : String(child())\n      );\n      this.element.appendChild(textNode);\n      if (child.observable?.subscribe) {\n        const sub = child.observable.subscribe((value: any) => {\n          textNode.textContent = value == null ? \"\" : String(value);\n        });\n        this.childTextSubscriptions.push(sub);\n      }\n      return;\n    }\n\n    if (isObservable(child)) {\n      child.subscribe((value: any) => {\n        if (value && typeof value === \"object\" && \"elements\" in value) {\n          const elements = value.elements || [];\n          elements.forEach((element: any) => this.appendChildElement(element));\n        } else if (Array.isArray(value)) {\n          value.forEach((element) => this.appendChildElement(element));\n        } else {\n          this.appendChildElement(value);\n        }\n      });\n      return;\n    }\n\n    if (Array.isArray(child)) {\n      child.forEach((item) => this.appendChildElement(item));\n      return;\n    }\n\n    const childElement = child?.componentInstance?.element;\n    if (childElement) {\n      this.element.appendChild(childElement);\n      return;\n    }\n\n    const nestedChildren = child?.props?.children;\n    if (nestedChildren) {\n      this.appendChildElement(nestedChildren);\n    }\n  }\n\n  onInit(props: DOMElementProps) {\n    if (typeof props.element === \"string\") {\n      this.element = document.createElement(props.element);\n      this.isFormElementType = this.isFormElement(props.element);\n    } else {\n      this.element = props.element?.value;\n      if (!this.element) {\n        throw new Error(\"DOMElement requires a valid element.\");\n      }\n      this.isFormElementType = this.isFormElement(this.element.tagName);\n    }\n    if (props.onBeforeDestroy || props[\"on-before-destroy\"]) {\n      this.onBeforeDestroy =\n        props.onBeforeDestroy || props[\"on-before-destroy\"];\n    }\n\n    for (const event of EVENTS) {\n      if (props.attrs?.[event]) {\n        const eventHandler = (e: Event) => {\n          // Special handling for form submit events\n          if (event === \"submit\" && this.element.tagName.toLowerCase() === \"form\") {\n            e.preventDefault(); // Stop form submission propagation\n\n            // Collect all form data\n            const formData = new FormData(this.element as HTMLFormElement);\n            const formObject: Record<string, any> = {};\n\n            // Convert FormData to plain object\n            formData.forEach((value, key) => {\n              if (formObject[key]) {\n                // Handle multiple values for same key (like checkboxes)\n                if (Array.isArray(formObject[key])) {\n                  formObject[key].push(value);\n                } else {\n                  formObject[key] = [formObject[key], value];\n                }\n              } else {\n                formObject[key] = value;\n              }\n            });\n\n            // Call the event handler with event and form data\n            props.attrs[event]?.(e, formObject);\n          } else {\n            props.attrs[event]?.(e);\n          }\n        };\n        this.eventListeners.set(event, eventHandler);\n        this.element.addEventListener(event, eventHandler, false);\n      }\n    }\n    if (props.children) {\n      this.appendChildElement(props.children);\n    }\n    this.onUpdate(props);\n  }\n\n  onMount(context: Element<CanvasDOMElement>) {\n    const props = context.propObservables;\n    const attrs = props.attrs as any;\n    // Handle form elements with signal value\n    if (\n      this.isFormElementType &&\n      attrs?.value &&\n      isSignal(attrs.value)\n    ) {\n      this.valueSignal = attrs.value;\n      // Set initial value from signal\n      (\n        this.element as\n        | HTMLInputElement\n        | HTMLTextAreaElement\n        | HTMLSelectElement\n      ).value = this.valueSignal();\n\n      // Listen for input events and update the signal\n      const inputHandler = (e: Event) => {\n        const target = e.target as\n          | HTMLInputElement\n          | HTMLTextAreaElement\n          | HTMLSelectElement;\n        this.valueSignal.set(target.value);\n      };\n\n      this.eventListeners.set(\"input\", inputHandler);\n      this.element.addEventListener(\"input\", inputHandler, false);\n    }\n  }\n\n  onUpdate(props: DOMElementProps) {\n    if (!this.element) return;\n    for (const [key, value] of Object.entries(props.attrs || {})) {\n      if (key === \"tabindex\") {\n        // Handle tabindex attribute\n        const tabindexValue = isSignal(value) ? value() : value;\n        if (tabindexValue !== undefined && tabindexValue !== null) {\n          this.element.setAttribute('tabindex', String(tabindexValue));\n        } else {\n          this.element.removeAttribute('tabindex');\n        }\n      } else if (key === \"class\") {\n        const rawClassList = value.items || value.value || value;\n        const classList = isSignal(rawClassList) ? rawClassList() : rawClassList;\n        this.applyClassList(classList);\n        this.syncClassSubscriptions(classList);\n      } else if (key === \"style\") {\n        const styleValue = value.items || value.value || value;\n\n        if (typeof styleValue === \"string\") {\n          // String: CSS style string\n          this.element.setAttribute(\"style\", styleValue);\n        } else if (typeof styleValue === \"object\" && styleValue !== null) {\n          // Object: { property: value }\n          for (const [styleProp, styleVal] of Object.entries(styleValue)) {\n            if (styleVal !== null && styleVal !== undefined) {\n              (this.element.style as any)[styleProp] = styleVal;\n            }\n          }\n        }\n      } else if (key === \"value\" && this.isFormElementType) {\n        // Handle value attribute for form elements\n        if (isSignal(value)) {\n          // If it's a signal, the value is already handled in onInit\n          // Update the DOM element value if the signal value changed\n          const currentValue = (\n            this.element as\n            | HTMLInputElement\n            | HTMLTextAreaElement\n            | HTMLSelectElement\n          ).value;\n          const signalValue = value();\n          if (currentValue !== signalValue) {\n            (\n              this.element as\n              | HTMLInputElement\n              | HTMLTextAreaElement\n              | HTMLSelectElement\n            ).value = signalValue;\n          }\n        } else {\n          // If it's not a signal, set the value directly\n          (\n            this.element as\n            | HTMLInputElement\n            | HTMLTextAreaElement\n            | HTMLSelectElement\n          ).value = value;\n        }\n      } else if (!EVENTS.includes(key)) {\n        this.element.setAttribute(key, value);\n      }\n    }\n    if (\"textContent\" in props) {\n      const textContent = props.textContent;\n      this.element.textContent = textContent == null ? \"\" : String(textContent);\n    }\n  }\n\n  async onDestroy(\n    parent: Element<CanvasDOMElement>,\n    afterDestroy: () => void\n  ): Promise<void> {\n    // Remove all event listeners from the DOM element\n\n    if (this.element) {\n      if (this.onBeforeDestroy) {\n        await this.onBeforeDestroy();\n      }\n\n      for (const [event, handler] of this.eventListeners) {\n        this.element.removeEventListener(event, handler, false);\n      }\n\n      this.eventListeners.clear();\n      for (const sub of this.classSubscriptions) {\n        sub.unsubscribe();\n      }\n      this.classSubscriptions = [];\n      for (const sub of this.childTextSubscriptions) {\n        sub.unsubscribe();\n      }\n      this.childTextSubscriptions = [];\n\n      this.element.remove();\n\n      if (afterDestroy) {\n        afterDestroy();\n      }\n    }\n  }\n}\n\nexport interface CanvasDOMElement extends DisplayObjectProps { }\n\nregisterComponent(\"DOMElement\", CanvasDOMElement);\n\nexport const DOMElement: ComponentFunction<DOMContainerProps> = (props) => {\n  return createComponent(\"DOMElement\", props);\n};\n"
  },
  {
    "path": "packages/core/src/components/DOMSprite.ts",
    "content": "import { isSignal, Signal } from \"@signe/reactive\";\nimport { Subscription } from \"rxjs\";\nimport { createComponent, Element, registerComponent } from \"../engine/reactive\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { arrayEquals, fps2ms, isBrowser, isFunction, preciseNow } from \"../engine/utils\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { CanvasDOMElement, DOMElementProps } from \"./DOMElement\";\nimport { OnHook } from \"./DisplayObject\";\nimport { Tick } from \"../directives/Scheduler\";\nimport {\n  AnimationFrames,\n  FrameOptions,\n  SpritesheetOptions,\n  TextureOptions,\n} from \"./types/Spritesheet\";\n\nexport interface DOMSpriteFrame {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n}\n\nexport interface DOMSpriteProps extends DOMElementProps {\n  image?: string;\n  rectangle?: DOMSpriteFrame | { value?: DOMSpriteFrame };\n  frames?: DOMSpriteFrame[];\n  frameIndex?: number;\n  fps?: number;\n  playing?: boolean;\n  loop?: boolean;\n  sheet?: {\n    definition?:\n    | DOMSpriteSheetDefinition\n    | { value?: DOMSpriteSheetDefinition }\n    | Signal<DOMSpriteSheetDefinition | undefined>\n    | Promise<DOMSpriteSheetDefinition>;\n    playing?: string;\n    params?: any;\n    onFinish?: () => void;\n  };\n  element?: \"div\" | \"img\";\n  class?: any;\n  style?: any;\n  attrs?: Record<string, any> & {\n    class?:\n    | string\n    | string[]\n    | Record<string, boolean>\n    | { items?: string[] }\n    | { value?: string | string[] | Record<string, boolean> };\n    style?:\n    | string\n    | Record<string, string | number>\n    | { value?: string | Record<string, string | number> };\n  };\n  onBeforeDestroy?: OnHook;\n  context?: {\n    tick?: Signal<Tick | null>;\n  };\n}\n\nconst EVENTS = [\n  \"click\",\n  \"mouseover\",\n  \"mouseout\",\n  \"mouseenter\",\n  \"mouseleave\",\n  \"mousemove\",\n  \"mouseup\",\n  \"mousedown\",\n  \"touchstart\",\n  \"touchend\",\n  \"touchmove\",\n  \"touchcancel\",\n  \"wheel\",\n  \"scroll\",\n  \"resize\",\n  \"focus\",\n  \"blur\",\n  \"change\",\n  \"input\",\n  \"submit\",\n  \"reset\",\n  \"keydown\",\n  \"keyup\",\n  \"keypress\",\n  \"contextmenu\",\n  \"drag\",\n  \"dragend\",\n  \"dragenter\",\n  \"dragleave\",\n  \"dragover\",\n  \"drop\",\n  \"dragstart\",\n  \"select\",\n  \"selectstart\",\n  \"selectend\",\n  \"selectall\",\n  \"selectnone\",\n];\n\ntype DOMSpriteTextureOptionsMerging = TextureOptions & {\n  spriteWidth: number;\n  spriteHeight: number;\n  image?: string;\n};\n\ntype DOMSpriteFrameOptions = FrameOptions & DOMSpriteFrame;\n\ntype DOMSpriteAnimationData = {\n  frames: DOMSpriteFrameOptions[];\n  animations: AnimationFrames;\n  params: any[];\n  data: DOMSpriteTextureOptionsMerging;\n  name: string;\n};\n\ntype DOMSpriteSheetDefinition = SpritesheetOptions & {\n  image?: string;\n};\n\nexport class CanvasDOMSprite extends CanvasDOMElement {\n  private frameIndex = 0;\n  private frames: DOMSpriteFrame[] = [];\n  private rectangle?: DOMSpriteFrame;\n  private image?: string;\n  private fps = 120;\n  private loop = true;\n  private playing = true;\n  private hasExternalFrameIndex = false;\n  private elapsed = 0;\n  private tickSignal?: Signal<Tick | null>;\n  private tickSubscription?: Subscription;\n  private sheetSubscriptions: Subscription[] = [];\n  private sheetDefinition?: DOMSpriteSheetDefinition;\n  private sheetAnimations: Map<string, DOMSpriteAnimationData> = new Map();\n  private sheetCurrentAnimation?: DOMSpriteAnimationData;\n  private sheetCurrentName?: string;\n  private sheetParams: any = {};\n  private sheetTime = 0;\n  private sheetFrameIndex = 0;\n  private sheetFinished = false;\n  private sheetLoadToken = 0;\n  private sheetOnFinish?: () => void;\n  private rafId?: number;\n  private lastRafTimestamp?: number;\n  private lastTickTimestamp?: number;\n  private renderElementType: \"div\" | \"img\" = \"div\";\n  private wrapperElementType: \"div\" | \"img\" = \"div\";\n  private isAnimating = false;\n  private playingSubscription?: Subscription;\n  private playingSignal?: Signal<boolean>;\n  private explicitWidth?: string;\n  private explicitHeight?: string;\n  private frameWidth = 0;\n  private frameHeight = 0;\n  private fitMode?: string;\n  private renderElement?: HTMLElement;\n  private isContained = false;\n\n  onInit(props: DOMElementProps) {\n    const spriteProps = props as DOMSpriteProps;\n    const hasSheet = spriteProps.sheet !== undefined;\n    const defaultElement: \"div\" | \"img\" = !hasSheet && spriteProps.image ? \"img\" : \"div\";\n    this.renderElementType = spriteProps.element ?? defaultElement;\n    const resolvedFit = this.resolveValue(spriteProps.objectFit);\n    this.fitMode = resolvedFit ?? undefined;\n    this.wrapperElementType =\n      this.fitMode === \"contain\" && this.renderElementType === \"img\"\n        ? \"div\"\n        : this.renderElementType;\n    const nextProps = this.mergeEventAttrs({ ...spriteProps, element: this.wrapperElementType });\n    this.tickSignal = nextProps.context?.tick;\n    this.applyProps(nextProps);\n    super.onInit(nextProps as any);\n    this.syncRenderElement();\n    this.applyDisplayProps(nextProps);\n    this.render();\n    this.updateAnimationLoop();\n  }\n\n  onMount(context: Element<CanvasDOMElement>) {\n    this.tickSignal = context.props.context?.tick;\n    super.onMount(context);\n    this.bindPlayingSignal(context);\n    this.bindSheetParams(context);\n    this.updateAnimationLoop();\n  }\n\n  onUpdate(props: DOMElementProps) {\n    const nextProps = this.mergeEventAttrs(props as DOMSpriteProps);\n    super.onUpdate(nextProps as any);\n    this.applyProps(nextProps);\n    this.syncRenderElement();\n    this.applyDisplayProps(nextProps);\n    this.render();\n    this.updateAnimationLoop();\n  }\n\n  async onDestroy(\n    parent: Element<CanvasDOMElement>,\n    afterDestroy: () => void\n  ): Promise<void> {\n    if (this.playingSubscription) {\n      this.playingSubscription.unsubscribe();\n      this.playingSubscription = undefined;\n    }\n    if (this.sheetSubscriptions.length > 0) {\n      this.sheetSubscriptions.forEach((sub) => sub.unsubscribe());\n      this.sheetSubscriptions = [];\n    }\n    this.stopAnimationLoop();\n    await super.onDestroy(parent, afterDestroy);\n  }\n\n  private resolveRectangle(\n    rectangle?: DOMSpriteFrame | { value?: DOMSpriteFrame } | Signal<DOMSpriteFrame | undefined>\n  ): DOMSpriteFrame | undefined {\n    if (!rectangle) return undefined;\n    const signalResolved = isSignal(rectangle as any)\n      ? (rectangle as Signal<DOMSpriteFrame | undefined>)()\n      : rectangle;\n    if (!signalResolved) return undefined;\n    const resolved = (signalResolved as any).value ?? signalResolved;\n    if (!resolved) return undefined;\n    return resolved as DOMSpriteFrame;\n  }\n\n  private resolveSheetDefinition(\n    definition?:\n      | DOMSpriteSheetDefinition\n      | { value?: DOMSpriteSheetDefinition }\n      | Signal<DOMSpriteSheetDefinition | undefined>\n      | Promise<DOMSpriteSheetDefinition>\n  ): DOMSpriteSheetDefinition | Promise<DOMSpriteSheetDefinition | undefined> | undefined {\n    if (!definition) return undefined;\n    const signalResolved = isSignal(definition as any)\n      ? (definition as Signal<DOMSpriteSheetDefinition | undefined>)()\n      : definition;\n    if (!signalResolved) return undefined;\n    return (signalResolved as any).value ?? signalResolved;\n  }\n\n  private async detectImageDimensions(\n    imagePath: string\n  ): Promise<{ width: number; height: number }> {\n    if (!isBrowser() || !imagePath) {\n      return { width: 0, height: 0 };\n    }\n    return new Promise((resolve, reject) => {\n      const img = new Image();\n      img.onload = () => resolve({ width: img.naturalWidth, height: img.naturalHeight });\n      img.onerror = () => reject(new Error(`Failed to load image: ${imagePath}`));\n      img.src = imagePath;\n    });\n  }\n\n  private async createSheetAnimations(definition: DOMSpriteSheetDefinition) {\n    this.sheetAnimations.clear();\n    const { textures } = definition;\n    if (!textures) return;\n\n    const parentProps: (keyof TextureOptions)[] = [\n      \"width\",\n      \"height\",\n      \"framesHeight\",\n      \"framesWidth\",\n      \"rectWidth\",\n      \"rectHeight\",\n      \"offset\",\n    ];\n\n    for (const animationName in textures) {\n      const baseOptions = parentProps.reduce(\n        (prev, val) => ({ ...prev, [val]: (definition as any)[val] }),\n        {}\n      );\n      const optionsTextures: DOMSpriteTextureOptionsMerging = {\n        ...baseOptions,\n        ...textures[animationName],\n        spriteWidth: 0,\n        spriteHeight: 0,\n      };\n      optionsTextures.image =\n        (textures[animationName] as any).image ?? definition.image;\n\n      const {\n        rectWidth,\n        rectHeight,\n        framesWidth = 1,\n        framesHeight = 1,\n        image,\n      } = optionsTextures;\n\n      let width = optionsTextures.width || 0;\n      let height = optionsTextures.height || 0;\n\n      if (image && ((!width || width <= 0) || (!height || height <= 0))) {\n        const dimensions = await this.detectImageDimensions(image);\n        if (!width || width <= 0) {\n          width = dimensions.width;\n        }\n        if (!height || height <= 0) {\n          height = dimensions.height;\n        }\n      }\n\n      if (!width || !height || !framesWidth || !framesHeight) {\n        continue;\n      }\n\n      optionsTextures.width = width;\n      optionsTextures.height = height;\n      optionsTextures.spriteWidth = rectWidth ? rectWidth : width / framesWidth;\n      optionsTextures.spriteHeight = rectHeight ? rectHeight : height / framesHeight;\n\n      this.sheetAnimations.set(animationName, {\n        frames: [],\n        name: animationName,\n        animations: textures[animationName].animations,\n        params: [],\n        data: optionsTextures,\n      });\n    }\n  }\n\n  private async setSheetDefinition(\n    definition?: DOMSpriteSheetDefinition | Promise<DOMSpriteSheetDefinition>\n  ) {\n    const token = ++this.sheetLoadToken;\n    if (!definition) {\n      this.sheetDefinition = undefined;\n      this.sheetAnimations.clear();\n      this.sheetCurrentAnimation = undefined;\n      this.sheetCurrentName = undefined;\n      return;\n    }\n\n    const resolved = await definition;\n    if (token !== this.sheetLoadToken) return;\n    if (!resolved) {\n      this.sheetDefinition = undefined;\n      this.sheetAnimations.clear();\n      this.sheetCurrentAnimation = undefined;\n      this.sheetCurrentName = undefined;\n      return;\n    }\n    this.sheetDefinition = resolved;\n    if (resolved.image) {\n      this.image = resolved.image;\n    }\n\n    await this.createSheetAnimations(resolved);\n\n    const textureKeys = resolved.textures ? Object.keys(resolved.textures) : [];\n    const fallbackName =\n      this.sheetCurrentName ||\n      (textureKeys.includes(\"stand\") ? \"stand\" : textureKeys[0]) ||\n      undefined;\n    if (fallbackName) {\n      this.playSheet(fallbackName, [this.sheetParams]);\n    }\n    this.render();\n    this.updateAnimationLoop();\n  }\n\n  private playSheet(name: string, params: any[] = []) {\n    const animParams = this.sheetCurrentAnimation?.params;\n    if (this.sheetCurrentAnimation && this.sheetCurrentAnimation.name === name) {\n      if (arrayEquals(params, animParams || [])) return;\n    }\n\n    const animation = this.sheetAnimations.get(name);\n    if (!animation) {\n      throw new Error(\n        `Impossible to play the ${name} animation because it doesn't exist on the spritesheet`\n      );\n    }\n\n    const cloneParams = structuredClone(params);\n    let animations: any = animation.animations;\n    animations = isFunction(animations) ? (animations as Function)(...cloneParams) : animations;\n\n    animation.frames = [];\n    animation.params = cloneParams;\n    this.sheetCurrentAnimation = animation;\n    this.sheetCurrentName = name;\n    this.sheetTime = 0;\n    this.sheetFrameIndex = 0;\n    this.sheetFinished = false;\n\n    const data = animation.data;\n    const spriteWidth = data.spriteWidth;\n    const spriteHeight = data.spriteHeight;\n    const offsetX = data.offset?.x ?? 0;\n    const offsetY = data.offset?.y ?? 0;\n\n    for (const container of animations as FrameOptions[][]) {\n      for (const frame of container) {\n        const frameX = frame.frameX ?? 0;\n        const frameY = frame.frameY ?? 0;\n        animation.frames.push({\n          ...frame,\n          x: frameX * spriteWidth + offsetX,\n          y: frameY * spriteHeight + offsetY,\n          width: spriteWidth,\n          height: spriteHeight,\n        });\n      }\n    }\n\n    this.render();\n    this.updateAnimationLoop();\n  }\n\n  private getCurrentSheetFrame(): DOMSpriteFrame | null {\n    if (!this.sheetCurrentAnimation || this.sheetCurrentAnimation.frames.length === 0) {\n      return null;\n    }\n    return this.sheetCurrentAnimation.frames[this.sheetFrameIndex] ?? null;\n  }\n\n  private advanceSheet(tick: Tick) {\n    if (!this.playing || !this.sheetCurrentAnimation) return;\n\n    const frames = this.sheetCurrentAnimation.frames;\n    if (frames.length <= 1) return;\n\n    const baseFps = this.fps > 0 ? this.fps : 60;\n    let deltaRatio = 0;\n    if (tick.deltaTime) {\n      deltaRatio = tick.deltaTime / fps2ms(baseFps);\n    } else if (typeof tick.deltaRatio === \"number\") {\n      deltaRatio = tick.deltaRatio * (baseFps / 60);\n    }\n\n    const nextFrame = frames[this.sheetFrameIndex + 1];\n    if (!nextFrame) {\n      if (this.loop) {\n        this.sheetTime = 0;\n        this.sheetFrameIndex = 0;\n        this.applyFrame(frames[0]);\n        return;\n      } else if (!this.sheetFinished) {\n        this.sheetFinished = true;\n        if (this.sheetOnFinish) this.sheetOnFinish();\n      }\n      this.applyFrame(frames[frames.length - 1]);\n      return;\n    }\n\n    this.sheetTime += deltaRatio || 0;\n    if (this.sheetTime >= nextFrame.time) {\n      this.sheetFrameIndex += 1;\n    }\n    this.applyFrame(frames[this.sheetFrameIndex]);\n  }\n\n  private mergeEventAttrs(props: DOMSpriteProps): DOMSpriteProps {\n    let merged = props.attrs ? { ...props.attrs } : undefined;\n    for (const event of EVENTS) {\n      const handler = (props as any)[event];\n      if (handler && !merged?.[event]) {\n        if (!merged) merged = {};\n        merged[event] = handler;\n      }\n    }\n    if (props.class !== undefined) {\n      if (!merged) merged = {};\n      if (merged.class) {\n        merged.class = [props.class, merged.class];\n      } else {\n        merged.class = props.class;\n      }\n    }\n    if (props.style !== undefined) {\n      if (!merged) merged = {};\n      if (\n        typeof merged.style === \"object\"\n        && merged.style !== null\n        && typeof props.style === \"object\"\n        && props.style !== null\n      ) {\n        merged.style = { ...merged.style, ...props.style };\n      } else if (merged.style === undefined) {\n        merged.style = props.style;\n      } else if (typeof merged.style === \"string\" && typeof props.style === \"string\") {\n        merged.style = `${merged.style}; ${props.style}`;\n      } else {\n        merged.style = props.style;\n      }\n    }\n    if (!merged) return props;\n    return { ...props, attrs: merged };\n  }\n\n  private applyProps(props: DOMSpriteProps) {\n    if (props.image !== undefined) {\n      this.image = isSignal(props.image as any) ? (props.image as any)() : props.image;\n    }\n    if (props.rectangle !== undefined) {\n      this.rectangle = this.resolveRectangle(props.rectangle);\n    }\n    if (props.frames !== undefined) {\n      const resolvedFrames = isSignal(props.frames as any)\n        ? (props.frames as any)()\n        : props.frames;\n      this.frames = resolvedFrames ?? [];\n    }\n    if (props.sheet !== undefined) {\n      const resolvedSheet = isSignal(props.sheet as any)\n        ? (props.sheet as any)()\n        : props.sheet;\n      if (resolvedSheet?.definition !== undefined) {\n        const resolvedDefinition = this.resolveSheetDefinition(resolvedSheet.definition);\n        if (resolvedDefinition instanceof Promise) {\n          void this.setSheetDefinition(resolvedDefinition);\n        } else if (resolvedDefinition && resolvedDefinition !== this.sheetDefinition) {\n          void this.setSheetDefinition(resolvedDefinition);\n        }\n      }\n      if (resolvedSheet?.params !== undefined) {\n        this.sheetParams = { ...this.sheetParams, ...resolvedSheet.params };\n      }\n      if (resolvedSheet?.playing !== undefined) {\n        this.sheetCurrentName = resolvedSheet.playing;\n      }\n      if (resolvedSheet?.onFinish !== undefined) {\n        this.sheetOnFinish = resolvedSheet.onFinish;\n      }\n      if (this.sheetAnimations.size > 0 && this.sheetCurrentName) {\n        this.playSheet(this.sheetCurrentName, [this.sheetParams]);\n      }\n    }\n    if (props.frameIndex !== undefined) {\n      const isFrameIndexSignal = isSignal(props.frameIndex as any);\n      const resolvedIndex = isFrameIndexSignal\n        ? (props.frameIndex as any)()\n        : props.frameIndex;\n      if (resolvedIndex !== undefined) {\n        this.frameIndex = resolvedIndex;\n      }\n      this.hasExternalFrameIndex = isFrameIndexSignal;\n    }\n    if (props.fps !== undefined) {\n      const resolvedFps = isSignal(props.fps as any) ? (props.fps as any)() : props.fps;\n      if (resolvedFps !== undefined) {\n        this.fps = resolvedFps;\n      }\n    }\n    if (props.playing !== undefined) {\n      const resolvedPlaying = isSignal(props.playing as any)\n        ? (props.playing as any)()\n        : props.playing;\n      this.playing = resolvedPlaying === true;\n      if (!this.playing) {\n        this.elapsed = 0;\n      }\n    }\n    if (props.loop !== undefined) {\n      const resolvedLoop = isSignal(props.loop as any) ? (props.loop as any)() : props.loop;\n      if (resolvedLoop !== undefined) {\n        this.loop = resolvedLoop;\n      }\n    }\n    if (props.objectFit !== undefined) {\n      const resolvedFit = this.resolveValue(props.objectFit);\n      this.fitMode = resolvedFit ?? undefined;\n    }\n  }\n\n  private resolveValue<T>(value: T | Signal<T> | { value?: T } | undefined): T | undefined {\n    if (value === undefined) return undefined;\n    const resolved = isSignal(value as any) ? (value as any)() : value;\n    if (resolved && typeof resolved === \"object\" && \"value\" in (resolved as any)) {\n      return (resolved as any).value as T;\n    }\n    return resolved as T;\n  }\n\n  private resolvePoint(\n    value: DOMSpriteProps[\"scale\"] | DOMSpriteProps[\"anchor\"] | DOMSpriteProps[\"skew\"] | DOMSpriteProps[\"pivot\"]\n  ): { x: number; y: number } | undefined {\n    const resolved = this.resolveValue<any>(value as any);\n    if (resolved === undefined || resolved === null) return undefined;\n    if (typeof resolved === \"number\") {\n      return { x: resolved, y: resolved };\n    }\n    if (Array.isArray(resolved)) {\n      const [x, y] = resolved;\n      return { x: x ?? 0, y: y ?? x ?? 0 };\n    }\n    if (typeof resolved === \"object\") {\n      return { x: resolved.x ?? 0, y: resolved.y ?? 0 };\n    }\n    return undefined;\n  }\n\n  private resolveSize(value: DOMSpriteProps[\"width\"] | DOMSpriteProps[\"height\"]): string | undefined {\n    const resolved = this.resolveValue<any>(value as any);\n    if (resolved === undefined || resolved === null) return undefined;\n    if (typeof resolved === \"number\") return `${resolved}px`;\n    if (typeof resolved === \"string\") return resolved;\n    return undefined;\n  }\n\n  private resolvePixelSize(value?: string): number | undefined {\n    if (!value) return undefined;\n    if (value.endsWith(\"px\")) {\n      const parsed = parseFloat(value);\n      return Number.isNaN(parsed) ? undefined : parsed;\n    }\n    if (/^\\d+(\\.\\d+)?$/.test(value)) {\n      const parsed = parseFloat(value);\n      return Number.isNaN(parsed) ? undefined : parsed;\n    }\n    return undefined;\n  }\n\n  private toCssColor(tint: number): string {\n    const clamped = Math.max(0, Math.min(0xffffff, tint));\n    return `#${clamped.toString(16).padStart(6, \"0\")}`;\n  }\n\n  private applyDisplayProps(props: DOMSpriteProps) {\n    if (!this.element) return;\n\n    if (props.width !== undefined) {\n      this.explicitWidth = this.resolveSize(props.width);\n    } else {\n      this.explicitWidth = undefined;\n    }\n    if (props.height !== undefined) {\n      this.explicitHeight = this.resolveSize(props.height);\n    } else {\n      this.explicitHeight = undefined;\n    }\n    if (this.explicitWidth !== undefined) {\n      this.element.style.width = this.explicitWidth;\n    }\n    if (this.explicitHeight !== undefined) {\n      this.element.style.height = this.explicitHeight;\n    }\n\n    if (props.alpha !== undefined) {\n      const alpha = this.resolveValue(props.alpha);\n      if (alpha !== undefined) {\n        this.element.style.opacity = String(alpha);\n      }\n    }\n\n    if (props.visible !== undefined) {\n      const visible = this.resolveValue(props.visible);\n      this.element.style.display = visible === false ? \"none\" : \"\";\n    }\n\n    if (props.zIndex !== undefined) {\n      const zIndex = this.resolveValue(props.zIndex);\n      if (zIndex !== undefined) {\n        this.element.style.zIndex = String(zIndex);\n      }\n    }\n\n    if (props.cursor !== undefined) {\n      const cursor = this.resolveValue(props.cursor);\n      if (cursor !== undefined) {\n        this.element.style.cursor = String(cursor);\n      }\n    }\n\n    if (props.tint !== undefined) {\n      const tint = this.resolveValue(props.tint);\n      if (typeof tint === \"number\") {\n        this.element.style.filter = `drop-shadow(0 0 0 ${this.toCssColor(tint)})`;\n      }\n    }\n\n    const hasTransformProps = [\n      props.x,\n      props.y,\n      props.scale,\n      props.rotation,\n      props.angle,\n      props.skew,\n      props.roundPixels,\n    ].some((value) => value !== undefined);\n\n    if (hasTransformProps) {\n      let x = this.resolveValue(props.x) ?? 0;\n      let y = this.resolveValue(props.y) ?? 0;\n      const roundPixels = this.resolveValue(props.roundPixels);\n      if (roundPixels) {\n        x = Math.round(x);\n        y = Math.round(y);\n      }\n\n      const scale = this.resolvePoint(props.scale) ?? { x: 1, y: 1 };\n      const skew = this.resolvePoint(props.skew);\n\n      const angle = this.resolveValue(props.angle);\n      const rotation = this.resolveValue(props.rotation);\n      const rotationDeg = angle !== undefined\n        ? angle\n        : rotation !== undefined\n          ? (rotation * 180) / Math.PI\n          : 0;\n\n      const transformParts = [\n        `translate3d(${x}px, ${y}px, 0)`,\n      ];\n\n      if (rotationDeg !== 0) {\n        transformParts.push(`rotate(${rotationDeg}deg)`);\n      }\n\n      if (skew) {\n        const skewX = (skew.x * 180) / Math.PI;\n        const skewY = (skew.y * 180) / Math.PI;\n        if (skewX !== 0 || skewY !== 0) {\n          transformParts.push(`skew(${skewX}deg, ${skewY}deg)`);\n        }\n      }\n\n      if (scale.x !== 1 || scale.y !== 1) {\n        transformParts.push(`scale(${scale.x}, ${scale.y})`);\n      }\n\n      this.element.style.transform = transformParts.join(\" \");\n\n    }\n\n    const pivot = this.resolvePoint(props.pivot);\n    const anchor = this.resolvePoint(props.anchor);\n    if (pivot) {\n      this.element.style.transformOrigin = `${pivot.x}px ${pivot.y}px`;\n    } else if (anchor) {\n      this.element.style.transformOrigin = `${anchor.x * 100}% ${anchor.y * 100}%`;\n    }\n  }\n\n  private syncRenderElement() {\n    if (!this.element) return;\n    if (this.fitMode === \"contain\" && !(this.element instanceof HTMLImageElement)) {\n      if (!this.isContained) {\n        const inner = document.createElement(this.renderElementType);\n        this.element.style.position = \"relative\";\n        this.element.style.overflow = \"hidden\";\n        inner.style.position = \"absolute\";\n        inner.style.left = \"0\";\n        inner.style.top = \"0\";\n        inner.style.transformOrigin = \"0 0\";\n        this.element.appendChild(inner);\n        this.renderElement = inner;\n        this.isContained = true;\n      }\n      return;\n    }\n\n    if (this.isContained) {\n      if (this.renderElement && this.renderElement !== this.element) {\n        this.renderElement.remove();\n      }\n      this.renderElement = undefined;\n      this.isContained = false;\n    }\n  }\n\n  private getRenderElement() {\n    return this.renderElement ?? this.element;\n  }\n\n  private applyContainScale() {\n    if (!this.isContained) return;\n    const target = this.getRenderElement();\n    if (!target || !this.element) return;\n    if (this.frameWidth <= 0 || this.frameHeight <= 0) return;\n\n    const containerWidth =\n      this.resolvePixelSize(this.explicitWidth) ?? this.element.clientWidth;\n    const containerHeight =\n      this.resolvePixelSize(this.explicitHeight) ?? this.element.clientHeight;\n\n    if (!containerWidth || !containerHeight) return;\n\n    const scale = Math.min(containerWidth / this.frameWidth, containerHeight / this.frameHeight);\n    if (!Number.isFinite(scale) || scale <= 0) return;\n    target.style.transform = `scale(${scale})`;\n  }\n\n  private bindPlayingSignal(context: Element<CanvasDOMElement>) {\n    const playingValue = context.propObservables?.playing as any;\n    if (!playingValue || !isSignal(playingValue)) return;\n    if (this.playingSignal === playingValue) return;\n\n    if (this.playingSubscription) {\n      this.playingSubscription.unsubscribe();\n      this.playingSubscription = undefined;\n    }\n\n    this.playingSignal = playingValue;\n    this.playing = playingValue();\n    this.playingSubscription = playingValue.observable.subscribe((value) => {\n      this.playing = value === true;\n      if (!this.playing) {\n        this.elapsed = 0;\n      }\n      this.updateAnimationLoop();\n    });\n  }\n\n  private bindSheetParams(context: Element<CanvasDOMElement>) {\n    const sheetProps = context.propObservables?.sheet as any;\n    const params = sheetProps?.params as any;\n    if (!params || typeof params !== \"object\") return;\n    for (const key in params) {\n      const value = params[key];\n      if (!isSignal(value)) continue;\n      this.sheetSubscriptions.push(\n        value.observable.subscribe((nextValue) => {\n          this.sheetParams = { ...this.sheetParams, [key]: nextValue };\n          if (this.sheetCurrentName) {\n            this.playSheet(this.sheetCurrentName, [this.sheetParams]);\n          }\n        })\n      );\n    }\n  }\n\n  private getFrames(): DOMSpriteFrame[] {\n    if (this.frames && this.frames.length > 0) return this.frames;\n    if (this.rectangle) return [this.rectangle];\n    return [];\n  }\n\n  private normalizeIndex(index: number, length: number) {\n    if (length <= 0) return 0;\n    if (this.loop) {\n      const mod = index % length;\n      return mod < 0 ? mod + length : mod;\n    }\n    if (index < 0) return 0;\n    if (index >= length) return length - 1;\n    return index;\n  }\n\n  private render() {\n    if (!this.element) return;\n    const target = this.getRenderElement();\n    const sheetFrame = this.getCurrentSheetFrame();\n    if (sheetFrame) {\n      this.applyFrame(sheetFrame);\n      return;\n    }\n    const frames = this.getFrames();\n    if (frames.length === 0) {\n      if (this.renderElementType === \"img\" && this.image && target) {\n        (target as HTMLImageElement).src = this.image;\n      } else if (this.image) {\n        target.style.backgroundImage = `url(\"${this.image}\")`;\n      }\n      return;\n    }\n\n    const normalizedIndex = this.normalizeIndex(this.frameIndex, frames.length);\n    if (normalizedIndex !== this.frameIndex && !this.loop) {\n      this.frameIndex = normalizedIndex;\n    }\n\n    const frame = frames[normalizedIndex];\n    this.applyFrame(frame);\n  }\n\n  private applyFrame(frame: DOMSpriteFrame) {\n    if (!this.element) return;\n    const target = this.getRenderElement();\n    if (!target) return;\n    this.frameWidth = frame.width;\n    this.frameHeight = frame.height;\n    if (this.fitMode === \"contain\") {\n      target.style.width = `${frame.width}px`;\n      target.style.height = `${frame.height}px`;\n    } else {\n      target.style.width = this.explicitWidth ?? `${frame.width}px`;\n      target.style.height = this.explicitHeight ?? `${frame.height}px`;\n    }\n\n    const x = frame.x ?? 0;\n    const y = frame.y ?? 0;\n\n    if (this.renderElementType === \"img\") {\n      const img = target as HTMLImageElement;\n      if (this.image) {\n        img.src = this.image;\n      }\n      img.style.objectFit = \"none\";\n      img.style.objectPosition = `-${x}px -${y}px`;\n      this.applyContainScale();\n      return;\n    }\n\n    if (this.image) {\n      target.style.backgroundImage = `url(\"${this.image}\")`;\n    }\n    target.style.backgroundRepeat = \"no-repeat\";\n    target.style.backgroundPosition = `-${x}px -${y}px`;\n    this.applyContainScale();\n  }\n\n  private updateAnimationLoop() {\n    const sheetFrames = this.sheetCurrentAnimation?.frames ?? [];\n    const shouldAnimate = this.sheetCurrentAnimation\n      ? this.playing && sheetFrames.length > 1\n      : this.playing &&\n      !this.hasExternalFrameIndex &&\n      this.getFrames().length > 1 &&\n      this.fps > 0;\n\n    if (shouldAnimate) {\n      this.startAnimationLoop();\n    } else {\n      this.stopAnimationLoop();\n    }\n  }\n\n  private startAnimationLoop() {\n    if (this.tickSubscription || this.rafId !== undefined) {\n      this.stopAnimationLoop();\n    }\n    this.isAnimating = true;\n    this.elapsed = 0;\n    this.lastTickTimestamp = undefined;\n\n    if (this.tickSignal?.observable) {\n      this.tickSubscription = (this.tickSignal.observable as any).subscribe((result: any) => {\n        const tick = result?.value ?? result;\n        if (!tick) return;\n        if (this.sheetCurrentAnimation) {\n          this.advanceSheet(tick);\n          return;\n        }\n        let deltaTime = tick.deltaTime || 0;\n        if (deltaTime <= 0) {\n          const now = preciseNow();\n          if (this.lastTickTimestamp === undefined) {\n            this.lastTickTimestamp = now;\n            return;\n          }\n          deltaTime = now - this.lastTickTimestamp;\n          this.lastTickTimestamp = now;\n        }\n        if (deltaTime > 0) {\n          this.advance(deltaTime);\n        }\n      });\n      return;\n    }\n\n    const step = (timestamp: number) => {\n      if (!this.playing || this.hasExternalFrameIndex) {\n        this.stopAnimationLoop();\n        return;\n      }\n      if (this.lastRafTimestamp === undefined) {\n        this.lastRafTimestamp = timestamp;\n      }\n      const delta = timestamp - this.lastRafTimestamp;\n      this.lastRafTimestamp = timestamp;\n      if (this.sheetCurrentAnimation) {\n        this.advanceSheet({\n          timestamp,\n          deltaTime: delta,\n          frame: 0,\n          deltaRatio: delta / fps2ms(this.fps),\n        });\n      } else {\n        this.advance(delta);\n      }\n\n      if (isBrowser()) {\n        this.rafId = window.requestAnimationFrame(step);\n      } else {\n        this.rafId = setTimeout(() => {\n          step(preciseNow());\n        }, fps2ms(this.fps)) as unknown as number;\n      }\n    };\n\n    if (isBrowser()) {\n      this.rafId = window.requestAnimationFrame(step);\n    } else {\n      this.rafId = setTimeout(() => {\n        step(preciseNow());\n      }, fps2ms(this.fps)) as unknown as number;\n    }\n  }\n\n  private stopAnimationLoop() {\n    this.isAnimating = false;\n    if (this.tickSubscription) {\n      this.tickSubscription.unsubscribe();\n      this.tickSubscription = undefined;\n    }\n    if (this.rafId !== undefined) {\n      if (isBrowser()) {\n        window.cancelAnimationFrame(this.rafId);\n      } else {\n        clearTimeout(this.rafId);\n      }\n      this.rafId = undefined;\n      this.lastRafTimestamp = undefined;\n    }\n    this.lastTickTimestamp = undefined;\n  }\n\n  private advance(deltaTime: number) {\n    const frames = this.getFrames();\n    if (!this.playing || frames.length <= 1 || this.fps <= 0) return;\n\n    this.elapsed += deltaTime;\n    const frameDuration = fps2ms(this.fps);\n\n    while (this.elapsed >= frameDuration) {\n      this.elapsed -= frameDuration;\n      this.frameIndex += 1;\n      if (!this.loop && this.frameIndex >= frames.length) {\n        this.frameIndex = frames.length - 1;\n        break;\n      }\n    }\n\n    this.render();\n  }\n}\n\nregisterComponent(\"DOMSprite\", CanvasDOMSprite);\n\nexport const DOMSprite: ComponentFunction<DOMSpriteProps> = (props) => {\n  return createComponent(\"DOMSprite\", props);\n};\n"
  },
  {
    "path": "packages/core/src/components/DisplayObject.ts",
    "content": "import { Element, isElement, Props, isElementFrozen } from \"../engine/reactive\";\nimport { setObservablePoint } from \"../engine/utils\";\nimport type {\n  AlignContent,\n  EdgeSize,\n  FlexDirection,\n  ObjectFit,\n  ObjectPosition,\n  TransformOrigin,\n} from \"./types/DisplayObject\";\nimport { signal } from \"@signe/reactive\";\nimport { BlurFilter, ObservablePoint, type Point, type Rectangle } from \"pixi.js\";\nimport * as FILTERS from \"pixi-filters\";\nimport { isPercent } from \"../utils/functions\";\nimport { BehaviorSubject, filter, Subject } from \"rxjs\";\n\nexport interface ComponentInstance extends PixiMixins.ContainerOptions {\n  id?: string;\n  children?: ComponentInstance[];\n  onInit?(props: Props): void;\n  onUpdate?(props: Props): void;\n  onDestroy?(parent: Element, afterDestroy: () => void): void;\n  onMount?(context: Element<any>, index?: number): void;\n  setWidth(width: number): void;\n  setHeight(height: number): void;\n  getLocalBounds?(): Rectangle;\n  getGlobalPosition?(): Point;\n}\n\nexport const EVENTS = [\n  \"added\",\n  \"childAdded\",\n  \"childRemoved\",\n  \"click\",\n  \"clickcapture\",\n  \"destroyed\",\n  \"globalmousemove\",\n  \"globalpointermove\",\n  \"globaltouchmove\",\n  \"mousedown\",\n  \"mousedowncapture\",\n  \"mouseenter\",\n  \"mouseentercapture\",\n  \"mouseleave\",\n  \"mouseleavecapture\",\n  \"mousemove\",\n  \"mousemovecapture\",\n  \"mouseout\",\n  \"mouseoutcapture\",\n  \"mouseover\",\n  \"mouseovercapture\",\n  \"mouseup\",\n  \"mouseupcapture\",\n  \"mouseupoutside\",\n  \"mouseupoutsidecapture\",\n  \"pointercancel\",\n  \"pointercancelcapture\",\n  \"pointerdown\",\n  \"pointerdowncapture\",\n  \"pointerenter\",\n  \"pointerentercapture\",\n  \"pointerleave\",\n  \"pointerleavecapture\",\n  \"pointermove\",\n  \"pointermovecapture\",\n  \"pointerout\",\n  \"pointeroutcapture\",\n  \"pointerover\",\n  \"pointerovercapture\",\n  \"pointertap\",\n  \"pointertapcapture\",\n  \"pointerup\",\n  \"pointerupcapture\",\n  \"pointerupoutside\",\n  \"pointerupoutsidecapture\",\n  \"removed\",\n  \"rightclick\",\n  \"rightclickcapture\",\n  \"rightdown\",\n  \"rightdowncapture\",\n  \"rightup\",\n  \"rightupcapture\",\n  \"rightupoutside\",\n  \"rightupoutsidecapture\",\n  \"tap\",\n  \"tapcapture\",\n  \"touchcancel\",\n  \"touchcancelcapture\",\n  \"touchend\",\n  \"touchendcapture\",\n  \"touchendoutside\",\n  \"touchendoutsidecapture\",\n  \"touchmove\",\n  \"touchmovecapture\",\n  \"touchstart\",\n  \"touchstartcapture\",\n  \"wheel\",\n  \"wheelcapture\",\n];\n\nexport type OnHook = (() => void) | (() => Promise<void> | void);\n\nexport function DisplayObject(extendClass) {\n  return class DisplayObject extends extendClass {\n    #canvasContext: {\n      [key: string]: any;\n    } | null = null;\n    isFlex: boolean = false;\n    fullProps: Props = {};\n    isMounted: boolean = false;\n    _anchorPoints = new ObservablePoint({ _onUpdate: () => {} }, 0, 0);\n    isCustomAnchor: boolean = false;\n    displayWidth = signal(0);\n    displayHeight = signal(0);\n    overrideProps: string[] = [];\n    layout = null;\n    onBeforeDestroy: OnHook | null = null;\n    onAfterMount: OnHook | null = null;\n    subjectInit = new BehaviorSubject(null);\n    disableLayout: boolean = false;\n    // Store registered event listeners for cleanup\n    #registeredEvents: Map<string, Function> = new Map();\n    // Store computed layout box dimensions\n    #computedLayoutBox: { width?: number; height?: number } | null = null;\n    // Store reference to element for freeze checking\n    #element: Element<any> | null = null;\n\n    /**\n     * Get the element reference for freeze checking\n     * @returns The element reference or null\n     */\n    getElement(): Element<any> | null {\n      return this.#element;\n    }\n\n    onLayoutComputed(_event: any) {}\n\n    get deltaRatio() {\n      return this.#canvasContext?.scheduler?.tick.value.deltaRatio;\n    }\n\n    get parentIsFlex() {\n      if (this.disableLayout) return false;\n      return this.parent?.isFlex;\n    }\n\n    onInit(props: Props) {\n      // Ensure layout setter from @pixi/layout is used when available.\n      if (Object.prototype.hasOwnProperty.call(this, \"layout\")) {\n        delete (this as any).layout;\n      }\n      this._id = props.id;\n      for (let event of EVENTS) {\n        if (props[event] && !this.overrideProps.includes(event)) {\n          this.eventMode = \"static\";\n          const originalEventHandler = props[event];\n          \n          // Wrap event handler to check freeze state\n          const wrappedHandler = (...args: any[]) => {\n            // Check if element is frozen before executing handler\n            if (this.#element && isElementFrozen(this.#element)) {\n              return;\n            }\n            return originalEventHandler(...args);\n          };\n          \n          // Store the wrapped event handler for cleanup\n          if (event === 'click') {\n            this.on('pointertap', wrappedHandler);\n            this.#registeredEvents.set('pointertap', wrappedHandler);\n          } else {\n            this.on(event, wrappedHandler);\n            this.#registeredEvents.set(event, wrappedHandler);\n          }\n        }\n      }\n      if (props.onBeforeDestroy || props['on-before-destroy']) {\n        this.onBeforeDestroy = props.onBeforeDestroy || props['on-before-destroy'];\n      }\n      if (props.onAfterMount || props['on-after-mount']) {\n        this.onAfterMount = props.onAfterMount || props['on-after-mount'];\n      }\n      if (\n        props.justifyContent ||\n        props.alignItems ||\n        props.flexDirection ||\n        props.flexWrap ||\n        props.alignContent ||\n        props.display == \"flex\" ||\n        isPercent(props.width) ||\n        isPercent(props.height) ||\n        props.isRoot\n      ) {\n        this.layout = {};\n        this.isFlex = true;\n      }\n\n      this.subjectInit.next(this);\n    }\n\n    async onMount(element: Element<any>, index?: number) {\n      if (this.destroyed) return\n      this.#element = element;\n      this.#canvasContext = element.props.context;\n      if (element.parent) {\n        let parentElement = element.parent;\n        let instance = parentElement.componentInstance as DisplayObject;\n        if (typeof (instance as any)?.addChild !== \"function\") {\n          let search = parentElement.parent;\n          while (search && typeof (search.componentInstance as any)?.addChild !== \"function\") {\n            search = search.parent;\n          }\n          if (search && typeof (search.componentInstance as any)?.addChild === \"function\") {\n            parentElement = search;\n            instance = parentElement.componentInstance as DisplayObject;\n          } else {\n            console.warn(\"DisplayObject mount skipped: parent has no addChild\", {\n              child: element.tag,\n              parent: element.parent?.tag,\n            });\n            return;\n          }\n        }\n        if (instance.isFlex && !this.layout && !this.disableLayout) {\n          try {\n            this.layout = {};\n          } catch (error) {\n            console.warn('Failed to set layout:', error);\n          }\n        }\n        if (index === undefined || parentElement !== element.parent || typeof (instance as any)?.addChildAt !== \"function\") {\n          instance.addChild(this);\n        } else {\n          instance.addChildAt(this, index);\n        }\n        this.isMounted = true;\n        this.onUpdate(element.props);\n        \n        // Listen to layout events to store computed layout dimensions\n        const layoutHandler = (event: any) => {\n          if (event.computedLayout) {\n            this.#computedLayoutBox = {\n              width: event.computedLayout.width,\n              height: event.computedLayout.height,\n            };\n          }\n          this.onLayoutComputed(event);\n        };\n        this.on('layout', layoutHandler);\n        this.#registeredEvents.set('layout', layoutHandler);\n        \n        if (this.onAfterMount) {\n          await this.onAfterMount();\n        }\n      }\n    }\n\n    onUpdate(props: Props) {\n      this.fullProps = {\n        ...this.fullProps,\n        ...props,\n      };\n\n      if (this.destroyed) return\n      if (!this.#canvasContext || !this.parent) return;\n\n      if (props.x !== undefined) this.setX(props.x);\n      if (props.y !== undefined) this.setY(props.y);\n      if (props.scale !== undefined)\n        setObservablePoint(this.scale, props.scale);\n      if (props.anchor !== undefined && !this.isCustomAnchor) {\n        setObservablePoint(this.anchor, props.anchor);\n      }\n      if (props.width !== undefined) this.setWidth(props.width);\n      if (props.height !== undefined) this.setHeight(props.height);\n      if (props.minWidth !== undefined) this.setMinWidth(props.minWidth);\n      if (props.minHeight !== undefined) this.setMinHeight(props.minHeight);\n      if (props.maxWidth !== undefined) this.setMaxWidth(props.maxWidth);\n      if (props.maxHeight !== undefined) this.setMaxHeight(props.maxHeight);\n      if (props.aspectRatio !== undefined)\n        this.setAspectRatio(props.aspectRatio);\n      if (props.flexGrow !== undefined) this.setFlexGrow(props.flexGrow);\n      if (props.flexShrink !== undefined) this.setFlexShrink(props.flexShrink);\n      if (props.flexBasis !== undefined) this.setFlexBasis(props.flexBasis);\n      if (props.rowGap !== undefined) this.setRowGap(props.rowGap);\n      if (props.columnGap !== undefined) this.setColumnGap(props.columnGap);\n      if (props.top !== undefined) this.setTop(props.top);\n      if (props.left !== undefined) this.setLeft(props.left);\n      if (props.right !== undefined) this.setRight(props.right);\n      if (props.bottom !== undefined) this.setBottom(props.bottom);\n      if (props.objectFit !== undefined) this.setObjectFit(props.objectFit);\n      if (props.objectPosition !== undefined)\n        this.setObjectPosition(props.objectPosition);\n      if (props.transformOrigin !== undefined)\n        this.setTransformOrigin(props.transformOrigin);\n      if (props.skew !== undefined) setObservablePoint(this.skew, props.skew);\n      if (props.tint) this.tint = props.tint;\n      if (props.rotation !== undefined) this.rotation = props.rotation;\n      if (props.angle !== undefined) this.angle = props.angle;\n      if (props.zIndex !== undefined) this.zIndex = props.zIndex;\n      if (props.roundPixels !== undefined) this.roundPixels = props.roundPixels;\n      if (props.cursor) this.cursor = props.cursor;\n      if (props.visible !== undefined) this.visible = props.visible;\n      if (props.alpha !== undefined) this.alpha = props.alpha;\n      if (props.pivot) setObservablePoint(this.pivot, props.pivot);\n      if (props.flexDirection) this.setFlexDirection(props.flexDirection);\n      if (props.flexWrap) this.setFlexWrap(props.flexWrap);\n      if (props.justifyContent) this.setJustifyContent(props.justifyContent);\n      if (props.alignItems) this.setAlignItems(props.alignItems);\n      if (props.alignContent) this.setAlignContent(props.alignContent);\n      if (props.alignSelf) this.setAlignSelf(props.alignSelf);\n      if (props.margin) this.setMargin(props.margin);\n      if (props.padding) this.setPadding(props.padding);\n      if (props.gap) this.setGap(props.gap);\n      if (props.border) this.setBorder(props.border);\n      if (props.positionType) this.setPositionType(props.positionType);\n      if (props.filters) this.filters = props.filters;\n      if (props.maskOf) {\n        if (isElement(props.maskOf)) {\n          props.maskOf.componentInstance.mask = this as any;\n        }\n      }\n      if (props.shadowCaster !== undefined) {\n        const shadowCasterValue = (props.shadowCaster as any)?.value ?? props.shadowCaster;\n        if (\n          shadowCasterValue &&\n          typeof shadowCasterValue === \"object\" &&\n          !Array.isArray(shadowCasterValue)\n        ) {\n          const current = ((this as any).shadowCaster ?? {}) as Record<string, unknown>;\n          (this as any).shadowCaster = { ...current, ...shadowCasterValue };\n        } else {\n          (this as any).shadowCaster = shadowCasterValue;\n        }\n      }\n      if (props.footprintCaster !== undefined) {\n        const footprintCasterValue =\n          (props.footprintCaster as any)?.value ?? props.footprintCaster;\n        if (\n          footprintCasterValue &&\n          typeof footprintCasterValue === \"object\" &&\n          !Array.isArray(footprintCasterValue)\n        ) {\n          const current = ((this as any).footprintCaster ?? {}) as Record<string, unknown>;\n          (this as any).footprintCaster = { ...current, ...footprintCasterValue };\n        } else {\n          (this as any).footprintCaster = footprintCasterValue;\n        }\n      }\n      if (props.blendMode) this.blendMode = props.blendMode;\n      if (props.filterArea) this.filterArea = props.filterArea;\n      const currentFilters = this.filters || [];\n\n      // TODO: Fix DropShadowFilter import issue\n      // if (props.shadow) {\n      //   let dropShadowFilter = currentFilters.find(\n      //     (filter) => filter instanceof FILTERS.DropShadowFilter\n      //   );\n      //   if (!dropShadowFilter) {\n      //     dropShadowFilter = new FILTERS.DropShadowFilter();\n      //     currentFilters.push(dropShadowFilter);\n      //   }\n      //   Object.assign(dropShadowFilter, props.shadow);\n      // }\n\n      if (props.blur) {\n        let blurFilter = currentFilters.find(\n          (filter) => filter instanceof BlurFilter\n        );\n        if (!blurFilter) {\n          const options =\n            typeof props.blur === \"number\"\n              ? {\n                  strength: props.blur,\n                }\n              : props.blur;\n          blurFilter = new BlurFilter(options);\n          currentFilters.push(blurFilter);\n        }\n        Object.assign(blurFilter, props.blur);\n      }\n\n      this.filters = currentFilters;\n    }\n\n    async onDestroy(parent: Element, afterDestroy?: () => void) {\n      // Remove all registered event listeners\n      for (const [eventName, eventHandler] of this.#registeredEvents) {\n        this.off(eventName, eventHandler);\n      }\n      this.#registeredEvents.clear();\n      this.#element = null;\n\n      if (this.onBeforeDestroy) {\n        await this.onBeforeDestroy();\n      }\n      if (afterDestroy) afterDestroy();\n      super.destroy();\n    }\n\n    setFlexDirection(direction: FlexDirection) {\n      this.layout = { flexDirection: direction };\n    }\n\n    setFlexWrap(wrap: \"wrap\" | \"nowrap\" | \"wrap-reverse\") {\n      this.layout = { flexWrap: wrap };\n    }\n\n    setAlignContent(align: AlignContent) {\n      this.layout = { alignContent: align };\n    }\n\n    setAlignSelf(align: AlignContent) {\n      this.layout = { alignSelf: align };\n    }\n\n    setAlignItems(align: AlignContent) {\n      this.layout = { alignItems: align };\n    }\n\n    setJustifyContent(\n      justifyContent:\n        | \"flex-start\"\n        | \"flex-end\"\n        | \"center\"\n        | \"space-between\"\n        | \"space-around\"\n    ) {\n      this.layout = { justifyContent };\n    }\n\n    setPosition(position: EdgeSize) {\n      if (position instanceof Array) {\n        if (position.length === 2) {\n          this.layout = {\n            positionY: position[0],\n            positionX: position[1],\n          };\n        } else if (position.length === 4) {\n          this.layout = {\n            positionTop: position[0],\n            positionRight: position[1],\n            positionBottom: position[2],\n            positionLeft: position[3],\n          };\n        }\n      } else {\n        this.layout = { position };\n      }\n    }\n\n    setX(x: number) {\n      x = x + this.getWidth() * this._anchorPoints.x;\n      if (!this.parentIsFlex) {\n        this.x = x;\n      } else {\n        this.x = x;\n        this.layout = { x };\n      }\n    }\n\n    setY(y: number) {\n      y = y + this.getHeight() * this._anchorPoints.y;\n      if (!this.parentIsFlex) {\n        this.y = y;\n      } else {\n        this.y = y;\n        this.layout = { y };\n      }\n    }\n\n    setPadding(padding: EdgeSize) {\n      if (padding instanceof Array) {\n        if (padding.length === 2) {\n          this.layout = {\n            paddingVertical: padding[0],\n            paddingHorizontal: padding[1],\n          };\n        } else if (padding.length === 4) {\n          this.layout = {\n            paddingTop: padding[0],\n            paddingRight: padding[1],\n            paddingBottom: padding[2],\n            paddingLeft: padding[3],\n          };\n        }\n      } else {\n        this.layout = { padding };\n      }\n    }\n\n    setMargin(margin: EdgeSize) {\n      if (margin instanceof Array) {\n        if (margin.length === 2) {\n          this.layout = {\n            marginVertical: margin[0],\n            marginHorizontal: margin[1],\n          };\n        } else if (margin.length === 4) {\n          this.layout = {\n            marginTop: margin[0],\n            marginRight: margin[1],\n            marginBottom: margin[2],\n            marginLeft: margin[3],\n          };\n        }\n      } else {\n        this.layout = { margin };\n      }\n    }\n\n    setGap(gap: EdgeSize) {\n      this.layout = { gap };\n    }\n\n    setBorder(border: EdgeSize) {\n      if (border instanceof Array) {\n        if (border.length === 2) {\n          this.layout = {\n            borderVertical: border[0],\n            borderHorizontal: border[1],\n          };\n        } else if (border.length === 4) {\n          this.layout = {\n            borderTop: border[0],\n            borderRight: border[1],\n            borderBottom: border[2],\n            borderLeft: border[3],\n          };\n        }\n      } else {\n        this.layout = { border };\n      }\n    }\n\n    setPositionType(positionType: \"relative\" | \"absolute\") {\n      this.layout = { position: positionType };\n    }\n\n    setWidth(width: number) {\n      this.displayWidth.set(width);\n      if (!this.parentIsFlex) {\n        this.width = width;\n      } else {\n        this.layout = { width };\n      }\n    }\n\n    setHeight(height: number) {\n      this.displayHeight.set(height);\n      if (!this.parentIsFlex) {\n        this.height = height;\n      } else {\n        this.layout = { height };\n      }\n    }\n\n    getWidth(): number {\n      // If width is a percentage, use computed layout box\n      if (isPercent(this.fullProps.width)) {\n        if (this.#computedLayoutBox?.width !== undefined) {\n          return this.#computedLayoutBox.width;\n        }\n        // Fallback to native width if layout not yet computed\n        return typeof this.width === 'number' ? this.width : 0;\n      }\n      // For static values, use native PixiJS width or displayWidth signal\n      const staticWidth = typeof this.width === 'number' && this.width > 0 \n        ? this.width \n        : (typeof this.displayWidth() === 'number' ? this.displayWidth() : 0);\n      return staticWidth;\n    }\n\n    getHeight(): number {\n      // If height is a percentage, use computed layout box\n      if (isPercent(this.fullProps.height)) {\n        if (this.#computedLayoutBox?.height !== undefined) {\n          return this.#computedLayoutBox.height;\n        }\n        // Fallback to native height if layout not yet computed\n        return typeof this.height === 'number' ? this.height : 0;\n      }\n      // For static values, use native PixiJS height or displayHeight signal\n      const staticHeight = typeof this.height === 'number' && this.height > 0 \n        ? this.height \n        : (typeof this.displayHeight() === 'number' ? this.displayHeight() : 0);\n      return staticHeight;\n    }\n\n    // Min/Max constraints\n    setMinWidth(minWidth: number | string) {\n      this.layout = { minWidth };\n    }\n\n    setMinHeight(minHeight: number | string) {\n      this.layout = { minHeight };\n    }\n\n    setMaxWidth(maxWidth: number | string) {\n      this.layout = { maxWidth };\n    }\n\n    setMaxHeight(maxHeight: number | string) {\n      this.layout = { maxHeight };\n    }\n\n    // Aspect ratio\n    setAspectRatio(aspectRatio: number) {\n      this.layout = { aspectRatio };\n    }\n\n    // Flex properties\n    setFlexGrow(flexGrow: number) {\n      this.layout = { flexGrow };\n    }\n\n    setFlexShrink(flexShrink: number) {\n      this.layout = { flexShrink };\n    }\n\n    setFlexBasis(flexBasis: number | string) {\n      this.layout = { flexBasis };\n    }\n\n    // Gap properties\n    setRowGap(rowGap: number) {\n      this.layout = { rowGap };\n    }\n\n    setColumnGap(columnGap: number) {\n      this.layout = { columnGap };\n    }\n\n    // Position insets\n    setTop(top: number | string) {\n      this.layout = { top };\n    }\n\n    setLeft(left: number | string) {\n      this.layout = { left };\n    }\n\n    setRight(right: number | string) {\n      this.layout = { right };\n    }\n\n    setBottom(bottom: number | string) {\n      this.layout = { bottom };\n    }\n\n    // Object properties\n    setObjectFit(objectFit: ObjectFit) {\n      try {\n        this.layout = { objectFit };\n      } catch (error) {\n        // Ignore layout errors in test environments or when yoga-layout is not available\n      }\n    }\n\n    setObjectPosition(objectPosition: ObjectPosition) {\n      try {\n        this.layout = { objectPosition };\n      } catch (error) {\n        // Ignore layout errors in test environments or when yoga-layout is not available\n      }\n    }\n\n    setTransformOrigin(transformOrigin: TransformOrigin) {\n      try {\n        this.layout = { transformOrigin };\n      } catch (error) {\n        // Ignore layout errors in test environments or when yoga-layout is not available\n      }\n    }\n  };\n}\n"
  },
  {
    "path": "packages/core/src/components/FocusContainer.ts",
    "content": "import { createComponent, registerComponent, type Element } from \"../engine/reactive\";\nimport { applyDirective } from \"../engine/directive\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { focusManager, ScrollOptions } from \"../engine/FocusManager\";\nimport { signal, Signal, WritableSignal, WritableObjectSignal, isSignal } from \"@signe/reactive\";\nimport { CanvasViewport } from \"./Viewport\";\nimport { Controls } from \"../directives/ControlsBase\";\n// Import FocusNavigation directive to ensure it's registered\nimport \"../directives/FocusNavigation\";\n\n/**\n * Properties for FocusContainer component\n * \n * @property tabindex - Focus index for the container (default: 0 if present)\n * @property controls - Controls configuration for automatic navigation\n * @property onFocusChange - Callback when focus changes\n * @property autoScroll - Enable automatic scrolling to focused element (default: false)\n * @property viewport - Viewport instance to use for scrolling (optional, uses context viewport by default)\n */\nexport interface FocusContainerProps extends DisplayObjectProps {\n  tabindex?: number;\n  controls?: Controls | Signal<Controls>;\n  onFocusChange?: (index: number, element: Element | null) => void;\n  autoScroll?: boolean | ScrollOptions;\n  viewport?: CanvasViewport;\n  context?: {\n    viewport?: CanvasViewport;\n  };\n}\n\n/**\n * FocusContainer component for managing focus navigation\n * \n * This component provides a container that manages focus navigation between\n * focusable child elements. It supports automatic navigation via Controls\n * (keyboard/gamepad) and automatic scrolling with Viewport.\n * \n * ## Features\n * \n * - **Focus Management**: Automatically registers focusable children\n * - **Navigation**: Supports keyboard/gamepad navigation via Controls\n * - **Auto-scroll**: Automatically scrolls viewport to show focused element\n * - **Hooks**: Provides reactive signals for focus state\n * \n * @example\n * ```typescript\n * // Basic usage\n * <FocusContainer tabindex={0}>\n *   <Button tabindex={0} text=\"Button 1\" />\n *   <Button tabindex={1} text=\"Button 2\" />\n * </FocusContainer>\n * \n * // With Controls\n * <FocusContainer tabindex={0} controls={controlsConfig}>\n *   <Button tabindex={0} text=\"Button 1\" />\n *   <Button tabindex={1} text=\"Button 2\" />\n * </FocusContainer>\n * \n * // With auto-scroll\n * <Viewport worldWidth={2000} worldHeight={5000}>\n *   <FocusContainer tabindex={0} autoScroll={true}>\n *     <Button tabindex={0} y={0} text=\"Item 1\" />\n *     <Button tabindex={1} y={100} text=\"Item 2\" />\n *   </FocusContainer>\n * </Viewport>\n * ```\n */\nexport class CanvasFocusContainer {\n  private containerId: string = '';\n  private currentIndexSignal: WritableSignal<number | null> | null = null;\n  private focusedElementSignal: WritableSignal<Element | null> | WritableObjectSignal<Element | null> | null = null;\n  private registeredFocusables: Set<number> = new Set();\n\n  /**\n   * Initialize the focus container\n   * \n   * @param props - Component properties\n   */\n  onInit(props: FocusContainerProps) {\n    // Generate unique container ID\n    this.containerId = `focus-container-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n\n    // Create signals for current index and focused element\n    const currentIndex = signal<number | null>(null);\n    const focusedElement = signal<Element | null>(null) as WritableSignal<Element | null> | WritableObjectSignal<Element | null>;\n\n    this.currentIndexSignal = currentIndex;\n    this.focusedElementSignal = focusedElement;\n\n    // Get viewport from context or props\n    const viewport = props.viewport || (props.context?.viewport as CanvasViewport | undefined);\n\n    // Register container with FocusManager\n    focusManager.registerContainer(this.containerId, {\n      focusables: new Map(),\n      currentIndex,\n      focusedElement,\n      onFocusChange: props.onFocusChange,\n      autoScroll: props.autoScroll,\n      viewport\n    });\n  }\n\n  /**\n   * Mount hook - register focusable children\n   * \n   * @param element - The element being mounted\n   */\n  async onMount(element: Element<CanvasFocusContainer>): Promise<void> {\n    // Update container with element reference for freeze checking\n    focusManager.updateContainer(this.containerId, { element });\n\n    // Apply focusNavigation directive if controls are provided\n    if (element.props.controls) {\n      const focusNavDirective = applyDirective(element, 'focusNavigation');\n      if (focusNavDirective && !element.directives) {\n        element.directives = {};\n      }\n      if (focusNavDirective) {\n        element.directives.focusNavigation = focusNavDirective;\n        // Initialize the directive\n        focusNavDirective.onInit(element);\n        focusNavDirective.onMount(element);\n      }\n    }\n\n    // Subscribe to allElements to detect when children are mounted\n    if (element.allElements) {\n      const subscription = element.allElements.subscribe(() => {\n        // Register children when they are mounted\n        this.registerChildren(element);\n      });\n      // Store subscription for cleanup\n      if (!element.effectSubscriptions) {\n        element.effectSubscriptions = [];\n      }\n      element.effectSubscriptions.push(subscription);\n    }\n\n    // if (element.propObservables.tabindex) {\n    //   const subscription = element.propObservables.tabindex.observable.subscribe((value: any) => {\n    //     console.log(\"tabindex changed\", value);\n    //     if (value !== null) {\n    //     //  focusManager.setIndex(this.containerId, value);\n    //     }\n    //   });\n    //   element.effectSubscriptions.push(subscription);\n    // }\n\n    focusManager.setTabindex(this.containerId, element.propObservables?.tabindex as any);\n\n    // Register all focusable children initially\n    // Use setTimeout to ensure children are mounted\n    setTimeout(() => {\n      this.registerChildren(element);\n    }, 0);\n  }\n\n  /**\n   * Update hook - handle prop changes\n   * \n   * @param props - Updated properties\n   */\n  onUpdate(props: FocusContainerProps) {\n    // Update viewport if changed\n    const viewport = props.viewport || (props.context?.viewport as CanvasViewport | undefined);\n    focusManager.updateContainer(this.containerId, {\n      viewport,\n      autoScroll: props.autoScroll,\n      onFocusChange: props.onFocusChange\n    });\n  }\n\n  /**\n   * Destroy hook - cleanup\n   * \n   * @param parent - Parent element\n   * @param afterDestroy - Callback after destruction\n   */\n  async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {\n    // Unregister all focusables\n    for (const index of this.registeredFocusables) {\n      focusManager.unregisterFocusable(this.containerId, index);\n    }\n    this.registeredFocusables.clear();\n\n    // Unregister container\n    focusManager.unregisterContainer(this.containerId);\n    if (afterDestroy) {\n      afterDestroy();\n    }\n  }\n\n  /**\n   * Register focusable children from element\n   * \n   * @param element - Container element\n   */\n  private registerChildren(element: Element<CanvasFocusContainer>) {\n    if (!element.props.children) return;\n\n\n    let registeredCount = 0;\n    const processChildren = (children: any[]) => {\n      for (const child of children) {\n        if (!child) continue;\n\n        // Handle signals/observables\n        if (isSignal(child) || (child && typeof child.subscribe === 'function')) {\n\n          // Subscribe to changes\n          const subscription = (isSignal(child) ? child.observable : child).subscribe((value: any) => {\n            // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property\n            if (value && typeof value === 'object' && 'elements' in value) {\n              const elements = value.elements || [];\n              if (Array.isArray(elements)) {\n                processChildren(elements);\n              }\n            } else if (Array.isArray(value)) {\n              processChildren(value);\n            } else if (value) {\n              processChild(value);\n            }\n          });\n          // Note: We should track subscriptions for cleanup, but for now this works\n          continue;\n        }\n\n        // Handle arrays\n        if (Array.isArray(child)) {\n          processChildren(child);\n          continue;\n        }\n\n        // Handle single element\n        processChild(child);\n      }\n    };\n\n    const processChild = (child: Element) => {\n      if (!child || !child.componentInstance) return;\n      if ((child.tag === \"Navigation\" || child.tag === \"FocusContainer\") && child !== (element as any)) {\n        return;\n      }\n\n      // Check for tabindex in props\n      let tabindex: number | undefined = undefined;\n\n      // For DOMElement/DOMContainer, check attrs.tabindex\n      if (child.props?.attrs?.tabindex !== undefined) {\n        const tabindexValue = child.props.attrs.tabindex;\n        tabindex = isSignal(tabindexValue) ? tabindexValue() : tabindexValue;\n      }\n      // For other components, check tabindex prop directly\n      else if (child.props?.tabindex !== undefined) {\n        const tabindexValue = child.props.tabindex;\n        tabindex = isSignal(tabindexValue) ? tabindexValue() : tabindexValue;\n      }\n\n      // Register if tabindex >= 0\n      if (tabindex !== undefined && tabindex >= 0) {\n        if (!this.registeredFocusables.has(tabindex)) {\n          focusManager.registerFocusable(this.containerId, child, tabindex);\n          this.registeredFocusables.add(tabindex);\n          registeredCount++;\n        }\n      }\n\n      // Recursively process children unless we hit another FocusContainer\n      if (child.props && child.props.children) {\n        if (Array.isArray(child.props.children)) {\n          processChildren(child.props.children);\n        } else if (isSignal(child.props.children) || (child.props.children && typeof child.props.children.subscribe === 'function')) {\n          const subscription = (isSignal(child.props.children) ? child.props.children.observable : child.props.children).subscribe((value: any) => {\n            // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property\n            if (value && typeof value === 'object' && 'elements' in value) {\n              const elements = value.elements || [];\n              if (Array.isArray(elements)) {\n                processChildren(elements);\n              }\n            } else if (Array.isArray(value)) {\n              processChildren(value);\n            } else if (value) {\n              processChild(value);\n            }\n          });\n          // Store subscription for cleanup if child has effectSubscriptions\n          if (child.effectSubscriptions) {\n            child.effectSubscriptions.push(subscription);\n          }\n        } else {\n          processChild(child.props.children as any);\n        }\n      }\n    };\n\n    if (Array.isArray(element.props.children)) {\n      processChildren(element.props.children);\n    } else if (element.props.children) {\n      if (isSignal(element.props.children) || (element.props.children && typeof element.props.children.subscribe === 'function')) {\n        const subscription = (isSignal(element.props.children) ? element.props.children.observable : element.props.children).subscribe((value: any) => {\n          // Handle FlowObservable result (from loop, cond, etc.) - has 'elements' property\n          if (value && typeof value === 'object' && 'elements' in value) {\n            const elements = value.elements || [];\n            if (Array.isArray(elements)) {\n              processChildren(elements);\n            }\n          } else if (Array.isArray(value)) {\n            processChildren(value);\n          } else if (value) {\n            processChild(value);\n          }\n        });\n        // Store subscription for cleanup\n        if (!element.effectSubscriptions) {\n          element.effectSubscriptions = [];\n        }\n        element.effectSubscriptions.push(subscription);\n      } else {\n        processChild(element.props.children as any);\n      }\n    }\n  }\n\n  /**\n   * Get the container ID\n   * \n   * @returns Container identifier\n   */\n  getContainerId(): string {\n    return this.containerId;\n  }\n\n  /**\n   * Get current index signal\n   * \n   * @returns Signal for current focus index\n   */\n  getCurrentIndexSignal(): Signal<number | null> | null {\n    return this.currentIndexSignal;\n  }\n\n  /**\n   * Get focused element signal\n   * \n   * @returns Signal for current focused element\n   */\n  getFocusedElementSignal(): Signal<Element | null> | null {\n    return this.focusedElementSignal;\n  }\n}\n\nexport interface CanvasFocusContainer extends DisplayObjectProps { }\n\nregisterComponent(\"Navigation\", CanvasFocusContainer);\n\n/**\n * FocusContainer component function\n * \n * @param props - Component properties\n * @returns FocusContainer element\n */\nexport const FocusContainer: ComponentFunction<FocusContainerProps> = (props) => {\n  return createComponent(\"Navigation\", props);\n};\n\nexport const Navigation = FocusContainer;\n"
  },
  {
    "path": "packages/core/src/components/Graphic.ts",
    "content": "import { Effect, effect, isSignal, signal, Signal, WritableSignal } from \"@signe/reactive\";\nimport { Assets, ObservablePoint, Graphics as PixiGraphics } from \"pixi.js\";\nimport { createComponent, Element, registerComponent } from \"../engine/reactive\";\nimport { ComponentInstance, DisplayObject } from \"./DisplayObject\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { useProps } from \"../hooks/useProps\";\nimport { SignalOrPrimitive } from \"./types\";\nimport { isPercent } from \"../utils/functions\";\nimport { setObservablePoint } from \"../engine/utils\";\n\ninterface GraphicsProps extends DisplayObjectProps {\n  draw?: (graphics: PixiGraphics, width: number, height: number, anchor?: [number, number]) => void;\n}\n\ninterface RectProps extends DisplayObjectProps {\n  color: SignalOrPrimitive<string>;\n}\n\ninterface CircleProps extends DisplayObjectProps {\n  radius: SignalOrPrimitive<number>;\n  color: SignalOrPrimitive<string>;\n}\n\ninterface EllipseProps extends DisplayObjectProps {\n  color: SignalOrPrimitive<string>;\n}\n\ninterface TriangleProps extends DisplayObjectProps {\n  base: SignalOrPrimitive<number>;\n  color: SignalOrPrimitive<string>;\n}\n\ninterface SvgProps extends DisplayObjectProps {\n  /** SVG content as string (legacy prop) */\n  svg?: string;\n  /** URL source of the SVG file to load */\n  src?: string;\n  /** Direct SVG content as string */\n  content?: string;\n}\n\nclass CanvasGraphics extends DisplayObject(PixiGraphics) {\n  clearEffect: Effect;\n  _width: WritableSignal<number>;\n  _height: WritableSignal<number>;\n\n  isCustomAnchor = true;\n  \n  /**\n   * Initializes the graphics component with reactive width and height handling.\n   * \n   * This method handles different types of width and height props:\n   * - **Numbers**: Direct pixel values\n   * - **Strings with %**: Percentage values that trigger flex layout and use layout box dimensions\n   * - **Signals**: Reactive values that update automatically\n   * \n   * When percentage values are detected, the component:\n   * 1. Sets `display: 'flex'` to enable layout calculations\n   * 2. Listens to layout events to get computed dimensions\n   * 3. Updates internal width/height signals with layout box values\n   * \n   * The draw function receives the reactive width and height signals as parameters.\n   * \n   * @param props - Component properties including width, height, and draw function\n   * @example\n   * ```typescript\n   * // With pixel values\n   * Graphics({ width: 100, height: 50, draw: (g, w, h) => g.rect(0, 0, w(), h()) });\n   * \n   * // With percentage values (uses layout box)\n   * Graphics({ width: \"50%\", height: \"100%\", draw: (g, w, h) => g.rect(0, 0, w(), h()) });\n   * \n   * // With signals\n   * const width = signal(100);\n   * Graphics({ width, height: 50, draw: (g, w, h) => g.rect(0, 0, w(), h()) });\n   * ```\n   */\n  async onInit(props) {\n    await super.onInit(props);\n    this.setObjectFit('none');\n  }\n\n  /**\n   * Called when the component is mounted to the scene graph.\n   * Creates the reactive effect for drawing using the original signals from propObservables.\n   * @param {Element<DisplayObject>} element - The element being mounted with props and propObservables.\n   * @param {number} [index] - The index of the component among its siblings.\n   */\n  async onMount(element: Element<any>, index?: number): Promise<void> {\n    await super.onMount(element, index);\n    const { props, propObservables } = element;\n    \n    // Use original signals from propObservables if available, otherwise create new ones\n    const width = (isSignal(propObservables?.width) ? propObservables.width : signal(props.width || 0)) as WritableSignal<number>;\n    const height = (isSignal(propObservables?.height) ? propObservables.height : signal(props.height || 0)) as WritableSignal<number>;\n    const anchor = (isSignal(propObservables?.anchor) ? propObservables.anchor : signal(props.anchor || [0, 0])) as WritableSignal<[number, number]>;\n\n    // Store as class properties for access in other methods\n    this._width = width;\n    this._height = height;\n    \n    // Check if width or height are percentages to set display flex\n    const isWidthPercentage = isPercent(width());\n    const isHeightPercentage = isPercent(height());\n    \n    if (props.draw) {\n      this.clearEffect = effect(() => {\n        const w = width();\n        const h = height();\n        const a = anchor();\n        if (typeof w == 'string' || typeof h == 'string') {\n          return\n        }\n        this.clear();\n        props.draw?.(this, w, h, a);\n        this.subjectInit.next(this)\n      });\n    }\n\n    this.on('layout', (event) => {\n      const layoutBox = event.computedLayout;\n      // Update width if it's a percentage and value has changed\n      if (isWidthPercentage && isSignal(width) && width() !== layoutBox.width) {\n        width.set(layoutBox.width);\n      }\n      \n      // Update height if it's a percentage and value has changed\n      if (isHeightPercentage && isSignal(height) && height() !== layoutBox.height) {\n        height.set(layoutBox.height);\n      }\n    });\n  }\n\n  /**\n   * Called when component props are updated.\n   * Updates the internal width and height signals when props change.\n   * @param props - Updated properties\n   */\n  onUpdate(props: any) {\n    super.onUpdate(props);\n\n    // Update width signal if width prop changed and value is different\n    if (props.width !== undefined && this._width && this._width() !== props.width) {\n      this._width.set(props.width);\n    }\n    \n    // Update height signal if height prop changed and value is different\n    if (props.height !== undefined && this._height && this._height() !== props.height) {\n      this._height.set(props.height);\n    }\n  }\n\n  /**\n   * Called when the component is about to be destroyed.\n   * This method should be overridden by subclasses to perform any cleanup.\n   * It ensures that the clearEffect subscription is unsubscribed before calling the original afterDestroy callback.\n   * @param parent The parent element.\n   * @param afterDestroy A callback function to be executed after the component's own destruction logic.\n   * @example\n   * // This method is typically called by the engine internally.\n   * // await component.onDestroy(parentElement, () => console.log('Component destroyed'));\n   */\n  async onDestroy(parent: Element<ComponentInstance>, afterDestroy: () => void): Promise<void> {\n    const _afterDestroyCallback = async () => {\n      this.clearEffect?.subscription.unsubscribe();\n      afterDestroy();\n    }\n    await super.onDestroy(parent, _afterDestroyCallback);\n  }\n}\n\nregisterComponent(\"Graphics\", CanvasGraphics);\n\nexport function Graphics(props: GraphicsProps) {\n  return createComponent(\"Graphics\", props);\n}\n\nconst graphicsAnchor = (anchor, width, height) => {\n  const observableAnchor = new ObservablePoint({ _onUpdate: () => {} }, 0, 0);\n  setObservablePoint(observableAnchor, anchor);\n  const ax = observableAnchor.x;\n  const ay = observableAnchor.y;\n\n  return { x: -ax * width, y: -ay * height };\n}\n\nexport function Rect(props: RectProps) {\n  const { color, borderRadius, border } = useProps(props, {\n    borderRadius: null,\n    border: null\n  })\n\n  return Graphics({\n    draw: (g, width, height, anchor) => {\n      const { x, y } = graphicsAnchor(anchor, width, height);\n      if (borderRadius()) {\n        g.roundRect(x, y, width, height, borderRadius());\n      } else {\n        g.rect(x, y, width, height);\n      }\n      if (border) {\n        g.stroke(border);\n      }\n      g.fill(color());\n    },\n    ...props\n  })\n}\n\nexport function Circle(props: CircleProps) {  \n  const { color, border, radius } = useProps(props, {\n    border: null,\n    radius: null\n  })\n  return Graphics({\n    draw: (g, width, height, anchor) => {\n      const { x, y } = graphicsAnchor(anchor, width, height);\n      if (width == height || height == 0) {\n        g.circle(x, y, radius() || width);\n      } else {\n        g.ellipse(x, y, width, height);\n      }\n      if (border()) {\n        g.stroke(border());\n      }\n      g.fill(color());\n    },\n    ...props\n  })\n}\n\nexport function Ellipse(props: EllipseProps) {\n  return Circle(props as CircleProps);\n}\n\nexport function Triangle(props: TriangleProps) {\n  const { color, border } = useProps(props, {\n    border: null,\n    color: '#000'\n  })\n  return Graphics({\n    draw: (g, gWidth, gHeight, anchor) => {\n      const { x, y } = graphicsAnchor(anchor, gWidth, gHeight);\n      g.moveTo(x, y + gHeight);\n      g.lineTo(x + gWidth / 2, y);\n      g.lineTo(x + gWidth, y + gHeight);\n      g.lineTo(x, y + gHeight);\n      g.fill(color());\n      if (border) {\n        g.stroke(border);\n      }\n    },\n    ...props\n  })\n}\n\n/**\n * Creates an SVG component that can render SVG graphics from URL, content, or legacy svg prop.\n * \n * This component provides three ways to display SVG graphics:\n * - **src**: Load SVG from a URL using Assets.load with parseAsGraphicsContext option\n * - **content**: Render SVG directly from string content using Graphics.svg() method\n * - **svg**: Legacy prop for SVG content (for backward compatibility)\n * \n * @param props - Component properties including src, content, or svg\n * @returns A reactive SVG component\n * @example\n * ```typescript\n * // Load from URL\n * const svgFromUrl = Svg({ src: \"/assets/logo.svg\" });\n * \n * // Direct content\n * const svgFromContent = Svg({ \n *   content: `<svg viewBox=\"0 0 100 100\">\n *     <circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"blue\"/>\n *   </svg>` \n * });\n * \n * // Legacy usage\n * const svgLegacy = Svg({ svg: \"<svg>...</svg>\" });\n * ```\n */\nexport function Svg(props: SvgProps) {\n  return Graphics({\n    draw: async (g) => {\n      if (props.src) {\n        // Load SVG from source URL with graphics context parsing\n        const svgData = await Assets.load({\n          src: props.src,\n          data: {\n            parseAsGraphicsContext: true,\n          },\n        });\n        \n        // Apply the loaded graphics context\n        const graphics = new PixiGraphics(svgData);\n        g.context = graphics.context;\n      } else if (props.content) {\n        // Render SVG directly from content string\n        g.svg(props.content);\n      } else if (props.svg) {\n        // Legacy prop support\n        g.svg(props.svg);\n      }\n    },\n    ...props\n  })\n}"
  },
  {
    "path": "packages/core/src/components/Joystick.ts",
    "content": "/*\n * Joystick\n *\n * Inspired by https://github.com/endel/pixi-virtual-joystick\n */\n\nimport * as PIXI from \"pixi.js\";\nimport { Container, Graphics, Sprite, h, signal, isSignal } from \"../\";\n\nexport interface JoystickChangeEvent {\n  angle: number;\n  direction: Direction;\n  power: number;\n}\n\nexport enum Direction {\n  LEFT = \"left\",\n  TOP = \"top\",\n  BOTTOM = \"bottom\",\n  RIGHT = \"right\",\n  TOP_LEFT = \"top_left\",\n  TOP_RIGHT = \"top_right\",\n  BOTTOM_LEFT = \"bottom_left\",\n  BOTTOM_RIGHT = \"bottom_right\",\n}\n\nexport interface JoystickSettings {\n  outer?: string;\n  inner?: string;\n  outerScale?: { x: number; y: number };\n  innerScale?: { x: number; y: number };\n  innerColor?: string;\n  outerColor?: string;\n  onChange?: (data: JoystickChangeEvent) => void;\n  onStart?: () => void;\n  onEnd?: () => void;\n  /** Controls instance to automatically apply joystick events to (e.g., JoystickControls or ControlsDirective) */\n  controls?: any;\n}\n\nexport function Joystick(opts: JoystickSettings = {}) {\n  const settings = Object.assign(\n    {\n      outerScale: { x: 1, y: 1 },\n      innerScale: { x: 1, y: 1 },\n      innerColor: \"black\",\n      outerColor: \"black\",\n    },\n    opts\n  );\n\n  // Unwrap controls if it's a signal\n  const getControls = () => {\n    if (isSignal(settings.controls)) {\n      return settings.controls();\n    }\n    return settings.controls;\n  };\n\n  let outerRadius = 70;\n  let innerRadius = 10;\n  const innerAlphaStandby = 0.5;\n\n  let dragging = false;\n  let startPosition: PIXI.PointData | null = null;\n  let power = 0;\n\n  const innerPositionX = signal(0);\n  const innerPositionY = signal(0);\n  const innerAlpha = signal(innerAlphaStandby);\n\n  function getPower(centerPoint: PIXI.Point) {\n    const a = centerPoint.x - 0;\n    const b = centerPoint.y - 0;\n    return Math.min(1, Math.sqrt(a * a + b * b) / outerRadius);\n  }\n\n  function getDirection(center: PIXI.Point) {\n    let rad = Math.atan2(center.y, center.x); // [-PI, PI]\n    if ((rad >= -Math.PI / 8 && rad < 0) || (rad >= 0 && rad < Math.PI / 8)) {\n      return Direction.RIGHT;\n    } else if (rad >= Math.PI / 8 && rad < (3 * Math.PI) / 8) {\n      return Direction.BOTTOM_RIGHT;\n    } else if (rad >= (3 * Math.PI) / 8 && rad < (5 * Math.PI) / 8) {\n      return Direction.BOTTOM;\n    } else if (rad >= (5 * Math.PI) / 8 && rad < (7 * Math.PI) / 8) {\n      return Direction.BOTTOM_LEFT;\n    } else if (\n      (rad >= (7 * Math.PI) / 8 && rad < Math.PI) ||\n      (rad >= -Math.PI && rad < (-7 * Math.PI) / 8)\n    ) {\n      return Direction.LEFT;\n    } else if (rad >= (-7 * Math.PI) / 8 && rad < (-5 * Math.PI) / 8) {\n      return Direction.TOP_LEFT;\n    } else if (rad >= (-5 * Math.PI) / 8 && rad < (-3 * Math.PI) / 8) {\n      return Direction.TOP;\n    } else {\n      return Direction.TOP_RIGHT;\n    }\n  }\n\n  function handleDragStart(event: any) {\n    const target = event.currentTarget || event.target;\n    startPosition = event.getLocalPosition(target);\n    dragging = true;\n    innerAlpha.set(1);\n    settings.onStart?.();\n    \n    // Notify controls if provided\n    const controls = getControls();\n    if (controls) {\n      // Check if it's JoystickControls instance\n      if (controls.handleJoystickStart) {\n        controls.handleJoystickStart();\n      }\n      // Check if it's ControlsDirective with joystick getter\n      else if (controls.joystick && controls.joystick.handleJoystickStart) {\n        controls.joystick.handleJoystickStart();\n      }\n    }\n  }\n\n  function handleDragEnd() {\n    if (!dragging) return;\n    innerPositionX.set(0);\n    innerPositionY.set(0);\n    dragging = false;\n    innerAlpha.set(innerAlphaStandby);\n    settings.onEnd?.();\n    \n    // Notify controls if provided\n    const controls = getControls();\n    if (controls) {\n      // Check if it's JoystickControls instance\n      if (controls.handleJoystickEnd) {\n        controls.handleJoystickEnd();\n      }\n      // Check if it's ControlsDirective with joystick getter\n      else if (controls.joystick && controls.joystick.handleJoystickEnd) {\n        controls.joystick.handleJoystickEnd();\n      }\n    }\n  }\n\n  function handleDragMove(event: any) {\n    if (dragging == false) {\n      return;\n    }\n\n    const target = event.currentTarget || event.target;\n    let newPosition = event.getLocalPosition(target);\n\n    let sideX = newPosition.x - (startPosition?.x ?? 0);\n    let sideY = newPosition.y - (startPosition?.y ?? 0);\n\n    let centerPoint = new PIXI.Point(0, 0);\n    let angle = 0;\n\n    if (sideX == 0 && sideY == 0) {\n      return;\n    }\n\n    let calRadius = 0;\n\n    if (sideX * sideX + sideY * sideY >= outerRadius * outerRadius) {\n      calRadius = outerRadius;\n    } else {\n      calRadius = outerRadius - innerRadius;\n    }\n\n    /**\n     * x:   -1 <-> 1\n     * y:   -1 <-> 1\n     *          Y\n     *          ^\n     *          |\n     *     180  |  90\n     *    ------------> X\n     *     270  |  360\n     *          |\n     *          |\n     */\n\n    let direction = Direction.LEFT;\n\n    if (sideX == 0) {\n      if (sideY > 0) {\n        centerPoint.set(0, sideY > outerRadius ? outerRadius : sideY);\n        angle = 270;\n        direction = Direction.BOTTOM;\n      } else {\n        centerPoint.set(\n          0,\n          -(Math.abs(sideY) > outerRadius ? outerRadius : Math.abs(sideY))\n        );\n        angle = 90;\n        direction = Direction.TOP;\n      }\n      innerPositionX.set(centerPoint.x);\n      innerPositionY.set(centerPoint.y);\n      power = getPower(centerPoint);\n      const changeEvent = { angle, direction, power };\n      settings.onChange?.(changeEvent);\n      \n      // Notify controls if provided\n      const controls = getControls();\n      if (controls) {\n        // Check if it's JoystickControls instance\n        if (controls.handleJoystickChange) {\n          controls.handleJoystickChange(changeEvent);\n        }\n        // Check if it's ControlsDirective with joystick getter\n        else if (controls.joystick && controls.joystick.handleJoystickChange) {\n          controls.joystick.handleJoystickChange(changeEvent);\n        }\n      }\n      return;\n    }\n\n    if (sideY == 0) {\n      if (sideX > 0) {\n        centerPoint.set(\n          Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX),\n          0\n        );\n        angle = 0;\n        direction = Direction.RIGHT;\n      } else {\n        centerPoint.set(\n          -(Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX)),\n          0\n        );\n        angle = 180;\n        direction = Direction.LEFT;\n      }\n\n      innerPositionX.set(centerPoint.x);\n      innerPositionY.set(centerPoint.y);\n      power = getPower(centerPoint);\n      const changeEvent = { angle, direction, power };\n      settings.onChange?.(changeEvent);\n      \n      // Notify controls if provided\n      const controls = getControls();\n      if (controls) {\n        // Check if it's JoystickControls instance\n        if (controls.handleJoystickChange) {\n          controls.handleJoystickChange(changeEvent);\n        }\n        // Check if it's ControlsDirective with joystick getter\n        else if (controls.joystick && controls.joystick.handleJoystickChange) {\n          controls.joystick.handleJoystickChange(changeEvent);\n        }\n      }\n      return;\n    }\n\n    let tanVal = Math.abs(sideY / sideX);\n    let radian = Math.atan(tanVal);\n    angle = (radian * 180) / Math.PI;\n\n    let centerX = 0;\n    let centerY = 0;\n\n    if (sideX * sideX + sideY * sideY >= outerRadius * outerRadius) {\n      centerX = outerRadius * Math.cos(radian);\n      centerY = outerRadius * Math.sin(radian);\n    } else {\n      centerX = Math.abs(sideX) > outerRadius ? outerRadius : Math.abs(sideX);\n      centerY = Math.abs(sideY) > outerRadius ? outerRadius : Math.abs(sideY);\n    }\n\n    if (sideY < 0) {\n      centerY = -Math.abs(centerY);\n    }\n    if (sideX < 0) {\n      centerX = -Math.abs(centerX);\n    }\n\n    if (sideX > 0 && sideY < 0) {\n      // < 90\n    } else if (sideX < 0 && sideY < 0) {\n      // 90 ~ 180\n      angle = 180 - angle;\n    } else if (sideX < 0 && sideY > 0) {\n      // 180 ~ 270\n      angle = angle + 180;\n    } else if (sideX > 0 && sideY > 0) {\n      // 270 ~ 369\n      angle = 360 - angle;\n    }\n    centerPoint.set(centerX, centerY);\n    power = getPower(centerPoint);\n\n    direction = getDirection(centerPoint);\n    innerPositionX.set(centerPoint.x);\n    innerPositionY.set(centerPoint.y);\n    const changeEvent = { angle, direction, power };\n    settings.onChange?.(changeEvent);\n    \n    // Notify controls if provided\n    const controls = getControls();\n    if (controls) {\n      // Check if it's JoystickControls instance\n      if (controls.handleJoystickChange) {\n        controls.handleJoystickChange(changeEvent);\n      }\n      // Check if it's ControlsDirective with joystick getter\n      else if (controls.joystick && controls.joystick.handleJoystickChange) {\n        controls.joystick.handleJoystickChange(changeEvent);\n      }\n    }\n  }\n\n  let innerElement;\n  let outerElement;\n\n  if (!settings.outer) {\n    outerElement = h(Graphics, {\n      draw: (g) => {\n        g.circle(0, 0, outerRadius).fill(settings.outerColor);\n      },\n      alpha: 0.5,\n    });\n  } else {\n    outerElement = h(Sprite, {\n      image: settings.outer,\n      anchor: { x: 0.5, y: 0.5 },\n      scale: settings.outerScale,\n    });\n  }\n\n  const innerOptions: any = {\n    scale: settings.innerScale,\n    x: innerPositionX,\n    y: innerPositionY,\n    alpha: innerAlpha,\n  };\n\n  if (!settings.inner) {\n    innerElement = h(Graphics, {\n      draw: (g) => {\n        g.circle(0, 0, innerRadius * 2.5).fill(settings.innerColor);\n      },\n      ...innerOptions,\n    });\n  } else {\n    innerElement = settings.inner\n  }\n\n  return h(\n    Container,\n    {\n      ...opts,\n      pointerdown: handleDragStart,\n      pointerup: handleDragEnd,\n      pointerupoutside: handleDragEnd,\n      pointermove: handleDragMove,\n    },\n    outerElement,\n    innerElement,\n  );\n}\n"
  },
  {
    "path": "packages/core/src/components/Mesh.ts",
    "content": "import { Effect, effect } from \"@signe/reactive\";\nimport { Mesh as PixiMesh, Geometry, Shader, Texture, Assets, BLEND_MODES } from \"pixi.js\";\nimport { createComponent, Element, registerComponent } from \"../engine/reactive\";\nimport { ComponentInstance, DisplayObject } from \"./DisplayObject\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { useProps } from \"../hooks/useProps\";\nimport { SignalOrPrimitive } from \"./types\";\nimport { ComponentFunction } from \"../engine/signal\";\n\n/**\n * Interface defining the properties for a Mesh component.\n * Extends DisplayObjectProps to inherit common display object properties.\n */\ninterface MeshProps extends DisplayObjectProps {\n  /** The geometry defining the mesh structure (vertices, indices, UVs, etc.) */\n  geometry?: Geometry;\n  /** The shader to render the mesh with */\n  shader?: Shader;\n  /** The texture to apply to the mesh */\n  texture?: Texture | string;\n  /** The image URL to load as texture */\n  image?: string;\n  /** The tint color to apply to the mesh */\n  tint?: SignalOrPrimitive<number>;\n  /** Whether to round pixels for sharper rendering */\n  roundPixels?: SignalOrPrimitive<boolean>;\n}\n\n/**\n * Canvas Mesh component class that extends DisplayObject with PixiMesh functionality.\n * This component allows rendering of custom 3D meshes with shaders and textures.\n * \n * @example\n * ```typescript\n * // Basic mesh with geometry and texture\n * const mesh = Mesh({\n *   geometry: myGeometry,\n *   texture: \"path/to/texture.png\",\n *   tint: 0xff0000\n * });\n * \n * // Mesh with custom shader\n * const customMesh = Mesh({\n *   geometry: myGeometry,\n *   shader: myCustomShader,\n *   draw: (mesh) => {\n *     // Custom mesh manipulation\n *     mesh.rotation += 0.01;\n *   }\n * });\n * ```\n */\nclass CanvasMesh extends DisplayObject(PixiMesh) {\n  /**\n   * Constructor for the CanvasMesh component.\n   * Initializes the PixiMesh with default geometry and shader to prevent errors.\n   * \n   * @example\n   * ```typescript\n   * // This constructor is called internally by the engine\n   * const mesh = new CanvasMesh();\n   * ```\n   */\n  constructor() {\n    // Call parent constructor with minimal options to prevent destructuring error\n    // @ts-ignore - PixiMesh constructor expects options object but TypeScript doesn't recognize it\n    super({\n      geometry: new Geometry()\n    });\n  }\n\n  /**\n   * Initializes the mesh component with the provided properties.\n   * This method is called before onUpdate to set up initial state.\n   * \n   * @param props - The initial properties\n   * @example\n   * ```typescript\n   * // This method is called internally when the component is created\n   * mesh.onInit({\n   *   geometry: myGeometry,\n   *   texture: \"texture.png\"\n   * });\n   * ```\n   */\n  onInit(props: MeshProps) {\n    super.onInit(props);\n\n    // Set initial geometry if provided\n    if (props.geometry) {\n      try {\n        this.geometry = props.geometry;\n      } catch (error) {\n        console.warn('Failed to set geometry:', error);\n      }\n    }\n    \n    // Set initial shader if provided\n    if (props.shader) {\n      this.shader = props.shader;\n    }\n  }\n\n  /**\n   * Updates the mesh component when properties change.\n   * Handles texture loading, shader updates, and other property changes.\n   * \n   * @param props - The updated properties\n   * @example\n   * ```typescript\n   * // This method is called internally when props change\n   * mesh.onUpdate({\n   *   tint: 0x00ff00,\n   *   texture: \"new-texture.png\"\n   * });\n   * ```\n   */\n  async onUpdate(props: MeshProps) {\n    super.onUpdate(props);\n\n    // Handle geometry updates\n    if (props.geometry) {\n      try {\n        this.geometry = props.geometry;\n      } catch (error) {\n        console.warn('Failed to update geometry:', error);\n      }\n    }\n\n    // Handle shader/material updates\n    if (props.shader) {\n      this.shader = props.shader;\n    }\n\n    // Handle texture updates\n    if (props.texture) {\n      if (typeof props.texture === 'string') {\n        this.texture = await Assets.load(props.texture);\n      } else {\n        this.texture = props.texture;\n      }\n    } else if (props.image) {\n      this.texture = await Assets.load(props.image);\n    }\n\n    // Handle tint updates\n    if (props.tint !== undefined) {\n      this.tint = props.tint;\n    }\n\n    // Handle blend mode updates\n    if (props.blendMode !== undefined) {\n      this.blendMode = props.blendMode;\n    }\n\n    // Handle round pixels updates\n    if (props.roundPixels !== undefined) {\n      this.roundPixels = props.roundPixels;\n    }\n  }\n\n  /**\n   * Called when the component is about to be destroyed.\n   * Cleans up the draw effect subscription and calls the parent destroy method.\n   * \n   * @param parent - The parent element\n   * @param afterDestroy - Callback function to execute after destruction\n   * @example\n   * ```typescript\n   * // This method is typically called by the engine internally\n   * await mesh.onDestroy(parentElement, () => console.log('Mesh destroyed'));\n   * ```\n   */\n  async onDestroy(parent: Element<ComponentInstance>, afterDestroy: () => void): Promise<void> {\n    const _afterDestroyCallback = async () => {\n      afterDestroy();\n    };\n    await super.onDestroy(parent, _afterDestroyCallback);\n  }\n}\n\n// Register the component with the engine\nregisterComponent(\"Mesh\", CanvasMesh);\n\n/**\n * Creates a Mesh component with the specified properties.\n * This is the main function used to create mesh instances in your application.\n * \n * @param props - The properties for the mesh component\n * @returns A mesh component element\n * @example\n * ```typescript\n * import { Mesh } from 'canvasengine';\n * \n * // Create a basic textured mesh\n * const myMesh = Mesh({\n *   geometry: triangleGeometry,\n *   texture: \"assets/texture.png\",\n *   x: 100,\n *   y: 100,\n *   tint: 0xff0000\n * });\n * \n * // Create a mesh with custom shader\n * const shaderMesh = Mesh({\n *   geometry: planeGeometry,\n *   shader: customShader,\n *   draw: (mesh) => {\n *     mesh.rotation += 0.01;\n *   }\n * });\n * ```\n */\nexport const Mesh: ComponentFunction<MeshProps> = (props) => {\n  return createComponent(\"Mesh\", props);\n};\n\n// Export the component class for advanced usage\nexport { CanvasMesh };\n\n// Export the props interface for TypeScript users\nexport type { MeshProps };"
  },
  {
    "path": "packages/core/src/components/NineSliceSprite.ts",
    "content": "import { Assets, NineSliceSprite as PixiNineSliceSprite, Texture } from \"pixi.js\";\nimport { createComponent, registerComponent } from \"../engine/reactive\";\nimport { DisplayObject } from \"./DisplayObject\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { Layout } from \"@pixi/layout\";\n\ninterface NineSliceSpriteProps extends DisplayObjectProps {\n    image?: string;\n    texture?: Texture;\n    width?: number;\n    height?: number;\n    leftWidth?: number;\n    rightWidth?: number;\n    topHeight?: number;\n    bottomHeight?: number;\n    roundPixels?: boolean;\n}\n\nclass CanvasNineSliceSprite extends DisplayObject(PixiNineSliceSprite) {\n  constructor() {\n    // @ts-ignore\n    super({\n        width: 0,\n        height: 0\n    });\n  }\n\n  async onUpdate(props: NineSliceSpriteProps) {\n    for (const [key, value] of Object.entries(props)) {\n      if (value !== undefined) {\n        if (key === 'image') {\n          this.texture = await Assets.load(value);\n        } else if (key in this) {\n          (this as any)[key] = value;\n        }\n      }\n    }\n  }\n}\n\ninterface CanvasNineSliceSprite extends PixiNineSliceSprite {\n  layout: Layout | null;\n}\n\nregisterComponent(\"NineSliceSprite\", CanvasNineSliceSprite);\n\nexport function NineSliceSprite(props: NineSliceSpriteProps) {\n  return createComponent(\"NineSliceSprite\", props);\n}\n"
  },
  {
    "path": "packages/core/src/components/ParticleEmitter.ts",
    "content": "import * as particles from \"@barvynkoa/particle-emitter\";\nimport { createComponent, Element, registerComponent } from \"../engine/reactive\";\nimport { CanvasContainer } from \"./Container\";\nimport { Signal } from \"@signe/reactive\";\nimport { ComponentInstance } from \"./DisplayObject\";\n\nclass CanvasParticlesEmitter extends CanvasContainer {\n  private emitter: particles.Emitter | null;\n  private elapsed: number = Date.now();\n\n  async onMount(params) {\n    await super.onMount(params);\n    const { props } = params;\n    const tick: Signal = props.context.tick;\n    this.emitter = new particles.Emitter(this as any, props.config);\n    //this.emitter.emit = true\n\n    this.subscriptionTick = tick.observable.subscribe((value) => {\n      if (!this.emitter) return;\n      const now = Date.now();\n      this.emitter.update((now - this.elapsed) * 0.001);\n      this.elapsed = now;\n    });\n  }\n\n  onUpdate(props) {}\n\n  async onDestroy(parent: Element<ComponentInstance>, afterDestroy: () => void) {\n    const _afterDestroy = async () => {\n      this.emitter?.destroy();\n      this.emitter = null;\n      this.subscriptionTick.unsubscribe();\n      afterDestroy();\n    }\n    await super.onDestroy(parent, _afterDestroy);\n  }\n}\n\nregisterComponent(\"ParticlesEmitter\", CanvasParticlesEmitter);\n\nexport function ParticlesEmitter(props) {\n  return createComponent(\"ParticlesEmitter\", props);\n}\n"
  },
  {
    "path": "packages/core/src/components/Scene.ts",
    "content": "import { h } from \"../engine/signal\";\nimport { Container } from \"./Container\";\n\nexport function Scene(props) {\n    return h(Container)\n}"
  },
  {
    "path": "packages/core/src/components/Sprite.ts",
    "content": "import { Howl } from 'howler';\nimport { computed, effect, isSignal, Signal } from \"@signe/reactive\";\nimport {\n  Application,\n  Assets,\n  Container,\n  Sprite as PixiSprite,\n  Rectangle,\n  Texture,\n} from \"pixi.js\";\nimport { Subscription } from \"rxjs\";\nimport {\n  Element,\n  createComponent,\n  isElement,\n  registerComponent,\n  isElementFrozen,\n} from \"../engine/reactive\";\nimport { arrayEquals, isFunction } from \"../engine/utils\";\nimport { DisplayObject } from \"./DisplayObject\";\nimport {\n  AnimationFrames,\n  FrameOptions,\n  SpritesheetOptions,\n  TextureOptions,\n  TransformOptions,\n} from \"./types/Spritesheet\";\nimport { ComponentFunction } from \"../engine/signal\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { AnimatedSignal, isAnimatedSignal } from \"../engine/animation\";\nimport { Layout } from '@pixi/layout';\nimport { GlobalAssetLoader } from \"../utils/GlobalAssetLoader\";\n\nconst log = console.log;\n\ntype Image = { image: string };\n\ntype TextureOptionsMerging = TextureOptions & {\n  spriteWidth: number;\n  spriteHeight: number;\n  sound?: string;\n} & Image &\n  TransformOptions;\n\ntype FrameOptionsMerging = TextureOptionsMerging & FrameOptions;\ntype SpritesheetOptionsMerging = TextureOptionsMerging & SpritesheetOptions;\ntype TransformOptionsAsArray = Pick<\n  TransformOptions,\n  \"anchor\" | \"scale\" | \"skew\" | \"pivot\"\n>;\n\ntype AnimationDataFrames = {\n  sprites: FrameOptionsMerging[];\n  frames: Texture[][];\n  name: string;\n  animations: AnimationFrames;\n  params: any[];\n  data: TextureOptionsMerging;\n};\n\nexport type HitboxAnchorMode = \"top-left\" | \"center\" | \"foot\";\n\nexport type Hitbox = {\n  w: number;\n  h: number;\n  anchorMode?: HitboxAnchorMode;\n};\n\nexport enum StandardAnimation {\n  Stand = \"stand\",\n  Walk = \"walk\",\n}\n\nexport class CanvasSprite extends DisplayObject(PixiSprite) {\n  public hitbox: Hitbox | null = null;\n  public applyTransform: (\n    frame: FrameOptionsMerging,\n    data: TextureOptionsMerging,\n    spritesheet: SpritesheetOptionsMerging\n  ) => Partial<FrameOptionsMerging>;\n  private spritesheet: SpritesheetOptionsMerging;\n  private currentAnimation: AnimationDataFrames | null = null;\n  private time: number = 0;\n  private frameIndex: number = 0;\n  private animations: Map<string, AnimationDataFrames> = new Map();\n  private subscriptionTick: Subscription;\n  private subscriptionSheet: Subscription[] = [];\n  private sheetParams: any = {};\n  private sheetCurrentAnimation: string = StandardAnimation.Stand;\n  private app: Application | null = null;\n  onFinish: () => void;\n  private globalLoader: GlobalAssetLoader | null = null;\n  private trackedAssetIds: Set<string> = new Set();\n\n  get renderer() {\n    return this.app?.renderer;\n  }\n\n  private currentAnimationContainer: Container | null = null;\n\n  /**\n   * Auto-detects image dimensions by loading the image and reading its natural size\n   * This is used when width/height are not explicitly provided in the spritesheet definition\n   * \n   * @param imagePath - Path to the image file\n   * @returns Object containing the detected width and height of the image\n   * \n   * @example\n   * ```typescript\n   * const { width, height } = await sprite.detectImageDimensions('path/to/image.png');\n   * // width: 256, height: 128\n   * ```\n   */\n  private async detectImageDimensions(imagePath: string): Promise<{ width: number; height: number }> {\n    if (!imagePath || typeof imagePath !== 'string' || imagePath.trim() === '') {\n      throw new Error(`Invalid image path provided to detectImageDimensions: ${imagePath}`);\n    }\n\n    // Register asset in global loader if available\n    let assetId: string | null = null;\n    if (this.globalLoader) {\n      assetId = this.globalLoader.registerAsset(imagePath);\n      this.trackedAssetIds.add(assetId);\n    }\n\n    const texture = await Assets.load(imagePath, (progress) => {\n      if (this.globalLoader && assetId) {\n        this.globalLoader.updateProgress(assetId, progress);\n      }\n    });\n\n    // Mark as complete\n    if (this.globalLoader && assetId) {\n      this.globalLoader.completeAsset(assetId);\n    }\n\n    return {\n      width: texture.width,\n      height: texture.height,\n    };\n  }\n\n  /**\n   * Creates textures from a spritesheet image by cutting it into frames\n   * Automatically detects image dimensions if width/height are not provided\n   * \n   * @param options - Texture options containing image path, dimensions, and frame configuration\n   * @returns A 2D array of textures organized by rows and columns\n   * \n   * @example\n   * ```typescript\n   * // With explicit dimensions\n   * const textures = await sprite.createTextures({\n   *   image: 'path/to/image.png',\n   *   width: 256,\n   *   height: 128,\n   *   framesWidth: 4,\n   *   framesHeight: 2,\n   *   spriteWidth: 64,\n   *   spriteHeight: 64\n   * });\n   * \n   * // Without dimensions (automatically detected)\n   * const textures = await sprite.createTextures({\n   *   image: 'path/to/image.png',\n   *   framesWidth: 4,\n   *   framesHeight: 2,\n   *   spriteWidth: 64,\n   *   spriteHeight: 64\n   * });\n   * ```\n   */\n  private async createTextures(\n    options: Required<TextureOptionsMerging>\n  ): Promise<Texture[][]> {\n    let { width, height, framesHeight, framesWidth, image, offset } = options;\n\n    if (!image || typeof image !== 'string' || image.trim() === '') {\n      console.warn('Invalid image path provided to createTextures:', image);\n      return [];\n    }\n\n    // Register asset in global loader if available\n    let assetId: string | null = null;\n    if (this.globalLoader) {\n      assetId = this.globalLoader.registerAsset(image);\n      this.trackedAssetIds.add(assetId);\n    }\n\n    const texture = await Assets.load(image, (progress) => {\n      if (this.globalLoader && assetId) {\n        this.globalLoader.updateProgress(assetId, progress);\n      }\n    });\n\n    // Mark as complete\n    if (this.globalLoader && assetId) {\n      this.globalLoader.completeAsset(assetId);\n    }\n\n    // Auto-detect width and height from the image if not provided\n    if (!width || width <= 0) {\n      width = texture.width;\n      options.width = width;\n    }\n    if (!height || height <= 0) {\n      height = texture.height;\n      options.height = height;\n    }\n\n    const spriteWidth = options.spriteWidth;\n    const spriteHeight = options.spriteHeight;\n    const frames: Texture[][] = [];\n    const offsetX = (offset && offset.x) || 0;\n    const offsetY = (offset && offset.y) || 0;\n    for (let i = 0; i < framesHeight; i++) {\n      frames[i] = [];\n      for (let j = 0; j < framesWidth; j++) {\n        const rectX = j * spriteWidth + offsetX;\n        const rectY = i * spriteHeight + offsetY;\n        if (rectY > height) {\n          throw log(\n            `Warning, there is a problem with the height of the \"${this.id}\" spritesheet. When cutting into frames, the frame exceeds the height of the image.`\n          );\n        }\n        if (rectX > width) {\n          throw log(\n            `Warning, there is a problem with the width of the \"${this.id}\" spritesheet. When cutting into frames, the frame exceeds the width of the image.`\n          );\n        }\n        frames[i].push(\n          new Texture({\n            source: texture.source,\n            frame: new Rectangle(rectX, rectY, spriteWidth, spriteHeight),\n          })\n        );\n      }\n    }\n    return frames;\n  }\n\n  private async createAnimations() {\n    const { textures } = this.spritesheet;\n    if (!textures) {\n      return;\n    }\n    for (let animationName in textures) {\n      const props: (keyof TextureOptionsMerging)[] = [\n        \"width\",\n        \"height\",\n        \"framesHeight\",\n        \"framesWidth\",\n        \"rectWidth\",\n        \"rectHeight\",\n        \"offset\",\n        \"image\",\n        \"sound\",\n      ];\n      const parentObj = props.reduce(\n        (prev, val) => ({ ...prev, [val]: this.spritesheet[val] }),\n        {}\n      );\n      const optionsTextures: TextureOptionsMerging = {\n        ...parentObj,\n        ...textures[animationName],\n      } as any;\n      const {\n        rectWidth,\n        width: widthOption = 0,\n        framesWidth = 1,\n        rectHeight,\n        height: heightOption = 0,\n        framesHeight = 1,\n        image,\n      } = optionsTextures;\n\n      // Auto-detect width and height from the image if not provided\n      let width = widthOption;\n      let height = heightOption;\n\n      if (image && ((!width || width <= 0) || (!height || height <= 0))) {\n        const dimensions = await this.detectImageDimensions(image);\n        if (!width || width <= 0) {\n          width = dimensions.width;\n          optionsTextures.width = width;\n        }\n        if (!height || height <= 0) {\n          height = dimensions.height;\n          optionsTextures.height = height;\n        }\n      }\n\n      optionsTextures.spriteWidth = rectWidth ? rectWidth : width / framesWidth;\n      optionsTextures.spriteHeight = rectHeight\n        ? rectHeight\n        : height / framesHeight;\n      this.animations.set(animationName, {\n        frames: await this.createTextures(\n          optionsTextures as Required<TextureOptionsMerging>\n        ),\n        name: animationName,\n        animations: textures[animationName].animations,\n        params: [],\n        data: optionsTextures,\n        sprites: [],\n      });\n    }\n  }\n\n  async onMount(params: Element<any>) {\n    // Set #element manually for freeze checking before calling super.onMount\n    // We need to set it early so update() can check freeze state\n    (this as any)['#element'] = params;\n    \n    const { props, propObservables } = params;\n    const tick: Signal = props.context.tick;\n    const sheet = props.sheet ?? {};\n    const definition = props.sheet?.definition ?? {};\n    this.app = props.context.app();\n    // Get global loader from context if available\n    this.globalLoader = props.context?.globalLoader || null;\n    if (sheet?.onFinish) {\n      this.onFinish = sheet.onFinish;\n    }\n    this.subscriptionTick = tick.observable.subscribe((value) => {\n      if (this.destroyed) return\n      this.update(value);\n    });\n    if (definition) {\n      const resolvedDefinition = definition instanceof Promise ? await definition : definition;\n      this.spritesheet = resolvedDefinition.value ?? resolvedDefinition;\n      await this.createAnimations();\n    }\n    if (sheet?.params) {\n      this.sheetParams = sheet.params;\n    }\n    if (sheet?.playing && this.has(sheet.playing)) {\n      this.sheetCurrentAnimation = sheet.playing;\n      this.play(this.sheetCurrentAnimation, [this.sheetParams]);\n    }\n    if (sheet.params) {\n      for (let key in propObservables?.sheet[\"params\"]) {\n        const value = propObservables?.sheet[\"params\"][key] as Signal;\n        if (isSignal(value)) {\n          this.subscriptionSheet.push(\n            value.observable.subscribe((value) => {\n              if (this.animations.size == 0) return;\n              if (!this.has(this.sheetCurrentAnimation)) return;\n              this.play(this.sheetCurrentAnimation, [{ ...this.sheetParams, [key]: value }]);\n            })\n          );\n        } else {\n          if (!this.has(this.sheetCurrentAnimation)) continue;\n          this.play(this.sheetCurrentAnimation, [{ ...this.sheetParams, [key]: value }]);\n        }\n      }\n    }\n\n    const isMoving = computed(() => {\n      const { x, y } = propObservables ?? {};\n      if (!x || !y) return false;\n      const xSignal = x as AnimatedSignal<any>;\n      const ySignal = y as AnimatedSignal<any>;\n      const isMovingX =\n        isAnimatedSignal(xSignal) &&\n        xSignal.animatedState().current !== xSignal.animatedState().end;\n      const isMovingY =\n        isAnimatedSignal(ySignal) &&\n        ySignal.animatedState().current !== ySignal.animatedState().end;\n      return isMovingX || isMovingY;\n    });\n\n    effect(() => {\n      const _isMoving = isMoving();\n\n      if (!this.isMounted) return;\n\n      if (_isMoving) {\n        this.sheetCurrentAnimation = StandardAnimation.Walk;\n      } else {\n        this.sheetCurrentAnimation = StandardAnimation.Stand;\n      }\n\n      if (this.spritesheet && this.has(this.sheetCurrentAnimation)) this.play(this.sheetCurrentAnimation, [this.sheetParams]);\n    });\n    super.onMount(params);\n  }\n\n  async onUpdate(props) {\n    if (this.destroyed) return\n    super.onUpdate(props);\n\n    // Initialize globalLoader from context if not already set\n    if (!this.globalLoader && props.context?.globalLoader) {\n      this.globalLoader = props.context.globalLoader;\n    }\n\n    const setTexture = async (image: string) => {\n      if (!image || typeof image !== 'string' || image.trim() === '') {\n        console.warn('Invalid image path provided to setTexture:', image);\n        return null;\n      }\n\n      // Register asset in global loader if available\n      let assetId: string | null = null;\n      if (this.globalLoader) {\n        assetId = this.globalLoader.registerAsset(image);\n        this.trackedAssetIds.add(assetId);\n      }\n\n      const onProgress = this.fullProps.loader?.onProgress;\n      const texture = await Assets.load(image, (progress) => {\n        // Update global loader progress\n        if (this.globalLoader && assetId) {\n          this.globalLoader.updateProgress(assetId, progress);\n        }\n        // Call local loader callback if provided\n        if (onProgress) onProgress(progress);\n        if (progress == 1) {\n          // Mark as complete in global loader\n          if (this.globalLoader && assetId) {\n            this.globalLoader.completeAsset(assetId);\n          }\n          const onComplete = this.fullProps.loader?.onComplete;\n          if (onComplete) {\n            // hack to memoize the texture\n            setTimeout(() => {\n              onComplete(texture);\n            });\n          }\n        }\n      });\n\n      return texture\n    }\n\n    const sheet = props.sheet\n    const definition = props.sheet?.definition ?? {};\n\n    if (definition?.type === 'reset') {\n      const resolvedValue = definition.value instanceof Promise ? await definition.value : definition.value;\n      this.spritesheet = resolvedValue ?? definition;\n      await this.resetAnimations();\n    }\n\n    if (sheet?.params) this.sheetParams = sheet?.params;\n\n    if (sheet?.playing && this.isMounted && this.spritesheet && this.animations.size > 0) {\n      this.sheetCurrentAnimation = sheet?.playing;\n      this.play(this.sheetCurrentAnimation, [this.sheetParams]);\n    }\n\n    if (props.hitbox !== undefined) {\n      this.hitbox = this.normalizeHitbox(props.hitbox);\n    }\n\n    if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;\n    else if (props.image && this.fullProps.rectangle === undefined) {\n      const texture = await setTexture(this.fullProps.image);\n      if (texture) {\n        this.texture = texture;\n      }\n    } else if (props.texture) {\n      if (isElement(props.texture)) {\n        const textureInstance = props.texture.componentInstance;\n        textureInstance.subjectInit\n          .subscribe()\n        this.texture = this.renderer?.generateTexture(props.texture.componentInstance);\n      } else {\n        this.texture = props.texture;\n      }\n    }\n    if (props.rectangle !== undefined) {\n      const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;\n      const texture = await setTexture(this.fullProps.image);\n      if (texture) {\n        this.texture = new Texture({\n          source: texture.source,\n          frame: new Rectangle(x, y, width, height),\n        });\n      }\n    }\n\n    if (this.hitbox && !this.spritesheet) {\n      this.applyHitboxAnchor(this.texture.width, this.texture.height);\n    }\n  }\n\n  async onDestroy(parent: Element, afterDestroy: () => void): Promise<void> {\n    const _afterDestroy = async () => {\n      // Clean up tracked assets from global loader\n      if (this.globalLoader) {\n        this.trackedAssetIds.forEach((assetId) => {\n          this.globalLoader!.removeAsset(assetId);\n        });\n        this.trackedAssetIds.clear();\n      }\n      this.subscriptionSheet.forEach((sub) => sub.unsubscribe());\n      this.subscriptionTick.unsubscribe();\n      if (this.currentAnimationContainer && this.parent instanceof Container) {\n        this.parent.removeChild(this.currentAnimationContainer);\n      }\n      if (afterDestroy) {\n        afterDestroy();\n      }\n    };\n    await super.onDestroy(parent, _afterDestroy);\n  }\n\n  has(name: string): boolean {\n    return this.animations.has(name);\n  }\n\n  get(name: string): AnimationDataFrames {\n    return this.animations.get(name) as AnimationDataFrames;\n  }\n\n  isPlaying(name?: string): boolean {\n    if (!name) return !!this.currentAnimation;\n    if (this.currentAnimation == null) return false;\n    return this.currentAnimation.name == name;\n  }\n\n  stop() {\n    this.currentAnimation = null;\n  }\n\n  play(name: string, params: any[] = []) {\n    const animParams = this.currentAnimation?.params;\n\n    if (this.isPlaying(name) && arrayEquals(params, animParams || [])) return;\n\n    const animation = this.get(name);\n\n    if (!animation) {\n      throw new Error(\n        `Impossible to play the ${name} animation because it doesn't exist on the \"${this.id}\" spritesheet`\n      );\n    }\n\n    const cloneParams = structuredClone(params);\n\n    this.removeChildren();\n    animation.sprites = [];\n    this.currentAnimation = animation;\n    this.currentAnimation.params = cloneParams;\n    this.time = 0;\n    this.frameIndex = 0;\n    let animations: any = animation.animations;\n    animations = isFunction(animations)\n      ? (animations as Function)(...cloneParams)\n      : animations;\n\n    this.currentAnimationContainer = new Container();\n\n    for (let container of animations as FrameOptionsMerging[][]) {\n      const sprite = new PixiSprite();\n      for (let frame of container) {\n        this.currentAnimation.sprites.push(frame);\n      }\n      this.currentAnimationContainer.addChild(sprite);\n    }\n\n    const sound = this.currentAnimation.data.sound;\n\n    if (sound) {\n      new Howl({\n        src: sound,\n        autoplay: true,\n        loop: false,\n        volume: 1,\n      })\n    }\n\n    // Updates immediately to avoid flickering\n    this.update({\n      deltaRatio: 1,\n    });\n  }\n\n  /**\n   * Resets the sprite by destroying and recreating all animations\n   * This method clears the current animation state, destroys existing textures,\n   * and recreates all animations from the spritesheet\n   * \n   * @example\n   * ```typescript\n   * // Reset all animations to their initial state\n   * sprite.resetAnimations();\n   * \n   * // Reset and then play a specific animation\n   * await sprite.resetAnimations();\n   * sprite.play('walk');\n   * ```\n   */\n  async resetAnimations(): Promise<void> {\n    // Stop current animation\n    this.stop();\n\n    // Clear all animations and textures\n    this.animations.clear();\n\n    // Reset animation state\n    this.currentAnimation = null;\n    this.currentAnimationContainer = null;\n    this.time = 0;\n    this.frameIndex = 0;\n\n    // Clear children\n    this.removeChildren();\n\n    // Recreate animations from spritesheet\n    if (this.spritesheet) {\n      await this.createAnimations();\n      this.play(this.sheetCurrentAnimation, [this.sheetParams]);\n    }\n  }\n\n  update({ deltaRatio }) {\n    // Block animation update if element is frozen\n    const element = this.getElement();\n    if (element && isElementFrozen(element)) {\n      return;\n    }\n    \n    if (\n      !this.isPlaying() ||\n      !this.currentAnimation ||\n      !this.currentAnimationContainer\n    )\n      return;\n\n    const self = this;\n    const { frames, sprites, data } = this.currentAnimation;\n    let frame = sprites[this.frameIndex];\n    const nextFrame = sprites[this.frameIndex + 1];\n\n    for (let _sprite of this.currentAnimationContainer.children) {\n      const sprite = _sprite as PixiSprite;\n\n      if (!frame || frame.frameY == undefined || frame.frameX == undefined) {\n        continue;\n      }\n\n      this.texture = frames[frame.frameY][frame.frameX];\n\n      const getVal = <T extends keyof TransformOptions>(\n        prop: T\n      ): TransformOptions[T] | undefined => {\n        return frame[prop] ?? data[prop] ?? this.spritesheet[prop];\n      };\n\n      const applyTransform = <T extends keyof TransformOptionsAsArray>(\n        prop: T\n      ): void => {\n        const val = getVal<T>(prop);\n        if (val) {\n          this[prop as string].set(...val!);\n        }\n      };\n\n      function applyTransformValue<T extends keyof TransformOptions>(prop: T);\n      function applyTransformValue<T extends keyof TransformOptions>(\n        prop: string,\n        alias: T\n      );\n      function applyTransformValue<T extends keyof TransformOptions>(\n        prop: T,\n        alias?: T\n      ): void {\n        const optionProp = alias || prop;\n        const val = getVal<T>(optionProp);\n        if (val !== undefined) {\n          self[prop as string] = val;\n        }\n      }\n\n      if (this.applyTransform) {\n        frame = {\n          ...frame,\n          ...this.applyTransform(frame, data, this.spritesheet),\n        };\n      }\n\n      const realSize = getVal<\"spriteRealSize\">(\"spriteRealSize\");\n\n      if (frame.sound) {\n        //RpgSound.get(frame.sound).play()\n      }\n\n      this.applyHitboxAnchor(data.spriteWidth, data.spriteHeight, realSize);\n\n      applyTransform(\"anchor\");\n      applyTransform(\"scale\");\n      applyTransform(\"skew\");\n      applyTransform(\"pivot\");\n\n      applyTransformValue(\"alpha\", \"opacity\");\n      applyTransformValue(\"x\");\n      applyTransformValue(\"y\");\n      applyTransformValue(\"angle\");\n      applyTransformValue(\"rotation\");\n      applyTransformValue(\"visible\");\n    }\n\n    if (!nextFrame) {\n      this.time = 0;\n      this.frameIndex = 0;\n      if (this.onFinish && sprites.length > 1) this.onFinish();\n      return;\n    }\n\n    this.time += deltaRatio ?? 1;\n\n    if (this.time >= nextFrame.time) {\n      this.frameIndex++;\n    }\n  }\n\n  private applyHitboxAnchor(\n    spriteWidth: number,\n    spriteHeight: number,\n    realSize?: TextureOptionsMerging[\"spriteRealSize\"]\n  ) {\n    if (!this.hitbox || !spriteWidth || !spriteHeight) {\n      return;\n    }\n\n    const heightOfSprite =\n      typeof realSize === \"number\" ? realSize : realSize?.height;\n    const resolvedHeight = heightOfSprite ?? spriteHeight;\n    const gap = Math.max(0, (spriteHeight - resolvedHeight) / 2);\n    const hitboxTopLeftX = this.clamp(\n      (spriteWidth - this.hitbox.w) / 2 / spriteWidth\n    );\n    const hitboxTopLeftY = this.clamp(\n      (spriteHeight - this.hitbox.h - gap) / spriteHeight\n    );\n    const hitboxCenterX = this.clamp(\n      hitboxTopLeftX + this.hitbox.w / 2 / spriteWidth\n    );\n    const hitboxCenterY = this.clamp(\n      hitboxTopLeftY + this.hitbox.h / 2 / spriteHeight\n    );\n    const footY = this.clamp((spriteHeight - gap) / spriteHeight);\n\n    let anchorX = hitboxTopLeftX;\n    let anchorY = hitboxTopLeftY;\n\n    switch (this.hitbox.anchorMode ?? \"top-left\") {\n      case \"center\":\n        anchorX = hitboxCenterX;\n        anchorY = hitboxCenterY;\n        break;\n      case \"foot\":\n        anchorX = hitboxCenterX;\n        anchorY = footY;\n        break;\n      case \"top-left\":\n      default:\n        break;\n    }\n\n    this.anchor.set(anchorX, anchorY);\n  }\n\n  private normalizeHitbox(hitbox: unknown): Hitbox | null {\n    const resolvedHitbox = (hitbox as any)?.value ?? hitbox;\n    if (!resolvedHitbox || typeof resolvedHitbox !== \"object\") {\n      return null;\n    }\n\n    const { w, h, anchorMode } = resolvedHitbox as Partial<Hitbox>;\n    if (typeof w !== \"number\" || typeof h !== \"number\") {\n      return null;\n    }\n\n    return {\n      w,\n      h,\n      anchorMode,\n    };\n  }\n\n  private clamp(value: number) {\n    return Math.min(1, Math.max(0, value));\n  }\n}\n\nexport interface CanvasSprite extends PixiSprite {\n  layout: Layout | null;\n}\n\nregisterComponent(\"Sprite\", CanvasSprite);\n\n// Define the props interface for Sprite\nexport interface SpriteProps extends DisplayObjectProps {\n  sheet?: {\n    definition?: SpritesheetOptionsMerging;\n    playing?: string;\n    params?: any;\n    onFinish?: () => void;\n  };\n  hitbox?: Hitbox;\n  scaleMode?: number;\n  image?: string;\n  rectangle?: {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n  };\n  context?: {\n    tick: Signal;\n  };\n}\n\nexport interface SpritePropsWithImage extends Omit<SpriteProps, \"sheet\"> {\n  image: string;\n  rectangle?: {\n    x: number;\n    y: number;\n    width: number;\n    height: number;\n  };\n}\n\nexport interface SpritePropsWithSheet\n  extends Omit<SpriteProps, \"image\" | \"rectangle\"> {\n  sheet: {\n    definition: SpritesheetOptionsMerging;\n    playing?: string;\n    params?: any;\n    onFinish?: () => void;\n  };\n  loader?: {\n    onProgress?: (progress: number) => void;\n    onComplete?: (texture: Texture) => void;\n  };\n}\n\nexport type SpritePropTypes = SpritePropsWithImage | SpritePropsWithSheet;\n\n// Update the Sprite function to use the props interface\nexport const Sprite: ComponentFunction<SpritePropTypes> = (props) => {\n  // Ensure component is registered in test environments where module cache may differ\n  registerComponent(\"Sprite\", CanvasSprite);\n  return createComponent(\"Sprite\", props);\n};\n"
  },
  {
    "path": "packages/core/src/components/Text.ts",
    "content": "import { Text as PixiText, TextStyle } from \"pixi.js\";\nimport { createComponent, registerComponent, Element, Props } from \"../engine/reactive\";\nimport { DisplayObject, ComponentInstance } from \"./DisplayObject\";\nimport { DisplayObjectProps } from \"./types/DisplayObject\";\nimport { Signal } from \"@signe/reactive\";\nimport { on, isTrigger } from \"../engine/trigger\";\nimport { Howl } from \"howler\";\n\nenum TextEffect {\n  Typewriter = \"typewriter\",\n}\n\nexport interface TextProps extends DisplayObjectProps {\n  text?: string;\n  style?: Partial<TextStyle>;\n  color?: string;\n  size?: string;\n  fontFamily?: string;\n  typewriter?: {\n    speed?: number;\n    start?: () => void;\n    onComplete?: () => void;\n    skip?: () => void;\n    sound?: {\n      src: string;\n      volume?: number;\n      rate?: number;\n    };\n  };\n  context?: any; // Ensure context is available, ideally typed from a base prop or injected\n}\n\nclass CanvasText extends DisplayObject(PixiText) {\n  private subscriptionTick: any;\n  private fullText: string = \"\";\n  private currentIndex: number = 0;\n  private typewriterSpeed: number = 1; // Default speed\n  private _wordWrapWidth: number = 0;\n  private typewriterOptions: any = {};\n  private skipSignal?: () => void;\n  private typewriterSound?: Howl;\n  private lastSoundTime: number = 0;\n  private soundDuration: number = 0; // Duration of the sound in milliseconds\n\n  /**\n   * Called when the component is mounted to the scene graph.\n   * Initializes the typewriter effect if configured.\n   * @param {Element<CanvasText>} element - The element being mounted with parent and props.\n   * @param {number} [index] - The index of the component among its siblings.\n   */\n  async onMount(element: Element<any>, index?: number): Promise<void> {\n    const { props } = element;\n    await super.onMount(element, index);\n    const tick: Signal = props.context.tick;\n\n    if (props.text && props.typewriter) {\n      this.fullText = props.text;\n      this.text = \"\";\n      this.currentIndex = 0;\n      // Set typewriter options\n      if (props.typewriter) {\n        this.typewriterOptions = props.typewriter;\n        if (this.typewriterOptions.skip && isTrigger(this.typewriterOptions.skip)) {\n          on(this.typewriterOptions.skip, () => {\n            this.skipTypewriter();\n          });\n        }\n        // Initialize typewriter sound if configured\n        if (this.typewriterOptions.sound) {\n          this.initializeTypewriterSound();\n        }\n      }\n      // Update layout after initializing typewriter\n      this.updateLayout();\n    }\n    this.subscriptionTick = tick.observable.subscribe(() => {\n      if (props.typewriter) {\n        this.typewriterEffect();\n      }\n    });\n  }\n\n  onUpdate(props: TextProps) {\n    super.onUpdate(props);\n    if (props.typewriter) {\n      if (props.typewriter) {\n        this.typewriterOptions = props.typewriter;\n        // Reinitialize sound if sound configuration changed\n        if (props.typewriter.sound) {\n          this.initializeTypewriterSound();\n        }\n      }\n    }\n    if (props.text !== undefined) {\n      this.text = ''+props.text;\n    }\n    if (props.text !== undefined && props.text !== this.fullText && this.fullProps.typewriter) {\n      this.text = \"\";\n      this.currentIndex = 0;\n      this.fullText = props.text;\n      // Update layout after resetting typewriter\n      this.updateLayout();\n    }\n    if (props.style) {\n      for (const key in props.style) {\n        this.style[key] = props.style[key];\n      }\n      if (props.style.wordWrapWidth) {\n        this._wordWrapWidth = props.style.wordWrapWidth;\n      }\n    }\n    if (props.color) {\n      this.style.fill = props.color;\n    }\n    if (props.size) {\n      this.style.fontSize = props.size;\n    }\n    if (props.fontFamily) {\n      this.style.fontFamily = props.fontFamily;\n    }\n    \n    // Use the centralized layout update method\n    this.updateLayout();\n  }\n\n  get onCompleteCallback() {\n    return this.typewriterOptions.onComplete;\n  }\n\n  /**\n   * Initializes the typewriter sound effect using Howler.\n   * Creates a Howl instance with the configured sound settings.\n   * Calculates the sound duration to prevent overlapping sounds.\n   */\n  private initializeTypewriterSound() {\n    if (!this.typewriterOptions.sound?.src) return;\n    \n    this.typewriterSound = new Howl({\n      src: [this.typewriterOptions.sound.src],\n      volume: this.typewriterOptions.sound.volume ?? 0.5,\n      rate: this.typewriterOptions.sound.rate ?? 1.0,\n      preload: true,\n      onload: () => {\n        // Calculate sound duration in milliseconds\n        if (this.typewriterSound) {\n          const duration = this.typewriterSound.duration();\n          const rate = this.typewriterOptions.sound?.rate ?? 1.0;\n          this.soundDuration = (duration / rate) * 1000;\n        }\n      }\n    });\n  }\n\n  /**\n   * Plays the typewriter sound with duration-based cooldown to prevent overlapping sounds.\n   * @param {number} currentTime - The current timestamp to check against sound duration.\n   */\n  private playTypewriterSound(currentTime: number) {\n    if (!this.typewriterSound || !this.typewriterOptions.sound) return;\n    \n    // Check if enough time has passed since the last sound play\n    // Use the actual sound duration to prevent overlap\n    if (this.soundDuration > 0 && currentTime - this.lastSoundTime < this.soundDuration) return;\n    \n    this.typewriterSound.play();\n    this.lastSoundTime = currentTime;\n  }\n\n  /**\n   * Updates the layout properties of the text component.\n   * This method ensures consistent width, height and word wrap behavior.\n   */\n  private updateLayout() {\n    if (this._wordWrapWidth) {\n      this.setWidth(this._wordWrapWidth);\n    } else {\n      this.setWidth(this.width);\n    }\n    this.setHeight(this.height);\n  }\n\n  private typewriterEffect() {\n    if (this.currentIndex < this.fullText.length) {\n      const nextIndex = Math.min(\n        this.currentIndex + (this.typewriterOptions.speed ?? 1),\n        this.fullText.length\n      );\n      this.text = this.fullText.slice(0, nextIndex);\n      this.currentIndex = nextIndex;\n\n      // Play typewriter sound if configured\n      if (this.typewriterOptions.sound) {\n        this.playTypewriterSound(Date.now());\n      }\n\n      // Update layout after text change to maintain proper word wrap and dimensions\n      this.updateLayout();\n\n      // Check if typewriter effect is complete\n      if (\n        this.currentIndex === this.fullText.length &&\n        this.onCompleteCallback\n      ) {\n        this.onCompleteCallback();\n      }\n    }\n  }\n\n  // Add a method to skip the typewriter effect\n  private skipTypewriter() {\n    if (this.skipSignal) {\n      this.skipSignal();\n    }\n    this.text = this.fullText;\n    this.currentIndex = this.fullText.length;\n    \n    // Update layout after setting full text to maintain proper word wrap and dimensions\n    this.updateLayout();\n  }\n\n  /**\n   * Called when the component is about to be destroyed.\n   * Unsubscribes from the tick observable and cleans up sound resources.\n   * @param {Element<any>} parent - The parent element.\n   * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.\n   */\n  async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {\n    const _afterDestroy = async () => {\n      if (this.subscriptionTick) {\n        this.subscriptionTick.unsubscribe();\n      }\n      // Clean up typewriter sound\n      if (this.typewriterSound) {\n        this.typewriterSound.stop();\n        this.typewriterSound.unload();\n        this.typewriterSound = undefined;\n      }\n      if (afterDestroy) {\n        afterDestroy();\n      }\n    }\n    await super.onDestroy(parent, _afterDestroy);\n  }\n}\n\n// interface CanvasText extends PixiText {} // Removed as it's redundant and causes type conflicts\n\nregisterComponent(\"Text\", CanvasText);\n\nexport function Text(props: TextProps) {\n  return createComponent(\"Text\", props);\n}\n"
  },
  {
    "path": "packages/core/src/components/TilingSprite.ts",
    "content": "import { TilingSprite as PixiTilingSprite, Texture } from 'pixi.js';\nimport { createComponent, registerComponent } from '../engine/reactive';\nimport { DisplayObject } from './DisplayObject';\nimport { DisplayObjectProps } from './types/DisplayObject';\n\ninterface TilingSpriteProps extends DisplayObjectProps {\n    image?: string;\n    tileScale?: { x: number; y: number };\n    tilePosition?: { x: number; y: number };\n    width?: number;\n    height?: number;\n}\n\nclass CanvasTilingSprite extends DisplayObject(PixiTilingSprite) {\n    onUpdate(props: TilingSpriteProps): void {\n        super.onUpdate(props);\n        if (props.image) {\n            this.texture = Texture.from(props.image);\n        }\n        if (props.tileScale) {\n            this.tileScale.set(props.tileScale.x, props.tileScale.y);\n        }\n        if (props.tilePosition) {\n            this.tilePosition.set(props.tilePosition.x, props.tilePosition.y);\n        }\n        if (props.width !== undefined) {\n            this.width = props.width;\n        }\n        if (props.height !== undefined) {\n            this.height = props.height;\n        }\n    }\n}\n\nregisterComponent('TilingSprite', CanvasTilingSprite)\n\nexport function TilingSprite(props: TilingSpriteProps) {\n    return createComponent('TilingSprite', props)\n}"
  },
  {
    "path": "packages/core/src/components/Video.ts",
    "content": "import { Texture } from \"pixi.js\";\nimport { h, mount } from \"../engine/signal\";\nimport { useDefineProps } from \"../hooks/useProps\";\nimport { Sprite } from \"./Sprite\";\nimport { effect, Signal, signal } from \"@signe/reactive\";\n\ninterface VideoProps {\n    src: string;\n    paused?: boolean;\n    loop?: boolean;\n    muted?: boolean;\n    loader?: {\n        onComplete?: (texture: Texture) => void;\n        onProgress?: (progress: number) => void;\n    };\n}\n\nexport function Video(props: VideoProps) {\n    const eventsMap = {\n        audioprocess: null,\n        canplay: null,\n        canplaythrough: null,\n        complete: null,\n        durationchange: null,\n        emptied: null,\n        ended: null,\n        loadeddata: null,\n        loadedmetadata: null,\n        pause: null,\n        play: null,\n        playing: null,\n        progress: null,\n        ratechange: null,\n        seeked: null,\n        seeking: null,\n        stalled: null,\n        suspend: null,\n        timeupdate: null,\n        volumechange: null,\n        waiting: null\n    }\n\n    const video: Signal<HTMLVideoElement | null> = signal(null)\n    const defineProps = useDefineProps(props)\n    const { play, loop, muted } = defineProps({\n        play: {\n            type: Boolean,\n            default: true\n        },\n        loop: {\n            type: Boolean,\n            default: false\n        },\n        muted: {\n            type: Boolean,\n            default: false\n        }\n    })\n\n    effect(() => {\n        const _video = video()\n        const state = play()\n        if (_video && state !== undefined) {\n            if (state) {\n                _video.play()\n            } else {\n                _video.pause()\n            }\n        }\n        if (_video && loop()) {\n            _video.loop = loop()\n        }\n        if (_video && muted()) {\n            _video.muted = muted()\n        }\n    })\n\n    mount(() => {\n        return () => {\n            for (let event in eventsMap) {\n                if (eventsMap[event]) {\n                    video().removeEventListener(event, eventsMap[event])\n                }\n            }\n        }\n    })\n\n    return h(Sprite, {\n        ...props,\n        image: props.src,\n        loader: {\n            onComplete: (texture) => {\n                const source = texture.source.resource\n                video.set(source)\n                if (props?.loader?.onComplete) {\n                    props.loader.onComplete(texture)\n                }\n                for (let event in eventsMap) {\n                    if (props[event]) {\n                        const cb = (ev) => {\n                            props[event](ev)\n                        }\n                        eventsMap[event] = cb\n                        source.addEventListener(event, cb)\n                    }\n                }\n            }\n        }\n    })\n}"
  },
  {
    "path": "packages/core/src/components/Viewport.ts",
    "content": "import { Viewport as PixiViewport } from 'pixi-viewport';\nimport { Subscription } from 'rxjs';\nimport { createComponent, registerComponent, Element, Props } from '../engine/reactive';\nimport { DisplayObject, ComponentInstance } from './DisplayObject';\nimport { effect, Signal } from '@signe/reactive';\nimport { Graphics, Container, ContainerChild, IRenderLayer } from 'pixi.js';\n\nconst EVENTS = [\n    'bounce-x-end',\n    'bounce-x-start',\n    'bounce-y-end',\n    'bounce-y-start',\n    'clicked',\n    'drag-end',\n    'drag-start',\n    'frame-end',\n    'mouse-edge-end',\n    'mouse-edge-start',\n    'moved',\n    'moved-end',\n    'pinch-end',\n    'pinch-start',\n    'snap-end',\n    'snap-start',\n    'snap-zoom-end',\n    'snap-zoom-start',\n    'wheel-scroll',\n    'zoomed',\n    'zoomed-end'\n]\n\nexport interface ViewportProps extends Props {\n    screenWidth?: number;\n    screenHeight?: number;\n    worldWidth?: number;\n    worldHeight?: number;\n    sortableChildren?: boolean;\n    clamp?: boolean | {\n        left?: number;\n        right?: number;\n        top?: number;\n        bottom?: number;\n    };\n    context?: any;\n    [key: string]: any;\n}\n\nexport class CanvasViewport extends DisplayObject(Container) {\n    private tickSubscription: Subscription\n    overrideProps = ['wheel']\n    #mask: Graphics\n    public viewport: PixiViewport\n\n    constructor() {\n        super()\n        const defaultOptions = {\n            noTicker: true,\n            events: {\n                domElement: {\n                    addEventListener: () => { }\n                }\n            },\n        }\n        // @ts-ignore\n        this.viewport = new PixiViewport(defaultOptions)\n        super.addChild(this.viewport)\n\n        this.#mask = new Graphics()\n        super.addChild(this.#mask)\n        this.mask = this.#mask\n    }\n\n    addChild<U extends any[]>(...children: U): U[0] {\n        return this.viewport.addChild(...children)\n    }\n\n    addChildAt<T extends ContainerChild | IRenderLayer>(child: T, index: number): T {\n        return this.viewport.addChildAt(child, index) as T\n    }\n\n    onInit(props) {\n        super.onInit(props)\n        for (let event of EVENTS) {\n            if (props[event]) this.viewport.on(event, props[event])\n        }\n    }\n\n    /**\n     * Called when the component is mounted to the scene graph.\n     * Initializes viewport settings and subscriptions.\n     * @param {Element<CanvasViewport>} element - The element being mounted. Its `props` property (of type ViewportProps) contains component properties and context.\n     * @param {number} [index] - The index of the component among its siblings.\n     */\n    async onMount(element: Element<any>, index?: number): Promise<void> {\n        element.props.context.viewport = this.viewport\n        await super.onMount(element, index);\n        const { props } = element;\n        const { tick, app, canvasSize } = props.context;\n\n        effect(() => {\n            if (props.screenWidth === undefined) {\n                this.viewport.screenWidth = canvasSize().width\n            }\n            if (props.screenHeight === undefined) {\n                this.viewport.screenHeight = canvasSize().height\n            }\n            this.updateMask()\n        })\n\n        effect(() => {\n            const _app = app()\n            if (!_app) return\n\n            const renderer = _app.renderer\n\n            renderer.events.domElement.addEventListener(\n                'wheel',\n                this.viewport.input.wheelFunction\n            );\n\n            this.viewport.options.events = renderer.events\n        })\n\n        this.tickSubscription = tick.observable.subscribe(({ value }) => {\n            this.viewport.update(value.deltaTime)\n        })\n\n        this.updateViewportSettings(props)\n    }\n\n    onUpdate(props) {\n        super.onUpdate(props)\n        this.updateViewportSettings(props)\n    }\n\n    private updateViewportSettings(props) {\n        if (props.screenWidth !== undefined) {\n            this.viewport.screenWidth = props.screenWidth\n        }\n        if (props.screenHeight !== undefined) {\n            this.viewport.screenHeight = props.screenHeight\n        }\n        this.updateMask()\n        if (props.worldWidth !== undefined) {\n            this.viewport.worldWidth = props.worldWidth\n        }\n        if (props.worldHeight !== undefined) {\n            this.viewport.worldHeight = props.worldHeight\n        }\n        if (props.sortableChildren !== undefined) {\n            this.viewport.sortableChildren = props.sortableChildren\n        }\n        if (props.drag) {\n            this.viewport.drag(props.drag)\n        }\n        if (props.clamp) {\n            this.viewport.clamp(props.clamp.value ?? props.clamp)\n        }\n        if (props.wheel) {\n            if (props.wheel === true) {\n                this.viewport.wheel()\n            } else {\n                this.viewport.wheel(props.wheel)\n            }\n        }\n        if (props.decelerate) {\n            if (props.decelerate === true) {\n                this.viewport.decelerate()\n            } else {\n                this.viewport.decelerate(props.decelerate)\n            }\n        }\n        if (props.pinch) {\n            if (props.pinch === true) {\n                this.viewport.pinch()\n            } else {\n                this.viewport.pinch(props.pinch)\n            }\n        }\n    }\n\n    private updateMask() {\n        if (!this.#mask) return\n        this.#mask.clear()\n        this.#mask.beginFill(0xffffff)\n        this.#mask.drawRect(0, 0, this.viewport.screenWidth, this.viewport.screenHeight)\n        this.#mask.endFill()\n    }\n\n    /**\n     * Called when the component is about to be destroyed.\n     * Unsubscribes from the tick observable.\n     * @param {Element<any>} parent - The parent element.\n     * @param {() => void} [afterDestroy] - An optional callback function to be executed after the component's own destruction logic.\n     */\n    async onDestroy(parent: Element<any>, afterDestroy?: () => void): Promise<void> {\n        const _afterDestroy = async () => {\n            this.tickSubscription.unsubscribe()\n            afterDestroy()\n        }\n        await super.onDestroy(parent, _afterDestroy);\n    }\n\n    // Proxy methods for viewport plugins\n    follow(...args: any[]) {\n        return (this.viewport.follow as any)(...args)\n    }\n\n    get plugins() {\n        return this.viewport.plugins\n    }\n}\n\nregisterComponent('Viewport', CanvasViewport)\n\nexport function Viewport(props: ViewportProps) {\n    return createComponent('Viewport', props);\n}\n"
  },
  {
    "path": "packages/core/src/components/index.ts",
    "content": "export { Canvas } from './Canvas'\nexport { Container } from './Container'\nexport { Graphics, Rect, Circle, Ellipse, Triangle, Svg } from './Graphic'\nexport { Mesh } from './Mesh'\nexport { Scene } from './Scene'\nexport { ParticlesEmitter } from './ParticleEmitter'\nexport { Sprite } from './Sprite'\nexport { Video } from './Video'\nexport { Text } from './Text'\nexport { TilingSprite } from './TilingSprite'\nexport { Viewport } from './Viewport'\nexport { NineSliceSprite } from './NineSliceSprite'\nexport { type ComponentInstance } from './DisplayObject'\nexport { DOMContainer } from './DOMContainer'\nexport { DOMElement } from './DOMElement'\nexport { DOMSprite } from './DOMSprite'\nexport { Button, ButtonState, type ButtonProps, type ButtonStyle } from './Button'\nexport { Joystick, type JoystickSettings } from './Joystick'\nexport { FocusContainer, Navigation, type FocusContainerProps } from './FocusContainer'\n"
  },
  {
    "path": "packages/core/src/components/types/DisplayObject.ts",
    "content": "import * as PIXI from \"pixi.js\";\nimport { SignalOrPrimitive } from \".\";\nimport { DragProps } from \"../../directives/Drag\";\nimport { ViewportFollowProps } from \"../../directives/ViewportFollow\";\nimport { ShakeProps } from \"../../directives/Shake\";\nimport { FlashProps } from \"../../directives/Flash\";\nimport { FogVisibilityProps } from \"../../directives/FogVisibility\";\n\nexport type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';\nexport type JustifyContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';\nexport type AlignContent = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around';\nexport type Size = number | `${number}%`\nexport type EdgeSize = SignalOrPrimitive<Size | [Size, Size] | [Size, Size, Size, Size]>\nexport type ObjectFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';\nexport type ObjectPosition = string;\nexport type TransformOrigin = string;\nexport type PositionType = 'relative' | 'absolute' | 'static';\n\nexport type ObservablePointSignal = [number, number] | SignalOrPrimitive<[number, number]> | { x: number, y: number } | SignalOrPrimitive<{ x: number, y: number }>;\n\nexport interface DisplayObjectProps {\n    attach?: any;\n    ref?: string;\n    x?: SignalOrPrimitive<number>;\n    y?: SignalOrPrimitive<number>;\n    width?: SignalOrPrimitive<Size>;\n    height?: SignalOrPrimitive<Size>;\n    minWidth?: SignalOrPrimitive<Size>;\n    minHeight?: SignalOrPrimitive<Size>;\n    maxWidth?: SignalOrPrimitive<Size>;\n    maxHeight?: SignalOrPrimitive<Size>;\n    aspectRatio?: SignalOrPrimitive<number>;\n    flexGrow?: SignalOrPrimitive<number>;\n    flexShrink?: SignalOrPrimitive<number>;\n    flexBasis?: SignalOrPrimitive<Size>;\n    rowGap?: SignalOrPrimitive<number>;\n    columnGap?: SignalOrPrimitive<number>;\n    positionType?: PositionType;\n    top?: SignalOrPrimitive<Size>;\n    right?: SignalOrPrimitive<Size>;\n    bottom?: SignalOrPrimitive<Size>;\n    left?: SignalOrPrimitive<Size>;\n    objectFit?: ObjectFit;\n    objectPosition?: ObjectPosition;\n    transformOrigin?: TransformOrigin;\n    children?: any[];\n    flexDirection?: FlexDirection;\n    justifyContent?: JustifyContent;\n    alpha?: SignalOrPrimitive<number>;\n    margin?: EdgeSize;\n    padding?: EdgeSize;\n    border?: EdgeSize;\n    absolute?: SignalOrPrimitive<boolean>;\n    scale?: ObservablePointSignal | number;\n    anchor?: ObservablePointSignal;\n    skew?: ObservablePointSignal;\n    tint?: SignalOrPrimitive<number>;\n    rotation?: SignalOrPrimitive<number>;\n    angle?: SignalOrPrimitive<number>;\n    zIndex?: SignalOrPrimitive<number>;\n    roundPixels?: SignalOrPrimitive<boolean>;\n    cursor?: SignalOrPrimitive<string>;\n    visible?: SignalOrPrimitive<boolean>;\n    pivot?: ObservablePointSignal;\n    filters?: any[];\n    blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;\n    blur?: SignalOrPrimitive<number>;\n    /**\n     * Optional metadata used by presets (for example `SpriteShadows`)\n     * to mark this display object as a shadow caster.\n     */\n    shadowCaster?: any;\n    /**\n     * Optional metadata used by presets (for example `Footprints`)\n     * to mark this display object as a footprint caster.\n     */\n    footprintCaster?: any;\n\n    // Directives\n    drag?: DragProps;\n    viewportFollow?: ViewportFollowProps;\n    shake?: ShakeProps;\n    flash?: FlashProps;\n    fogVisibility?: FogVisibilityProps;\n\n    // Events\n    click?: PIXI.FederatedEventHandler;\n    mousedown?: PIXI.FederatedEventHandler;\n    mouseenter?: PIXI.FederatedEventHandler;\n    mouseleave?: PIXI.FederatedEventHandler;\n    mousemove?: PIXI.FederatedEventHandler;\n    mouseout?: PIXI.FederatedEventHandler;\n    mouseover?: PIXI.FederatedEventHandler;\n    mouseup?: PIXI.FederatedEventHandler;\n    mouseupoutside?: PIXI.FederatedEventHandler;\n    pointercancel?: PIXI.FederatedEventHandler;\n    pointerdown?: PIXI.FederatedEventHandler;\n    pointerenter?: PIXI.FederatedEventHandler;\n    pointerleave?: PIXI.FederatedEventHandler;\n    pointermove?: PIXI.FederatedEventHandler;\n    pointerout?: PIXI.FederatedEventHandler;\n    pointerover?: PIXI.FederatedEventHandler;\n    pointertap?: PIXI.FederatedEventHandler;\n    pointerup?: PIXI.FederatedEventHandler;\n    pointerupoutside?: PIXI.FederatedEventHandler;\n    rightclick?: PIXI.FederatedEventHandler;\n    rightdown?: PIXI.FederatedEventHandler;\n    rightup?: PIXI.FederatedEventHandler;\n    rightupoutside?: PIXI.FederatedEventHandler;\n    tap?: PIXI.FederatedEventHandler;\n    touchcancel?: PIXI.FederatedEventHandler;\n    touchend?: PIXI.FederatedEventHandler;\n    touchendoutside?: PIXI.FederatedEventHandler;\n    touchmove?: PIXI.FederatedEventHandler;\n    touchstart?: PIXI.FederatedEventHandler;\n    wheel?: PIXI.FederatedEventHandler<PIXI.FederatedWheelEvent>;\n    tabindex?: SignalOrPrimitive<number>;\n}\n"
  },
  {
    "path": "packages/core/src/components/types/MouseEvent.ts",
    "content": "export interface MouseEvent {\n    click?: (e: any) => void\n}"
  },
  {
    "path": "packages/core/src/components/types/Spritesheet.ts",
    "content": "export interface TransformOptions {\n    /** \n     * The global value of opacity (between 0 and 1)\n     * \n     * @prop {number} [opacity]\n     * @memberof Spritesheet\n     * */\n    opacity?: number\n    /** \n     * The global value of pivot.\n     * \n     * Invariant under rotation, scaling, and skewing. The projection of into the parent's space of the pivot is equal to position, regardless of the other three transformations. In other words, It is the center of rotation, scaling, and skewing.\n     * \n     * The array has two elements: [x, y].  If y is omitted, both x and y will be set to x.\n     * \n     * ```ts\n     * pivot: [0.5, 0.8]\n     * ```\n     * \n     * @prop {Array<number>} [pivot]\n     * @memberof Spritesheet\n     * */\n    pivot?: number[]\n\n    /** \n    * The global value of anchor.\n    * \n    * Position of the origin point\n    * \n    * The array has two elements: [x, y].  If y is omitted, both x and y will be set to x.\n    * \n    * ```ts\n    * anchor: [0.5, 0.8]\n    * ```\n    * \n    * @prop {Array<number>} [anchor]\n    * @memberof Spritesheet\n    * */\n    anchor?: number[]\n\n    /** \n     * Defines the actual size of the sprite that is inside a larger rectangle.\n     * For example, if the texture rectangle is 192x192 while the character, which is in the center, is only 64x64 then set `spriteRealSize: 64`. This way the character will be well positioned in relation to the animations that have a different rectangle\n     * \n     * > You can also put `spriteRealSize: { width: 64, height: 64 }` but be aware that the width is not concerned because it will always be centered while the height depends on the hitbox\n     * \n     * @prop {{ width: number, height: number } | number} [spriteRealSize]\n     * @since 3.2.0\n     * @memberof Spritesheet\n     * */\n    spriteRealSize?: { width: number, height: number } | number\n\n    /** \n     * The global value of rotation\n     * \n     * Rotation. This will rotate the display object's projection by this angle (in radians).\n     * \n     * @prop {number} [angle]\n     * @memberof Spritesheet\n     * */\n    angle?: number\n\n    /** \n     * The global value of rotation\n     * \n     * Rotation. This is an alias for rotation, but in degrees.\n     * \n     * @prop {number} [rotation]\n     * @memberof Spritesheet\n     * */\n    rotation?: number\n\n    /** \n    * The global value of scale.\n    * \n    * Scaling. This will stretch (or compress) the display object's projection. The scale factors are along the local coordinate axes. In other words, the display object is scaled before rotated or skewed. The center of scaling is the pivot.\n    * \n    * The array has two elements: [x, y].  If y is omitted, both x and y will be set to x.\n    * \n    * ```ts\n    * scale: [0.5, 0.8]\n    * ```\n    * \n    * @prop {Array<number>} [scale]\n    * @memberof Spritesheet\n    * */\n    scale?: number[]\n\n    /** \n    * The global value of skew.\n    * \n    * Skewing. This can be used to deform a rectangular display object into a parallelogram.\n    * \n    * In PixiJS, skew has a slightly different behaviour than the conventional meaning. It can be thought of the net rotation applied to the coordinate axes (separately). For example, if \"skew.x\" is ⍺ and \"skew.y\" is β, then the line x = 0 will be rotated by ⍺ (y = -x*cot⍺) and the line y = 0 will be rotated by β (y = x*tanβ). A line y = x*tanϴ (i.e. a line at angle ϴ to the x-axis in local-space) will be rotated by an angle between ⍺ and β.\n    * \n    * It can be observed that if skew is applied equally to both axes, then it will be equivalent to applying a rotation. Indeed, if \"skew.x\" = -ϴ and \"skew.y\" = ϴ, it will produce an equivalent of \"rotation\" = ϴ.\n    * \n    * Another quite interesting observation is that \"skew.x\", \"skew.y\", rotation are communtative operations. Indeed, because rotation is essentially a careful combination of the two.\n    * \n    * The array has two elements: [x, y].  If y is omitted, both x and y will be set to x.\n    * \n    * @prop {Array<number>} [skew]\n    * @memberof Spritesheet\n    * */\n    skew?: number[]\n\n    /** \n    * The global value of X translation\n    * \n    * @prop {number} [x]\n    * @memberof Spritesheet\n    * */\n    x?: number\n\n    /** \n    * The global value of Y translation\n    * \n    * @prop {number} [y]\n    * @memberof Spritesheet\n    * */\n    y?: number\n\n    /** \n     * The global value of visible\n     * \n     * @prop {boolean} [visible]\n     * @memberof Spritesheet\n     * */\n    visible?: boolean\n\n    /** \n    * Define the sound that will be played for all animations in the spritesheet. Remember to create the sound before with the @Sound decorator\n    * \n    * @prop {string} [sound]\n    * @memberof Spritesheet\n    * */\n    sound?: string\n}\n\nexport interface FrameOptions extends TransformOptions {\n    time: number\n    frameX?: number\n    frameY?: number\n}\n\nexport interface TextureOptions {\n    /** \n    * The number of frames on the width\n    * \n    * @prop {number} framesWidth\n    * @memberof Spritesheet\n    * */\n    framesWidth?: number,\n\n    /** \n     * The number of frames on the height\n     * \n     * @prop {number} framesHeight\n     * @memberof Spritesheet\n     * */\n    framesHeight?: number,\n\n    /** \n    * The width of the image (in pixels)\n    * \n    * @prop {number} width\n    * @memberof Spritesheet\n    * */\n    width?: number,\n\n    /** \n     * The height of the image (in pixels)\n     * \n     * @prop {number} height\n     * @memberof Spritesheet\n     * */\n    height?: number\n\n    /** \n    * Takes a width of a rectangle in the image. Equivalent to `width / framesWidth`\n    * \n    * @prop {number} [rectWidth]\n    * @memberof Spritesheet\n    * */\n    rectWidth?: number,\n\n    /** \n    * Takes a height of a rectangle in the image. Equivalent to `height / framesHeight`\n    * \n    * @prop {number} [rectHeight]\n    * @memberof Spritesheet\n    * */\n    rectHeight?: number,\n\n    /** \n    * To take the texture, start at a well defined X and Y position. Otherwise, it starts at 0,0\n    * \n    * @prop {number} [offset]\n    * @memberof Spritesheet\n    * */\n    offset?: { x: number, y: number }\n}\n\nexport type AnimationFrames = FrameOptions[][] | ((...args: any) => FrameOptions[][])\n\nexport interface TexturesOptions extends TextureOptions, TransformOptions {\n    animations: AnimationFrames\n}\n\nexport interface SpritesheetOptions extends TransformOptions, TextureOptions {\n    textures?: {\n        [animationName: string]: Partial<TexturesOptions> & Pick<TexturesOptions, 'animations'>\n    }\n}\n\ntype SpritesheetImageOptions = SpritesheetOptions & {\n    /** \n     * The link to the image\n     * \n     * > Do not use the `images` property\n     * > Remember to wrap the link to the image with the `require` function.\n     * \n     * ```ts\n     * image: require('./assets/hero.png')\n     * ```\n     * \n     * @prop {string} [image]\n     * @memberof Spritesheet\n     * */\n    image?: string,\n    /** \n    * Spritesheet identifier.\n    * \n    * > Do not use the `images` property\n    * \n    * @prop {string} [id]\n    * @memberof Spritesheet\n    * */\n    id: string\n}\ntype SpritesheetImagesOptions = SpritesheetOptions & {\n    /** \n     * Put the different images that are concerned by the properties below.\n     * The key of the object is the identifier of the spritesheet and the value and the link to the image.\n     * \n     * > Remember to wrap the link to the image with the `require` function.\n     * \n     * ```ts\n     * images: {\n     *    hero: require('./assets/hero.png')\n     * }\n     * ```\n     * \n     * @prop { { [id: string]: string } } [images]\n     * @memberof Spritesheet\n     * */\n    images?: { [id: string]: string }\n}\n\nexport function Spritesheet(options: SpritesheetImageOptions)\nexport function Spritesheet(options: SpritesheetImagesOptions)\nexport function Spritesheet(options: SpritesheetImageOptions | SpritesheetImagesOptions) {\n    return (target: Function) => {\n        if ('images' in options) target['images'] = options.images\n        if ('id' in options) target['id'] = options.id\n        for (let key in options) {\n            target.prototype[key] = options[key]\n        }\n        return\n    }\n}"
  },
  {
    "path": "packages/core/src/components/types/index.ts",
    "content": "import { Signal } from \"@signe/reactive\";\nimport { AnimatedSignal } from \"../../engine/animation\";\n\nexport type SignalOrPrimitive<T> = T | Signal<T> | AnimatedSignal<T>;"
  },
  {
    "path": "packages/core/src/directives/Controls.ts",
    "content": "import { Directive, registerDirective } from \"../engine/directive\";\nimport { Element, isElementFrozen } from \"../engine/reactive\";\nimport { ControlsBase, Controls } from \"./ControlsBase\";\nimport { KeyboardControls } from \"./KeyboardControls\";\nimport { GamepadControls, GamepadConfig } from \"./GamepadControls\";\nimport { JoystickControls, JoystickConfig } from \"./JoystickControls\";\nimport { Signal, isSignal } from \"@signe/reactive\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Controls directive that coordinates keyboard, gamepad, and joystick input systems\n * \n * This directive automatically activates keyboard, gamepad, and joystick controls when available.\n * The gamepad is automatically enabled if joypad.js is detected in the environment.\n * \n * All systems share the same control configuration and can work simultaneously.\n * \n * @example\n * ```html\n * <Sprite \n *   image=\"path/to/image.png\" \n *   controls={controlsConfig}\n *   x={x}\n *   y={y}\n * />\n * ```\n */\nexport class ControlsDirective extends Directive {\n    private keyboardControls: KeyboardControls | null = null;\n    private gamepadControls: GamepadControls | null = null;\n    private joystickControls: JoystickControls | null = null;\n    private freezeSubscription: Subscription | null = null;\n    private element: Element | null = null;\n\n    /**\n     * Initialize the controls directive\n     * Sets up keyboard, gamepad, and joystick controls if available\n     */\n    onInit(element: Element<any>) {\n        this.element = element;\n        const value = element.props.controls?.value ?? element.props.controls;\n        if (!value) return;\n\n        // Initialize keyboard controls (always available)\n        this.keyboardControls = new KeyboardControls();\n        this.keyboardControls.setInputs(value as Controls);\n        this.keyboardControls.start();\n\n        // Initialize gamepad controls if gamepad config is present\n        // GamepadControls will handle joypad.js availability internally\n        const gamepadConfig = (value as Controls & { gamepad?: GamepadConfig }).gamepad;\n        if (gamepadConfig !== undefined && gamepadConfig.enabled !== false) {\n            this.gamepadControls = new GamepadControls();\n            this.gamepadControls.setInputs(value as Controls & { gamepad?: GamepadConfig });\n            this.gamepadControls.start();\n        }\n\n        // Initialize joystick controls if joystick config is present\n        const joystickConfig = (value as Controls & { joystick?: JoystickConfig }).joystick;\n        if (joystickConfig !== undefined && joystickConfig.enabled !== false) {\n            this.joystickControls = new JoystickControls();\n            this.joystickControls.setInputs(value as Controls & { joystick?: JoystickConfig });\n            this.joystickControls.start();\n        }\n\n        // Check initial freeze state\n        if (isElementFrozen(element)) {\n            this.stopInputs();\n        }\n\n        // Subscribe to freeze prop if it's a signal\n        const freezeProp = element.propObservables?.freeze ?? element.props?.freeze;\n        if (isSignal(freezeProp)) {\n            this.freezeSubscription = ((freezeProp as Signal<boolean>).observable as any).subscribe((isFrozen) => {\n                if (isFrozen) {\n                    this.stopInputs();\n                } else {\n                    this.listenInputs();\n                }\n            });\n        }\n    }\n\n    /**\n     * Mount hook (no specific action needed)\n     */\n    onMount(element: Element<any>) { }\n\n    /**\n     * Update controls configuration\n     * Updates both keyboard and gamepad controls\n     */\n    onUpdate(props: any, element: Element<any>) {\n        const value = props.controls?.value ?? props.controls;\n        if (value) {\n            if (this.keyboardControls) {\n                this.keyboardControls.setInputs(value as Controls);\n            }\n\n            if (this.gamepadControls) {\n                this.gamepadControls.setInputs(value as Controls & { gamepad?: GamepadConfig });\n            }\n        }\n\n        // Handle freeze prop update\n        if (props.freeze !== undefined && this.element) {\n            if (isElementFrozen(this.element)) {\n                this.stopInputs();\n            } else {\n                this.listenInputs();\n            }\n        }\n    }\n\n    /**\n     * Cleanup and destroy all control systems\n     */\n    onDestroy(element: Element<any>) {\n        if (this.freezeSubscription) {\n            this.freezeSubscription.unsubscribe();\n            this.freezeSubscription = null;\n        }\n\n        if (this.keyboardControls) {\n            this.keyboardControls.destroy();\n            this.keyboardControls = null;\n        }\n\n        if (this.gamepadControls) {\n            this.gamepadControls.destroy();\n            this.gamepadControls = null;\n        }\n\n        if (this.joystickControls) {\n            this.joystickControls.destroy();\n            this.joystickControls = null;\n        }\n\n        this.element = null;\n    }\n\n    /**\n     * Get a control by input name\n     * Delegates to keyboard controls (primary system)\n     * \n     * @param inputName - Name of the input/key\n     * @returns BoundKey if found, undefined otherwise\n     */\n    getControl(inputName: string) {\n        return this.keyboardControls?.getControl(inputName);\n    }\n\n    /**\n     * Get all bound controls\n     * Delegates to keyboard controls (primary system)\n     * \n     * @returns Object mapping input names to BoundKey objects\n     */\n    getControls() {\n        return this.keyboardControls?.getControls() || {};\n    }\n\n    /**\n     * Apply a control action programmatically\n     * Applies to both keyboard and gamepad if available\n     * \n     * @param controlName - Name of the control\n     * @param isDown - Whether the control is pressed (true) or released (false)\n     * @param payload - Optional payload to pass to keyDown/keyUp callbacks (e.g., { power: 0.8 })\n     * @returns Promise that resolves when the action is complete\n     */\n    async applyControl(controlName: string | number, isDown?: boolean, payload?: any): Promise<void> {\n        if (this.keyboardControls) {\n            await this.keyboardControls.applyControl(controlName, isDown);\n        }\n        if (this.gamepadControls) {\n            await this.gamepadControls.applyControl(controlName, isDown, payload);\n        }\n        if (this.joystickControls) {\n            await this.joystickControls.applyControl(controlName, isDown, payload);\n        }\n    }\n\n    /**\n     * Stop listening to inputs\n     * Stops keyboard, gamepad, and joystick input processing\n     */\n    stopInputs() {\n        if (this.keyboardControls) {\n            this.keyboardControls.stopInputs();\n        }\n        if (this.gamepadControls) {\n            this.gamepadControls.stopInputs();\n        }\n        if (this.joystickControls) {\n            this.joystickControls.stopInputs();\n        }\n    }\n\n    /**\n     * Resume listening to inputs\n     * Resumes keyboard, gamepad, and joystick input processing\n     */\n    listenInputs() {\n        if (this.keyboardControls) {\n            this.keyboardControls.listenInputs();\n        }\n        if (this.gamepadControls) {\n            this.gamepadControls.listenInputs();\n        }\n        if (this.joystickControls) {\n            this.joystickControls.listenInputs();\n        }\n    }\n\n    /**\n     * Get the current controls configuration\n     * Returns keyboard controls options (both systems share the same config)\n     * \n     * @returns The controls options object\n     */\n    get options(): Controls {\n        return this.keyboardControls?.options || {};\n    }\n\n    /**\n     * Get the keyboard controls instance\n     * \n     * @returns KeyboardControls instance or null\n     */\n    get keyboard(): KeyboardControls | null {\n        return this.keyboardControls;\n    }\n\n    /**\n     * Get the gamepad controls instance\n     * \n     * @returns GamepadControls instance or null\n     */\n    get gamepad(): GamepadControls | null {\n        return this.gamepadControls;\n    }\n\n    /**\n     * Get the joystick controls instance\n     * \n     * @returns JoystickControls instance or null\n     */\n    get joystick(): JoystickControls | null {\n        return this.joystickControls;\n    }\n}\n\nregisterDirective('controls', ControlsDirective);\n"
  },
  {
    "path": "packages/core/src/directives/ControlsBase.ts",
    "content": "import { fps2ms } from \"../engine/utils\";\n\nexport interface ControlOptions {\n    repeat?: boolean;\n    bind: string | string[];\n    keyUp?: Function;\n    keyDown?: Function;\n    throttle?: number;\n    delay?: number | {\n        duration: number;\n        otherControls?: (string)[];\n    };\n}\n\nexport interface Controls {\n    [controlName: string]: ControlOptions;\n}\n\nexport type BoundKey = { actionName: string, options: ControlOptions, parameters?: any };\n\n/**\n * Abstract base class for control systems (keyboard, gamepad, etc.)\n * \n * This class provides common functionality shared across all control implementations:\n * - Input binding and management\n * - Control configuration\n * - Input state management\n * - Common methods for querying and triggering controls\n * \n * @example\n * ```ts\n * class MyControls extends ControlsBase {\n *   protected setupListeners() {\n *     // Setup specific input listeners\n *   }\n *   \n *   protected cleanup() {\n *     // Cleanup specific resources\n *   }\n *   \n *   protected preStep() {\n *     // Process inputs each frame\n *   }\n * }\n * ```\n */\nexport abstract class ControlsBase {\n    protected boundKeys: {\n        [keyName: string]: BoundKey\n    } = {}\n    protected stop: boolean = false\n    protected _controlsOptions: Controls = {}\n    protected interval: any\n    protected serverFps: number = 60\n\n    /**\n     * Setup input listeners specific to this control implementation\n     * Must be implemented by subclasses\n     */\n    protected abstract setupListeners(): void;\n\n    /**\n     * Cleanup resources specific to this control implementation\n     * Must be implemented by subclasses\n     */\n    protected abstract cleanup(): void;\n\n    /**\n     * Process inputs each step/frame\n     * Must be implemented by subclasses\n     */\n    protected abstract preStep(): void;\n\n    /**\n     * Start the control processing loop\n     * Initializes listeners and starts the interval\n     */\n    start() {\n        this.setupListeners();\n        this.interval = setInterval(() => {\n            this.preStep()\n        }, fps2ms(this.serverFps ?? 60))\n    }\n\n    /**\n     * Stop the control processing and cleanup resources\n     */\n    destroy() {\n        if (this.interval) {\n            clearInterval(this.interval)\n        }\n        this.cleanup();\n    }\n\n    /**\n     * Bind a key/input to a control action\n     * \n     * @param keys - Single key or array of keys to bind\n     * @param actionName - Name of the control action\n     * @param options - Control options (repeat, keyDown, keyUp, etc.)\n     * @param parameters - Optional parameters to pass to the control callbacks\n     */\n    protected bindKey(keys: string | string[], actionName: string, options: ControlOptions, parameters?: object) {\n        if (!Array.isArray(keys)) keys = [keys]\n        const keyOptions = Object.assign({\n            repeat: false\n        }, options);\n        keys.forEach(keyName => {\n            this.boundKeys[keyName] = { actionName, options: keyOptions, parameters }\n        })\n    }\n\n    /**\n     * Apply an input action for a bound key\n     * Can be overridden by subclasses for custom behavior\n     * \n     * @param keyName - Name of the key/input to process\n     */\n    protected applyInput(keyName: string) {\n        const boundKey = this.boundKeys[keyName];\n        if (!boundKey) return;\n\n        const { repeat, keyDown } = boundKey.options;\n        // Default implementation - subclasses may override for state tracking\n        if (keyDown) {\n            let parameters = boundKey.parameters;\n            if (typeof parameters === \"function\") {\n                parameters = parameters();\n            }\n            keyDown(boundKey);\n        }\n    }\n\n    /**\n     * Get a control by input name\n     * \n     * @param inputName - Name of the input/key\n     * @returns BoundKey if found, undefined otherwise\n     * @example\n     * ```ts\n     * const control = controls.getControl('up');\n     * if (control) {\n     *   console.log(control.actionName); // 'up'\n     * }\n     * ```\n     */\n    getControl(inputName: string): BoundKey | undefined {\n        return this.boundKeys[inputName]\n    }\n\n    /**\n     * Get all bound controls\n     * \n     * @returns Object mapping input names to BoundKey objects\n     * @example\n     * ```ts\n     * const allControls = controls.getControls();\n     * console.log(Object.keys(allControls)); // ['up', 'down', 'left', 'right', ...]\n     * ```\n     */\n    getControls(): { [key: string]: BoundKey } {\n        return this.boundKeys\n    }\n\n    /**\n     * Apply a control action programmatically\n     * \n     * Must be implemented by subclasses to provide input-specific behavior\n     * \n     * @param controlName - Name or identifier of the control\n     * @param isDown - Whether the control is pressed down (true) or released (false)\n     * @returns Promise that resolves when the control action is complete\n     * @example\n     * ```ts\n     * // Press a control\n     * await controls.applyControl('action', true);\n     * \n     * // Release a control\n     * await controls.applyControl('action', false);\n     * \n     * // Press and release (default)\n     * await controls.applyControl('action');\n     * ```\n     */\n    abstract applyControl(controlName: string | number, isDown?: boolean): Promise<void>;\n\n    /**\n     * Stop listening to inputs\n     * Input events will be ignored until listenInputs() is called\n     * \n     * @example\n     * ```ts\n     * controls.stopInputs();\n     * // ... later\n     * controls.listenInputs();\n     * ```\n     */\n    stopInputs() {\n        this.stop = true\n    }\n\n    /**\n     * Resume listening to inputs after stopInputs() was called\n     * \n     * @example\n     * ```ts\n     * controls.stopInputs();\n     * // ... later\n     * controls.listenInputs();\n     * ```\n     */\n    listenInputs() {\n        this.stop = false\n    }\n\n    /**\n     * Configure controls with input mappings\n     * \n     * This method sets up the binding between input keys/buttons and control actions.\n     * It clears existing bindings and creates new ones based on the provided configuration.\n     * \n     * @param inputs - Control configuration object\n     * @example\n     * ```ts\n     * controls.setInputs({\n     *   up: {\n     *     repeat: true,\n     *     bind: 'up',\n     *     keyDown() {\n     *       console.log('Up pressed');\n     *     }\n     *   },\n     *   action: {\n     *     bind: ['space', 'enter'],\n     *     keyDown() {\n     *       console.log('Action triggered');\n     *     }\n     *   }\n     * });\n     * ```\n     */\n    setInputs(inputs: Controls) {\n        if (!inputs) return\n        this.boundKeys = {}\n        for (let control in inputs) {\n            const option = inputs[control]\n            const { bind } = option\n            let inputsKey: any = bind\n            if (!Array.isArray(inputsKey)) {\n                inputsKey = [bind]\n            }\n            for (let input of inputsKey) {\n                this.bindKey(input, control, option)\n            }\n        }\n        this._controlsOptions = inputs\n    }\n\n    /**\n     * Get the current controls configuration\n     * \n     * @returns The controls options object\n     */\n    get options(): Controls {\n        return this._controlsOptions\n    }\n}\n"
  },
  {
    "path": "packages/core/src/directives/Drag.ts",
    "content": "import { effect, isComputed, isSignal, signal } from '@signe/reactive';\nimport { Container, Rectangle, Point, FederatedPointerEvent } from 'pixi.js';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { snap } from 'popmotion';\nimport { addContext } from '../hooks/addContext';\nimport { Subscription } from 'rxjs';\nimport { useProps } from '../hooks/useProps';\nimport { SignalOrPrimitive } from '../components/types';\n\nexport type DragProps = {\n    move?: (event: FederatedPointerEvent) => void;\n    start?: () => void;\n    end?: () => void;\n    snap?: SignalOrPrimitive<number>;\n    direction?: SignalOrPrimitive<'x' | 'y' | 'all'>;\n    keyToPress?: SignalOrPrimitive<string[]>;\n    viewport?: {\n        edgeThreshold?: SignalOrPrimitive<number>;\n        maxSpeed?: SignalOrPrimitive<number>;\n    };\n}\n\nexport class Drop extends Directive {\n    private elementRef: Element<Container> | null = null;\n\n    onInit(element: Element<Container>) {\n        this.elementRef = element;\n    }\n\n    onMount(element: Element<Container>) {\n        addContext(element, 'drop', element);\n    }\n\n    onUpdate() {}\n\n    onDestroy() {\n        this.elementRef = null;\n    }\n}\n\nexport class Drag extends Directive {\n    private elementRef: Element<Container> | null = null;\n    private stageRef: Container | null = null;\n    private offsetInParent = new Point();\n    private isDragging = false;\n    private viewport: any | null = null;\n    private animationFrameId: number | null = null;\n    private lastPointerPosition: Point = new Point();\n    private pressedKeys: Set<string> = new Set();\n    private pointerIsDown = false;\n\n    private onDragMoveHandler: (event: FederatedPointerEvent) => void = () => {};\n    private onDragEndHandler: () => void = () => {};\n    private onDragStartHandler: (event: FederatedPointerEvent) => void = () => {};\n    private onKeyDownHandler: (event: KeyboardEvent) => void = () => {};\n    private onKeyUpHandler: (event: KeyboardEvent) => void = () => {};\n\n    private subscriptions: Subscription[] = [];\n\n    onInit(element: Element<Container>) {\n        this.elementRef = element;\n        this.onDragMoveHandler = this.onDragMove.bind(this);\n        this.onDragEndHandler = this.onDragEnd.bind(this);\n        this.onDragStartHandler = this.onPointerDown.bind(this);\n        this.onKeyDownHandler = this.onKeyDown.bind(this);\n        this.onKeyUpHandler = this.onKeyUp.bind(this);\n    }\n\n    onMount(element: Element<Container>) {\n        const { rootElement, canvasSize, viewport, tick } = element.props.context;\n        const instance = element.componentInstance;\n        const dragProps = this.dragProps;\n        const haveNotProps = Object.keys(dragProps).length === 0;\n\n        if (haveNotProps) {\n            this.onDestroy();\n            return;\n        }\n        \n        if (!instance) return;\n        this.stageRef = rootElement.componentInstance;\n        if (!this.stageRef) return;\n        this.viewport = viewport;\n\n        instance.eventMode = 'static';\n        this.stageRef.eventMode = 'static';\n\n        const _effect = effect(() => {\n            if (this.stageRef) {\n                this.stageRef.hitArea = new Rectangle(0, 0, canvasSize().width, canvasSize().height);\n            }\n        });\n\n        instance.on('pointerdown', this.onDragStartHandler);\n        this.stageRef.on('pointerup', this.onDragEndHandler);\n        this.stageRef.on('pointerupoutside', this.onDragEndHandler);\n\n        const keysToPress = dragProps.keyToPress ? dragProps.keyToPress : [];\n        \n        // Always add keyboard event listeners to track pressed keys\n        window.addEventListener('keydown', this.onKeyDownHandler);\n        window.addEventListener('keyup', this.onKeyUpHandler);\n\n        this.subscriptions = [\n            tick.observable.subscribe(() => {\n                if (this.isDragging && this.viewport) {\n                    this.updateViewportPosition(this.lastPointerPosition);\n                }\n            }),\n            _effect.subscription\n        ]\n    }\n\n    get dragProps() {\n        const drag = this.elementRef?.props.drag\n        const options = useProps(drag?.value ?? drag, {\n            snap: 0,\n            viewport: {},\n            direction: 'all',\n            keyToPress: []\n        });\n        options.viewport = useProps(options.viewport, {\n            edgeThreshold: 300,\n            maxSpeed: 40\n        });\n        return options;\n    }\n\n    get axis() {\n        const direction = this.dragProps.direction();\n        const axis = {\n            x: true,\n            y: true,\n        }\n        if (direction === 'x') {\n            axis.y = false;\n        }\n        if (direction === 'y') {\n            axis.x = false;\n        }\n        return axis;\n    }\n\n    /**\n     * Updates element position when dragging and starts continuous viewport movement\n     * @param event The pointer event that triggered the drag move\n     */\n    private onDragMove(event: FederatedPointerEvent) {\n        if (!this.isDragging || !this.elementRef?.componentInstance || !this.elementRef.componentInstance.parent) return;\n\n        const instance = this.elementRef.componentInstance;\n        const parent = instance.parent;\n        const dragProps = this.dragProps;\n        const propObservables = this.elementRef.propObservables;\n        const snapTo = snap(dragProps?.snap() ?? 0);\n\n        dragProps?.move?.(event);\n\n        const currentParentLocalPointer = parent.toLocal(event.global);\n\n        const newX = currentParentLocalPointer.x - this.offsetInParent.x;\n        const newY = currentParentLocalPointer.y - this.offsetInParent.y;\n\n        if (dragProps?.snap()) {\n            instance.position.x = snapTo(newX);\n            instance.position.y = snapTo(newY);\n        } else {\n           if (this.axis.x) instance.position.x = newX;\n           if (this.axis.y) instance.position.y = newY;\n        }\n\n        // Store the last pointer position for continuous viewport movement\n        this.lastPointerPosition.copyFrom(event.global);\n\n        const { x: xProp, y: yProp } = propObservables as any;\n\n        const updatePosition = (prop: any, value: number) => {\n            if (isComputed(prop)) {\n                prop.dependencies.forEach(dependency => {\n                    dependency.set(value)\n                })\n            } else if (isSignal(prop)) {\n                prop.set(value)\n            }\n        }\n\n        if (xProp !== undefined) updatePosition(xProp, instance.position.x)\n        if (yProp !== undefined) updatePosition(yProp, instance.position.y)\n    }\n\n    /**\n     * Moves the viewport if the dragged element is near screen edges\n     * @param globalPosition The global pointer position\n     */\n    private updateViewportPosition(globalPosition: Point) {\n        if (!this.viewport || !this.elementRef) return;\n\n        const dragProps = this.dragProps;\n        const edgeThreshold = dragProps?.viewport?.edgeThreshold(); // Distance from edge to trigger viewport movement\n        const maxSpeed = dragProps?.viewport?.maxSpeed(); // Maximum speed when element is at the very edge\n        \n        // Calculate screen boundaries\n        const screenLeft = 0;\n        const screenRight = this.viewport.screenWidth;\n        const screenTop = 0;\n        const screenBottom = this.viewport.screenHeight;\n        const instance = this.elementRef.componentInstance;\n        \n        // Calculate distances from element to screen edges\n        const distanceFromLeft = globalPosition.x - screenLeft;\n        const distanceFromRight = screenRight - globalPosition.x;\n        const distanceFromTop = globalPosition.y - screenTop;\n        const distanceFromBottom = screenBottom - globalPosition.y;\n        \n        let moveX = 0;\n        let moveY = 0;\n        \n        // Calculate horizontal movement with dynamic velocity\n        if (distanceFromLeft < edgeThreshold) {\n            // Velocity increases as distance decreases\n            // When distance = 0, velocity = maxSpeed\n            // When distance = threshold, velocity = 0\n            const velocity = maxSpeed * (1 - (distanceFromLeft / edgeThreshold));\n            moveX = -velocity;\n        } else if (distanceFromRight < edgeThreshold) {\n            const velocity = maxSpeed * (1 - (distanceFromRight / edgeThreshold));\n            moveX = velocity;\n        }\n        \n        // Calculate vertical movement with dynamic velocity\n        if (distanceFromTop < edgeThreshold) {\n            const velocity = maxSpeed * (1 - (distanceFromTop / edgeThreshold));\n            moveY = -velocity;\n        } else if (distanceFromBottom < edgeThreshold) {\n            const velocity = maxSpeed * (1 - (distanceFromBottom / edgeThreshold));\n            moveY = velocity;\n        }\n        \n        // Apply movement with velocity-based displacement\n        if (moveX !== 0 || moveY !== 0) {\n            const lastViewValue = this.viewport.center;\n            this.viewport.moveCenter(\n                this.viewport.center.x + moveX,\n                this.viewport.center.y + moveY\n            );\n            if (this.axis.x && lastViewValue.x !== this.viewport.center.x) {\n                instance.position.x += moveX;\n            }\n            if (this.axis.y && lastViewValue.y !== this.viewport.center.y) {\n                instance.position.y += moveY;\n            }\n        }\n    }\n\n    /**\n     * Handles drag end event and stops viewport movement\n     */\n    private onDragEnd() {\n        this.pointerIsDown = false;\n\n        if (!this.isDragging) return;\n\n        const dragProps = this.dragProps;\n        this.isDragging = false;\n        \n        dragProps?.end?.();\n        \n        if (this.stageRef) {\n            this.stageRef.off('pointermove', this.onDragMoveHandler);\n        }\n    }\n\n    onKeyDown(event: KeyboardEvent) {\n        this.pressedKeys.add(event.code);\n        this.pressedKeys.add(event.key.toLowerCase());\n\n        if (this.pointerIsDown && !this.isDragging && this.areRequiredKeysPressed()) {\n            this.startDrag();\n        }\n    }\n\n    onKeyUp(event: KeyboardEvent) {\n        this.pressedKeys.delete(event.code);\n        this.pressedKeys.delete(event.key.toLowerCase());\n        if (this.isDragging && !this.areRequiredKeysPressed()) {\n            this.onDragEnd();\n        }\n    }\n\n    private areRequiredKeysPressed(): boolean {\n        const keyToPress = this.dragProps.keyToPress ? this.dragProps.keyToPress : [];\n        if (!keyToPress || keyToPress.length === 0) {\n            return true; // No keys required, always return true\n        }\n        \n        return keyToPress.some(key => {\n            // Check if the key is pressed directly\n            if (this.pressedKeys.has(key)) {\n                return true;\n            }\n            \n            // Check common alternative formats\n            // Space key can be \"Space\", \" \", or \"space\"\n            if (key.toLowerCase() === 'space') {\n                return this.pressedKeys.has('Space') || this.pressedKeys.has(' ');\n            }\n            \n            // Shift key can be \"ShiftLeft\", \"ShiftRight\", or \"shift\"\n            if (key.toLowerCase() === 'shift') {\n                return this.pressedKeys.has('ShiftLeft') || this.pressedKeys.has('ShiftRight');\n            }\n            \n            // Control key can be \"ControlLeft\", \"ControlRight\", or \"control\"\n            if (key.toLowerCase() === 'control' || key.toLowerCase() === 'ctrl') {\n                return this.pressedKeys.has('ControlLeft') || this.pressedKeys.has('ControlRight');\n            }\n            \n            // Alt key can be \"AltLeft\", \"AltRight\", or \"alt\"\n            if (key.toLowerCase() === 'alt') {\n                return this.pressedKeys.has('AltLeft') || this.pressedKeys.has('AltRight');\n            }\n            \n            return false;\n        });\n    }\n\n    private onPointerDown(event: FederatedPointerEvent) {\n        if (!this.elementRef?.componentInstance || !this.stageRef || !this.elementRef.componentInstance.parent) return;\n        \n        this.pointerIsDown = true;\n\n        const instance = this.elementRef.componentInstance;\n        const parent = instance.parent;\n\n        const parentLocalPointer = parent.toLocal(event.global);\n\n        this.offsetInParent.x = parentLocalPointer.x - instance.position.x;\n        this.offsetInParent.y = parentLocalPointer.y - instance.position.y;\n        \n        // Store initial pointer position\n        this.lastPointerPosition.copyFrom(event.global);\n        \n        if (this.areRequiredKeysPressed()) {\n            this.startDrag();\n        }\n    }\n\n    private startDrag() {\n        if (this.isDragging || !this.stageRef) return;\n\n        this.isDragging = true;\n        const dragProps = this.dragProps;\n        dragProps?.start?.();\n        this.stageRef.on('pointermove', this.onDragMoveHandler);\n    }\n\n    onUpdate(props) {\n       if (props.type && props.type === 'reset') {\n        this.onDestroy();\n        this.onMount(this.elementRef);\n       }\n    }\n\n    onDestroy() {\n        this.subscriptions.forEach(subscription => subscription.unsubscribe());\n        const instance = this.elementRef?.componentInstance;\n        if (instance) {\n            instance.off('pointerdown', this.onDragStartHandler);\n        }\n        if (this.stageRef) {\n            this.stageRef.off('pointermove', this.onDragMoveHandler);\n            this.stageRef.off('pointerup', this.onDragEndHandler);\n            this.stageRef.off('pointerupoutside', this.onDragEndHandler);\n        }\n        \n        // Remove keyboard event listeners\n        window.removeEventListener('keydown', this.onKeyDownHandler);\n        window.removeEventListener('keyup', this.onKeyUpHandler);\n        \n        this.stageRef = null;\n        this.viewport = null;\n        this.pressedKeys.clear();\n        this.pointerIsDown = false;\n    }\n}\n\nregisterDirective('drag', Drag);\nregisterDirective('drop', Drop);"
  },
  {
    "path": "packages/core/src/directives/Flash.ts",
    "content": "import { Container } from 'pixi.js';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { effect, isSignal } from '@signe/reactive';\nimport { on, isTrigger, Trigger } from '../engine/trigger';\nimport { useProps } from '../hooks/useProps';\nimport { SignalOrPrimitive } from '../components/types';\nimport { animatedSignal, AnimatedSignal } from '../engine/animation';\nimport { Subscription } from 'rxjs';\n\nexport type FlashType = 'alpha' | 'tint' | 'both';\n\nexport type FlashProps = {\n    /**\n     * Trigger that activates the flash animation\n     * When the trigger is activated, the flash animation will start\n     */\n    trigger?: Trigger<any>;\n    /**\n     * Type of flash effect: 'alpha' (opacity), 'tint' (color), or 'both'\n     * @default 'alpha'\n     */\n    type?: SignalOrPrimitive<FlashType>;\n    /**\n     * Duration of the flash animation in milliseconds\n     * @default 300\n     */\n    duration?: SignalOrPrimitive<number>;\n    /**\n     * Number of flash cycles (flash on/off)\n     * @default 1\n     */\n    cycles?: SignalOrPrimitive<number>;\n    /**\n     * Alpha value when flashing (0 to 1)\n     * Only used when type is 'alpha' or 'both'\n     * @default 0.3\n     */\n    alpha?: SignalOrPrimitive<number>;\n    /**\n     * Tint color when flashing (hex color value)\n     * Only used when type is 'tint' or 'both'\n     * @default 0xffffff (white)\n     */\n    tint?: SignalOrPrimitive<number>;\n    /**\n     * Original alpha value to restore after flash\n     * If not provided, uses the current alpha value\n     */\n    originalAlpha?: number;\n    /**\n     * Original tint value to restore after flash\n     * If not provided, uses the current tint value\n     */\n    originalTint?: number;\n    /**\n     * Callback function called when flash starts\n     */\n    onStart?: () => void;\n    /**\n     * Callback function called when flash completes\n     */\n    onComplete?: () => void;\n}\n\n/**\n * Flash directive that animates a display object's alpha and/or tint when a trigger is activated.\n * Creates a flash effect by rapidly changing opacity or color.\n * \n * @example\n * ```typescript\n * // Basic usage with trigger\n * const flashTrigger = trigger();\n * \n * onMount(element) {\n *   // Element will flash when trigger is activated\n *   element.props.flash = { trigger: flashTrigger };\n * }\n * \n * // Trigger the flash\n * flashTrigger.start();\n * ```\n */\nexport class Flash extends Directive {\n    private elementRef: Element<Container> | null = null;\n    private progressSignal: AnimatedSignal<number> | null = null;\n    private flashSubscription: any = null;\n    private alphaEffect: Subscription | null = null;\n    private tintEffect: Subscription | null = null;\n    private originalAlpha: number = 1;\n    private originalTint: number = 0xffffff;\n    private currentFlashConfig: {\n        type: FlashType;\n        duration: number;\n        cycles: number;\n        flashAlpha: number;\n        flashTint: number;\n    } | null = null;\n\n    /**\n     * Initializes the flash directive\n     * @param element - The element to attach the flash effect to\n     */\n    onInit(element: Element<Container>) {\n        this.elementRef = element;\n    }\n\n    /**\n     * Mounts the flash directive and sets up trigger listener\n     * @param element - The element being mounted\n     */\n    onMount(element: Element<Container>) {\n        const instance = element.componentInstance;\n        if (!instance) return;\n\n        const flashProps = this.flashProps;\n        \n        // Check if trigger is provided\n        if (!flashProps.trigger || !isTrigger(flashProps.trigger)) {\n            return;\n        }\n\n        // Store original values once at mount time\n        // Only set if not already stored (to preserve values from first mount)\n        if (this.originalAlpha === 1 && !flashProps.originalAlpha) {\n            this.originalAlpha = instance.alpha ?? 1;\n        } else if (flashProps.originalAlpha !== undefined) {\n            this.originalAlpha = flashProps.originalAlpha;\n        }\n        \n        const currentTint = (instance as any).tint;\n        if (this.originalTint === 0xffffff && !flashProps.originalTint) {\n            this.originalTint = (isSignal(currentTint) ? currentTint() : currentTint) ?? 0xffffff;\n        } else if (flashProps.originalTint !== undefined) {\n            this.originalTint = flashProps.originalTint;\n        }\n\n        // Listen to trigger activation\n        this.flashSubscription = on(flashProps.trigger, async (data) => {\n            await this.performFlash(data);\n        });\n    }\n\n    /**\n     * Gets the flash props with default values\n     * @returns FlashProps with defaults applied\n     */\n    get flashProps(): FlashProps {\n        const flash = this.elementRef?.props.flash;\n        return useProps(flash?.value ?? flash, {\n            type: 'alpha',\n            duration: 300,\n            cycles: 1,\n            alpha: 0.3,\n            tint: 0xffffff,\n        });\n    }\n\n    /**\n     * Performs the flash animation using animatedSignal\n     * @param data - Optional data passed from the trigger that can override default options\n     */\n    private async performFlash(data?: any): Promise<void> {\n        if (!this.elementRef?.componentInstance) return;\n\n        const instance = this.elementRef.componentInstance;\n        const flashProps = this.flashProps;\n        \n        // Use data from trigger to override defaults if provided\n        const type = data?.type ?? (typeof flashProps.type === 'function' ? flashProps.type() : flashProps.type);\n        const duration = data?.duration ?? (typeof flashProps.duration === 'function' ? flashProps.duration() : flashProps.duration);\n        const cycles = data?.cycles ?? (typeof flashProps.cycles === 'function' ? flashProps.cycles() : flashProps.cycles);\n        const flashAlpha = data?.alpha ?? (typeof flashProps.alpha === 'function' ? flashProps.alpha() : flashProps.alpha);\n        const flashTint = data?.tint ?? (typeof flashProps.tint === 'function' ? flashProps.tint() : flashProps.tint);\n\n        // Clean up effects BEFORE stopping animation\n        // This prevents effects from continuing to update values\n        if (this.alphaEffect) {\n            this.alphaEffect.unsubscribe();\n            this.alphaEffect = null;\n        }\n        if (this.tintEffect) {\n            this.tintEffect.unsubscribe();\n            this.tintEffect = null;\n        }\n\n        // DO NOT update original values here if a flash is in progress\n        // Only restore to the already-stored original values to avoid overwriting\n        // with intermediate animation values when multiple flashes trigger quickly\n\n        // Always restore to original values immediately after stopping effects\n        // This ensures that if a new flash starts before the previous one completes,\n        // we restore to the true original values, not the intermediate animation values\n        instance.alpha = this.originalAlpha;\n        const currentInstanceTint = (instance as any).tint;\n        if (currentInstanceTint !== undefined) {\n            // Ensure originalTint is a primitive value, not a signal\n            const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;\n            // Handle both signal and primitive tint\n            if (isSignal(currentInstanceTint)) {\n                currentInstanceTint.set(tintValue);\n            } else {\n                (instance as any).tint = tintValue;\n            }\n        }\n\n        // Call onStart callback early, before async operations\n        flashProps.onStart?.();\n\n        // Stop any existing animation after cleanup and callback\n        if (this.progressSignal) {\n            // Stop the animation immediately and wait for completion\n            await this.progressSignal.set(0, { duration: 0 });\n        }\n\n        // Store current flash configuration for use in effect\n        const flashConfig = {\n            type,\n            duration,\n            cycles,\n            flashAlpha,\n            flashTint,\n        };\n        this.currentFlashConfig = flashConfig;\n\n        // Create or recreate progress signal for flash animation\n        // Note: We already stopped the previous animation above, so we can reuse the signal\n        if (!this.progressSignal) {\n            this.progressSignal = animatedSignal(0, {\n                duration: duration,\n                ease: (t) => t, // Linear ease\n            });\n        }\n        // Signal is already reset to 0 above if it existed, no need to reset again\n\n        // Store references to the effects we're creating to verify they're still active later\n        const expectedAlphaEffect = type === 'alpha' || type === 'both';\n        const expectedTintEffect = type === 'tint' || type === 'both';\n\n        // Create effect to update alpha based on progress\n        if (type === 'alpha' || type === 'both') {\n            this.alphaEffect = effect(() => {\n                if (!instance || !this.progressSignal || !this.currentFlashConfig) return;\n\n                const progress = this.progressSignal();\n                const config = this.currentFlashConfig;\n                \n                // Calculate flash value based on cycles\n                // Each cycle goes from 0 to 1, so we use modulo to repeat\n                const cycleProgress = (progress * config.cycles) % 1;\n                \n                // Create flash effect: fade to flashAlpha then back to original\n                // For each cycle, we flash twice (on/off)\n                const flashPhase = cycleProgress < 0.5 \n                    ? cycleProgress * 2  // Fade to flashAlpha (0 to 1)\n                    : 1 - ((cycleProgress - 0.5) * 2); // Fade back to original (1 to 0)\n                \n                // Interpolate between original and flash alpha\n                const currentAlpha = this.originalAlpha + (config.flashAlpha - this.originalAlpha) * flashPhase;\n                instance.alpha = currentAlpha;\n            }).subscription;\n        }\n\n        // Create effect to update tint based on progress\n        if (type === 'tint' || type === 'both') {\n            this.tintEffect = effect(() => {\n                if (!instance || !this.progressSignal || !this.currentFlashConfig) return;\n                \n                // Get current tint value - handle both signal and primitive\n                const currentTint = (instance as any).tint;\n                if (currentTint === undefined) return;\n                \n                // Check if tint is a signal\n                const tintIsSignal = isSignal(currentTint);\n                \n                const progress = this.progressSignal();\n                const config = this.currentFlashConfig;\n                \n                // Calculate flash value based on cycles\n                const cycleProgress = (progress * config.cycles) % 1;\n                \n                // Create flash effect: change to flashTint then back to original\n                const flashPhase = cycleProgress < 0.5 \n                    ? cycleProgress * 2  // Change to flashTint (0 to 1)\n                    : 1 - ((cycleProgress - 0.5) * 2); // Change back to original (1 to 0)\n                \n                // Interpolate between original and flash tint\n                // Simple linear interpolation for RGB values\n                const r1 = (this.originalTint >> 16) & 0xff;\n                const g1 = (this.originalTint >> 8) & 0xff;\n                const b1 = this.originalTint & 0xff;\n                \n                const r2 = (config.flashTint >> 16) & 0xff;\n                const g2 = (config.flashTint >> 8) & 0xff;\n                const b2 = config.flashTint & 0xff;\n                \n                const r = Math.round(r1 + (r2 - r1) * flashPhase);\n                const g = Math.round(g1 + (g2 - g1) * flashPhase);\n                const b = Math.round(b1 + (b2 - b1) * flashPhase);\n                \n                const newTintValue = (r << 16) | (g << 8) | b;\n                \n                // Handle both signal and primitive tint\n                if (tintIsSignal) {\n                    currentTint.set(newTintValue);\n                } else {\n                    (instance as any).tint = newTintValue;\n                }\n            }).subscription;\n        }\n\n        // Start animation and wait for completion\n        await this.progressSignal.set(1, {\n            duration: duration,\n        });\n\n        // Animation completed - clean up and call callbacks\n        // Only restore and clean up if this flash is still the active one\n        // If currentFlashConfig has changed, it means a new flash has started\n        const isStillActive = this.currentFlashConfig === flashConfig;\n\n        if (isStillActive && instance) {\n            // Restore original values\n            instance.alpha = this.originalAlpha;\n            const currentTint = (instance as any).tint;\n            if (currentTint !== undefined) {\n                // Ensure originalTint is a primitive value, not a signal\n                const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;\n                // Handle both signal and primitive tint\n                if (isSignal(currentTint)) {\n                    currentTint.set(tintValue);\n                } else {\n                    (instance as any).tint = tintValue;\n                }\n            }\n            \n            // Clean up effects\n            if (this.alphaEffect) {\n                this.alphaEffect.unsubscribe();\n                this.alphaEffect = null;\n            }\n            if (this.tintEffect) {\n                this.tintEffect.unsubscribe();\n                this.tintEffect = null;\n            }\n            \n            // Clear flash config\n            this.currentFlashConfig = null;\n        }\n        \n        // Call onComplete callback\n        flashProps.onComplete?.();\n    }\n\n    /**\n     * Updates the flash directive when props change\n     * @param props - Updated props\n     */\n    onUpdate(props: any) {\n        // Re-mount if props change significantly\n        if (props.type && props.type === 'reset') {\n            this.onDestroy();\n            if (this.elementRef) {\n                this.onMount(this.elementRef);\n            }\n        }\n    }\n\n    /**\n     * Cleans up the flash directive\n     */\n    onDestroy() {\n        // Stop any running animation by resetting progress\n        if (this.progressSignal) {\n            this.progressSignal.set(0, { duration: 0 });\n            this.progressSignal = null;\n        }\n\n        // Clean up effects\n        if (this.alphaEffect) {\n            this.alphaEffect.unsubscribe();\n            this.alphaEffect = null;\n        }\n        if (this.tintEffect) {\n            this.tintEffect.unsubscribe();\n            this.tintEffect = null;\n        }\n\n        // Clear flash config\n        this.currentFlashConfig = null;\n\n        // Restore original values\n        if (this.elementRef?.componentInstance) {\n            const instance = this.elementRef.componentInstance;\n            instance.alpha = this.originalAlpha;\n            const currentTint = (instance as any).tint;\n            if (currentTint !== undefined) {\n                // Ensure originalTint is a primitive value, not a signal\n                const tintValue = typeof this.originalTint === 'number' ? this.originalTint : 0xffffff;\n                // Handle both signal and primitive tint\n                if (isSignal(currentTint)) {\n                    currentTint.set(tintValue);\n                } else {\n                    (instance as any).tint = tintValue;\n                }\n            }\n        }\n\n        // Clean up subscription\n        if (this.flashSubscription) {\n            this.flashSubscription = null;\n        }\n\n        this.elementRef = null;\n    }\n}\n\nregisterDirective('flash', Flash);\n\n"
  },
  {
    "path": "packages/core/src/directives/FocusNavigation.ts",
    "content": "import { Directive, registerDirective, applyDirective } from \"../engine/directive\";\nimport { type Element } from \"../engine/reactive\";\nimport { ControlsDirective } from \"./Controls\";\nimport { Controls } from \"./ControlsBase\";\nimport { isSignal, Signal } from \"@signe/reactive\";\nimport { CanvasFocusContainer } from \"../components/FocusContainer\";\n\n/**\n * FocusNavigation directive for wiring Controls with FocusContainer\n * \n * This directive integrates with the Controls system and lets external\n * control handlers update the FocusContainer tabindex signal.\n * \n * The directive is automatically applied when a FocusContainer has a `controls` prop.\n * It keeps the Controls directive in sync with the provided controls config.\n * \n * @example\n * ```typescript\n * // Automatic navigation with Controls\n * <FocusContainer tabindex={0} controls={controlsConfig}>\n *   <Button tabindex={0} text=\"Button 1\" />\n *   <Button tabindex={1} text=\"Button 2\" />\n * </FocusContainer>\n * ```\n */\nexport class FocusNavigationDirective extends Directive {\n  private element: Element<CanvasFocusContainer> | null = null;\n  private controlsDirective: ControlsDirective | null = null;\n  private controlsSubscription: any = null;\n\n  /**\n   * Initialize the focus navigation directive\n   * \n   * @param element - FocusContainer element\n   */\n  onInit(element: Element<CanvasFocusContainer>) {\n    this.element = element;\n  }\n\n  /**\n   * Mount hook\n   * \n   * @param element - FocusContainer element\n   */\n  onMount(element: Element<CanvasFocusContainer>) {\n    // Get or create Controls directive\n    this.controlsDirective = element.directives?.controls as ControlsDirective;\n\n    // If Controls directive doesn't exist, create it\n    if (!this.controlsDirective) {\n      const controlsDirective = applyDirective(element, 'controls');\n      if (controlsDirective) {\n        if (!element.directives) {\n          element.directives = {};\n        }\n        element.directives.controls = controlsDirective;\n        this.controlsDirective = controlsDirective as ControlsDirective;\n      }\n    }\n\n    // Get controls from props\n    const controlsProp = element.props.controls;\n    if (controlsProp) {\n      const controlsValue = isSignal(controlsProp) ? controlsProp() : controlsProp;\n      if (controlsValue) {\n        this.controlsDirective?.onUpdate({ controls: controlsValue }, element);\n      }\n    }\n\n    // Handle controls prop updates if it's a signal\n    if (isSignal(controlsProp)) {\n      this.controlsSubscription = ((controlsProp as Signal<Controls>).observable as any).subscribe((controls) => {\n        if (controls) {\n          this.controlsDirective?.onUpdate({ controls }, element);\n        }\n      });\n    }\n  }\n\n  /**\n   * Update hook\n   * \n   * @param props - Updated properties\n   * @param element - FocusContainer element\n   */\n  onUpdate(props: any, element: Element<CanvasFocusContainer>) {\n    // Update controls if changed\n    if (props.controls !== undefined) {\n      const controlsValue = isSignal(props.controls) ? props.controls() : props.controls;\n      if (controlsValue) {\n        this.controlsDirective?.onUpdate({ controls: controlsValue }, element);\n      }\n    }\n  }\n\n  /**\n   * Destroy hook\n   * \n   * @param element - FocusContainer element\n   */\n  onDestroy(element: Element<CanvasFocusContainer>) {\n    // Cleanup subscription\n    if (this.controlsSubscription) {\n      this.controlsSubscription.unsubscribe();\n      this.controlsSubscription = null;\n    }\n\n    this.element = null;\n    this.controlsDirective = null;\n  }\n}\n\nregisterDirective('focusNavigation', FocusNavigationDirective);\n"
  },
  {
    "path": "packages/core/src/directives/FogVisibility.ts",
    "content": "import { isSignal } from \"@signe/reactive\";\nimport { Container } from \"pixi.js\";\nimport { Subscription } from \"rxjs\";\nimport { SignalOrPrimitive } from \"../components/types\";\nimport { Directive, registerDirective } from \"../engine/directive\";\nimport { Element } from \"../engine/reactive\";\n\nexport type FogVisibilityState = \"visible\" | \"explored\" | \"unknown\";\nexport type FogVisibilityMode = \"visible\" | \"explored\";\nexport type FogVisibilityHideAs = \"visible\" | \"alpha\";\n\nexport type FogVisibilityController = {\n  version?: () => number;\n  clarityAt?: (x: number, y: number) => number;\n  isVisibleAt?: (x: number, y: number, threshold?: number) => boolean;\n  isExploredAt?: (x: number, y: number) => boolean;\n  stateAt?: (x: number, y: number, clearThreshold?: number) => FogVisibilityState | string;\n};\n\nexport type FogVisibilityPoint = {\n  x: SignalOrPrimitive<number>;\n  y: SignalOrPrimitive<number>;\n};\n\nexport type FogVisibilityProps = {\n  controller?: SignalOrPrimitive<FogVisibilityController | null | undefined>;\n  mode?: SignalOrPrimitive<FogVisibilityMode>;\n  threshold?: SignalOrPrimitive<number>;\n  point?: SignalOrPrimitive<FogVisibilityPoint>;\n  hideAs?: SignalOrPrimitive<FogVisibilityHideAs>;\n  hiddenAlpha?: SignalOrPrimitive<number>;\n  sampleHz?: SignalOrPrimitive<number>;\n};\n\ntype NormalizedFogVisibilityProps = {\n  controller: FogVisibilityController | null;\n  mode: FogVisibilityMode;\n  threshold: number;\n  hideAs: FogVisibilityHideAs;\n  hiddenAlpha: number;\n  sampleHz: number;\n  point?: FogVisibilityPoint;\n};\n\nconst clamp = (value: number, min: number, max: number) =>\n  Math.max(min, Math.min(max, value));\n\nexport class FogVisibility extends Directive {\n  private elementRef: Element<Container> | null = null;\n  private tickSubscription: Subscription | null = null;\n  private sampleAccumulatorMs = 0;\n  private managesAlpha = false;\n\n  onInit(element: Element<Container>) {\n    this.elementRef = element;\n  }\n\n  onMount(element: Element<Container>) {\n    this.elementRef = element;\n    this.evaluateVisibility();\n    this.bindTick();\n  }\n\n  onUpdate() {\n    this.sampleAccumulatorMs = 0;\n    this.evaluateVisibility();\n  }\n\n  onDestroy() {\n    const instance = this.elementRef?.componentInstance as any;\n    if (instance) {\n      const baseVisible = this.readBaseVisible();\n      instance.visible = baseVisible;\n      if (this.managesAlpha) {\n        instance.alpha = this.readBaseAlpha();\n      }\n    }\n\n    this.tickSubscription?.unsubscribe();\n    this.tickSubscription = null;\n    this.sampleAccumulatorMs = 0;\n    this.managesAlpha = false;\n    this.elementRef = null;\n  }\n\n  private bindTick() {\n    this.tickSubscription?.unsubscribe();\n    this.tickSubscription = null;\n\n    const tick = this.elementRef?.props?.context?.tick;\n    if (!tick?.observable) return;\n\n    this.tickSubscription = tick.observable.subscribe((payload: any) => {\n      const tickValue = payload?.value ?? payload;\n      const deltaTime = Number(tickValue?.deltaTime);\n      const options = this.readOptions();\n      const intervalMs = 1000 / options.sampleHz;\n\n      this.sampleAccumulatorMs += Number.isFinite(deltaTime) ? deltaTime : intervalMs;\n      if (this.sampleAccumulatorMs < intervalMs) return;\n\n      this.sampleAccumulatorMs = 0;\n      this.evaluateVisibility(options);\n    });\n  }\n\n  private resolveSignalValue<T>(value: SignalOrPrimitive<T> | undefined, fallback: T): T {\n    if (value === undefined || value === null) return fallback;\n    if (isSignal(value as any)) {\n      const signalValue = (value as any)();\n      return signalValue === undefined || signalValue === null ? fallback : signalValue;\n    }\n    return value as T;\n  }\n\n  private readOptions(): NormalizedFogVisibilityProps {\n    const fogVisibility = this.elementRef?.props?.fogVisibility;\n    const raw = (fogVisibility as any)?.value ?? fogVisibility ?? {};\n\n    const controller = this.resolveSignalValue(\n      raw.controller as SignalOrPrimitive<FogVisibilityController | null | undefined>,\n      null\n    );\n    const mode = this.resolveSignalValue(raw.mode as SignalOrPrimitive<FogVisibilityMode>, \"visible\");\n    const threshold = clamp(\n      Number(this.resolveSignalValue(raw.threshold as SignalOrPrimitive<number>, 0.65)),\n      0,\n      1\n    );\n    const hideAs = this.resolveSignalValue(\n      raw.hideAs as SignalOrPrimitive<FogVisibilityHideAs>,\n      \"visible\"\n    );\n    const hiddenAlpha = clamp(\n      Number(this.resolveSignalValue(raw.hiddenAlpha as SignalOrPrimitive<number>, 0)),\n      0,\n      1\n    );\n    const sampleHz = clamp(\n      Number(this.resolveSignalValue(raw.sampleHz as SignalOrPrimitive<number>, 30)),\n      1,\n      240\n    );\n    const point = raw.point\n      ? this.resolveSignalValue(raw.point as SignalOrPrimitive<FogVisibilityPoint>, undefined as any)\n      : undefined;\n\n    return {\n      controller: controller && typeof controller === \"object\" ? controller : null,\n      mode,\n      threshold,\n      hideAs,\n      hiddenAlpha,\n      sampleHz,\n      point,\n    };\n  }\n\n  private readBaseVisible() {\n    const visibleSource = (this.elementRef?.propObservables as any)?.visible ?? this.elementRef?.props?.visible;\n    return !!this.resolveSignalValue(visibleSource as SignalOrPrimitive<boolean>, true);\n  }\n\n  private readBaseAlpha() {\n    const alphaSource = (this.elementRef?.propObservables as any)?.alpha ?? this.elementRef?.props?.alpha;\n    const value = Number(this.resolveSignalValue(alphaSource as SignalOrPrimitive<number>, 1));\n    if (!Number.isFinite(value)) return 1;\n    return clamp(value, 0, 1);\n  }\n\n  private samplePoint(options: NormalizedFogVisibilityProps) {\n    if (options.point && typeof options.point === \"object\") {\n      const x = Number(this.resolveSignalValue(options.point.x, NaN));\n      const y = Number(this.resolveSignalValue(options.point.y, NaN));\n      if (Number.isFinite(x) && Number.isFinite(y)) {\n        return { x, y };\n      }\n    }\n\n    const instance = this.elementRef?.componentInstance as any;\n    return {\n      x: Number(instance?.x ?? 0),\n      y: Number(instance?.y ?? 0),\n    };\n  }\n\n  private resolveVisibleState(\n    controller: FogVisibilityController,\n    x: number,\n    y: number,\n    threshold: number\n  ) {\n    if (typeof controller.isVisibleAt === \"function\") {\n      return !!controller.isVisibleAt(x, y, threshold);\n    }\n    if (typeof controller.clarityAt === \"function\") {\n      const clarity = Number(controller.clarityAt(x, y));\n      if (!Number.isFinite(clarity)) return true;\n      return clarity >= threshold;\n    }\n    if (typeof controller.stateAt === \"function\") {\n      const state = controller.stateAt(x, y, threshold);\n      return state === \"visible\";\n    }\n    return true;\n  }\n\n  private resolveExploredState(\n    controller: FogVisibilityController,\n    x: number,\n    y: number,\n    threshold: number\n  ) {\n    if (typeof controller.isExploredAt === \"function\") {\n      return !!controller.isExploredAt(x, y);\n    }\n    if (typeof controller.stateAt === \"function\") {\n      const state = controller.stateAt(x, y, threshold);\n      return state !== \"unknown\";\n    }\n    return this.resolveVisibleState(controller, x, y, threshold);\n  }\n\n  private evaluateVisibility(explicitOptions?: NormalizedFogVisibilityProps) {\n    const element = this.elementRef;\n    const instance = element?.componentInstance as any;\n    if (!instance) return;\n\n    const options = explicitOptions ?? this.readOptions();\n    const baseVisible = this.readBaseVisible();\n    const baseAlpha = this.readBaseAlpha();\n\n    if (!options.controller) {\n      instance.visible = baseVisible;\n      if (this.managesAlpha) {\n        instance.alpha = baseAlpha;\n        this.managesAlpha = false;\n      }\n      return;\n    }\n\n    // Link directive reactivity to FogOfWar controller internal revision.\n    if (typeof options.controller.version === \"function\") {\n      options.controller.version();\n    }\n\n    const { x, y } = this.samplePoint(options);\n    let fogAllowsVisibility = true;\n\n    if (options.mode === \"explored\") {\n      fogAllowsVisibility = this.resolveExploredState(options.controller, x, y, options.threshold);\n    } else {\n      fogAllowsVisibility = this.resolveVisibleState(options.controller, x, y, options.threshold);\n    }\n\n    if (options.hideAs === \"alpha\") {\n      instance.visible = baseVisible;\n      instance.alpha = fogAllowsVisibility\n        ? baseAlpha\n        : Math.min(baseAlpha, options.hiddenAlpha);\n      this.managesAlpha = true;\n      return;\n    }\n\n    instance.visible = baseVisible && fogAllowsVisibility;\n    if (this.managesAlpha) {\n      instance.alpha = baseAlpha;\n      this.managesAlpha = false;\n    }\n  }\n}\n\nregisterDirective(\"fogVisibility\", FogVisibility);\n"
  },
  {
    "path": "packages/core/src/directives/GamepadControls.ts",
    "content": "import { ControlsBase, Controls } from \"./ControlsBase\";\nimport { WritableSignal } from \"@signe/reactive\";\nimport 'joypad.js'\n\n/**\n * Gamepad configuration interface\n * \n * @example\n * ```ts\n * const gamepadConfig: GamepadConfig = {\n *   enabled: true,\n *   buttonMapping: {\n *     'button_0': 'action',\n *     'button_1': 'back'\n *   },\n *   axisMapping: {\n *     'top': 'up',\n *     'bottom': 'down',\n *     'left': 'left',\n *     'right': 'right'\n *   },\n *   moveInterval: 400,\n *   onConnect: () => console.log('Gamepad connected!'),\n *   onDisconnect: () => console.log('Gamepad disconnected!')\n * };\n * ```\n */\nexport interface GamepadConfig {\n    /** Whether gamepad is enabled (default: true) */\n    enabled?: boolean;\n    /** Mapping of gamepad button names to control names */\n    buttonMapping?: {\n        [buttonName: string]: string; // e.g., 'button_0' -> 'action'\n    };\n    /** Mapping of axis directions to control directions */\n    axisMapping?: {\n        [axisDirection: string]: string; // e.g., 'top' -> 'up'\n    };\n    /** Threshold for axis movement detection (default: 0.5) */\n    axisThreshold?: number;\n    /** Interval in milliseconds for repeating movement actions (default: 400) */\n    moveInterval?: number;\n    /** Callback called when a gamepad is connected */\n    onConnect?: () => void;\n    /** Callback called when a gamepad is disconnected */\n    onDisconnect?: () => void;\n    /** Signal that tracks gamepad connection status (optional) */\n    gamepadConnected?: WritableSignal<boolean>;\n}\n\n/**\n * Default button mapping\n */\nconst DEFAULT_BUTTON_MAPPING: { [buttonName: string]: string } = {\n    'button_0': 'action',\n    'button_1': 'back',\n    'button_9': 'back'\n};\n\n/**\n * Default axis mapping\n */\nconst DEFAULT_AXIS_MAPPING: { [axisDirection: string]: string } = {\n    'top': 'up',\n    'bottom': 'down',\n    'left': 'left',\n    'right': 'right'\n};\n\n/**\n * Gamepad input controls implementation\n * \n * Handles gamepad input events using joypad.js library and maps them to control actions.\n * Supports button presses and analog stick movement with configurable mappings.\n * \n * The gamepad controls are automatically activated when joypad.js is available and enabled.\n * \n * @example\n * ```ts\n * const gamepadControls = new GamepadControls();\n * gamepadControls.setInputs({\n *   up: {\n *     repeat: true,\n *     bind: 'up',\n *     keyDown() {\n *       console.log('Up pressed');\n *     }\n *   }\n * });\n * gamepadControls.updateGamepadConfig({\n *   enabled: true,\n *   buttonMapping: {\n *     'button_0': 'action'\n *   }\n * });\n * gamepadControls.start();\n * ```\n */\nexport class GamepadControls extends ControlsBase {\n    private gamepadEnabled: boolean = true;\n    private gamepadConfig: GamepadConfig = {\n        enabled: true,\n        buttonMapping: DEFAULT_BUTTON_MAPPING,\n        axisMapping: DEFAULT_AXIS_MAPPING,\n        axisThreshold: 0.5,\n        moveInterval: 400\n    };\n    private gamepadMoving: boolean = false;\n    private gamepadDirections: { [direction: string]: boolean } = {};\n    private gamepadAxisDate: number = 0;\n    private gamepadMoveInterval: any = null;\n    private joypad: any = null;\n    private connectCallbacks: Array<() => void> = [];\n    private disconnectCallbacks: Array<() => void> = [];\n    private currentPower: number = 0;\n\n    /**\n     * Setup gamepad event listeners\n     * Initializes joypad.js if available\n     */\n    protected setupListeners(): void {\n        this.initGamepad();\n    }\n\n    /**\n     * Cleanup gamepad event listeners and intervals\n     */\n    protected cleanup(): void {\n        if (this.gamepadMoveInterval) {\n            clearInterval(this.gamepadMoveInterval);\n            this.gamepadMoveInterval = null;\n        }\n    }\n\n    /**\n     * Initialize joypad.js library if available\n     */\n    private initGamepad(): void {\n        if (typeof window === 'undefined') return;\n        \n        const joypadLib = (window as any)['joypad'];\n\n        if (!joypadLib) {\n            // joypad.js not available\n            // Set initial state if signal is provided\n            if (this.gamepadConfig.gamepadConnected) {\n                this.gamepadConfig.gamepadConnected.set(false);\n            }\n            return;\n        }\n\n        this.joypad = joypadLib;\n\n        // Setup event listeners\n        this.joypad.on('connect', () => this.handleGamepadConnect());\n        this.joypad.on('disconnect', () => this.handleGamepadDisconnect());\n        this.joypad.on('button_press', (e: any) => this.handleGamepadButtonPress(e));\n        this.joypad.on('axis_move', (e: any) => this.handleGamepadAxisMove(e));\n    }\n\n    /**\n     * Handle gamepad connection event\n     */\n    private handleGamepadConnect(): void {\n        if (!this.gamepadEnabled || !this.gamepadConfig.enabled) return;\n        \n        // Start movement processing interval\n        this.gamepadMoveInterval = setInterval(() => {\n            this.processGamepadMovement();\n        }, this.gamepadConfig.moveInterval || 400);\n\n        // Update gamepadConnected signal if provided\n        if (this.gamepadConfig.gamepadConnected) {\n            this.gamepadConfig.gamepadConnected.set(true);\n        }\n\n        // Call all registered connect callbacks\n        this.connectCallbacks.forEach(callback => callback());\n    }\n\n    /**\n     * Handle gamepad disconnection event\n     */\n    private handleGamepadDisconnect(): void {\n        // Stop movement interval\n        if (this.gamepadMoveInterval) {\n            clearInterval(this.gamepadMoveInterval);\n            this.gamepadMoveInterval = null;\n        }\n        \n        // Reset states\n        this.gamepadMoving = false;\n        this.gamepadDirections = {};\n        this.gamepadAxisDate = 0;\n        this.currentPower = 0;\n\n        // Update gamepadConnected signal if provided\n        if (this.gamepadConfig.gamepadConnected) {\n            this.gamepadConfig.gamepadConnected.set(false);\n        }\n\n        // Call all registered disconnect callbacks\n        this.disconnectCallbacks.forEach(callback => callback());\n    }\n\n    /**\n     * Handle gamepad button press event\n     * \n     * @param e - Button press event from joypad.js\n     */\n    private handleGamepadButtonPress(e: any): void {\n        if (!this.gamepadEnabled || !this.gamepadConfig.enabled) return;\n        if (this.stop) return;\n\n        const { buttonName } = e.detail;\n        const buttonMapping = this.gamepadConfig.buttonMapping || DEFAULT_BUTTON_MAPPING;\n        const controlName = buttonMapping[buttonName];\n\n        if (controlName) {\n            // Apply the control action (press and release)\n            this.applyControl(controlName).catch(() => {\n                // Ignore errors\n            });\n        }\n    }\n\n    /**\n     * Handle gamepad axis movement event\n     * \n     * @param e - Axis move event from joypad.js\n     */\n    private handleGamepadAxisMove(e: any): void {\n        if (!this.gamepadEnabled || !this.gamepadConfig.enabled) return;\n        if (this.stop) return;\n\n        this.gamepadMoving = true;\n        this.gamepadAxisDate = Date.now();\n\n        let direction = e.detail.directionOfMovement;\n        const axisMapping = this.gamepadConfig.axisMapping || DEFAULT_AXIS_MAPPING;\n\n        // Map joypad direction to control direction\n        if (direction === 'top') direction = axisMapping['top'] || 'up';\n        else if (direction === 'bottom') direction = axisMapping['bottom'] || 'down';\n        else if (direction === 'left') direction = axisMapping['left'] || 'left';\n        else if (direction === 'right') direction = axisMapping['right'] || 'right';\n\n        // Calculate power/intensity from axis values\n        // Get the first connected gamepad instance\n        if (this.joypad && this.joypad.instances) {\n            const gamepadInstances = Object.values(this.joypad.instances) as any[];\n            if (gamepadInstances.length > 0) {\n                const gamepad = gamepadInstances[0];\n                // Get axes values (axes 0-1 for left stick, 2-3 for right stick)\n                // We'll use the left stick by default (axes 0 and 1)\n                const axisX = gamepad.axes?.[0] || 0;\n                const axisY = gamepad.axes?.[1] || 0;\n                // Calculate power as magnitude of the vector\n                this.currentPower = Math.min(1, Math.sqrt(axisX * axisX + axisY * axisY));\n            }\n        }\n\n        // Update active directions\n        this.gamepadDirections = {\n            [direction]: true\n        };\n\n        // Release other directions\n        const allDirections = ['up', 'down', 'left', 'right'];\n        for (const dir of allDirections) {\n            if (!this.gamepadDirections[dir]) {\n                this.applyControl(dir, false).catch(() => {\n                    // Ignore errors\n                });\n            }\n        }\n\n        // Trigger movement with power\n        this.processGamepadMovement();\n    }\n\n    /**\n     * Process continuous gamepad movement\n     * Called at intervals to repeat movement actions while axes are active\n     */\n    private processGamepadMovement(): void {\n        if (!this.gamepadMoving) return;\n        if (this.stop) return;\n\n        // Update current power from gamepad axes if available\n        if (this.joypad && this.joypad.instances) {\n            const gamepadInstances = Object.values(this.joypad.instances) as any[];\n            if (gamepadInstances.length > 0) {\n                const gamepad = gamepadInstances[0];\n                const axisX = gamepad.axes?.[0] || 0;\n                const axisY = gamepad.axes?.[1] || 0;\n                this.currentPower = Math.min(1, Math.sqrt(axisX * axisX + axisY * axisY));\n            }\n        }\n\n        for (const direction in this.gamepadDirections) {\n            if (this.gamepadDirections[direction]) {\n                this.applyControl(direction, true, { power: this.currentPower }).catch(() => {\n                    // Ignore errors\n                });\n            }\n        }\n    }\n\n    /**\n     * Process gamepad inputs each step\n     * Handles timeout for stopping movements after axis inactivity\n     */\n    protected preStep(): void {\n        if (this.stop) return;\n\n        // Stop movements if no axis input for 100ms\n        const now = Date.now();\n        if (now - this.gamepadAxisDate > 100 && this.gamepadMoving) {\n            const allDirections = ['up', 'down', 'left', 'right'];\n            for (const dir of allDirections) {\n                this.gamepadDirections = {};\n                this.gamepadMoving = false;\n                this.applyControl(dir, false).catch(() => {\n                    // Ignore errors\n                });\n            }\n        }\n    }\n\n    /**\n     * Update gamepad configuration\n     * Merges provided config with defaults\n     * Automatically registers callbacks from config\n     * \n     * @param config - Partial gamepad configuration\n     */\n    updateGamepadConfig(config: Partial<GamepadConfig>): void {\n        // Remove old callbacks if they were registered\n        if (this.gamepadConfig.onConnect) {\n            this.offConnect(this.gamepadConfig.onConnect);\n        }\n        if (this.gamepadConfig.onDisconnect) {\n            this.offDisconnect(this.gamepadConfig.onDisconnect);\n        }\n\n        this.gamepadConfig = {\n            enabled: config.enabled !== undefined ? config.enabled : true,\n            buttonMapping: config.buttonMapping || DEFAULT_BUTTON_MAPPING,\n            axisMapping: config.axisMapping || DEFAULT_AXIS_MAPPING,\n            axisThreshold: config.axisThreshold || 0.5,\n            moveInterval: config.moveInterval || 400,\n            onConnect: config.onConnect,\n            onDisconnect: config.onDisconnect,\n            gamepadConnected: config.gamepadConnected\n        };\n\n        // Register new callbacks if provided\n        if (this.gamepadConfig.onConnect) {\n            this.onConnect(this.gamepadConfig.onConnect);\n        }\n        if (this.gamepadConfig.onDisconnect) {\n            this.onDisconnect(this.gamepadConfig.onDisconnect);\n        }\n    }\n\n    /**\n     * Extract gamepad config from controls configuration and update\n     * Note: Callbacks are stored but not automatically registered, they should be registered in mount()\n     * \n     * @param inputs - Controls configuration that may contain a 'gamepad' property\n     */\n    extractGamepadConfig(inputs: Controls & { gamepad?: GamepadConfig }): void {\n        if (inputs.gamepad) {\n            this.updateGamepadConfig(inputs.gamepad);\n        }\n    }\n\n    /**\n     * Get the current gamepad configuration\n     * \n     * @returns The gamepad configuration object\n     */\n    getGamepadConfig(): GamepadConfig {\n        return this.gamepadConfig;\n    }\n\n    /**\n     * Apply a control action programmatically\n     * Uses the bound controls to trigger actions\n     * \n     * @param controlName - Name of the control\n     * @param isDown - Whether the control is pressed (true) or released (false)\n     * @param payload - Optional payload to pass to keyDown/keyUp callbacks (e.g., { power: 0.8 })\n     * @returns Promise that resolves when the action is complete\n     */\n    async applyControl(controlName: string | number, isDown?: boolean, payload?: any): Promise<void> {\n        const control = this._controlsOptions[controlName];\n        if (!control) return;\n\n        // Find the bound key for this control\n        const boundKeys = Object.keys(this.boundKeys);\n        for (const keyName of boundKeys) {\n            const boundKey = this.boundKeys[keyName];\n            if (boundKey.actionName === String(controlName)) {\n                // Execute the control callback\n                if (isDown === undefined) {\n                    // Press and release (simulate button press)\n                    if (boundKey.options.keyDown) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyDown(boundKey, parameters);\n                    }\n                    // Release after a short delay (similar to keyboard)\n                    return new Promise((resolve) => {\n                        setTimeout(() => {\n                            if (boundKey.options.keyUp) {\n                                let parameters = payload ?? boundKey.parameters;\n                                if (typeof parameters === \"function\") {\n                                    parameters = parameters();\n                                }\n                                boundKey.options.keyUp(boundKey, parameters);\n                            }\n                            resolve();\n                        }, 200);\n                    });\n                } else if (isDown) {\n                    if (boundKey.options.keyDown) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyDown(boundKey, parameters);\n                    }\n                } else {\n                    if (boundKey.options.keyUp) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyUp(boundKey, parameters);\n                    }\n                }\n                break;\n            }\n        }\n    }\n\n    /**\n     * Override setInputs to extract gamepad config\n     */\n    setInputs(inputs: Controls & { gamepad?: GamepadConfig }): void {\n        super.setInputs(inputs);\n        this.extractGamepadConfig(inputs);\n    }\n\n    /**\n     * Register a callback to be called when a gamepad is connected\n     * \n     * @param callback - Function to call when gamepad connects\n     * @example\n     * ```ts\n     * gamepadControls.onConnect(() => {\n     *   console.log('Gamepad connected!');\n     * });\n     * ```\n     */\n    onConnect(callback: () => void): void {\n        this.connectCallbacks.push(callback);\n    }\n\n    /**\n     * Register a callback to be called when a gamepad is disconnected\n     * \n     * @param callback - Function to call when gamepad disconnects\n     * @example\n     * ```ts\n     * gamepadControls.onDisconnect(() => {\n     *   console.log('Gamepad disconnected!');\n     * });\n     * ```\n     */\n    onDisconnect(callback: () => void): void {\n        this.disconnectCallbacks.push(callback);\n    }\n\n    /**\n     * Remove a connect callback\n     * \n     * @param callback - Callback to remove\n     */\n    offConnect(callback: () => void): void {\n        const index = this.connectCallbacks.indexOf(callback);\n        if (index > -1) {\n            this.connectCallbacks.splice(index, 1);\n        }\n    }\n\n    /**\n     * Remove a disconnect callback\n     * \n     * @param callback - Callback to remove\n     */\n    offDisconnect(callback: () => void): void {\n        const index = this.disconnectCallbacks.indexOf(callback);\n        if (index > -1) {\n            this.disconnectCallbacks.splice(index, 1);\n        }\n    }\n\n    /**\n     * Check if gamepad is currently connected\n     * \n     * @returns true if gamepad is connected, false otherwise\n     */\n    isConnected(): boolean {\n        return this.gamepadMoveInterval !== null;\n    }\n\n    /**\n     * Reinitialize gamepad listeners\n     * Useful if joypad.js becomes available after initialization\n     * \n     * @example\n     * ```ts\n     * // If joypad.js loads later\n     * gamepadControls.reinit();\n     * ```\n     */\n    reinit(): void {\n        if (!this.joypad) {\n            this.initGamepad();\n        }\n    }\n}\n"
  },
  {
    "path": "packages/core/src/directives/JoystickControls.ts",
    "content": "import { ControlsBase, Controls } from \"./ControlsBase\";\n\n/**\n * Joystick directions reported by the Joystick component\n */\nexport type JoystickDirection =\n    | 'left'\n    | 'right'\n    | 'top'\n    | 'bottom'\n    | 'top_left'\n    | 'top_right'\n    | 'bottom_left'\n    | 'bottom_right';\n\n/**\n * Joystick change event payload\n */\nexport interface JoystickChangeEvent {\n    angle: number;\n    direction: JoystickDirection;\n    power: number;\n}\n\n/**\n * Joystick configuration interface\n * \n * @example\n * ```ts\n * const joystickConfig: JoystickConfig = {\n *   enabled: true,\n *   directionMapping: {\n *     'top': 'up',\n *     'bottom': 'down',\n *     'left': 'left',\n *     'right': 'right',\n *     'top_left': ['up', 'left'],\n *     'top_right': ['up', 'right'],\n *     'bottom_left': ['down', 'left'],\n *     'bottom_right': ['down', 'right']\n *   },\n *   moveInterval: 50,\n *   threshold: 0.1\n * };\n * ```\n */\nexport interface JoystickConfig {\n    /** Whether joystick is enabled (default: true) */\n    enabled?: boolean;\n    /** Mapping of joystick direction names to control names (can be single string or array for diagonals) */\n    directionMapping?: {\n        [joystickDirection: string]: string | string[]; // e.g., 'top' -> 'up', 'top_left' -> ['up', 'left']\n    };\n    /** Interval in milliseconds for repeating movement actions (default: 50) */\n    moveInterval?: number;\n    /** Threshold for power value to trigger movement (default: 0.1) */\n    threshold?: number;\n}\n\n/**\n * Default direction mapping\n */\nconst DEFAULT_DIRECTION_MAPPING: { [direction: string]: string | string[] } = {\n    'top': 'up',\n    'bottom': 'down',\n    'left': 'left',\n    'right': 'right',\n    'top_left': ['up', 'left'],\n    'top_right': ['up', 'right'],\n    'bottom_left': ['down', 'left'],\n    'bottom_right': ['down', 'right']\n};\n\n/**\n * Joystick input controls implementation\n * \n * Handles joystick input events from the Joystick component and maps them to control actions.\n * Supports directional movement with configurable mappings, including diagonal directions.\n * \n * The joystick controls work by receiving change events from a Joystick component instance.\n * \n * @example\n * ```ts\n * const joystickControls = new JoystickControls();\n * joystickControls.setInputs({\n *   up: {\n *     repeat: true,\n *     bind: 'up',\n *     keyDown() {\n *       console.log('Up pressed');\n *     }\n *   }\n * });\n * joystickControls.updateJoystickConfig({\n *   enabled: true,\n *   directionMapping: {\n *     'top': 'up'\n *   }\n * });\n * joystickControls.start();\n * \n * // Later, when joystick changes:\n * joystickControls.handleJoystickChange({ angle: 90, direction: Direction.TOP, power: 0.8 });\n * ```\n */\nexport class JoystickControls extends ControlsBase {\n    private joystickEnabled: boolean = true;\n    private joystickConfig: JoystickConfig = {\n        enabled: true,\n        directionMapping: DEFAULT_DIRECTION_MAPPING,\n        moveInterval: 50,\n        threshold: 0.1\n    };\n    private joystickMoving: boolean = false;\n    private joystickDirections: { [direction: string]: boolean } = {};\n    private joystickLastUpdate: number = 0;\n    private joystickMoveInterval: any = null;\n    private currentPower: number = 0;\n\n    /**\n     * Setup joystick event listeners\n     * Note: Joystick events are handled via handleJoystickChange() method\n     */\n    protected setupListeners(): void {\n        // Joystick events are handled externally via handleJoystickChange()\n        // This method is kept for consistency with ControlsBase interface\n    }\n\n    /**\n     * Cleanup joystick intervals\n     */\n    protected cleanup(): void {\n        if (this.joystickMoveInterval) {\n            clearInterval(this.joystickMoveInterval);\n            this.joystickMoveInterval = null;\n        }\n    }\n\n    /**\n     * Process joystick inputs each step\n     * Continuous actions are handled by the interval; no inactivity timeout here.\n     */\n    protected preStep(): void {\n        if (this.stop) return;\n        // No-op: continuous movement is driven by processJoystickMovement interval\n    }\n\n    /**\n     * Handle joystick change event\n     * Called by the Joystick component when its position changes\n     * \n     * @param event - Joystick change event containing angle, direction, and power\n     */\n    handleJoystickChange(event: JoystickChangeEvent): void {\n        if (!this.joystickEnabled || !this.joystickConfig.enabled) return;\n        if (this.stop) return;\n\n        this.joystickLastUpdate = Date.now();\n        this.currentPower = event.power;\n\n        // Check threshold\n        if (event.power < (this.joystickConfig.threshold || 0.1)) {\n            // Power too low, stop all movements\n            this.stopAllMovements();\n            return;\n        }\n\n        const directionMapping = this.joystickConfig.directionMapping || DEFAULT_DIRECTION_MAPPING;\n        const directionKey = event.direction;\n        const mappedControls = directionMapping[directionKey];\n\n        if (!mappedControls) {\n            // No mapping for this direction, stop all movements\n            this.stopAllMovements();\n            return;\n        }\n\n        // Convert to array if single string\n        const controlNames = Array.isArray(mappedControls) ? mappedControls : [mappedControls];\n\n        // Determine which directions to activate and deactivate\n        const previousDirections = this.joystickDirections;\n        const newDirections: { [dir: string]: boolean } = {};\n        controlNames.forEach(controlName => {\n            newDirections[controlName] = true;\n        });\n\n        // Deactivate directions that are no longer active\n        const allDirections = new Set([\n            ...Object.keys(this.joystickDirections),\n            ...Object.keys(newDirections)\n        ]);\n\n        for (const dir of allDirections) {\n            const wasActive = this.joystickDirections[dir];\n            const shouldBeActive = newDirections[dir] || false;\n\n            if (wasActive && !shouldBeActive) {\n                // Deactivate this direction\n                this.applyControl(dir, false).catch(() => {\n                    // Ignore errors\n                });\n            }\n        }\n\n        // Update active directions\n        this.joystickDirections = { ...newDirections };\n        this.joystickMoving = true;\n\n        // Activate new directions\n        const directionsToActivate = controlNames.filter((name) => !previousDirections[name]);\n        for (const controlName of directionsToActivate) {\n            this.applyControl(controlName, true, { power: event.power }).catch(() => {\n                // Ignore errors\n            });\n        }\n\n        // Start movement interval if not already running\n        if (!this.joystickMoveInterval) {\n            this.joystickMoveInterval = setInterval(() => {\n                this.processJoystickMovement();\n            }, this.joystickConfig.moveInterval || 50);\n        }\n    }\n\n    /**\n     * Handle joystick start event\n     * Called when user starts interacting with the joystick\n     */\n    handleJoystickStart(): void {\n        if (!this.joystickEnabled || !this.joystickConfig.enabled) return;\n        if (this.stop) return;\n        // Start event doesn't need special handling, change event will handle activation\n    }\n\n    /**\n     * Handle joystick end event\n     * Called when user stops interacting with the joystick\n     */\n    handleJoystickEnd(): void {\n        if (!this.joystickEnabled || !this.joystickConfig.enabled) return;\n        this.stopAllMovements();\n    }\n\n    /**\n     * Stop all active joystick movements\n     */\n    private stopAllMovements(): void {\n        if (this.joystickMoveInterval) {\n            clearInterval(this.joystickMoveInterval);\n            this.joystickMoveInterval = null;\n        }\n\n        const allDirections = Object.keys(this.joystickDirections);\n        for (const dir of allDirections) {\n            this.applyControl(dir, false).catch(() => {\n                // Ignore errors\n            });\n        }\n\n        this.joystickDirections = {};\n        this.joystickMoving = false;\n        this.currentPower = 0;\n    }\n\n    /**\n     * Process continuous joystick movement\n     * Called at intervals to repeat movement actions while joystick is active\n     */\n    private processJoystickMovement(): void {\n        if (!this.joystickMoving) return;\n        if (this.stop) return;\n\n        for (const direction in this.joystickDirections) {\n            if (this.joystickDirections[direction]) {\n                this.applyControl(direction, true, { power: this.currentPower }).catch(() => {\n                    // Ignore errors\n                });\n            }\n        }\n    }\n\n    /**\n     * Update joystick configuration\n     * Merges provided config with defaults\n     * \n     * @param config - Partial joystick configuration\n     */\n    updateJoystickConfig(config: Partial<JoystickConfig>): void {\n        this.joystickConfig = {\n            enabled: config.enabled !== undefined ? config.enabled : true,\n            directionMapping: config.directionMapping || DEFAULT_DIRECTION_MAPPING,\n            moveInterval: config.moveInterval || 50,\n            threshold: config.threshold || 0.1\n        };\n    }\n\n    /**\n     * Extract joystick config from controls configuration and update\n     * \n     * @param inputs - Controls configuration that may contain a 'joystick' property\n     */\n    extractJoystickConfig(inputs: Controls & { joystick?: JoystickConfig }): void {\n        if (inputs.joystick) {\n            this.updateJoystickConfig(inputs.joystick);\n        }\n    }\n\n    /**\n     * Get the current joystick configuration\n     * \n     * @returns The joystick configuration object\n     */\n    getJoystickConfig(): JoystickConfig {\n        return this.joystickConfig;\n    }\n\n    /**\n     * Apply a control action programmatically\n     * Uses the bound controls to trigger actions\n     * \n     * @param controlName - Name of the control\n     * @param isDown - Whether the control is pressed (true) or released (false)\n     * @returns Promise that resolves when the action is complete\n     */\n    async applyControl(controlName: string | number, isDown?: boolean, payload?: any): Promise<void> {\n        const control = this._controlsOptions[controlName];\n        if (!control) return;\n\n        // Find the bound key for this control\n        const boundKeys = Object.keys(this.boundKeys);\n        for (const keyName of boundKeys) {\n            const boundKey = this.boundKeys[keyName];\n            if (boundKey.actionName === String(controlName)) {\n                // Execute the control callback\n                if (isDown === undefined) {\n                    // Press and release (simulate button press)\n                    if (boundKey.options.keyDown) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyDown(boundKey, parameters);\n                    }\n                    // Release after a short delay (similar to keyboard)\n                    return new Promise((resolve) => {\n                        setTimeout(() => {\n                            if (boundKey.options.keyUp) {\n                                let parameters = payload ?? boundKey.parameters;\n                                if (typeof parameters === \"function\") {\n                                    parameters = parameters();\n                                }\n                                boundKey.options.keyUp(boundKey, parameters);\n                            }\n                            resolve();\n                        }, 200);\n                    });\n                } else if (isDown) {\n                    if (boundKey.options.keyDown) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyDown(boundKey, parameters);\n                    }\n                } else {\n                    if (boundKey.options.keyUp) {\n                        let parameters = payload ?? boundKey.parameters;\n                        if (typeof parameters === \"function\") {\n                            parameters = parameters();\n                        }\n                        boundKey.options.keyUp(boundKey, parameters);\n                    }\n                }\n                break;\n            }\n        }\n    }\n\n    /**\n     * Override setInputs to extract joystick config\n     */\n    setInputs(inputs: Controls & { joystick?: JoystickConfig }): void {\n        super.setInputs(inputs);\n        this.extractJoystickConfig(inputs);\n    }\n\n    /**\n     * Check if joystick is currently active\n     * \n     * @returns true if joystick is moving, false otherwise\n     */\n    isActive(): boolean {\n        return this.joystickMoving;\n    }\n}\n"
  },
  {
    "path": "packages/core/src/directives/KeyboardControls.ts",
    "content": "import { ControlsBase, ControlOptions, Controls, BoundKey } from \"./ControlsBase\";\n\nexport enum Input {\n    Break = 'break',\n    Backspace = 'backspace',\n    Tab = 'tab',\n    Clear = 'clear',\n    Enter = 'enter',\n    Shift = 'shift',\n    Ctrl = 'ctrl',\n    Alt = 'alt',\n    Pause = 'pause/break',\n    CapsLock = 'caps lock',\n    Escape = 'escape',\n    Conversion = 'conversion',\n    NonConversion = 'non-conversion',\n    Space = 'space',\n    PageUp = 'page up',\n    PageDown = 'page down',\n    End = 'end',\n    Home = 'home',\n    Left = 4,\n    Up = 1,\n    Right = 2,\n    Down = 3,\n    Select = 'select',\n    Print = 'print',\n    Execute = 'execute',\n    PrintScreen = 'Print Screen',\n    Insert = 'insert',\n    Delete = 'delete',\n    Zero = '0',\n    One = '1',\n    Two = '2',\n    Three = '3',\n    Four = '4',\n    Five = '5',\n    Six = '6',\n    Seven = '7',\n    Height = '8',\n    Nine = '9',\n    Equal = '=',\n    Semicolon = 'semicolon (firefox), equals',\n    LessThan = '<',\n    Equals = 'equals (firefox)',\n    Beta = 'ß',\n    At = '@',\n    A = 'a',\n    B = 'b',\n    C = 'c',\n    D = 'd',\n    E = 'e',\n    F = 'f',\n    G = 'g',\n    H = 'h',\n    I = 'i',\n    J = 'j',\n    K = 'k',\n    L = 'l',\n    M = 'm',\n    N = 'n',\n    O = 'o',\n    P = 'p',\n    Q = 'q',\n    R = 'r',\n    S = 's',\n    T = 't',\n    U = 'u',\n    V = 'v',\n    W = 'w',\n    X = 'x',\n    Y = 'y',\n    Z = 'z',\n    SearchKey = 'Windows Key / Left ⌘ / Chromebook Search key',\n    NumPad0 = 'numpad 0',\n    NumPad1 = 'numpad 1',\n    NumPad2 = 'numpad 2',\n    NumPad3 = 'numpad 3',\n    NumPad4 = 'numpad 4',\n    NumPad5 = 'numpad 5',\n    NumPad6 = 'numpad 6',\n    NumPad7 = 'numpad 7',\n    NumPad8 = 'numpad 8',\n    NumPad9 = 'numpad 9',\n    Multiply = 'multiply',\n    Add = 'add',\n    Subtract = 'subtract',\n    DecimalPoint = 'decimal point',\n    Divide = 'divide',\n    F1 = 'f1',\n    F2 = 'f2',\n    F3 = 'f3',\n    F4 = 'f4',\n    F5 = 'f5',\n    F6 = 'f6',\n    F7 = 'f7',\n    F8 = 'f8',\n    F9 = 'f9',\n    F10 = 'f10',\n    F11 = 'f11',\n    F12 = 'f12',\n    F13 = 'f13',\n    F14 = 'f14',\n    F15 = 'f15',\n    F16 = 'f16',\n    F17 = 'f17',\n    F18 = 'f18',\n    F19 = 'f19',\n    F20 = 'f20',\n    F21 = 'f21',\n    F22 = 'f22',\n    F23 = 'f23',\n    F24 = 'f24',\n    NumLock = 'num lock',\n    ScrollLock = 'scroll lock',\n    CircumflexAccent = '^',\n    ExclamationMark = '!',\n    Hash = '#',\n    Dollar = '$',\n    AccentU = 'ù',\n    PageBackward = 'page backward',\n    PageForWard = 'page forward',\n    Star = '*',\n    DecreaseVolume = 'decrease volume level',\n    IncreaseVolume = 'increase volume level',\n    Next = 'next',\n    Previous = 'previous',\n    Stop = 'stop',\n    PlayPause = 'play/pause',\n    Email = 'e-mail',\n    SemiColon = 'semi-colon / ñ',\n    EqualSign = 'equal sign',\n    Comma = 'comma',\n    Dash = 'dash',\n    FowardSlach = 'forward slash / ç',\n    GraveAccent = 'grave accent / ñ / æ',\n    OpenBracket = 'open bracket',\n    BackSlach = 'back slash',\n    CloseBracket = 'close bracket / å',\n    SingleQuote = 'single quote / ø',\n    BackQuote = '`',\n    Altgr = 'altgr'\n}\n\n// Re-export for backward compatibility\nexport type { ControlOptions, Controls, BoundKey };\n\n// keyboard handling\nconst keyCodeTable = {\n    3: 'break',\n    8: 'backspace', // backspace / delete\n    9: 'tab',\n    12: 'clear',\n    13: 'enter',\n    16: 'shift',\n    17: 'ctrl',\n    18: 'alt',\n    19: 'pause/break',\n    20: 'caps lock',\n    27: 'escape',\n    28: 'conversion',\n    29: 'non-conversion',\n    32: 'space',\n    33: 'page up',\n    34: 'page down',\n    35: 'end',\n    36: 'home',\n    37: 'left',\n    38: 'up',\n    39: 'right',\n    40: 'down',\n    41: 'select',\n    42: 'print',\n    43: 'execute',\n    44: 'Print Screen',\n    45: 'insert',\n    46: 'delete',\n    48: 'n0',\n    49: 'n1',\n    50: 'n2',\n    51: 'n3',\n    52: 'n4',\n    53: 'n5',\n    54: 'n6',\n    55: 'n7',\n    56: 'n8',\n    57: 'n9',\n    58: ':',\n    59: 'semicolon (firefox), equals',\n    60: '<',\n    61: 'equals (firefox)',\n    63: 'ß',\n    64: '@',\n    65: 'a',\n    66: 'b',\n    67: 'c',\n    68: 'd',\n    69: 'e',\n    70: 'f',\n    71: 'g',\n    72: 'h',\n    73: 'i',\n    74: 'j',\n    75: 'k',\n    76: 'l',\n    77: 'm',\n    78: 'n',\n    79: 'o',\n    80: 'p',\n    81: 'q',\n    82: 'r',\n    83: 's',\n    84: 't',\n    85: 'u',\n    86: 'v',\n    87: 'w',\n    88: 'x',\n    89: 'y',\n    90: 'z',\n    91: 'Windows Key / Left ⌘ / Chromebook Search key',\n    92: 'right window key',\n    93: 'Windows Menu / Right ⌘',\n    96: 'numpad 0',\n    97: 'numpad 1',\n    98: 'numpad 2',\n    99: 'numpad 3',\n    100: 'numpad 4',\n    101: 'numpad 5',\n    102: 'numpad 6',\n    103: 'numpad 7',\n    104: 'numpad 8',\n    105: 'numpad 9',\n    106: 'multiply',\n    107: 'add',\n    108: 'numpad period (firefox)',\n    109: 'subtract',\n    110: 'decimal point',\n    111: 'divide',\n    112: 'f1',\n    113: 'f2',\n    114: 'f3',\n    115: 'f4',\n    116: 'f5',\n    117: 'f6',\n    118: 'f7',\n    119: 'f8',\n    120: 'f9',\n    121: 'f10',\n    122: 'f11',\n    123: 'f12',\n    124: 'f13',\n    125: 'f14',\n    126: 'f15',\n    127: 'f16',\n    128: 'f17',\n    129: 'f18',\n    130: 'f19',\n    131: 'f20',\n    132: 'f21',\n    133: 'f22',\n    134: 'f23',\n    135: 'f24',\n    144: 'num lock',\n    145: 'scroll lock',\n    160: '^',\n    161: '!',\n    163: '#',\n    164: '$',\n    165: 'ù',\n    166: 'page backward',\n    167: 'page forward',\n    169: 'closing paren (AZERTY)',\n    170: '*',\n    171: '~ + * key',\n    173: 'minus (firefox), mute/unmute',\n    174: 'decrease volume level',\n    175: 'increase volume level',\n    176: 'next',\n    177: 'previous',\n    178: 'stop',\n    179: 'play/pause',\n    180: 'e-mail',\n    181: 'mute/unmute (firefox)',\n    182: 'decrease volume level (firefox)',\n    183: 'increase volume level (firefox)',\n    186: 'semi-colon / ñ',\n    187: 'equal sign',\n    188: 'comma',\n    189: 'dash',\n    190: 'period',\n    191: 'forward slash / ç',\n    192: 'grave accent / ñ / æ',\n    193: '?, / or °',\n    194: 'numpad period (chrome)',\n    219: 'open bracket',\n    220: 'back slash',\n    221: 'close bracket / å',\n    222: 'single quote / ø',\n    223: '`',\n    224: 'left or right ⌘ key (firefox)',\n    225: 'altgr',\n    226: '< /git >',\n    230: 'GNOME Compose Key',\n    231: 'ç',\n    233: 'XF86Forward',\n    234: 'XF86Back',\n    240: 'alphanumeric',\n    242: 'hiragana/katakana',\n    243: 'half-width/full-width',\n    244: 'kanji',\n    255: 'toggle touchpad'\n};\n\nconst inverse = (obj) => {\n    const newObj = {}\n    for (let key in obj) {\n        const val = obj[key]\n        newObj[val] = key\n    }\n    return newObj\n}\n\nconst inverseKeyCodeTable = inverse(keyCodeTable)\n\n/**\n * Keyboard input controls implementation\n * \n * Handles keyboard input events and maps them to control actions.\n * Supports composite directions (diagonal movement) and key repeat functionality.\n * \n * @example\n * ```ts\n * const keyboardControls = new KeyboardControls();\n * keyboardControls.setInputs({\n *   up: {\n *     repeat: true,\n *     bind: Input.Up,\n *     keyDown() {\n *       console.log('Up pressed');\n *     }\n *   }\n * });\n * keyboardControls.start();\n * ```\n */\nexport class KeyboardControls extends ControlsBase {\n    private keyState: {\n        [keyName: string]: {\n            isDown: boolean,\n            count: number\n        } | null\n    } = {}\n    private lastKeyPressed: number | null = null\n    private lastActionTimes: Record<string, number> = {}\n    private directionState: {\n        up: boolean,\n        down: boolean,\n        left: boolean,\n        right: boolean\n    } = {\n            up: false,\n            down: false,\n            left: false,\n            right: false\n        };\n\n    /**\n     * Setup keyboard event listeners\n     */\n    protected setupListeners(): void {\n        document.addEventListener('keydown', (e) => { this.onKeyChange(e, true); });\n        document.addEventListener('keyup', (e) => { this.onKeyChange(e, false); });\n    }\n\n    /**\n     * Cleanup keyboard event listeners\n     */\n    protected cleanup(): void {\n        document.removeEventListener('keydown', (e) => { this.onKeyChange(e, true); });\n        document.removeEventListener('keyup', (e) => { this.onKeyChange(e, false); });\n    }\n\n    /**\n     * Process keyboard inputs each step\n     */\n    protected preStep() {\n        if (this.stop) return;\n\n        const direction = this.getDirection();\n        if (direction !== 'none') {\n            // Trigger only the composite direction\n            const directionControl = this.boundKeys[direction];\n            if (directionControl) {\n                const { keyDown } = directionControl.options;\n                if (keyDown) {\n                    this.applyInput(direction);\n                }\n            }\n        } else {\n            // Process other controls as before\n            const boundKeys = Object.keys(this.boundKeys);\n            for (let keyName of boundKeys) {\n                this.applyInput(keyName);\n            }\n        }\n    }\n\n    /**\n     * Apply input for a keyboard key\n     * Overrides base implementation to handle key state and repeat logic\n     */\n    protected applyInput(keyName: string) {\n        const keyState = this.keyState[keyName];\n        if (!keyState) {\n            return;\n        }\n        const { isDown, count } = keyState;\n        if (isDown) {\n            const boundKey = this.boundKeys[keyName];\n            if (!boundKey) {\n                return;\n            }\n            const { repeat, keyDown, throttle } = boundKey.options;\n            if ((repeat || count == 0)) {\n                if (typeof throttle === \"number\") {\n                    const now = Date.now();\n                    const lastTime = this.lastActionTimes[boundKey.actionName] ?? 0;\n                    if (now - lastTime < throttle) {\n                        return;\n                    }\n                    this.lastActionTimes[boundKey.actionName] = now;\n                }\n                let parameters = boundKey.parameters;\n                if (typeof parameters === \"function\") {\n                    parameters = parameters();\n                }\n                if (keyDown) {\n                    keyDown(boundKey);\n                }\n                this.keyState[keyName]!.count++;\n            }\n        }\n    }\n\n    private applyKeyDown(name: string) {\n        const code = inverseKeyCodeTable[name]\n        const e: any = new Event('keydown')\n        e.keyCode = code\n        this.onKeyChange(e, true)\n    }\n\n    private applyKeyUp(name: string) {\n        const code = inverseKeyCodeTable[name]\n        const e: any = new Event('keyup')\n        e.keyCode = code\n        this.onKeyChange(e, false)\n    }\n\n    private applyKeyPress(name: string): Promise<void> {\n        return new Promise((resolve: any) => {\n            this.applyKeyDown(name)\n            setTimeout(() => {\n                this.applyKeyUp(name)\n                resolve()\n            }, 200)\n        })\n    }\n\n    private onKeyChange(e: KeyboardEvent, isDown: boolean) {\n        e = (e || window.event) as KeyboardEvent;\n\n        const keyName: string = keyCodeTable[e.keyCode];\n\n        if (keyName && this.boundKeys[keyName]) {\n            if (this.keyState[keyName] == null) {\n                this.keyState[keyName] = {\n                    count: 0,\n                    isDown: true\n                };\n            }\n            this.keyState[keyName]!.isDown = isDown;\n\n            // key up, reset press count\n            if (!isDown) {\n                this.keyState[keyName]!.count = 0\n                const { keyUp } = this.boundKeys[keyName].options\n                if (keyUp) {\n                    keyUp(this.boundKeys[keyName]);\n                }\n            }\n\n            // keep reference to the last key pressed to avoid duplicates\n            this.lastKeyPressed = isDown ? e.keyCode : null;\n        }\n\n        if (keyName) {\n            this.updateDirectionState(keyName, isDown);\n        }\n    }\n\n    private updateDirectionState(keyName: string, isDown: boolean) {\n        switch (keyName) {\n            case 'up':\n                this.directionState.up = isDown;\n                break;\n            case 'down':\n                this.directionState.down = isDown;\n                break;\n            case 'left':\n                this.directionState.left = isDown;\n                break;\n            case 'right':\n                this.directionState.right = isDown;\n                break;\n        }\n    }\n\n    private getDirection(): string {\n        const { up, down, left, right } = this.directionState;\n\n        if (up && left) return 'up_left';\n        if (up && right) return 'up_right';\n        if (down && left) return 'down_left';\n        if (down && right) return 'down_right';\n        if (up) return 'up';\n        if (down) return 'down';\n        if (left) return 'left';\n        if (right) return 'right';\n\n        return 'none';\n    }\n\n    /**\n     * Apply a control action programmatically\n     * Triggers keyboard events to simulate key presses\n     * \n     * @param controlName - Name of the control\n     * @param isDown - Whether the key is pressed (true) or released (false)\n     * @returns Promise that resolves when the action is complete\n     * @example\n     * ```ts\n     * // Press a key\n     * await keyboardControls.applyControl('action', true);\n     * \n     * // Release a key\n     * await keyboardControls.applyControl('action', false);\n     * \n     * // Press and release (default)\n     * await keyboardControls.applyControl('action');\n     * ```\n     */\n    async applyControl(controlName: string | number, isDown?: boolean | undefined): Promise<void> {\n        const control = this._controlsOptions[controlName]\n        if (control) {\n            const input = Array.isArray(control.bind) ? control.bind[0] : control.bind\n            if (isDown === undefined) {\n                await this.applyKeyPress(input as string)\n            }\n            else if (isDown) {\n                this.applyKeyDown(input as string)\n            }\n            else {\n                this.applyKeyUp(input as string)\n            }\n        }\n    }\n\n    /**\n     * Resume listening to inputs after stopInputs() was called\n     * Also resets keyboard state\n     */\n    listenInputs() {\n        super.listenInputs();\n        this.keyState = {}\n    }\n\n}\n"
  },
  {
    "path": "packages/core/src/directives/Scheduler.ts",
    "content": "import { WritableSignal } from '@signe/reactive';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport * as Utils from '../engine/utils';\n\nexport interface Tick {\n    timestamp: number\n    deltaTime: number\n    frame: number\n    deltaRatio: number\n}\n\nexport class Scheduler extends Directive {\n    private maxFps?: number\n    private fps: number = 60\n    private deltaTime: number = 0\n    public frame: number = 0\n    private timestamp: number = 0\n    private requestedDelay: number = 0\n    private lastTimestamp: number = 0\n    private _stop: boolean = false\n    private tick: WritableSignal<Tick | null>\n    \n    onInit(element: Element) { \n        this.tick = element.propObservables?.tick as any\n    }\n\n    onDestroy() { }\n    onMount(element: Element) { }\n    onUpdate(props: any) { }\n\n    nextTick(timestamp: number) {\n        const now = (typeof timestamp === \"number\" && timestamp > 0)\n            ? timestamp\n            : Utils.preciseNow()\n        if (this.lastTimestamp === 0) {\n            this.lastTimestamp = now\n            this.deltaTime = 0\n        } else {\n            this.deltaTime = now - this.lastTimestamp\n            this.lastTimestamp = now\n        }\n        this.timestamp = now\n        this.tick.set({\n            timestamp: this.timestamp,\n            deltaTime: this.deltaTime,\n            frame: this.frame,\n            deltaRatio: ~~this.deltaTime / ~~Utils.fps2ms(this.fps)\n        })\n        this.lastTimestamp = this.timestamp\n        this.frame++\n    }\n    /**\n     * start the schedule\n     * @return {Scheduler} returns this scheduler instance\n     */\n    start(options: {\n        maxFps?: number\n        fps?: number,\n        delay?: number\n    } = {}) {\n        if (options.maxFps) this.maxFps = options.maxFps\n        if (options.fps) this.fps = options.fps\n        if (options.delay) this.requestedDelay = options.delay\n        const requestAnimationFrame = (fn: (timestamp: number) => void) => {\n            if (Utils.isBrowser()) {\n                window.requestAnimationFrame(fn.bind(this))\n            }\n            else {\n                setTimeout(() => {\n                    this.requestedDelay = 0\n                    fn(Utils.preciseNow())\n                }, Utils.fps2ms(this.fps) + this.requestedDelay)\n            }\n        }\n\n        if (!this.maxFps) {\n            const loop = (timestamp: number) => {\n                requestAnimationFrame(loop)\n                this.nextTick(timestamp)\n            }\n            requestAnimationFrame(loop)\n        }\n        else {\n            const msInterval = Utils.fps2ms(this.maxFps)\n            let now = Utils.preciseNow()\n            let then = Utils.preciseNow()\n            const loop = (timestamp: number) => {\n                if (this._stop) return\n                requestAnimationFrame(loop)\n                now = Utils.preciseNow()\n                const elapsed = now - then\n                if (elapsed > msInterval) {\n                    then = now - (elapsed % msInterval)\n                    this.nextTick(timestamp)\n                }\n            }\n            requestAnimationFrame(loop)\n        }\n\n        return this;\n    }\n\n    stop() {\n        this._stop = true\n    }\n}\n\nregisterDirective('tick', Scheduler)\n"
  },
  {
    "path": "packages/core/src/directives/Shake.ts",
    "content": "import { Container, Point } from 'pixi.js';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { effect, isSignal } from '@signe/reactive';\nimport { on, isTrigger, Trigger } from '../engine/trigger';\nimport { useProps } from '../hooks/useProps';\nimport { SignalOrPrimitive } from '../components/types';\nimport { animatedSignal, AnimatedSignal } from '../engine/animation';\nimport { Subscription } from 'rxjs';\n\nexport type ShakeProps = {\n    /**\n     * Trigger that activates the shake animation\n     * When the trigger is activated, the shake animation will start\n     */\n    trigger?: Trigger<any>;\n    /**\n     * Intensity of the shake effect (in pixels)\n     * @default 10\n     */\n    intensity?: SignalOrPrimitive<number>;\n    /**\n     * Duration of the shake animation in milliseconds\n     * @default 500\n     */\n    duration?: SignalOrPrimitive<number>;\n    /**\n     * Number of shake oscillations during the animation\n     * Higher values create more rapid shaking\n     * @default 10\n     */\n    frequency?: SignalOrPrimitive<number>;\n    /**\n     * Direction of the shake: 'x', 'y', or 'both'\n     * @default 'both'\n     */\n    direction?: SignalOrPrimitive<'x' | 'y' | 'both'>;\n    /**\n     * Callback function called when shake starts\n     */\n    onStart?: () => void;\n    /**\n     * Callback function called when shake completes\n     */\n    onComplete?: () => void;\n}\n\n/**\n * Shake directive that animates a display object's position when a trigger is activated.\n * Creates a shake effect by rapidly oscillating the x and/or y position.\n * \n * @example\n * ```typescript\n * // Basic usage with trigger\n * const shakeTrigger = trigger();\n * \n * onMount(element) {\n *   // Element will shake when trigger is activated\n *   element.props.shake = { trigger: shakeTrigger };\n * }\n * \n * // Trigger the shake\n * shakeTrigger.start();\n * ```\n */\nexport class Shake extends Directive {\n    private elementRef: Element<Container> | null = null;\n    private originalPosition: Point = new Point();\n    private progressSignal: AnimatedSignal<number> | null = null;\n    private shakeSubscription: any = null;\n    private positionEffect: Subscription | null = null;\n    private currentShakeConfig: {\n        intensity: number;\n        frequency: number;\n        direction: 'x' | 'y' | 'both';\n        randomSeed: number;\n    } | null = null;\n\n    /**\n     * Initializes the shake directive\n     * @param element - The element to attach the shake effect to\n     */\n    onInit(element: Element<Container>) {\n        this.elementRef = element;\n    }\n\n    /**\n     * Mounts the shake directive and sets up trigger listener\n     * @param element - The element being mounted\n     */\n    onMount(element: Element<Container>) {\n        const instance = element.componentInstance;\n        if (!instance) return;\n\n        const shakeProps = this.shakeProps;\n        \n        // Check if trigger is provided\n        if (!shakeProps.trigger || !isTrigger(shakeProps.trigger)) {\n            return;\n        }\n\n        // Store original position\n        this.originalPosition.set(instance.position.x, instance.position.y);\n\n        // Clean up previous subscription if it exists\n        if (this.shakeSubscription) {\n            this.shakeSubscription.unsubscribe();\n            this.shakeSubscription = null;\n        }\n\n        // Listen to trigger activation\n        this.shakeSubscription = on(shakeProps.trigger, async (data) => {\n            await this.performShake(data);\n        });\n    }\n\n    /**\n     * Gets the shake props with default values\n     * @returns ShakeProps with defaults applied\n     */\n    get shakeProps(): ShakeProps {\n        const shake = this.elementRef?.props.shake;\n        return useProps(shake?.value ?? shake, {\n            intensity: 10,\n            duration: 500,\n            frequency: 10,\n            direction: 'both',\n        });\n    }\n\n    private resolveSignalValue<T>(value: SignalOrPrimitive<T>): T {\n        return (isSignal(value as any) ? (value as any)() : value) as T;\n    }\n\n    /**\n     * Performs the shake animation using animatedSignal\n     * @param data - Optional data passed from the trigger that can override default options\n     */\n    private async performShake(data?: any): Promise<void> {\n        if (!this.elementRef?.componentInstance) return;\n\n        const instance = this.elementRef.componentInstance;\n        const shakeProps = this.shakeProps;\n        \n        // Use data from trigger to override defaults if provided\n        const intensity = data?.intensity ?? this.resolveSignalValue(shakeProps.intensity);\n        const duration = data?.duration ?? this.resolveSignalValue(shakeProps.duration);\n        const frequency = data?.frequency ?? this.resolveSignalValue(shakeProps.frequency);\n        const direction = data?.direction ?? this.resolveSignalValue(shakeProps.direction);\n\n        // Stop any existing animation and clean up\n        if (this.positionEffect) {\n            this.positionEffect.unsubscribe();\n            this.positionEffect = null;\n        }\n\n        // Only update originalPosition if it hasn't been properly initialized (still at 0,0 and no parent was present when saved)\n        // OR if the current position is different from the stored original (element was moved)\n        const isOriginalUninitialized = this.originalPosition.x === 0 && this.originalPosition.y === 0 && instance.parent;\n        const hasPositionChanged = instance.position.x !== this.originalPosition.x || instance.position.y !== this.originalPosition.y;\n        \n        if (isOriginalUninitialized || hasPositionChanged) {\n            this.originalPosition.set(instance.position.x, instance.position.y);\n        }\n        \n        // Reset position to original before starting new shake\n        instance.position.x = this.originalPosition.x;\n        instance.position.y = this.originalPosition.y;\n\n        // Call onStart callback\n        shakeProps.onStart?.();\n\n        // Store current shake configuration for use in effect\n        this.currentShakeConfig = {\n            intensity,\n            frequency,\n            direction,\n            randomSeed: Math.random() * 1000, // Fixed random seed for this shake\n        };\n\n        // Create or recreate progress signal for shake animation\n        // We recreate it to ensure a fresh animation state\n        if (this.progressSignal) {\n            // Reset to 0 immediately without animation and wait for completion\n            await this.progressSignal.set(0, { duration: 0 });\n        } else {\n            this.progressSignal = animatedSignal(0, {\n                duration: duration,\n                ease: (t) => t, // Linear ease, we'll handle oscillation in effect\n            });\n        }\n\n        const shakeX = direction === 'y' ? false : true;\n        const shakeY = direction === 'x' ? false : true;\n\n        // Create effect to update position based on progress\n        this.positionEffect = effect(() => {\n            if (!instance || !this.progressSignal || !this.currentShakeConfig) return;\n\n            const progress = this.progressSignal();\n            const config = this.currentShakeConfig;\n            \n            // Calculate decay factor (shake intensity decreases over time)\n            const decay = 1 - progress;\n            \n            // Generate oscillation based on progress and frequency\n            // progress goes from 0 to 1, so we multiply by frequency to get oscillations\n            const time = progress * config.frequency;\n            const oscillation = Math.sin(time * Math.PI * 2);\n            \n            // Apply shake with decay and consistent random variation\n            // Use the stored random seed for consistency during this shake\n            const randomValue = (Math.sin(config.randomSeed + progress * 10) * 0.25 + 1); // Between 0.75 and 1.25\n            const offsetX = shakeX ? oscillation * config.intensity * decay * randomValue : 0;\n            const offsetY = shakeY ? oscillation * config.intensity * decay * randomValue : 0;\n\n            // Update position\n            instance.position.x = this.originalPosition.x + offsetX;\n            instance.position.y = this.originalPosition.y + offsetY;\n        }).subscription;\n\n        // Start animation and wait for completion\n        // Note: animatedSignal.set() replaces onComplete with resolve, so we call onComplete after await\n        await this.progressSignal.set(1, {\n            duration: duration,\n        });\n\n        // Animation completed - clean up and call callbacks\n        // Reset to original position\n        if (instance) {\n            instance.position.x = this.originalPosition.x;\n            instance.position.y = this.originalPosition.y;\n        }\n        \n        // Clean up position effect\n        if (this.positionEffect) {\n            this.positionEffect.unsubscribe();\n            this.positionEffect = null;\n        }\n        \n        // Clear shake config\n        this.currentShakeConfig = null;\n        \n        // Call onComplete callback\n        shakeProps.onComplete?.();\n    }\n\n    /**\n     * Updates the shake directive when props change\n     * @param props - Updated props\n     */\n    onUpdate(props: any) {\n        // Re-mount if props change significantly\n        if (props.type && props.type === 'reset') {\n            this.onDestroy();\n            if (this.elementRef) {\n                this.onMount(this.elementRef);\n            }\n        }\n    }\n\n    /**\n     * Cleans up the shake directive\n     */\n    onDestroy() {\n        // Stop any running animation by resetting progress\n        if (this.progressSignal) {\n            this.progressSignal.set(0, { duration: 0 });\n            this.progressSignal = null;\n        }\n\n        // Clean up position effect\n        if (this.positionEffect) {\n            this.positionEffect.unsubscribe();\n            this.positionEffect = null;\n        }\n\n        // Clear shake config\n        this.currentShakeConfig = null;\n\n        // Reset position to original\n        if (this.elementRef?.componentInstance) {\n            const instance = this.elementRef.componentInstance;\n            instance.position.x = this.originalPosition.x;\n            instance.position.y = this.originalPosition.y;\n        }\n\n        // Clean up subscription\n        if (this.shakeSubscription) {\n            this.shakeSubscription.unsubscribe();\n            this.shakeSubscription = null;\n        }\n\n        this.elementRef = null;\n    }\n}\n\nregisterDirective('shake', Shake);\n"
  },
  {
    "path": "packages/core/src/directives/Sound.ts",
    "content": "import { effect } from '@signe/reactive';\nimport { Howl } from 'howler';\nimport { Container } from 'pixi.js';\nimport { Subscription } from 'rxjs';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { calculateDistance, error } from '../engine/utils';\n\nconst EVENTS = ['load', 'loaderror', 'playerror', 'play', 'end', 'pause', 'stop', 'mute', 'volume', 'rate', 'seek', 'fade', 'unlock']\n\n/**\n * Sound directive for playing audio with support for spatial audio and multiple sound sources\n * \n * This directive manages audio playback using Howler.js library. It supports:\n * - Single or multiple sound sources\n * - Spatial audio with distance-based volume calculation\n * - All standard audio controls (play, pause, volume, etc.)\n * - Event handling for audio lifecycle\n * \n */\nexport class Sound extends Directive {\n    private sounds: Howl[] = []\n    private eventsFn: ((...args: any[]) => void)[] = []\n    private maxVolume: number = 1\n    private maxDistance: number = 100\n    private tickSubscription?: Subscription \n\n    onInit(element: Element<Container>) { }\n\n    onMount(element: Element<Container>) {\n        const { props } = element\n        const tick = props.context.tick\n        const propsSound = props.sound.value ?? props.sound\n\n        // Check if src is null or undefined\n        if (!propsSound.src) {\n            return\n        }\n\n        const { src, autoplay, loop, volume, spatial } = propsSound\n        \n        // Handle multiple sources\n        const sources = Array.isArray(src) ? src : [src]\n\n        // Create Howl instances for each source\n        for (const source of sources) {\n            if (!source) continue // Skip null/undefined sources\n            \n            const sound = new Howl({\n                src: source,\n                autoplay,\n                loop,\n                volume\n            })\n \n            // Add event listeners for each sound\n            for (let event of EVENTS) {\n                if (!propsSound[event]) continue\n                const fn = propsSound[event]\n                this.eventsFn.push(fn)\n                sound.on(event, fn);\n            }\n            \n            this.sounds.push(sound)\n        }\n\n        // Setup spatial audio if enabled\n        if (spatial && this.sounds.length > 0) {\n            const { soundListenerPosition } = props.context\n            if (!soundListenerPosition) {\n                throw new error('SoundListenerPosition directive is required for spatial sound in component parent')\n            }\n            const { x: listenerX, y: listenerY } = soundListenerPosition\n            this.tickSubscription = effect(() => {\n                tick()\n                const { x, y } = element.componentInstance\n                const distance = calculateDistance(x, y, listenerX(), listenerY());\n                const volume = Math.max(this.maxVolume - (distance / this.maxDistance), 0)\n                \n                // Apply volume to all sounds\n                this.sounds.forEach(sound => sound.volume(volume))\n            }).subscription\n        }\n\n        this.onUpdate(propsSound)\n    }\n\n    onUpdate(props: any) {\n        const soundProps = props.value ?? props\n        const { volume, loop, mute, seek, playing, rate, spatial } = soundProps\n        // Apply updates to all sounds\n        this.sounds.forEach(sound => {\n            if (volume !== undefined) sound.volume(volume)\n            if (loop !== undefined) sound.loop(loop)\n            if (mute !== undefined) sound.mute(mute)\n            if (seek !== undefined) sound.seek(seek)\n            if (playing !== undefined) {\n                if (playing) sound.play()\n                else sound.pause()\n            }\n            if (rate !== undefined) sound.rate(rate)\n        })\n        \n        // Update spatial audio settings\n        if (spatial) {\n            this.maxVolume = spatial.maxVolume ?? this.maxVolume\n            this.maxDistance = spatial.maxDistance ?? this.maxDistance\n        }\n    }\n\n    onDestroy() {\n        // Stop and clean up all sounds\n        this.sounds.forEach(sound => {\n            sound.stop()\n            \n            // Remove event listeners\n            for (let event of EVENTS) {\n                const eventFn = this.eventsFn.find(fn => fn === this.eventsFn[event])\n                if (eventFn) {\n                    sound.off(event, eventFn);\n                }\n            }\n        })\n        \n        this.sounds = []\n        this.eventsFn = []\n        this.tickSubscription?.unsubscribe()\n    }\n}\n\n/**\n * SoundListenerPosition directive for spatial audio\n * \n * This directive provides the listener position for spatial audio calculations.\n * It should be placed on a parent component that contains spatial sound sources.\n * \n * @example\n * ```tsx\n * <Player soundListenerPosition={{ x: playerX, y: playerY }}>\n *   <Enemy sound={{ src: 'growl.mp3', spatial: { maxDistance: 100 } }} />\n * </Player>\n * ```\n */\nclass SoundListenerPosition extends Directive {\n    onMount(element: Element<any>) {\n        element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition\n    }\n    onInit(element: Element<any>) { }\n    onUpdate(props: any) { }\n    onDestroy() { }\n}\n\nregisterDirective('sound', Sound)\nregisterDirective('soundListenerPosition', SoundListenerPosition)"
  },
  {
    "path": "packages/core/src/directives/Transition.ts",
    "content": "import { Container, DisplacementFilter, Sprite, Texture, WRAP_MODES } from 'pixi.js';\nimport { animate } from 'popmotion';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\n\n\nexport class Transition extends Directive {\n   \n\n    onInit(element: Element<Container>) {\n    }\n\n    onMount(element: Element<Container>) {\n        const { image } = element.props.transition\n        const displacementSprite = new Sprite(Texture.from(image))\n        displacementSprite.texture.baseTexture.wrapMode = WRAP_MODES.REPEAT\n        const displacementFilter = new DisplacementFilter(displacementSprite)\n        const instance = element.componentInstance\n        instance.filters = [displacementFilter]\n\n        instance.addChild(displacementSprite)\n\n        setTimeout(() => {\n            animate({\n                from: 0,\n                to: 1,\n                duration: 500,\n                onUpdate: (progress) => {\n                    displacementFilter.scale.x = progress\n                    displacementFilter.scale.y = progress\n                }\n            })\n        }, 5000)\n    }\n\n    onUpdate(props: any) {\n\n    }\n\n    onDestroy() {\n\n    }\n}\n\nregisterDirective('transition', Transition)"
  },
  {
    "path": "packages/core/src/directives/ViewportCull.ts",
    "content": "import { effect } from '@signe/reactive';\nimport { Simple } from \"pixi-cull\";\nimport { Container } from 'pixi.js';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { error } from '../engine/utils';\n\nexport class ViewportCull extends Directive {\n    private cull: Simple\n\n    onInit(element) {\n        this.cull = new Simple({\n            dirtyTest: false,\n        })\n    }\n    onMount(element: Element<Container>) {\n        const tick = element.props.context.tick\n        const { viewportCull } = element.props\n        const { viewport } = element.props.context\n        if (!viewport) {\n            throw error('ViewportCull directive requires a Viewport component to be mounted in the same context')\n        }\n\n        element.props.children[0].subscribe((val) => {\n            this.cull.lists[0] = val.fullElements.map((el: any) => el.componentInstance)\n        })\n\n        effect(() => {\n            tick()\n            if (viewport.dirty) {\n                this.cull.cull(viewport.getVisibleBounds())\n                viewport.dirty = false\n            }\n        })\n    }\n    onUpdate(props: any) { }\n    onDestroy() { }\n}\n\nregisterDirective('viewportCull', ViewportCull)"
  },
  {
    "path": "packages/core/src/directives/ViewportFollow.ts",
    "content": "import { ComponentInstance } from '../components/DisplayObject';\nimport { SignalOrPrimitive } from '../components/types';\nimport { Directive, registerDirective } from '../engine/directive';\nimport { Element } from '../engine/reactive';\nimport { error } from '../engine/utils';\nimport { useProps } from '../hooks/useProps';\n\nexport type ViewportFollowProps = {\n    viewportFollow?: boolean | {\n        speed?: SignalOrPrimitive<number>;\n        acceleration?: SignalOrPrimitive<number>;\n        radius?: SignalOrPrimitive<number>;\n    };\n}\n\nexport class ViewportFollow extends Directive {\n    onInit(element: Element<ComponentInstance>) {\n\n    }\n    onMount(element: Element) {\n        this.onUpdate(element.props.viewportFollow, element)\n    }\n    onUpdate(viewportFollow: any, element: Element) {\n        const viewport = element.props.context?.viewport\n        if (!viewport) {\n            if (viewportFollow) {\n                throw error('ViewportFollow directive requires a Viewport component to be mounted in the same context')\n            }\n            return\n        }\n        if (viewportFollow) {\n            if (viewportFollow === true) {\n                viewport.follow(element.componentInstance)\n            } else {\n                const options = useProps(viewportFollow, {\n                    speed: undefined,\n                    acceleration: undefined,\n                    radius: undefined\n                })\n                viewport.follow(element.componentInstance, {\n                    speed: options.speed(),\n                    acceleration: options.acceleration(),\n                    radius: options.radius()\n                })\n            }\n        } else if (viewportFollow === null) {\n            viewport.plugins.remove('follow')\n        }\n    }\n    onDestroy(element: Element) {\n        const { viewportFollow } = element.props\n        const viewport = element.props.context?.viewport\n        if (viewportFollow && viewport) viewport.plugins.remove('follow')\n    }\n}\n\nregisterDirective('viewportFollow', ViewportFollow)"
  },
  {
    "path": "packages/core/src/directives/index.ts",
    "content": "export * from './ControlsBase'\nexport * from './KeyboardControls'\nexport * from './GamepadControls'\nexport * from './JoystickControls'\nexport * from './Controls'\nexport * from './Scheduler'\nexport * from './ViewportFollow'\n//import './ViewportCull'\nexport * from './Sound'\nexport * from './Drag'\nexport * from './Transition'\nexport * from './Shake'\nexport * from './Flash'\nexport * from './FogVisibility'\n"
  },
  {
    "path": "packages/core/src/engine/FocusManager.ts",
    "content": "import { isSignal, signal, Signal, WritableSignal, WritableObjectSignal } from \"@signe/reactive\";\nimport { Element, isElementFrozen } from \"./reactive\";\nimport { CanvasViewport } from \"../components/Viewport\";\nimport { SignalOrPrimitive } from \"../components/types\";\n\n/**\n * Options for scroll behavior when navigating to focused elements\n * \n * @property padding - Padding around the element in pixels (default: 0)\n * @property smooth - Enable smooth scrolling animation (default: false)\n * @property center - Center the element in the viewport (default: true)\n * @property duration - Animation duration in ms if smooth=true (default: 300)\n */\nexport interface ScrollOptions {\n  padding?: number;\n  smooth?: boolean;\n  center?: boolean;\n  duration?: number;\n}\n\n/**\n * Data structure for a focus container\n */\ntype WritableElementSignal = WritableSignal<Element | null> | WritableObjectSignal<Element | null>;\n\ninterface FocusContainerData {\n  id: string;\n  element?: Element<any>;\n  focusables: Map<number, Element<any>>;\n  currentIndex: WritableSignal<number | null>;\n  focusedElement: WritableElementSignal;\n  onFocusChange?: (index: number, element: Element | null) => void;\n  autoScroll?: boolean | ScrollOptions;\n  viewport?: CanvasViewport;\n  tabindex?: SignalOrPrimitive<number> | null;\n  tabindexSubscription?: any;\n  pendingIndex?: number;\n}\n\n/**\n * Central manager for focus navigation system\n * \n * Manages focusable elements within containers, handles navigation,\n * and provides scroll integration with Viewport.\n * \n * @example\n * ```typescript\n * const manager = FocusManager.getInstance();\n * manager.registerContainer('menu', containerData);\n * manager.navigate('menu', 'next');\n * ```\n */\nexport class FocusManager {\n  private static instance: FocusManager | null = null;\n  private containers: Map<string, FocusContainerData> = new Map();\n  private scrollAnimations: Map<string, { startTime: number; startX: number; startY: number; targetX: number; targetY: number; duration: number }> = new Map();\n\n  /**\n   * Get the singleton instance of FocusManager\n   * \n   * @returns The FocusManager instance\n   */\n  static getInstance(): FocusManager {\n    if (!FocusManager.instance) {\n      FocusManager.instance = new FocusManager();\n    }\n    return FocusManager.instance;\n  }\n\n  /**\n   * Register a focus container\n   * \n   * @param id - Unique identifier for the container\n   * @param data - Container data including signals and callbacks\n   */\n  registerContainer(id: string, data: Omit<FocusContainerData, 'id'>): void {\n    this.containers.set(id, { ...data, id });\n  }\n\n  /**\n   * Update a focus container's data\n   * \n   * @param id - Container identifier\n   * @param data - Partial container data to update\n   */\n  updateContainer(id: string, data: Partial<Omit<FocusContainerData, 'id'>>): void {\n    const container = this.containers.get(id);\n    if (container) {\n      this.containers.set(id, { ...container, ...data });\n    }\n  }\n\n  setTabindex(id: string, tabindex?: SignalOrPrimitive<number> | null): void {\n    const container = this.containers.get(id);\n    if (!container) return;\n\n    // Cleanup previous subscription\n    if (container.tabindexSubscription) {\n      container.tabindexSubscription.unsubscribe();\n    }\n\n    if (tabindex === undefined || tabindex === null) {\n      container.tabindex = undefined;\n      return;\n    }\n\n    container.tabindex = tabindex;\n\n    const currentTabindex = isSignal(tabindex) ? (tabindex as Signal<number>)() : tabindex;\n    if (typeof currentTabindex === \"number\") {\n      this.setIndex(id, currentTabindex);\n    }\n\n    if (isSignal(tabindex)) {\n      container.tabindexSubscription = ((tabindex as Signal<number>).observable as any).subscribe((value: any) => {\n        if (value !== null && value !== container.currentIndex()) {\n          this.setIndex(id, value);\n        }\n      });\n    }\n  }\n\n  /**\n   * Unregister a focus container\n   * \n   * @param id - Container identifier to remove\n   */\n  unregisterContainer(id: string): void {\n    this.containers.delete(id);\n    this.scrollAnimations.delete(id);\n  }\n\n  /**\n   * Register a focusable element in a container\n   * \n   * @param containerId - Container identifier\n   * @param element - Element to register\n   * @param index - Focus index for this element\n   */\n  registerFocusable(containerId: string, element: Element, index: number): void {\n    const container = this.containers.get(containerId);\n    if (!container) {\n      console.warn(`FocusContainer with id \"${containerId}\" not found`);\n      return;\n    }\n    container.focusables.set(index, element);\n\n    // If this is the index we are supposed to be at, set it now\n    const currentTabindex = isSignal(container.tabindex) ? (container.tabindex as Signal<number>)() : container.tabindex;\n    if (container.pendingIndex === index || (currentTabindex === index && container.currentIndex() === null)) {\n      container.pendingIndex = undefined;\n      this.applyFocus(container, containerId, index, element);\n    }\n  }\n\n  /**\n   * Unregister a focusable element from a container\n   * \n   * @param containerId - Container identifier\n   * @param index - Focus index to remove\n   */\n  unregisterFocusable(containerId: string, index: number): void {\n    const container = this.containers.get(containerId);\n    if (!container) return;\n    container.focusables.delete(index);\n  }\n\n  /**\n   * Navigate to next or previous focusable element\n   * \n   * @param containerId - Container identifier\n   * @param direction - Navigation direction ('next' or 'previous')\n   */\n  navigate(containerId: string, direction: 'next' | 'previous'): void {\n    const container = this.containers.get(containerId);\n    if (!container) {\n      return;\n    }\n\n    // Check if container is frozen (including parent containers)\n    if (container.element && isElementFrozen(container.element)) {\n      return;\n    }\n\n    const currentIndex = container.currentIndex();\n    const focusableIndices = Array.from(container.focusables.keys()).sort((a, b) => a - b);\n\n    if (focusableIndices.length === 0) return;\n\n    let newIndex: number | null = null;\n\n    if (currentIndex === null) {\n      // No current focus, go to first or last\n      newIndex = direction === 'next' ? focusableIndices[0] : focusableIndices[focusableIndices.length - 1];\n    } else {\n      const currentIndexPos = focusableIndices.indexOf(currentIndex);\n      if (direction === 'next') {\n        if (currentIndexPos < focusableIndices.length - 1) {\n          newIndex = focusableIndices[currentIndexPos + 1];\n        } else {\n          // Wrap around to first\n          newIndex = focusableIndices[0];\n        }\n      } else {\n        if (currentIndexPos > 0) {\n          newIndex = focusableIndices[currentIndexPos - 1];\n        } else {\n          // Wrap around to last\n          newIndex = focusableIndices[focusableIndices.length - 1];\n        }\n      }\n    }\n\n    if (newIndex !== null) {\n      const tabindex = container.tabindex;\n      if (isSignal(tabindex) && typeof (tabindex as any).set === \"function\") {\n        (tabindex as any).set(newIndex);\n      } else {\n        this.setIndex(containerId, newIndex);\n      }\n    }\n  }\n\n  /**\n   * Set the focus index for a container\n   * \n   * @param containerId - Container identifier\n   * @param index - Focus index to set\n   */\n  setIndex(containerId: string, index: number): void {\n    const container = this.containers.get(containerId);\n    if (!container) return;\n\n    const element = container.focusables.get(index);\n    if (!element) {\n      container.pendingIndex = index;\n      return;\n    }\n    this.applyFocus(container, containerId, index, element);\n  }\n\n  private applyFocus(\n    container: FocusContainerData,\n    containerId: string,\n    index: number,\n    element: Element\n  ): void {\n    container.currentIndex.set(index);\n    container.focusedElement.set(element);\n\n    // Sync back to tabindex signal if it exists\n    const tabindex = container.tabindex;\n    if (isSignal(tabindex) && (tabindex as any)() !== index && typeof (tabindex as any).set === \"function\") {\n      (tabindex as any).set(index);\n    }\n\n    // Trigger callback\n    if (container.onFocusChange) {\n      container.onFocusChange(index, element);\n    }\n    // Handle DOM focus and scrolling\n    const instance = element.componentInstance as any;\n    if (instance && instance.element && typeof instance.element.focus === 'function') {\n      const domElement = instance.element as HTMLElement;\n      // Focus the native DOM element so :focus styles apply\n      domElement.focus();\n\n      // Scroll the element into view, centering it in the scrollable parent\n      if (typeof domElement.scrollIntoView === 'function') {\n        domElement.scrollIntoView({\n          block: 'center',\n          behavior: 'smooth'\n        });\n      }\n    }\n\n    // Handle auto-scroll if enabled\n    if (container.autoScroll) {\n      const viewport = container.viewport;\n      if (viewport) {\n        const options: ScrollOptions = typeof container.autoScroll === 'boolean'\n          ? { center: true }\n          : container.autoScroll;\n        this.scrollToElement(containerId, index, viewport, options);\n      }\n    }\n  }\n\n  /**\n   * Get the element at a specific index\n   * \n   * @param containerId - Container identifier\n   * @param index - Focus index\n   * @returns Element at index or null\n   */\n  getElement(containerId: string, index: number): Element | null {\n    const container = this.containers.get(containerId);\n    if (!container) return null;\n    return container.focusables.get(index) || null;\n  }\n\n  /**\n   * Get current focus index for a container\n   * \n   * @param containerId - Container identifier\n   * @returns Current index signal\n   */\n  getCurrentIndexSignal(containerId: string): Signal<number | null> | null {\n    const container = this.containers.get(containerId);\n    return container ? container.currentIndex : null;\n  }\n\n  /**\n   * Get current focused element signal for a container\n   * \n   * @param containerId - Container identifier\n   * @returns Current element signal\n   */\n  getFocusedElementSignal(containerId: string): Signal<Element | null> | null {\n    const container = this.containers.get(containerId);\n    return container ? (container.focusedElement as unknown as Signal<Element | null>) : null;\n  }\n\n  /**\n   * Check if an element is visible in the viewport\n   * \n   * @param element - Element to check\n   * @param viewport - Viewport to check against (optional)\n   * @returns True if element is visible\n   */\n  isElementVisible(element: Element, viewport?: CanvasViewport): boolean {\n    if (!viewport) return true;\n\n    const bounds = this.getElementBounds(element);\n    const visibleBounds = viewport.getVisibleBounds();\n\n    return (\n      bounds.x < visibleBounds.right &&\n      bounds.x + bounds.width > visibleBounds.left &&\n      bounds.y < visibleBounds.bottom &&\n      bounds.y + bounds.height > visibleBounds.top\n    );\n  }\n\n  /**\n   * Get global bounds of an element\n   * \n   * @param element - Element to get bounds for\n   * @returns Bounds object with x, y, width, height\n   */\n  getElementBounds(element: Element): { x: number; y: number; width: number; height: number } {\n    const instance = element.componentInstance;\n    if (!instance) {\n      return { x: 0, y: 0, width: 0, height: 0 };\n    }\n\n    // Get local bounds\n    const localBounds = instance.getLocalBounds?.();\n    if (!localBounds) {\n      return { x: 0, y: 0, width: 0, height: 0 };\n    }\n\n    // Get global position\n    const globalPos = instance.getGlobalPosition?.();\n    if (!globalPos) {\n      return { x: 0, y: 0, width: 0, height: 0 };\n    }\n\n    return {\n      x: globalPos.x,\n      y: globalPos.y,\n      width: localBounds.width,\n      height: localBounds.height\n    };\n  }\n\n  /**\n   * Scroll viewport to show an element\n   * \n   * @param containerId - Container identifier\n   * @param index - Focus index of element to scroll to\n   * @param viewport - Viewport instance (optional, uses container's viewport if not provided)\n   * @param options - Scroll options\n   */\n  scrollToElement(\n    containerId: string,\n    index: number,\n    viewport?: CanvasViewport,\n    options: ScrollOptions = {}\n  ): void {\n    const container = this.containers.get(containerId);\n    if (!container) return;\n\n    const element = container.focusables.get(index);\n    if (!element) return;\n\n    const targetViewport = viewport || container.viewport;\n    if (!targetViewport) return;\n\n    const bounds = this.getElementBounds(element);\n    const visibleBounds = targetViewport.getVisibleBounds();\n    const padding = options.padding || 0;\n    const center = options.center !== false; // Default to true\n    const smooth = options.smooth || false;\n    const duration = options.duration || 300;\n\n    // Check if element is already visible\n    if (this.isElementVisible(element, targetViewport)) {\n      // Element is visible, but check if we need to center it\n      if (center) {\n        const centerX = bounds.x + bounds.width / 2;\n        const centerY = bounds.y + bounds.height / 2;\n\n        if (smooth) {\n          this.animateScroll(containerId, targetViewport, centerX, centerY, duration);\n        } else {\n          targetViewport.moveCenter(centerX, centerY);\n        }\n      }\n      return;\n    }\n\n    // Element is not visible, scroll to it\n    if (center) {\n      const centerX = bounds.x + bounds.width / 2;\n      const centerY = bounds.y + bounds.height / 2;\n\n      if (smooth) {\n        this.animateScroll(containerId, targetViewport, centerX, centerY, duration);\n      } else {\n        targetViewport.moveCenter(centerX, centerY);\n      }\n    } else {\n      // Scroll to make element visible with padding\n      const targetX = bounds.x - padding;\n      const targetY = bounds.y - padding;\n      const targetWidth = bounds.width + padding * 2;\n      const targetHeight = bounds.height + padding * 2;\n\n      if (smooth) {\n        // For smooth fit, we'll animate to center\n        const centerX = bounds.x + bounds.width / 2;\n        const centerY = bounds.y + bounds.height / 2;\n        this.animateScroll(containerId, targetViewport, centerX, centerY, duration);\n      } else {\n        targetViewport.fit(targetX, targetY, targetWidth, targetHeight, padding);\n      }\n    }\n  }\n\n  /**\n   * Animate smooth scrolling\n   * \n   * @param containerId - Container identifier\n   * @param viewport - Viewport instance\n   * @param targetX - Target X position\n   * @param targetY - Target Y position\n   * @param duration - Animation duration in ms\n   */\n  private animateScroll(\n    containerId: string,\n    viewport: CanvasViewport,\n    targetX: number,\n    targetY: number,\n    duration: number\n  ): void {\n    const currentCenter = viewport.center;\n    const startX = currentCenter.x;\n    const startY = currentCenter.y;\n\n    const animation = {\n      startTime: Date.now(),\n      startX,\n      startY,\n      targetX,\n      targetY,\n      duration\n    };\n\n    this.scrollAnimations.set(containerId, animation);\n\n    // Use requestAnimationFrame for smooth animation\n    const animate = () => {\n      const anim = this.scrollAnimations.get(containerId);\n      if (!anim) return;\n\n      const elapsed = Date.now() - anim.startTime;\n      const progress = Math.min(elapsed / anim.duration, 1);\n\n      // Easing function (ease-out)\n      const eased = 1 - Math.pow(1 - progress, 3);\n\n      const currentX = anim.startX + (anim.targetX - anim.startX) * eased;\n      const currentY = anim.startY + (anim.targetY - anim.startY) * eased;\n\n      viewport.moveCenter(currentX, currentY);\n\n      if (progress < 1) {\n        requestAnimationFrame(animate);\n      } else {\n        this.scrollAnimations.delete(containerId);\n      }\n    };\n\n    requestAnimationFrame(animate);\n  }\n}\n\n// Export singleton instance\nexport const focusManager = FocusManager.getInstance();\n"
  },
  {
    "path": "packages/core/src/engine/animation.ts",
    "content": "import { effect, signal, type WritableSignal, type Signal } from \"@signe/reactive\";\nimport { animate as animatePopmotion } from \"popmotion\";\nimport { Tick } from \"../directives/Scheduler\";\nimport { Subscription } from \"rxjs\";\n\n/**\n * Gets the global tick signal from the engine context.\n * This is automatically set by the Canvas component when it initializes.\n * \n * @returns The global tick signal if available, undefined otherwise\n */\nfunction getGlobalTickSignal(): Signal<Tick> | undefined {\n  return (globalThis as any).__CANVAS_ENGINE_TICK__;\n}\n\nexport interface AnimateOptions<T> {\n  duration?: number;\n  ease?: (t: number) => number;\n  onUpdate?: (value: T) => void;\n  onComplete?: () => void;\n  tick?: Signal<Tick>;\n}\n\nexport interface AnimatedState<T> {\n  current: T;\n  start: T;\n  end: T;\n}\n\nexport interface AnimatedSignal<T> extends Omit<WritableSignal<T>, 'set'> {\n  (): T;\n  set: (newValue: T, options?: AnimateOptions<T>) => Promise<void>;\n  animatedState: WritableSignal<AnimatedState<T>>;\n  update: (updater: (value: T) => T) => void;\n  pause: () => void;\n  resume: () => void;\n}\n\nexport function isAnimatedSignal(signal: WritableSignal<any>): boolean {\n  return (signal as unknown as AnimatedSignal<any>).animatedState !== undefined;\n}\n\n/**\n * Creates a popmotion driver that uses the engine's tick system.\n * The driver subscribes to the tick signal and calls the update function with deltaTime on each tick.\n * \n * @param tickSignal - The tick signal from the engine context\n * @returns A driver function for popmotion\n * @example\n * ```ts\n * const driver = createTickDriver(context.tick);\n * animate({\n *   to: 100,\n *   driver: driver\n * });\n * ```\n */\nfunction createTickDriver(tickSignal: Signal<Tick>) {\n  return (update: (delta: number) => void) => {\n    let subscription: Subscription | undefined;\n    let lastTimestamp: number | null = null;\n    \n    const start = () => {\n      if (subscription) return;\n\n      subscription = (tickSignal.observable as any).subscribe((result: any) => {\n        const tick = result?.value ?? result;\n        if (!tick) return;\n\n        if (lastTimestamp === null) {\n          lastTimestamp = tick.timestamp;\n          return;\n        }\n\n        const delta = tick.deltaTime;\n        lastTimestamp = tick.timestamp;\n        update(delta);\n      });\n    };\n\n    const stop = () => {\n      subscription?.unsubscribe();\n      subscription = undefined;\n      lastTimestamp = null;\n    };\n\n    return { start, stop };\n  };\n}\n\n/**\n * Creates an animated signal with the given initial value and animation options.\n * It's a writable signal that can be animated using popmotion. Properties of the animated signal are:\n * - current: the current value of the signal.\n * - start: the start value of the animation.\n * - end: the end value of the animation.\n * \n * If a tick signal is provided in options, the animation will use the engine's tick system.\n * Otherwise, it will automatically use the global tick signal from the Canvas context if available.\n * If no tick signal is available, it will use requestAnimationFrame by default.\n * \n * @param initialValue The initial value of the signal.\n * @param options The animation options. Can include a `tick` signal to use a specific tick system.\n * @returns The animated signal.\n * @example\n * ```ts\n * // Automatically uses the Canvas tick system if available, otherwise requestAnimationFrame\n * const animatedValue = animatedSignal(0, { duration: 1000 });\n * animatedValue.set(10);\n * \n * // Explicitly using a specific tick signal\n * mount((element) => {\n *   const tickSignal = element.props.context.tick;\n *   const animatedValue = animatedSignal(0, { duration: 1000, tick: tickSignal });\n *   animatedValue.set(10);\n * });\n * ```\n */\nexport function animatedSignal<T>(initialValue: T, options: AnimateOptions<T> = {}): AnimatedSignal<T> {\n  const state: AnimatedState<T> = {\n    current: initialValue,\n    start: initialValue,\n    end: initialValue,\n  };\n  const DEFAULT_DURATION = 20;\n  let animation: { stop: () => void } | null = null;\n  let isPaused = false;\n\n  const publicSignal = signal(initialValue);\n  const privateSignal = signal(state);\n\n  effect(() => {\n    const currentState = privateSignal();\n    publicSignal.set(currentState.current);\n  });\n\n  function animatedSignal(): AnimatedState<T>;\n  function animatedSignal(newValue: T): void;\n  function animatedSignal(newValue: T, animationConfig: AnimateOptions<T>): void;\n  function animatedSignal(newValue?: T, animationConfig: AnimateOptions<T> = {}): AnimatedState<T> | void {\n    if (newValue === undefined) {\n      return privateSignal();\n    }\n    \n    const prevState = privateSignal();\n    const newState: AnimatedState<T> = {\n      current: prevState.current,\n      start: prevState.current,\n      end: newValue,\n    };\n\n    privateSignal.set(newState);\n\n    // Stop any running animation\n    if (animation) {\n      animation.stop();\n      animation = null;\n    }\n\n    isPaused = false;\n    const mergedConfig = { ...options, ...animationConfig };\n    const duration = mergedConfig.duration ?? DEFAULT_DURATION;\n    const ease = mergedConfig.ease ?? ((t: number) => t);\n    const tickSignal = mergedConfig.tick || getGlobalTickSignal();\n\n    const startValue = prevState.current;\n    const endValue = newValue;\n\n    const onCompleteCb = animationConfig.onComplete ?? options.onComplete;\n    \n\n    animation = animatePopmotion({\n      from: startValue as any,\n      to: endValue as any,\n      duration,\n      ease,\n      \n      onUpdate: (value: any) => {\n        if (isPaused) return;\n        const nextValue = value as T;\n        privateSignal.update(s => ({ ...s, current: nextValue }));\n        mergedConfig.onUpdate?.(nextValue);\n        animationConfig.onUpdate?.(nextValue);\n      },\n      onComplete: () => {\n        privateSignal.update(s => ({ ...s, current: endValue }));\n        onCompleteCb?.();\n      }\n    });\n     \n  }\n\n  const fn = function() {\n    return privateSignal().current\n  }\n\n  for (const key in publicSignal) {\n    fn[key] = publicSignal[key]\n  }\n\n  fn.animatedState = privateSignal\n  fn.update = (updater: (value: T) => any) => {\n    animatedSignal(updater(privateSignal().current));\n  }\n  fn.set = async (newValue: T, animationConfig: AnimateOptions<T> = {}) => {\n    return new Promise<void>((resolve) => {\n      const userOnComplete = animationConfig.onComplete;\n      animatedSignal(newValue, {\n        ...animationConfig,\n        onComplete: () => {\n          if (userOnComplete) {\n            userOnComplete();\n          } else if (options.onComplete) {\n            options.onComplete();\n          }\n          resolve();\n        }\n      });\n    });\n  }\n  fn.pause = () => {\n    if (isPaused) return;\n    isPaused = true;\n    if (animation) {\n      animation.stop();\n      animation = null;\n    }\n  }\n  fn.resume = () => {\n    if (!isPaused) return;\n    isPaused = false;\n    const currentState = privateSignal();\n    if (currentState.current !== currentState.end) {\n      animatedSignal(currentState.end, options);\n    }\n  }\n\n  return fn as any\n}\n\n/**\n * Executes a sequence of animations. If an array is provided as an element in the sequence,\n * those animations will be executed in parallel.\n * \n * @param sequence Array of animation functions or arrays of animation functions for parallel execution\n * @returns Promise that resolves when all animations are complete\n * @example\n * ```ts\n * await animatedSequence([\n *   () => value1.set(10),\n *   [\n *     () => value2.set(20),\n *     () => value3.set(30)\n *   ],\n *   () => value1.set(0)\n * ])\n * ```\n */\nexport async function animatedSequence(sequence: ((() => Promise<void>) | (() => Promise<void>)[])[]) {\n  for (const item of sequence) {\n    if (Array.isArray(item)) {\n      await Promise.all(item.map(fn => fn()));\n    } else {\n      await item();\n    }\n  }\n}"
  },
  {
    "path": "packages/core/src/engine/bootstrap.ts",
    "content": "import { Application, ApplicationOptions } from \"pixi.js\";\nimport { ComponentFunction, h } from \"./signal\";\nimport { useProps } from '../hooks/useProps';\nimport { registerAllComponents, registerComponent } from './reactive';\n\n// Import all components to ensure they are registered\n// This is done here (not in reactive.ts) to avoid circular dependencies\n// Components register themselves when their modules are imported\nimport '../components/Canvas';\nimport '../components/Container';\nimport '../components/Sprite';\nimport '../components/Text';\nimport '../components/Graphic';\nimport '../components/Mesh';\nimport '../components/Viewport';\nimport '../components/TilingSprite';\nimport '../components/NineSliceSprite';\nimport '../components/DOMContainer';\nimport '../components/DOMElement';\nimport '../components/ParticleEmitter';\n\n/**\n * Extended options for bootstrapCanvas that includes component registration configuration.\n * \n * @property components - Optional mapping of component names to their classes (can include mocks for testing)\n * @property autoRegister - If true (default), registers all default components before applying custom components. If false, only registers the specified components.\n */\nexport interface BootstrapOptions extends ApplicationOptions {\n  components?: {\n    [name: string]: any; // ComponentClass\n  };\n  autoRegister?: boolean; // true by default if components is not provided\n  enableLayout?: boolean; // true by default\n}\n\n/**\n * Bootstraps a canvas element and renders it to the DOM.\n * \n * @param rootElement - The HTML element where the canvas will be rendered. Can be null.\n * @param canvas - A Promise that resolves to an Element representing the canvas component.\n * @param options - Optional bootstrap options including ApplicationOptions and component registration configuration.\n * @returns A Promise that resolves to the rendered canvas element.\n * @throws {Error} If the provided element is not a Canvas component.\n * \n * @example\n * ```typescript\n * // Default: all components registered automatically\n * await bootstrapCanvas(rootElement, MyComponent, {\n *   width: 800,\n *   height: 600\n * });\n * ```\n * \n * @example\n * ```typescript\n * // With mocks for testing\n * import { mockComponents } from '@canvasengine/testing';\n * await bootstrapCanvas(rootElement, MyComponent, {\n *   components: mockComponents,\n *   autoRegister: false\n * });\n * ```\n */\nexport const bootstrapCanvas = async (rootElement: HTMLElement | null, canvas: ComponentFunction<any>, options?: BootstrapOptions) => {\n  // Extract component registration options\n  const { components, autoRegister, enableLayout, ...appOptions } = options ?? {};\n  if (enableLayout !== false) {\n    await import('@pixi/layout');\n  }\n  \n  // Handle component registration\n  if (components) {\n    if (autoRegister !== false) {\n      // Register all default components first, then override with custom ones\n      registerAllComponents();\n    }\n    // Register the specified components (overriding defaults if autoRegister is true)\n    Object.entries(components).forEach(([name, componentClass]) => {\n      registerComponent(name, componentClass);\n    });\n  } else {\n    // Default behavior: register all components\n    registerAllComponents();\n  }\n  \n  const app = new Application();\n  await app.init({\n    resizeTo: rootElement,\n    autoStart: false,\n    antialias: true,\n    ...appOptions\n  });\n  const canvasElement = await h(canvas);\n  if (canvasElement.tag != 'Canvas') {\n    throw new Error('Canvas is required');\n  }\n  (canvasElement as any).render(rootElement, app);\n\n  const { backgroundColor } = useProps(canvasElement.props, {\n    backgroundColor: 'black'\n  });\n\n  app.renderer.background.color = backgroundColor()\n\n  return {\n    canvasElement,\n    app\n  };\n};\n"
  },
  {
    "path": "packages/core/src/engine/directive.ts",
    "content": "import { Element } from \"./reactive\"\n\nexport const directives: { [key: string]: any } = {}\n\nexport abstract class Directive {\n    abstract onDestroy(element: Element<any>);\n    abstract onInit(element:  Element<any>);\n    abstract onMount(element: Element<any>);\n    abstract onUpdate(props: any, element: Element<any>);\n}\n\nexport function registerDirective(name: string, directive: any) {\n    directives[name] = directive\n}\n\nexport function applyDirective(element: Element<any>, directiveName: string) {\n    if (!directives[directiveName]) {\n        return null\n    }\n    const directive = new directives[directiveName]()\n    directive.onInit?.(element)\n    return directive\n}\n"
  },
  {
    "path": "packages/core/src/engine/reactive.ts",
    "content": "import { ArrayChange, ObjectChange, Signal, WritableArraySignal, WritableObjectSignal, isComputed, isSignal, signal, computed } from \"@signe/reactive\";\nimport { isAnimatedSignal, AnimatedSignal } from \"./animation\";\nimport {\n  Observable,\n  Subject,\n  Subscription,\n  defer,\n  from,\n  map,\n  of,\n  share,\n  shareReplay,\n  switchMap,\n  debounceTime,\n  distinctUntilChanged,\n  bufferTime,\n  filter,\n  throttleTime,\n  combineLatest,\n} from \"rxjs\";\nimport { ComponentInstance } from \"../components/DisplayObject\";\nimport { Directive, applyDirective } from \"./directive\";\nimport { isObject, isPromise, set } from \"./utils\";\n\nexport interface Props {\n  [key: string]: any;\n}\n\ntype NestedSignalObjects = {\n  [Key in string]: NestedSignalObjects | Signal<any>;\n};\n\nexport interface Element<T = ComponentInstance> {\n  tag: string;\n  props: Props;\n  componentInstance: T;\n  propSubscriptions: Subscription[];\n  effectSubscriptions: Subscription[];\n  effectMounts: (() => void)[];\n  effectUnmounts: ((element?: Element) => void)[];\n  propObservables: NestedSignalObjects | undefined;\n  parent: Element | null;\n  context?: {\n    [key: string]: any;\n  };\n  directives: {\n    [key: string]: Directive;\n  };\n  destroy: () => void;\n  allElements: Subject<void>;\n  isFrozen: boolean;\n}\n\ntype FlowResult = {\n  elements: Element[];\n  prev?: Element;\n  fullElements?: Element[];\n};\n\ntype FlowObservable = Observable<FlowResult>;\n\nconst components: { [key: string]: any } = {};\n\nexport const isElement = (value: any): value is Element => {\n  return (\n    value &&\n    typeof value === \"object\" &&\n    \"tag\" in value &&\n    \"props\" in value &&\n    \"componentInstance\" in value\n  );\n};\n\nexport const isPrimitive = (value) => {\n  return (\n    typeof value === \"string\" ||\n    typeof value === \"number\" ||\n    typeof value === \"boolean\" ||\n    value === null ||\n    value === undefined\n  );\n};\n\nconst DOM_ROUTING_MAP: Record<string, string> = {\n  Sprite: \"DOMSprite\",\n};\n\nconst DOM_ALLOWED_TAGS = new Set([\"DOMContainer\", \"DOMElement\", \"DOMSprite\"]);\nconst DOM_UNSUPPORTED_TAGS = new Set([\n  \"Canvas\",\n  \"Container\",\n  \"Graphics\",\n  \"Rect\",\n  \"Circle\",\n  \"Ellipse\",\n  \"Triangle\",\n  \"Svg\",\n  \"Mesh\",\n  \"Scene\",\n  \"ParticlesEmitter\",\n  \"Sprite\",\n  \"Video\",\n  \"Text\",\n  \"TilingSprite\",\n  \"Viewport\",\n  \"NineSliceSprite\",\n  \"Button\",\n  \"Joystick\",\n  \"FocusContainer\",\n]);\n\nconst hasDomAncestor = (element: Element | null): boolean => {\n  let current = element;\n  while (current) {\n    if (current.tag === \"DOMContainer\" || current.tag === \"DOMElement\") {\n      return true;\n    }\n    current = current.parent;\n  }\n  return false;\n};\n\nconst cleanupElementForRouting = (element: Element) => {\n  element.propSubscriptions?.forEach((sub) => sub.unsubscribe());\n  element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());\n  element.effectUnmounts?.forEach((fn) => fn?.());\n};\n\nconst routeDomComponent = (parent: Element, child: Element): Element => {\n  if (!hasDomAncestor(parent)) {\n    return child;\n  }\n  if (DOM_ALLOWED_TAGS.has(child.tag)) {\n    return child;\n  }\n  const routedTag = DOM_ROUTING_MAP[child.tag];\n  if (routedTag) {\n    cleanupElementForRouting(child);\n    const routedProps = child.propObservables ?? child.props;\n    return createComponent(routedTag, routedProps);\n  }\n  if (DOM_UNSUPPORTED_TAGS.has(child.tag)) {\n    throw new Error(\n      `Component ${child.tag} is not implemented for DOMContainer context yet. Only Sprite is supported.`\n    );\n  }\n  return child;\n};\n\nexport function registerComponent(name, component) {\n  components[name] = component;\n}\n\n// Track if components have been registered to avoid duplicate imports\nlet componentsRegistered = false;\n\n/**\n * Registers all default CanvasEngine components.\n * \n * This function imports and registers all core components that are available by default.\n * It's called automatically by bootstrapCanvas() if no custom component configuration is provided.\n * \n * Components register themselves when their modules are imported, so this function ensures\n * all component modules are loaded. Since components call registerComponent() at module load time,\n * importing them will automatically register them synchronously.\n * \n * @example\n * ```typescript\n * // Register all default components manually\n * registerAllComponents();\n * \n * // Now you can use any component\n * const sprite = createComponent('Sprite', { image: 'hero.png' });\n * ```\n */\nexport function registerAllComponents() {\n  if (componentsRegistered) {\n    return;\n  }\n\n  // Components are registered when their modules are imported\n  // Since bootstrap.ts imports all components, they should already be registered\n  // when bootstrapCanvas() is called. This function just marks that registration\n  // has been attempted. If components aren't registered yet, they will be when\n  // bootstrap.ts imports them (which happens before bootstrapCanvas() is called).\n  componentsRegistered = true;\n}\n\n/**\n * Checks if all dependencies are ready (not undefined).\n * Handles signals synchronously and promises asynchronously.\n * For reactive signals, sets up subscriptions to mount when all become ready.\n * \n * @param deps - Array of signals, promises, or direct values\n * @returns Promise<boolean> - true if all dependencies are ready\n */\nexport async function checkDependencies(\n  deps: any[]\n): Promise<boolean> {\n  const values = await Promise.all(\n    deps.map(async (dep) => {\n      if (isSignal(dep)) {\n        return dep(); // Read current signal value\n      } else if (isPromise(dep)) {\n        return await dep; // Await promise resolution\n      }\n      return dep; // Direct value\n    })\n  );\n  return values.every((v) => v !== undefined);\n}\n\nexport function waitForDependencies(deps: any[]): Promise<void> {\n  return new Promise(async (resolve) => {\n    const ready = await checkDependencies(deps);\n    if (ready) {\n      resolve();\n      return;\n    }\n\n    const signalDeps = deps.filter((dep) => isSignal(dep));\n    if (signalDeps.length === 0) {\n      return;\n    }\n\n    const signalObservables = signalDeps.map((sig) => sig.observable);\n    const subscription = combineLatest(signalObservables).subscribe(async () => {\n      const allReady = await checkDependencies(deps);\n      if (allReady) {\n        subscription.unsubscribe();\n        resolve();\n      }\n    });\n  });\n}\n\n/**\n * Checks if an element is currently frozen.\n * An element is frozen when the `freeze` prop is set to `true` (either as a boolean or Signal<boolean>),\n * or when any of its parent elements are frozen (recursive freeze propagation).\n * \n * @param element - The element to check\n * @returns `true` if the element is frozen, `false` otherwise\n */\nexport function isElementFrozen(element: Element): boolean {\n  if (!element) return false;\n\n  // Check if this element itself is frozen\n  const freezeProp = element.propObservables?.freeze ?? element.props?.freeze;\n\n  if (freezeProp !== undefined && freezeProp !== null) {\n    // Handle Signal<boolean>\n    if (isSignal(freezeProp)) {\n      if (freezeProp() === true) {\n        return true;\n      }\n    } else if (freezeProp === true) {\n      // Handle direct boolean\n      return true;\n    }\n  }\n\n  // Check if any parent is frozen (recursive check)\n  if (element.parent) {\n    return isElementFrozen(element.parent);\n  }\n\n  return false;\n}\n\n/**\n * Pauses or resumes all animatedSignals in an element based on freeze state.\n * \n * @param element - The element containing animatedSignals\n * @param shouldPause - Whether to pause (true) or resume (false) animations\n */\nfunction handleAnimatedSignalsFreeze(element: Element, shouldPause: boolean) {\n  if (!element.propObservables) return;\n\n  const processValue = (value: any) => {\n    if (isSignal(value) && isAnimatedSignal(value as any)) {\n      const animatedSig = value as unknown as AnimatedSignal<any>;\n      if (shouldPause) {\n        animatedSig.pause();\n      } else {\n        animatedSig.resume();\n      }\n    } else if (isObject(value) && !isElement(value)) {\n      // Recursively process nested objects\n      Object.values(value).forEach(processValue);\n    }\n  };\n\n  Object.values(element.propObservables).forEach(processValue);\n}\n\nfunction destroyElement(element: Element | Element[]) {\n  if (Array.isArray(element)) {\n    element.forEach((e) => destroyElement(e));\n    return;\n  }\n  if (!element) {\n    return;\n  }\n  if (element.props?.children) {\n    for (let child of element.props.children) {\n      destroyElement(child)\n    }\n  }\n  for (let name in element.directives) {\n    element.directives[name].onDestroy?.(element);\n  }\n  if (element.componentInstance && element.componentInstance.onDestroy) {\n    element.componentInstance.onDestroy(element.parent as any, () => {\n      element.propSubscriptions?.forEach((sub) => sub.unsubscribe());\n      element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());\n      element.effectUnmounts?.forEach((fn) => {\n        if (isPromise(fn)) {\n          (fn as unknown as Promise<any>).then((retFn) => {\n            retFn?.();\n          });\n        } else {\n          fn?.();\n        }\n      });\n    });\n  } else {\n    // If componentInstance is undefined or doesn't have onDestroy, still clean up subscriptions\n    element.propSubscriptions?.forEach((sub) => sub.unsubscribe());\n    element.effectSubscriptions?.forEach((sub) => sub.unsubscribe());\n    element.effectUnmounts?.forEach((fn) => fn?.());\n  }\n}\n\n/**\n * Creates a virtual element or a representation thereof, with properties that can be dynamically updated based on BehaviorSubjects.\n *\n * @param {string} tag - The tag name of the element to create.\n * @param {Object} props - An object containing properties for the element. Each property can either be a direct value\n *                         or an array where the first element is a function that returns a value based on input parameters,\n *                         and the second element is an array of BehaviorSubjects. The property is updated dynamically\n *                         using the combineLatest RxJS operator to wait for all BehaviorSubjects to emit.\n * @returns {Object} An object representing the created element, including tag name and dynamic properties.\n */\nexport function createComponent(tag: string, props?: Props): Element {\n  if (!components[tag]) {\n    throw new Error(`Component ${tag} is not registered`);\n  }\n  const instance = new components[tag]();\n  const element: Element = {\n    tag,\n    props: {},\n    componentInstance: instance,\n    propSubscriptions: [],\n    propObservables: props,\n    parent: null,\n    directives: {},\n    effectUnmounts: [],\n    effectSubscriptions: [],\n    effectMounts: [],\n    destroy() {\n      destroyElement(this);\n    },\n    allElements: new Subject(),\n    isFrozen: false,\n  };\n\n  // Iterate over each property in the props object\n  if (props) {\n    const recursiveProps = (props, path = \"\") => {\n      const _set = (path, key, value) => {\n        if (path == \"\") {\n          element.props[key] = value;\n          return;\n        }\n        set(element.props, path + \".\" + key, value);\n      };\n\n      Object.entries(props).forEach(([key, value]: [string, unknown]) => {\n        if (isSignal(value)) {\n          const _value = value as Signal<any>;\n          if (\"dependencies\" in _value && _value.dependencies.size == 0) {\n            _set(path, key, _value());\n            // Handle freeze prop initialization\n            if (key === \"freeze\") {\n              element.isFrozen = _value() === true;\n            }\n            return;\n          }\n\n          // Handle freeze prop as signal\n          if (key === \"freeze\") {\n            element.isFrozen = _value() === true;\n\n            // Pause/resume animatedSignals based on initial freeze state\n            handleAnimatedSignalsFreeze(element, element.isFrozen);\n\n            element.propSubscriptions.push(\n              _value.observable.subscribe((freezeValue) => {\n                const wasFrozen = element.isFrozen;\n                element.isFrozen = freezeValue === true;\n\n                // Handle animatedSignal pause/resume when freeze state changes\n                if (wasFrozen !== element.isFrozen) {\n                  handleAnimatedSignalsFreeze(element, element.isFrozen);\n                }\n              })\n            );\n            return;\n          }\n\n          element.propSubscriptions.push(\n            _value.observable.subscribe((value) => {\n              // Block updates if element is frozen\n              if (isElementFrozen(element)) {\n                // Pause animatedSignal if it's an animated signal\n                if (isAnimatedSignal(_value as any)) {\n                  (_value as unknown as AnimatedSignal<any>).pause();\n                }\n                return;\n              }\n\n              // Resume animatedSignal if it was paused\n              if (isAnimatedSignal(_value as any)) {\n                (_value as unknown as AnimatedSignal<any>).resume();\n              }\n\n              _set(path, key, value);\n              if (element.directives[key]) {\n                element.directives[key].onUpdate?.(value, element);\n              }\n              if (key == \"tick\") {\n                // Block tick updates if element is frozen\n                if (isElementFrozen(element)) {\n                  return;\n                }\n                return\n              }\n              instance.onUpdate?.(\n                path == \"\"\n                  ? {\n                    [key]: value,\n                  }\n                  : set({}, path + \".\" + key, value)\n              );\n            })\n          );\n        } else {\n          // Handle freeze prop as direct boolean\n          if (key === \"freeze\") {\n            element.isFrozen = value === true;\n\n            // Pause/resume animatedSignals based on freeze state\n            handleAnimatedSignalsFreeze(element, element.isFrozen);\n          }\n          if (isObject(value) && key != \"context\" && !isElement(value)) {\n            recursiveProps(value, (path ? path + \".\" : \"\") + key);\n          } else {\n            _set(path, key, value);\n          }\n        }\n      });\n    };\n    recursiveProps(props);\n  }\n\n  instance.onInit?.(element.props);\n\n  const elementsListen = new Subject<any>()\n\n  if (props?.isRoot) {\n    element.allElements = elementsListen\n    element.props.context.rootElement = element;\n    element.componentInstance.onMount?.(element);\n    propagateContext(element);\n  }\n\n  if (props) {\n    for (let key in props) {\n      const directive = applyDirective(element, key);\n      if (directive) element.directives[key] = directive;\n    }\n  }\n\n  /**\n   * Checks if all dependencies are ready (not undefined).\n   * Handles signals synchronously and promises asynchronously.\n   * For reactive signals, sets up subscriptions to mount when all become ready.\n   * \n   * @param deps - Array of signals, promises, or direct values\n   * @returns Promise<boolean> - true if all dependencies are ready\n   */\n\n\n  /**\n   * Sets up subscriptions to reactive signal dependencies.\n   * When all signals become defined, mounts the component.\n   */\n  /**\n   * Sets up subscriptions to reactive signal dependencies.\n   * When all signals become defined, mounts the component.\n   */\n  function setupDependencySubscriptions(\n    parent: Element,\n    element: Element,\n    deps: any[],\n    index?: number\n  ) {\n    const signalDeps = deps.filter((dep) => isSignal(dep));\n    const promiseDeps = deps.filter((dep) => isPromise(dep));\n\n    if (signalDeps.length === 0) {\n      // No reactive signals, nothing to subscribe to\n      return;\n    }\n\n    // Create observables from signals\n    const signalObservables = signalDeps.map((sig) => sig.observable);\n\n    // Combine all signal observables\n    const subscription = combineLatest(signalObservables).subscribe(\n      async () => {\n        // Check if all dependencies are now ready\n        const allReady = await checkDependencies(deps);\n        if (allReady) {\n          // Unsubscribe - we only need to mount once\n          subscription.unsubscribe();\n          // Remove from subscriptions\n          const idx = element.propSubscriptions.indexOf(subscription);\n          if (idx > -1) {\n            element.propSubscriptions.splice(idx, 1);\n          }\n          // Now mount the component\n          performMount(parent, element, index);\n          propagateContext(element);\n        }\n      }\n    );\n\n    // Store subscription for cleanup\n    element.propSubscriptions.push(subscription);\n  }\n\n  /**\n   * Performs the actual mounting of the component.\n   */\n  function performMount(parent: Element, element: Element, index?: number) {\n    element.componentInstance.onMount?.(element, index);\n    for (let name in element.directives) {\n      element.directives[name].onMount?.(element);\n    }\n    element.effectMounts.forEach((fn: any) => {\n      element.effectUnmounts.push(fn(element));\n    });\n  }\n\n  async function onMount(parent: Element, element: Element, index?: number) {\n    let actualParent = parent;\n    while (actualParent?.tag === 'fragment') {\n      actualParent = actualParent.parent;\n    }\n\n    element.props.context = actualParent.props.context;\n    element.parent = actualParent;\n\n    // Inherit freeze state from parent if element doesn't have its own freeze prop\n    if (!element.propObservables?.freeze && !element.props?.freeze && isElementFrozen(actualParent)) {\n      element.isFrozen = true;\n    }\n\n    // Check dependencies before mounting\n    if (element.props.dependencies && Array.isArray(element.props.dependencies)) {\n      const deps = element.props.dependencies;\n      const ready = await checkDependencies(deps);\n      if (!ready) {\n        // Set up subscriptions for reactive signals to trigger mount later\n        setupDependencySubscriptions(actualParent, element, deps, index);\n        return;\n      }\n    }\n\n    performMount(actualParent, element, index);\n  };\n\n  async function propagateContext(element) {\n    if (element.props.attach) {\n      const isReactiveAttach = isSignal(element.propObservables?.attach)\n      if (!isReactiveAttach) {\n        element.props.children.push(element.props.attach)\n      }\n      else {\n        await new Promise((resolve) => {\n          let lastElement = null\n          element.propSubscriptions.push(element.propObservables.attach.observable.subscribe(async (args) => {\n            const value = args?.value ?? args\n            if (!value) {\n              throw new Error(`attach in ${element.tag} is undefined or null, add a component`)\n            }\n            if (lastElement) {\n              destroyElement(lastElement)\n            }\n            lastElement = value\n            await createElement(element, value)\n            resolve(undefined)\n          }))\n        })\n      }\n    }\n    if (!element.props.children) {\n      return;\n    }\n    for (let child of element.props.children) {\n      if (!child) continue;\n      await createElement(element, child)\n    }\n  };\n\n  /**\n * Creates and mounts a child element to a parent element.\n * Handles different types of children: Elements, Promises resolving to Elements, and Observables.\n * \n * @description This function is designed to handle reactive child components that can be:\n * - Direct Element instances\n * - Promises that resolve to Elements (for async components)\n * - Observables that emit Elements, arrays of Elements, or FlowObservable results\n * - Nested observables within arrays or FlowObservable results (handled recursively)\n * \n * For Observables, it subscribes to the stream and automatically mounts/unmounts elements\n * as they are emitted. The function handles nested observables recursively, ensuring that\n * observables within arrays or FlowObservable results are also properly subscribed to.\n * All subscriptions are stored in the parent's effectSubscriptions for automatic cleanup.\n * \n * @param {Element} parent - The parent element to mount the child to\n * @param {Element | Observable<any> | Promise<Element>} child - The child to create and mount\n * \n * @example\n * ```typescript\n * // Direct element\n * await createElement(parent, childElement);\n * \n * // Observable of elements (from cond, loop, etc.)\n * await createElement(parent, cond(signal(visible), () => h(Container)));\n * \n * // Observable that emits arrays containing other observables\n * await createElement(parent, observableOfObservables);\n * \n * // Promise resolving to element\n * await createElement(parent, import('./MyComponent').then(mod => h(mod.default)));\n * ```\n */\n  async function createElement(parent: Element, child: Element | Observable<any> | Promise<Element>) {\n    if (isPromise(child)) {\n      child = await child;\n    }\n    if (child instanceof Observable) {\n      const mountedFlowElements = new Map<Element, Element>();\n\n      const mountFlowElement = (element: Element, index?: number) => {\n        if (mountedFlowElements.has(element)) {\n          return;\n        }\n\n        const routed = routeDomComponent(parent, element);\n        mountedFlowElements.set(element, routed);\n        onMount(parent, routed, index);\n        propagateContext(routed);\n      };\n\n      const syncFlowElements = (nextElements: Set<Element>) => {\n        mountedFlowElements.forEach((mounted, source) => {\n          if (nextElements.has(source)) {\n            return;\n          }\n          mountedFlowElements.delete(source);\n          if (mounted !== source) {\n            destroyElement(mounted);\n          }\n        });\n      };\n\n      const processFlowComponent = (\n        component: any,\n        nextElements: Set<Element>,\n        index?: number\n      ) => {\n        if (component instanceof Observable) {\n          void createElement(parent, component);\n          return;\n        }\n        if (Array.isArray(component)) {\n          component.forEach((comp) =>\n            processFlowComponent(comp, nextElements, index)\n          );\n          return;\n        }\n        if (!isElement(component)) {\n          return;\n        }\n\n        nextElements.add(component);\n        mountFlowElement(component, index);\n      };\n\n      // Subscribe to the observable and handle the emitted values\n      const subscription = child.subscribe(\n        (value: any) => {\n          // Handle different types of observable emissions\n          if (value && typeof value === 'object' && 'elements' in value) {\n            // Handle FlowObservable result (from loop, cond, etc.)\n            const {\n              elements: comp,\n              prev,\n            }: {\n              elements: Element[];\n              prev?: Element;\n            } = value;\n\n            const components = comp.filter((c) => c !== null);\n            const nextElements = new Set<Element>();\n            if (prev) {\n              components.forEach((c) => {\n                const index = parent.props.children.indexOf(prev.props.key);\n                processFlowComponent(c, nextElements, index + 1);\n              });\n              syncFlowElements(nextElements);\n              return;\n            }\n            components.forEach((component, index) => {\n              processFlowComponent(component, nextElements, index);\n            });\n            syncFlowElements(nextElements);\n          } else if (isElement(value)) {\n            // Handle direct Element emission\n            const routed = routeDomComponent(parent, value);\n            onMount(parent, routed);\n            propagateContext(routed);\n          } else if (Array.isArray(value)) {\n            // Handle array of elements (which can also be observables)\n            value.forEach(async (element) => {\n              if (element instanceof Observable) {\n                // Handle observable element recursively\n                await createElement(parent, element);\n              } else if (isElement(element)) {\n                const routed = routeDomComponent(parent, element);\n                onMount(parent, routed);\n                propagateContext(routed);\n              }\n            });\n          }\n          elementsListen.next(undefined);\n        }\n      );\n\n      // Store subscription for cleanup\n      parent.effectSubscriptions.push(subscription);\n    } else if (isElement(child)) {\n      const routed = routeDomComponent(parent, child);\n      onMount(parent, routed);\n      await propagateContext(routed);\n    }\n  }\n\n  // Return the created element representation\n  return element;\n}\n\n/**\n * Observes a BehaviorSubject containing an array or object of items and dynamically creates child elements for each item.\n *\n * @param {WritableArraySignal<T> | WritableObjectSignal<T>} itemsSubject - A signal that emits an array or object of items.\n * @param {Function} createElementFn - A function that takes an item and returns an element representation.\n * @returns {Observable} An observable that emits the list of created child elements.\n */\nexport function loop<T>(\n  itemsSubject: any,\n  createElementFn: (item: T, index: number | string) => Element | null\n): FlowObservable {\n\n  if (isComputed(itemsSubject) && itemsSubject.dependencies.size == 0) {\n    itemsSubject = signal(itemsSubject());\n  }\n  else if (!isSignal(itemsSubject)) {\n    itemsSubject = signal(itemsSubject);\n  }\n\n  return defer(() => {\n    let elements: Element[] = [];\n    let elementMap = new Map<string | number, Element>();\n    let isFirstSubscription = true;\n\n    const ensureElement = (itemResult: any): Element | null => {\n      if (!itemResult) return null;\n      if (isElement(itemResult)) return itemResult;\n      return {\n        tag: 'fragment',\n        props: { children: Array.isArray(itemResult) ? itemResult : [itemResult] },\n        componentInstance: {} as any,\n        propSubscriptions: [],\n        effectSubscriptions: [],\n        effectMounts: [],\n        effectUnmounts: [],\n        propObservables: {},\n        parent: null,\n        directives: {},\n        destroy() { destroyElement(this) },\n        allElements: new Subject(),\n        isFrozen: false\n      };\n    }\n\n    const isArraySignal = (signal: any): signal is WritableArraySignal<T[]> =>\n      Array.isArray(signal());\n\n    return new Observable<FlowResult>(subscriber => {\n      const subscription = isArraySignal(itemsSubject)\n        ? itemsSubject.observable.subscribe(change => {\n          if (isFirstSubscription) {\n            isFirstSubscription = false;\n            elements.forEach(el => el.destroy());\n            elements = [];\n            elementMap.clear();\n\n            const items = itemsSubject();\n            if (items) {\n              items.forEach((item, index) => {\n                const element = ensureElement(createElementFn(item, index));\n                if (element) {\n                  elements.push(element);\n                  elementMap.set(index, element);\n                }\n              });\n            }\n            subscriber.next({\n              elements: [...elements]\n            });\n            return;\n          }\n\n          // Handle computed signals that emit array values directly (not ArrayChange objects)\n          // When a computed emits, `change` is the array itself, not an object with `type`\n          const isDirectArrayChange = Array.isArray(change) || (change && typeof change === 'object' && !('type' in change));\n\n          if (change.type === 'init' || change.type === 'reset' || isDirectArrayChange) {\n            elements.forEach(el => destroyElement(el));\n            elements = [];\n            elementMap.clear();\n\n            const items = itemsSubject();\n            if (items) {\n              items.forEach((item, index) => {\n                const element = ensureElement(createElementFn(item, index));\n                if (element) {\n                  elements.push(element);\n                  elementMap.set(index, element);\n                }\n              });\n            }\n          } else if (change.type === 'add' && change.index !== undefined) {\n            const newElements = change.items.map((item, i) => {\n              const element = ensureElement(createElementFn(item as T, change.index! + i));\n              if (element) {\n                elementMap.set(change.index! + i, element);\n              }\n              return element;\n            }).filter((el): el is Element => el !== null);\n\n            elements.splice(change.index, 0, ...newElements);\n          } else if (change.type === 'remove' && change.index !== undefined) {\n            const removed = elements.splice(change.index, 1);\n            removed.forEach(el => {\n              destroyElement(el)\n              elementMap.delete(change.index!);\n            });\n          } else if (change.type === 'update' && change.index !== undefined && change.items.length === 1) {\n            const index = change.index;\n            const newItem = change.items[0];\n\n            // Check if the previous item at this index was effectively undefined or non-existent\n            if (index >= elements.length || elements[index] === undefined || !elementMap.has(index)) {\n              // Treat as add operation\n              const newElement = ensureElement(createElementFn(newItem as T, index));\n              if (newElement) {\n                elements.splice(index, 0, newElement); // Insert at the correct index\n                elementMap.set(index, newElement);\n                // Adjust indices in elementMap for subsequent elements might be needed if map relied on exact indices\n                // This simple implementation assumes keys are stable or createElementFn handles context correctly\n              } else {\n                console.warn(`Element creation returned null for index ${index} during add-like update.`);\n              }\n            } else {\n              // Treat as a standard update operation\n              const oldElement = elements[index];\n              destroyElement(oldElement)\n              const newElement = ensureElement(createElementFn(newItem as T, index));\n              if (newElement) {\n                elements[index] = newElement;\n                elementMap.set(index, newElement);\n              } else {\n                // Handle case where new element creation returns null\n                elements.splice(index, 1);\n                elementMap.delete(index);\n              }\n            }\n          }\n\n          subscriber.next({\n            elements: [...elements] // Create a new array to ensure change detection\n          });\n        })\n        : (itemsSubject as WritableObjectSignal<T>).observable.subscribe(change => {\n          const key = change.key as string | number\n          if (isFirstSubscription) {\n            isFirstSubscription = false;\n            elements.forEach(el => destroyElement(el));\n            elements = [];\n            elementMap.clear();\n\n            const items = (itemsSubject as WritableObjectSignal<T>)();\n            if (items) {\n              Object.entries(items).forEach(([key, value]) => {\n                const element = ensureElement(createElementFn(value, key));\n                if (element) {\n                  elements.push(element);\n                  elementMap.set(key, element);\n                }\n              });\n            }\n            subscriber.next({\n              elements: [...elements]\n            });\n            return;\n          }\n\n          if (change.type === 'init' || change.type === 'reset') {\n            elements.forEach(el => destroyElement(el));\n            elements = [];\n            elementMap.clear();\n\n            const items = (itemsSubject as WritableObjectSignal<T>)();\n            if (items) {\n              Object.entries(items).forEach(([key, value]) => {\n                const element = ensureElement(createElementFn(value, key));\n                if (element) {\n                  elements.push(element);\n                  elementMap.set(key, element);\n                }\n              });\n            }\n          } else if (change.type === 'add' && change.key && change.value !== undefined) {\n            const element = ensureElement(createElementFn(change.value as T, key));\n            if (element) {\n              elements.push(element);\n              elementMap.set(key, element);\n            }\n          } else if (change.type === 'remove' && change.key) {\n            const index = elements.findIndex(el => elementMap.get(key) === el);\n            if (index !== -1) {\n              const [removed] = elements.splice(index, 1);\n              destroyElement(removed)\n              elementMap.delete(key);\n            }\n          } else if (change.type === 'update' && change.key && change.value !== undefined) {\n            const index = elements.findIndex(el => elementMap.get(key) === el);\n            if (index !== -1) {\n              const oldElement = elements[index];\n              destroyElement(oldElement)\n              const newElement = ensureElement(createElementFn(change.value as T, key));\n              if (newElement) {\n                elements[index] = newElement;\n                elementMap.set(key, newElement);\n              }\n            }\n          }\n\n          subscriber.next({\n            elements: [...elements] // Create a new array to ensure change detection\n          });\n        });\n\n      return () => {\n        subscription.unsubscribe();\n        elements.forEach(el => destroyElement(el));\n      };\n    });\n  }).pipe(shareReplay({ bufferSize: 1, refCount: true }));\n}\n\n/**\n * Conditionally creates and destroys elements based on condition signals with support for else if and else.\n *\n * @description This function creates conditional rendering with support for multiple conditions (if/else if/else pattern).\n * It evaluates conditions in order and renders the first matching condition's element.\n * The function maintains full reactivity with signals and ensures proper cleanup of elements.\n *\n * @param {Signal<boolean> | boolean | (() => boolean)} condition - A signal, boolean, or function that determines whether to create an element.\n * @param {Function} createElementFn - A function that returns an element or a promise that resolves to an element.\n * @param {...Array} additionalConditions - Additional conditions for else if and else cases.\n *   Can be:\n *   - A function for else case: `() => Element | Promise<Element>`\n *   - An array for else if case: `[Signal<boolean> | boolean | (() => boolean), () => Element | Promise<Element>]`\n * @returns {Observable} An observable that emits the created element based on the matching condition.\n *\n * @example\n * ```typescript\n * // Simple if/else\n * cond(\n *   signal(isVisible),\n *   () => h(Container),\n *   () => h(Text, { text: 'Hidden' }) // else\n * );\n *\n * // Multiple else if + else\n * cond(\n *   signal(status === 'loading'),\n *   () => h(LoadingSpinner),\n *   [signal(status === 'error'), () => h(ErrorMessage)], // else if\n *   [signal(status === 'success'), () => h(SuccessMessage)], // else if\n *   () => h(DefaultMessage) // else\n * );\n * ```\n */\nexport function cond(\n  condition: Signal<boolean> | boolean | (() => boolean),\n  createElementFn: () => Element | Promise<Element>,\n  ...additionalConditions: Array<\n    | (() => Element | Promise<Element>) // else final\n    | [Signal<boolean> | boolean | (() => boolean), () => Element | Promise<Element>] // else if\n  >\n): FlowObservable {\n  let currentElement: Element | null = null;\n  let currentConditionIndex = -1;\n\n  // Parse additional conditions\n  const elseIfConditions: Array<{\n    condition: Signal<boolean>;\n    elementFn: () => Element | Promise<Element>;\n  }> = [];\n  let elseElementFn: (() => Element | Promise<Element>) | null = null;\n\n  // Convert function conditions to computed signals\n  const convertConditionToSignal = (cond: Signal<boolean> | boolean | (() => boolean)): Signal<boolean> => {\n    if (isSignal(cond)) {\n      return cond as Signal<boolean>;\n    } else if (typeof cond === 'function') {\n      return computed(cond as () => boolean);\n    } else {\n      return signal(cond as boolean);\n    }\n  };\n\n  // Process additional conditions\n  for (const param of additionalConditions) {\n    if (Array.isArray(param)) {\n      // else if case: [condition, elementFn]\n      elseIfConditions.push({\n        condition: convertConditionToSignal(param[0]),\n        elementFn: param[1],\n      });\n    } else if (typeof param === 'function') {\n      // else case: elementFn (should be the last one)\n      elseElementFn = param;\n      break; // Stop processing after else\n    }\n  }\n\n  // Collect all conditions with their element functions\n  const allConditions = [\n    { condition: convertConditionToSignal(condition), elementFn: createElementFn },\n    ...elseIfConditions,\n  ];\n\n  // All conditions are now signals, so we always use the reactive path\n  return new Observable<{ elements: Element[], type?: \"init\" | \"remove\" }>(subscriber => {\n    const subscriptions: Subscription[] = [];\n\n    const evaluateConditions = () => {\n      // Find the first matching condition\n      let matchingIndex = -1;\n      for (let i = 0; i < allConditions.length; i++) {\n        const condition = allConditions[i].condition;\n        const conditionValue = condition();\n\n        if (conditionValue) {\n          matchingIndex = i;\n          break;\n        }\n      }\n\n      // If no condition matches and we have an else, use else\n      const shouldUseElse = matchingIndex === -1 && elseElementFn;\n      const newConditionIndex = shouldUseElse ? -2 : matchingIndex; // -2 for else, -1 for nothing\n\n      // Only update if the condition changed\n      if (newConditionIndex !== currentConditionIndex) {\n        // Destroy current element if it exists\n        if (currentElement) {\n          destroyElement(currentElement);\n          currentElement = null;\n        }\n\n        currentConditionIndex = newConditionIndex;\n\n        if (shouldUseElse) {\n          // Render else element\n          let _el = elseElementFn!();\n          if (isPromise(_el)) {\n            from(_el as Promise<Element>).subscribe(el => {\n              currentElement = el;\n              subscriber.next({\n                type: \"init\",\n                elements: [el],\n              });\n            });\n          } else {\n            currentElement = _el as Element;\n            subscriber.next({\n              type: \"init\",\n              elements: [currentElement],\n            });\n          }\n        } else if (matchingIndex >= 0) {\n          // Render matching condition element\n          let _el = allConditions[matchingIndex].elementFn();\n          if (isPromise(_el)) {\n            from(_el as Promise<Element>).subscribe(el => {\n              currentElement = el;\n              subscriber.next({\n                type: \"init\",\n                elements: [el],\n              });\n            });\n          } else {\n            currentElement = _el as Element;\n            subscriber.next({\n              type: \"init\",\n              elements: [currentElement],\n            });\n          }\n        } else {\n          // No matching condition and no else\n          subscriber.next({\n            elements: [],\n          });\n        }\n      }\n    };\n\n    // Subscribe to all signal conditions\n    allConditions.forEach(({ condition }) => {\n      const signalCondition = condition as WritableObjectSignal<boolean>;\n      subscriptions.push(\n        signalCondition.observable.subscribe(() => {\n          evaluateConditions();\n        })\n      );\n    });\n\n    // Initial evaluation\n    evaluateConditions();\n\n    // Return cleanup function\n    return () => {\n      subscriptions.forEach(sub => sub.unsubscribe());\n      if (currentElement) {\n        destroyElement(currentElement);\n      }\n    };\n  }).pipe(share());\n}\n"
  },
  {
    "path": "packages/core/src/engine/signal.ts",
    "content": "import {\n  Observable,\n  Subscription\n} from \"rxjs\";\nimport { isSignal } from \"@signe/reactive\";\nimport type { Element } from \"./reactive\";\nimport { isElementFrozen, waitForDependencies } from \"./reactive\";\nimport { isPromise } from \"./utils\";\nimport { Tick } from \"../directives/Scheduler\";\nimport { Container } from \"../components\";\n\ntype MountFunction = (fn: (element: Element) => void) => void;\n\n// Define ComponentFunction type\nexport type ComponentFunction<P = {}> = (props: P) => Element | Promise<Element>;\n\nexport let currentSubscriptionsTracker: ((subscription: Subscription) => void) | null = null;\nexport let mountTracker: MountFunction | null = null;\n\n/**\n * Registers a mount function to be called when the component is mounted.\n * To unmount the component, the function must return a function that will be called by the engine.\n * \n * @param {(element: Element) => void} fn - The function to be called on mount.\n * @example\n * ```ts\n  * mount((el) => {\n * console.log('mounted', el);\n * });\n * ```\n * Unmount the component by returning a function:\n * ```ts\n  * mount((el) => {\n * console.log('mounted', el);\n *   return () => {\n * console.log('unmounted', el);\n *   }\n * });\n * ```\n */\nexport function mount(fn: (element: Element) => void) {\n  mountTracker?.(fn);\n}\n\n/**\n * Registers a tick function to be called on each tick of the component's context.\n * @param {(tickValue: Tick, element: Element) => void} fn - The function to be called on each tick.\n * @example\n * ```ts\n  * tick((tickValue, el) => {\n * console.log('tick', tickValue, el);\n * });\n * ```\n */\nexport function tick(fn: (tickValue: Tick, element: Element) => void) {\n  mount((el: Element) => {\n    const { context } = el.props\n    let subscription: Subscription | undefined\n    if (context.tick) {\n      subscription = context.tick.observable.subscribe(({ value }) => {\n        // Block tick if element is frozen\n        if (isElementFrozen(el)) {\n          return;\n        }\n        fn(value, el)\n      })\n    }\n    return () => {\n      subscription?.unsubscribe()\n    }\n  })\n}\n\n/**\n * Add tracking for subscriptions and mounts, then create an element from a component function.\n * @template C\n * @param {C} componentFunction - The component function to create an element from.\n * @param {Parameters<C>[0]} [props={}] - The props to pass to the component function.\n * @param {...any[]} children - The children elements of the component.\n * @returns {ReturnType<C>}\n * @example\n * ```ts\n  * const el = h(MyComponent, {\n    *   x: 100,\n    *   y: 100,\n    * });\n * ```\n * \n * with children:\n * ```ts\n  * const el = h(MyComponent, {\n    *   x: 100,\n    *   y: 100,\n    * }, \n * h(MyChildComponent, {\n      *     x: 50,\n      *     y: 50,\n      *   }),\n * );\n * ```\n */\nfunction _h<C extends ComponentFunction<any>>(\n  componentFunction: C | Element,\n  props: Parameters<C>[0] = {} as Parameters<C>[0],\n  children: any[]\n): ReturnType<C> {\n  const allSubscriptions = new Set<Subscription>();\n  const allMounts = new Set<MountFunction>();\n\n  currentSubscriptionsTracker = (subscription) => {\n    allSubscriptions.add(subscription);\n  };\n\n  mountTracker = (fn: any) => {\n    allMounts.add(fn);\n  };\n\n  if (children[0] instanceof Array) {\n    children = children[0]\n  }\n\n  let component: Element\n\n  if (Array.isArray(componentFunction)) {\n    if (componentFunction.length === 1) {\n      component = componentFunction[0]\n    }\n    else {\n      component = _h(Container, {}, componentFunction) as Element\n    }\n  }\n  else if ('tag' in componentFunction) {\n    component = componentFunction\n  }\n  else if (componentFunction instanceof Observable) {\n    component = componentFunction as any\n  }\n  else {\n    component = componentFunction({ ...props, children }) as Element;\n  }\n\n  if (!component) {\n    component = {} as any\n  }\n\n  component.effectSubscriptions = Array.from(allSubscriptions);\n  component.effectMounts = [\n    ...Array.from(allMounts),\n    ...((component as any).effectMounts ?? [])\n  ];\n\n  // Copy dependencies prop to the returned element so it can be used for delayed mounting\n  if (props?.dependencies) {\n    component.props = component.props || {};\n    component.props.dependencies = props.dependencies;\n  }\n\n  // call mount hook for root component\n  if (component instanceof Promise) {\n    component.then((component) => {\n      if (component.props.isRoot) {\n        allMounts.forEach((fn) => fn(component));\n      }\n    })\n  }\n\n  currentSubscriptionsTracker = null;\n  mountTracker = null;\n\n  return component as ReturnType<C>;\n}\n\n/**\n * Add tracking for subscriptions and mounts, then create an element from a component function.\n * @template C\n * @param {C} componentFunction - The component function to create an element from.\n * @param {Parameters<C>[0]} [props={}] - The props to pass to the component function.\n * @param {...any[]} children - The children elements of the component.\n * @returns {ReturnType<C>}\n * @example\n * ```ts\n  * const el = h(MyComponent, {\n    *   x: 100,\n    *   y: 100,\n    * });\n * ```\n * \n * with children:\n * ```ts\n  * const el = h(MyComponent, {\n    *   x: 100,\n    *   y: 100,\n    * }, \n * h(MyChildComponent, {\n      *     x: 50,\n      *     y: 50,\n      *   }),\n * );\n * ```\n */\nexport function h<C extends ComponentFunction<any>>(\n  componentFunction: C | Element,\n  props: Parameters<C>[0] = {} as Parameters<C>[0],\n  ...children: any[]\n): ReturnType<C> {\n  if (props?.dependencies) {\n    const hasPromise = props.dependencies.some(isPromise);\n    if (!hasPromise) {\n      const allReady = props.dependencies.every(dep => {\n        if (isSignal(dep)) return dep() !== undefined;\n        return dep !== undefined;\n      });\n      if (allReady) {\n        return _h(componentFunction, props, children);\n      }\n    }\n\n    return new Observable(subscriber => {\n      waitForDependencies(props.dependencies).then(() => {\n        const el = _h(componentFunction, props, children);\n        subscriber.next(el);\n      });\n    }) as any;\n  }\n  return _h(componentFunction, props, children);\n}\n"
  },
  {
    "path": "packages/core/src/engine/trigger.ts",
    "content": "import { effect, signal } from \"@signe/reactive\";\n\nexport interface Listen<T = any> {\n  config: T | undefined;\n  seed: {\n    config: T | undefined;\n    value: number;\n    resolve: (value: any) => void;\n  };\n}\n\nexport interface Trigger<T = any> {\n  start: () => Promise<void>;\n  listen: () => Listen<T> | undefined;\n}\n\n/**\n * Checks if the given argument is a Trigger object\n * @param arg - The value to check\n * @returns True if the argument is a Trigger object\n */\nexport function isTrigger(arg: any): arg is Trigger<any> {\n  return arg?.start && arg?.listen;\n}\n\n/**\n * Creates a new trigger that can be used to pass data between components\n * @param globalConfig - Optional configuration data to be passed when the trigger is activated\n * @returns A Trigger object with start and listen methods\n * @example\n * ```ts\n * const myTrigger = trigger()\n * \n * on(myTrigger, (data) => {\n *   console.log('Triggered with data:', data)\n * })\n * \n * myTrigger.start({ message: 'Hello' })\n * ```\n */\nexport function trigger<T = any>(globalConfig?: T): Trigger<T> {\n  const _signal = signal({\n    config: globalConfig,\n    value: 0,\n    resolve: (value: any) => void 0,\n  });\n  return {\n    start: (config?: T) => {\n      return new Promise((resolve: (value: any) => void) => {\n        const newValue = Math.random();\n        _signal.set({\n          config: {\n            ...globalConfig,\n            ...config,\n          },\n          resolve,\n          value: newValue,\n        });\n      });\n    },\n    listen: (): Listen<T> | undefined => {\n      return {\n        config: globalConfig,\n        seed: _signal(),\n      };\n    },\n  };\n}\n\n/**\n * Subscribes to a trigger and executes a callback when the trigger is activated\n * @param triggerSignal - The trigger to subscribe to\n * @param callback - Function to execute when the trigger is activated\n * @returns Subscription that can be unsubscribed to stop listening\n * @throws Error if triggerSignal is not a valid trigger\n * @example\n * ```ts\n * const click = trigger()\n * \n * const subscription = on(click, () => {\n *   console.log('Click triggered')\n * })\n * \n * // Later, to stop listening:\n * subscription.unsubscribe()\n * ```\n */\nexport function on(triggerSignal: any, callback: (config: any) => void | Promise<void>) {\n  if (!isTrigger(triggerSignal)) {\n    throw new Error(\"In 'on(arg)' must have a trigger signal type\");\n  }\n  let lastValue: number | undefined;\n\n  const effectResult = effect(() => {\n    const result = triggerSignal.listen();\n    const seed = result?.seed;\n\n    if (!seed) return;\n\n    // Only run callback when the trigger value actually changes\n    if (lastValue === undefined) {\n      lastValue = seed.value;\n      return;\n    }\n    if (seed.value === lastValue) {\n      return;\n    }\n    lastValue = seed.value;\n\n    try {\n      const ret = callback(result?.seed.config);\n      if (ret && typeof ret.then === 'function') {\n        ret.then((value: any) => seed.resolve(value)).catch(() => seed.resolve(undefined));\n      } else {\n        seed.resolve(ret);\n      }\n    } catch (err) {\n      seed.resolve(undefined);\n    }\n  });\n\n  return effectResult.subscription;\n}\n"
  },
  {
    "path": "packages/core/src/engine/utils.ts",
    "content": "import { isSignal } from \"@signe/reactive\"\nimport { ObservablePoint } from \"pixi.js\"\nimport { Observable } from \"rxjs\"\n\n/**\n * Checks if code is running in a browser environment\n * @returns {boolean} True if running in browser, false otherwise\n */\nexport function isBrowser(): boolean {\n    return typeof window !== 'undefined'\n}\n\n/**\n * Returns current high-resolution timestamp\n * @returns {number} Current time in milliseconds\n */\nexport function preciseNow(): number {\n    return typeof performance !== 'undefined' ? performance.now() : Date.now()\n}\n\n/**\n * Converts frames per second to milliseconds\n * @param {number} fps - Frames per second\n * @returns {number} Milliseconds per frame\n */\nexport function fps2ms(fps: number): number {\n    return 1000 / fps\n}\n\n/**\n * Checks if a value is a Promise\n * @param {any} value - Value to check\n * @returns {boolean} True if value is a Promise, false otherwise\n */\nexport function isPromise(value: any): boolean {\n    return value && value instanceof Promise\n}\n\nexport function arrayEquals(a: any[], b: any[]): boolean {\n    if (a.length !== b.length) return false;\n    for (let i = 0; i < a.length; i++) {\n        const v = a[i];\n        const bv = b[i];\n        if (typeof v === 'object' && v !== null) {\n            if (typeof bv !== 'object' || bv === null) return false;\n            if (Array.isArray(v)) {\n                if (!Array.isArray(bv) || !arrayEquals(v, bv)) return false;\n            } else if (!objectEquals(v, bv)) {\n                return false;\n            }\n        } else if (v !== bv) {\n            return false;\n        }\n    }\n    return true;\n}\n\nfunction objectEquals(a: object, b: object): boolean {\n    const keysA = Object.keys(a);\n    const keysB = Object.keys(b);\n    if (keysA.length !== keysB.length) return false;\n    for (let key of keysA) {\n        if (!b.hasOwnProperty(key)) return false;\n        if (!deepEquals(a[key], b[key])) return false;\n    }\n    return true;\n}\n\nfunction deepEquals(a: any, b: any): boolean {\n    if (a === b) return true;\n    if (typeof a !== typeof b) return false;\n    if (typeof a === 'object' && a !== null) {\n        if (Array.isArray(a)) {\n            return Array.isArray(b) && arrayEquals(a, b);\n        }\n        return objectEquals(a, b);\n    }\n    return false;\n}\n\n/**\n * Checks if a value is a function\n * @param {unknown} val - Value to check\n * @returns {boolean} True if value is a function, false otherwise\n */\nexport function isFunction(val: unknown): boolean {\n    return {}.toString.call(val) === '[object Function]'\n}\n\n/**\n * Checks if a value is a plain object (not an instance of a class)\n * @param {unknown} val - Value to check\n * @returns {boolean} True if value is a plain object (not null, not array, not instance), false otherwise\n * @example\n * ```ts\n * isObject({}) // true\n * isObject(new Date()) // false\n * isObject([]) // false\n * isObject(null) // false\n * ```\n */\nexport function isObject(val: unknown): boolean {\n    return typeof val == 'object' && val != null && !Array.isArray(val) && val.constructor === Object\n}\n\nexport function isObservable(val: unknown): boolean {\n    return val instanceof Observable\n}\n\n/**\n * Sets a value in an object using a dot notation path\n * @param {Record<string, any>} obj - Target object\n * @param {string | string[]} path - Path to set value at (e.g., 'a.b.c' or ['a', 'b', 'c'])\n * @param {any} value - Value to set\n * @param {boolean} onlyPlainObject - If true, only creates plain objects in path\n * @returns {Record<string, any>} Modified object\n */\nexport function set(\n    obj: Record<string, any>, \n    path: string | string[], \n    value: any, \n    onlyPlainObject = false\n): Record<string, any> {\n    if (Object(obj) !== obj) return obj;\n\n    if (typeof path === 'string') {\n        path = path.split('.');\n    }\n\n    let len = path.length;\n    if (!len) return obj;\n\n    let current = obj;\n    for (let i = 0; i < len - 1; i++) {\n        let segment = path[i];\n        let nextSegment: number | string = path[i + 1];\n        let isNextNumeric = !isNaN(Number(nextSegment)) && isFinite(Number(nextSegment));\n\n        if (!current[segment] || typeof current[segment] !== 'object') {\n            current[segment] = (isNextNumeric && !onlyPlainObject) ? [] : {};\n        }\n\n        current = current[segment];\n    }\n\n    current[path[len - 1]] = value;\n\n    return obj;\n}\n\n/**\n * Gets a value from an object using a dot notation path\n * @param {Record<string, any>} obj - Source object\n * @param {string} path - Path to get value from (e.g., 'a.b.c')\n * @returns {any} Value at path or undefined if not found\n */\nexport function get(obj: Record<string, any>, path: string): any {\n    const keys = path.split('.');\n    let current = obj;\n\n    for (let key of keys) {\n        if (current[key] === undefined) {\n            return undefined;\n        }\n        current = current[key];\n    }\n\n    return current;\n}\n\n/**\n * Logs a message to console\n * @param {any} text - Message to log\n */\nexport function log(text: any): void {\n    console.log(text)\n}\n\n/**\n * Logs an error message to console\n * @param {any} text - Error message to log\n */\nexport function error(text: any): void {\n    console.error(text)\n}\n\n/**\n * Sets the position of an ObservablePoint using various input formats\n * @param {ObservablePoint} observablePoint - The point to modify\n * @param {Object | number | [number, number]} point - New position value\n */\nexport function setObservablePoint(\n    observablePoint: ObservablePoint, \n    point: { x: number, y: number } | number | [number, number]\n): void {\n    if (typeof point === 'number') {\n        observablePoint.set(point);\n    }\n    else if (Array.isArray(point)) {\n        observablePoint.set(point[0], point[1]);\n    }\n    else if (isObject(point) && 'value' in point) {\n        observablePoint.set((point as any).value.x, (point as any).value.y);\n    }\n    else {\n        observablePoint.set(point.x, point.y);\n    }\n}\n\n/**\n * Calculates the Euclidean distance between two points\n * @param {number} x1 - X coordinate of first point\n * @param {number} y1 - Y coordinate of first point\n * @param {number} x2 - X coordinate of second point\n * @param {number} y2 - Y coordinate of second point\n * @returns {number} Distance between the points\n */\nexport function calculateDistance(\n    x1: number, \n    y1: number, \n    x2: number, \n    y2: number\n): number {\n    const dx = x1 - x2;\n    const dy = y1 - y2;\n    return Math.sqrt(dx * dx + dy * dy);\n}"
  },
  {
    "path": "packages/core/src/hooks/addContext.ts",
    "content": "export const addContext = (element, key, value) => {\n    element.props.context = {\n        ...(element.props.context ?? {}),\n        [key]: value\n    }\n}"
  },
  {
    "path": "packages/core/src/hooks/useFocus.ts",
    "content": "import { Signal } from \"@signe/reactive\";\nimport { Element } from \"../engine/reactive\";\nimport { focusManager } from \"../engine/FocusManager\";\nimport { effect } from \"@signe/reactive\";\n\n/**\n * Get the current focus index signal for a container\n * \n * Returns a reactive signal that updates when the focus index changes.\n * \n * @param containerId - Container identifier\n * @returns Signal for current focus index, or null if container not found\n * \n * @example\n * ```typescript\n * const focusIndex = useFocusIndex('myContainer');\n * effect(() => {\n *   console.log('Current focus index:', focusIndex?.());\n * });\n * ```\n */\nexport function useFocusIndex(containerId: string): Signal<number | null> | null {\n  return focusManager.getCurrentIndexSignal(containerId);\n}\n\n/**\n * Get the current focused element signal for a container\n * \n * Returns a reactive signal that updates when the focused element changes.\n * \n * @param containerId - Container identifier\n * @returns Signal for current focused element, or null if container not found\n * \n * @example\n * ```typescript\n * const focusedElement = useFocusedElement('myContainer');\n * effect(() => {\n *   const element = focusedElement?.();\n *   if (element) {\n *     console.log('Focused element:', element);\n *   }\n * });\n * ```\n */\nexport function useFocusedElement(containerId: string): Signal<Element | null> | null {\n  return focusManager.getFocusedElementSignal(containerId);\n}\n\n/**\n * Hook to react to focus changes\n * \n * Sets up a reactive effect that calls the callback whenever the focus changes.\n * \n * @param containerId - Container identifier\n * @param callback - Function to call when focus changes\n * @returns Cleanup function to unsubscribe\n * \n * @example\n * ```typescript\n * useFocusChange('myContainer', (index, element) => {\n *   console.log('Focus changed to index', index);\n *   if (element) {\n *     console.log('Focused element:', element);\n *   }\n * });\n * ```\n */\nexport function useFocusChange(\n  containerId: string,\n  callback: (index: number | null, element: Element | null) => void\n): () => void {\n  const indexSignal = focusManager.getCurrentIndexSignal(containerId);\n  const elementSignal = focusManager.getFocusedElementSignal(containerId);\n\n  if (!indexSignal || !elementSignal) {\n    console.warn(`FocusContainer with id \"${containerId}\" not found`);\n    return () => {};\n  }\n\n  // Set up reactive effect\n  const effectResult = effect(() => {\n    const index = indexSignal();\n    const element = elementSignal();\n    callback(index, element);\n  });\n\n  // Return cleanup function\n  return () => {\n    effectResult.subscription?.unsubscribe();\n  };\n}\n"
  },
  {
    "path": "packages/core/src/hooks/useProps.ts",
    "content": "import { isSignal, signal } from \"@signe/reactive\"\nimport { isPrimitive } from \"../engine/reactive\"\n\n/**\n * Converts props into reactive signals if they are primitive values.\n * \n * @param {object} props - The properties to convert.\n * @param {object} [defaults={}] - Default values for properties.\n * @returns {object} An object with reactive signals.\n * \n * @example\n * const props = useProps({ count: 0, name: \"John\" });\n * console.log(props.count()); // 0\n * props.count.set(1);\n * console.log(props.count()); // 1\n */\nexport const useProps = (props, defaults = {}): any => {\n    if (isSignal(props)) {\n        return props()\n    }\n    const obj = {}\n    for (let key in props) {\n        const value = props[key]\n        obj[key] = isPrimitive(value) ? signal(value) : value\n    }\n    for (let key in defaults) {\n        if (!(key in obj)) {\n            obj[key] = isPrimitive(defaults[key]) ? signal(defaults[key]) : defaults[key]\n        }\n    }\n    return obj\n}\n\ntype PropType = NumberConstructor | StringConstructor | BooleanConstructor | \n                FunctionConstructor | ObjectConstructor | ArrayConstructor | \n                null | (new (...args: any[]) => any);\n\ninterface PropConfig {\n    type?: PropType | PropType[];\n    required?: boolean;\n    default?: any | ((props: any) => any);\n    validator?: (value: any, props: any) => boolean;\n}\n\ntype PropSchema = {\n    [key: string]: PropType | PropType[] | PropConfig;\n}\n\n/**\n * Validates and defines properties based on a schema.\n * \n * @param {object} props - The properties to validate.\n * @returns {function} A function that takes a schema and returns validated properties.\n * \n * @example\n * const schema = {\n *   age: { type: Number, required: true },\n *   name: { type: String, default: \"Anonymous\" }\n * };\n * const validatedProps = useDefineProps({ age: 25 })(schema);\n * console.log(validatedProps.age()); // 25\n * console.log(validatedProps.name()); // \"Anonymous\"\n */\nexport const useDefineProps = (props: any) => {\n    return (schema?: PropSchema) => {\n        const rawProps = isSignal(props) ? props() : props\n        const validatedProps: { [key: string]: any } = {}\n\n        for (const key in schema) {\n            const propConfig = schema[key]\n            const value = rawProps[key]\n            let validatedValue: any\n\n            // Handle simple type definition\n            if (typeof propConfig === 'function') {\n                validateType(key, value, [propConfig])\n                validatedValue = value\n            }\n            // Handle array of types\n            else if (Array.isArray(propConfig)) {\n                validateType(key, value, propConfig)\n                validatedValue = value\n            }\n            // Handle detailed configuration object\n            else if (propConfig && typeof propConfig === 'object') {\n                // Check required prop\n                if (propConfig.required && value === undefined) {\n                    throw new Error(`Missing required prop: ${key}`)\n                }\n                \n                // Validate type if specified\n                if (propConfig.type) {\n                    const types = Array.isArray(propConfig.type) ? propConfig.type : [propConfig.type]\n                    validateType(key, value, types)\n                }\n                \n                // Run custom validator if provided\n                if (propConfig.validator && !propConfig.validator(value, rawProps)) {\n                    throw new Error(`Invalid prop: custom validation failed for prop \"${key}\"`)\n                }\n                \n                // Set default value if value is undefined\n                if (value === undefined && 'default' in propConfig) {\n                    validatedValue = typeof propConfig.default === 'function' \n                        ? propConfig.default(rawProps)\n                        : propConfig.default\n                } else {\n                    validatedValue = value\n                }\n            }\n\n            validatedProps[key] = isSignal(validatedValue) \n                ? validatedValue \n                : signal(validatedValue)\n        }\n        \n        return {\n            ...useProps(rawProps),\n            ...validatedProps\n        }\n    }\n}\n\n/**\n * Validates the type of a property.\n * \n * @param {string} key - The property key.\n * @param {any} value - The property value.\n * @param {any[]} types - The expected types.\n * @throws Will throw an error if the type check fails.\n */\nfunction validateType(key: string, value: any, types: any[]) {\n    if (value === undefined || value === null) return\n    \n    // Si c'est un signal, on vérifie la valeur du signal\n    const valueToCheck = isSignal(value) ? value() : value\n    \n    const valid = types.some(type => {\n        if (type === Number) return typeof valueToCheck === 'number'\n        if (type === String) return typeof valueToCheck === 'string'\n        if (type === Boolean) return typeof valueToCheck === 'boolean'\n        if (type === Function) return typeof valueToCheck === 'function'\n        if (type === Object) return typeof valueToCheck === 'object'\n        if (type === Array) return Array.isArray(valueToCheck)\n        if (type === null) return valueToCheck === null\n        return valueToCheck instanceof type\n    })\n    \n    if (!valid) {\n        throw new Error(\n            `Invalid prop: type check failed for prop \"${key}\". ` +\n            `Expected ${types.map(t => t.name).join(' or ')}`\n        )\n    }\n}"
  },
  {
    "path": "packages/core/src/hooks/useRef.ts",
    "content": "import { Element } from \"../engine/reactive\";\nimport { ComponentInstance } from \"../components/DisplayObject\";\n\nexport function useRef(element: Element<ComponentInstance>, ref: string): Element<ComponentInstance> | null {\n    const { props } = element;\n    if (props.ref == ref) {\n        return element;\n    }\n    // Recursive search for the component with the given id\n    if (props.children) {\n        for (const child of props.children) {\n            const result = useRef(child, ref);\n            if (result) {\n                return result;\n            }\n        }\n    }\n\n    // If not found, return undefined\n    return null;\n}"
  },
  {
    "path": "packages/core/src/index.ts",
    "content": "\nexport * from './directives'\nexport * from '@signe/reactive'\nexport { Howler } from 'howler'\nexport * from './components'\nexport * from './engine/reactive'\nexport { registerAllComponents } from './engine/reactive'\nexport * from './engine/signal'\nexport * from './engine/trigger'\nexport * from './engine/bootstrap'\nexport * from './engine/animation'\nexport { FocusManager, focusManager, type ScrollOptions } from './engine/FocusManager'\nexport { useProps, useDefineProps } from './hooks/useProps'\nexport { useFocusIndex, useFocusedElement, useFocusChange } from './hooks/useFocus'\nexport * from './utils/Ease'\nexport * from './utils/RadialGradient'\nexport * from './utils/tabindex'\nexport * from './components/DisplayObject'\nexport { isObservable } from 'rxjs'\nexport * as Utils from './engine/utils'\nexport * as Howl from 'howler'\n"
  },
  {
    "path": "packages/core/src/types/pixi-cull.d.ts",
    "content": "declare module \"pixi-cull\" {\n  export class Simple {\n    constructor(options?: any);\n    lists: Array<any>;\n    cull(bounds: any): void;\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/Ease.ts",
    "content": "import { \n    linear,\n    easeIn,\n    easeInOut,\n    easeOut,\n    circIn,\n    circInOut,\n    circOut,\n    backIn,\n    backInOut,\n    backOut,\n    anticipate,\n    bounceIn,\n    bounceInOut,\n    bounceOut\n} from \"popmotion\"\n\nexport const Easing = {\n    linear,\n    easeIn,\n    easeInOut,\n    easeOut,\n    circIn,\n    circInOut,\n    circOut,\n    backIn,\n    backInOut,\n    backOut,\n    anticipate,\n    bounceIn,\n    bounceInOut,\n    bounceOut\n}"
  },
  {
    "path": "packages/core/src/utils/GlobalAssetLoader.ts",
    "content": "/**\n * Global Asset Loader\n * \n * Tracks the loading progress of all assets (images, spritesheets, etc.) across all sprites in a component tree.\n * This allows components to know when all assets are loaded, useful for displaying loaders or progress bars.\n * \n * @example\n * ```typescript\n * const loader = new GlobalAssetLoader();\n * \n * loader.onProgress((progress) => {\n *   console.log(`Loading: ${(progress * 100).toFixed(0)}%`);\n * });\n * \n * loader.onComplete(() => {\n *   console.log('All assets loaded!');\n * });\n * \n * // Register assets as they start loading\n * const assetId = loader.registerAsset('path/to/image.png');\n * \n * // Update progress\n * loader.updateProgress(assetId, 0.5);\n * \n * // Mark as complete\n * loader.completeAsset(assetId);\n * ```\n */\nexport class GlobalAssetLoader {\n  private assets: Map<string, { progress: number; completed: boolean }> = new Map();\n  private onProgressCallbacks: Set<(progress: number) => void> = new Set();\n  private onCompleteCallbacks: Set<() => void> = new Set();\n  private assetCounter: number = 0;\n  private isComplete: boolean = false;\n\n  /**\n   * Registers a new asset to track\n   * \n   * @param assetPath - The path or identifier of the asset being loaded\n   * @returns A unique ID for this asset that should be used for progress updates\n   * \n   * @example\n   * ```typescript\n   * const assetId = loader.registerAsset('path/to/image.png');\n   * ```\n   */\n  registerAsset(assetPath: string): string {\n    const assetId = `asset_${this.assetCounter++}_${assetPath}`;\n    this.assets.set(assetId, { progress: 0, completed: false });\n    this.isComplete = false;\n    this.updateGlobalProgress();\n    return assetId;\n  }\n\n  /**\n   * Updates the progress of a specific asset\n   * \n   * @param assetId - The ID returned by registerAsset\n   * @param progress - Progress value between 0 and 1\n   * \n   * @example\n   * ```typescript\n   * loader.updateProgress(assetId, 0.5); // 50% loaded\n   * ```\n   */\n  updateProgress(assetId: string, progress: number): void {\n    const asset = this.assets.get(assetId);\n    if (!asset) {\n      console.warn(`Asset ${assetId} not found in tracker`);\n      return;\n    }\n    \n    asset.progress = Math.max(0, Math.min(1, progress));\n    this.updateGlobalProgress();\n  }\n\n  /**\n   * Marks an asset as completely loaded\n   * \n   * @param assetId - The ID returned by registerAsset\n   * \n   * @example\n   * ```typescript\n   * loader.completeAsset(assetId);\n   * ```\n   */\n  completeAsset(assetId: string): void {\n    const asset = this.assets.get(assetId);\n    if (!asset) {\n      console.warn(`Asset ${assetId} not found in tracker`);\n      return;\n    }\n    \n    asset.progress = 1;\n    asset.completed = true;\n    this.updateGlobalProgress();\n    this.checkCompletion();\n  }\n\n  /**\n   * Removes an asset from tracking (useful for cleanup)\n   * \n   * @param assetId - The ID returned by registerAsset\n   */\n  removeAsset(assetId: string): void {\n    this.assets.delete(assetId);\n    this.updateGlobalProgress();\n  }\n\n  /**\n   * Registers a callback that will be called whenever the global progress changes\n   * \n   * @param callback - Function that receives the global progress (0-1)\n   * @returns A function to unregister the callback\n   * \n   * @example\n   * ```typescript\n   * const unsubscribe = loader.onProgress((progress) => {\n   *   console.log(`Loading: ${(progress * 100).toFixed(0)}%`);\n   * });\n   * \n   * // Later, to unsubscribe:\n   * unsubscribe();\n   * ```\n   */\n  onProgress(callback: (progress: number) => void): () => void {\n    this.onProgressCallbacks.add(callback);\n    \n    // Immediately call with current progress (wrap in try-catch for safety)\n    try {\n      callback(this.getGlobalProgress());\n    } catch (error) {\n      console.error('Error in onProgress callback:', error);\n    }\n    \n    return () => {\n      this.onProgressCallbacks.delete(callback);\n    };\n  }\n\n  /**\n   * Registers a callback that will be called when all assets are loaded\n   * \n   * @param callback - Function to call when all assets are complete\n   * @returns A function to unregister the callback\n   * \n   * @example\n   * ```typescript\n   * const unsubscribe = loader.onComplete(() => {\n   *   console.log('All assets loaded!');\n   * });\n   * \n   * // Later, to unsubscribe:\n   * unsubscribe();\n   * ```\n   */\n  onComplete(callback: () => void): () => void {\n    this.onCompleteCallbacks.add(callback);\n    \n    // If already complete, call immediately\n    if (this.isComplete) {\n      callback();\n    }\n    \n    return () => {\n      this.onCompleteCallbacks.delete(callback);\n    };\n  }\n\n  /**\n   * Gets the current global progress (0-1)\n   * \n   * @returns Progress value between 0 and 1\n   */\n  getGlobalProgress(): number {\n    if (this.assets.size === 0) {\n      return 1; // No assets means everything is \"loaded\"\n    }\n    \n    let totalProgress = 0;\n    for (const asset of this.assets.values()) {\n      totalProgress += asset.progress;\n    }\n    \n    return totalProgress / this.assets.size;\n  }\n\n  /**\n   * Gets the number of assets currently being tracked\n   * \n   * @returns Number of registered assets\n   */\n  getAssetCount(): number {\n    return this.assets.size;\n  }\n\n  /**\n   * Gets the number of completed assets\n   * \n   * @returns Number of completed assets\n   */\n  getCompletedCount(): number {\n    let count = 0;\n    for (const asset of this.assets.values()) {\n      if (asset.completed) count++;\n    }\n    return count;\n  }\n\n  /**\n   * Checks if all assets are loaded and triggers onComplete callbacks\n   */\n  private checkCompletion(): void {\n    if (this.isComplete) return;\n    \n    const allCompleted = Array.from(this.assets.values()).every(asset => asset.completed);\n    \n    if (allCompleted && this.assets.size > 0) {\n      this.isComplete = true;\n      this.onCompleteCallbacks.forEach(callback => {\n        try {\n          callback();\n        } catch (error) {\n          console.error('Error in onComplete callback:', error);\n        }\n      });\n    }\n  }\n\n  /**\n   * Updates global progress and notifies all progress callbacks\n   */\n  private updateGlobalProgress(): void {\n    const progress = this.getGlobalProgress();\n    // Create a copy of callbacks to avoid issues if callbacks modify the set\n    const callbacks = Array.from(this.onProgressCallbacks);\n    callbacks.forEach(callback => {\n      try {\n        callback(progress);\n      } catch (error) {\n        console.error('Error in onProgress callback:', error);\n      }\n    });\n  }\n\n  /**\n   * Resets the loader, clearing all assets and callbacks\n   */\n  reset(): void {\n    this.assets.clear();\n    this.onProgressCallbacks.clear();\n    this.onCompleteCallbacks.clear();\n    this.assetCounter = 0;\n    this.isComplete = false;\n  }\n}\n\n"
  },
  {
    "path": "packages/core/src/utils/RadialGradient.ts",
    "content": "import { Texture, ImageSource, DOMAdapter, Matrix } from \"pixi.js\";\n\n/**\n * Creates a radial gradient texture that can be used in PixiJS.\n * @example\n * const gradient = new RadialGradient(size, size, 0, size, size, 0);\n * gradient.addColorStop(0, \"rgba(255, 255, 0, 1)\");\n * gradient.addColorStop(0.5, \"rgba(255, 255, 0, 0.3)\");\n * gradient.addColorStop(0.8, \"rgba(255, 255, 0, 0)\");\n */\nexport class RadialGradient {\n  private canvas: HTMLCanvasElement;\n  private ctx: CanvasRenderingContext2D | null;\n  private gradient: CanvasGradient | null = null;\n  private texture: Texture | null = null;\n  public transform: Matrix;\n\n  public size = 600;\n\n  /**\n   * Creates a new RadialGradient instance\n   * @param x0 - The x-coordinate of the starting circle\n   * @param y0 - The y-coordinate of the starting circle\n   * @param x1 - The x-coordinate of the ending circle\n   * @param y1 - The y-coordinate of the ending circle\n   * @param x2 - The x-coordinate for gradient transformation\n   * @param y2 - The y-coordinate for gradient transformation\n   * @param focalPoint - The focal point of the gradient (0-1), defaults to 0\n   */\n  constructor(\n    private x0: number,\n    private y0: number,\n    private x1: number,\n    private y1: number,\n    private x2: number,\n    private y2: number,\n    private focalPoint: number = 0\n  ) {\n    this.size = x0;\n    const halfSize = this.size * 0.5;\n\n    this.canvas = DOMAdapter.get().createCanvas() as any;\n    this.canvas.width = this.size;\n    this.canvas.height = this.size;\n    this.ctx = this.canvas.getContext(\"2d\");\n\n    if (this.ctx) {\n      this.gradient = this.ctx.createRadialGradient(\n        halfSize * (1 - focalPoint),\n        halfSize,\n        0,\n        halfSize,\n        halfSize,\n        halfSize - 0.5\n      );\n    }\n  }\n\n  /**\n   * Adds a color stop to the gradient\n   * @param offset - The position of the color stop (0-1)\n   * @param color - The color value (any valid CSS color string)\n   */\n  addColorStop(offset: number, color: string) {\n    if (this.gradient) {\n      this.gradient.addColorStop(offset, color);\n    }\n  }\n\n  /**\n   * Renders the gradient and returns the texture with its transformation matrix\n   * @param options - Render options\n   * @param options.translate - Optional translation coordinates\n   * @returns Object containing the texture and transformation matrix\n   */\n  render({ translate }: { translate?: { x: number; y: number } } = {}) {\n    const { x0, y0, x1, y1, x2, y2, focalPoint } = this;\n    const defaultSize = this.size;\n    if (this.ctx && this.gradient) {\n      this.ctx.fillStyle = this.gradient;\n      this.ctx.fillRect(0, 0, defaultSize, defaultSize);\n\n      this.texture = new Texture({\n        source: new ImageSource({\n          resource: this.canvas,\n          addressModeU: \"clamp-to-edge\",\n          addressModeV: \"clamp-to-edge\",\n        }),\n      });\n\n      const m = new Matrix();\n      const dx = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));\n      const dy = Math.sqrt((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0));\n      const angle = Math.atan2(y1 - y0, x1 - x0);\n\n      // Calculate the scale factors correctly\n      const scaleX = dx / defaultSize;\n      const scaleY = dy / defaultSize;\n\n      // Apply transformations in the correct order\n      m.rotate(-angle);\n      m.scale(scaleX, scaleY);\n      if (translate) {\n        m.translate(translate.x, translate.y);\n      }\n\n      this.transform = m;\n    }\n\n    return {\n      texture: this.texture,\n      matrix: this.transform,\n    };\n  }\n}\n"
  },
  {
    "path": "packages/core/src/utils/functions.ts",
    "content": "export function isPercent(value?: string | number) {\n    if (!value) return false\n    if (typeof value === \"string\") {\n        return value.endsWith(\"%\")\n    }\n    return false\n}"
  },
  {
    "path": "packages/core/src/utils/tabindex.ts",
    "content": "import { WritableSignal } from \"@signe/reactive\";\n\nexport type TabindexBoundaryMode = \"wrap\" | \"clamp\" | \"none\";\n\nexport type TabindexBounds =\n  | { count: () => number; min?: number }\n  | { min: number; max: number };\n\ntype TabindexNavigator = {\n  next: (delta: number) => void;\n  set: (value: number) => void;\n};\n\nfunction resolveBounds(bounds: TabindexBounds): { min: number; max: number; size: number } | null {\n  if (\"count\" in bounds) {\n    const count = bounds.count();\n    if (!Number.isFinite(count) || count <= 0) return null;\n    const min = bounds.min ?? 0;\n    const max = min + count - 1;\n    return { min, max, size: count };\n  }\n\n  const min = bounds.min;\n  const max = bounds.max;\n  if (!Number.isFinite(min) || !Number.isFinite(max) || max < min) return null;\n  return { min, max, size: max - min + 1 };\n}\n\nfunction normalizeValue(\n  value: number,\n  current: number,\n  bounds: { min: number; max: number; size: number },\n  mode: TabindexBoundaryMode\n): number {\n  if (mode === \"clamp\") {\n    return Math.min(bounds.max, Math.max(bounds.min, value));\n  }\n\n  if (mode === \"none\") {\n    return value < bounds.min || value > bounds.max ? current : value;\n  }\n\n  // wrap\n  const size = bounds.size;\n  if (size <= 0) return current;\n  const offset = value - bounds.min;\n  const wrapped = ((offset % size) + size) % size;\n  return bounds.min + wrapped;\n}\n\nexport function createTabindexNavigator(\n  tabindex: WritableSignal<number>,\n  bounds: TabindexBounds,\n  mode: TabindexBoundaryMode = \"wrap\"\n): TabindexNavigator {\n  const applyValue = (value: number) => {\n    const current = tabindex();\n    const resolved = resolveBounds(bounds);\n    if (!resolved) return;\n    const nextValue = normalizeValue(value, current, resolved, mode);\n    if (nextValue !== current) {\n      tabindex.set(nextValue);\n    }\n  };\n\n  return {\n    next: (delta: number) => applyValue(tabindex() + delta),\n    set: (value: number) => applyValue(value),\n  };\n}\n"
  },
  {
    "path": "packages/core/testing/index.ts",
    "content": "import { bootstrapCanvas, Canvas, ComponentInstance, Element, h } from \"canvasengine\";\nimport type { Application } from \"pixi.js\";\n\nexport class TestBed {\n    private static lastApp: Application | null = null;\n\n    static async createComponent(\n        component: any,\n        props: any = {},\n        children: any = [],\n        options: { enableLayout?: boolean } = {}\n    ): Promise<Element<ComponentInstance>> {\n        if (TestBed.lastApp) {\n            try {\n                TestBed.lastApp.destroy(\n                    { removeView: true },\n                    { children: true, texture: true, textureSource: true, context: true }\n                );\n            } catch {\n                // ignore cleanup errors in test environment\n            }\n            TestBed.lastApp = null;\n        }\n\n        const root = document.getElementById('root');\n        if (root) {\n            root.innerHTML = '';\n        }\n\n        const comp = () => h(Canvas, {\n            tickStart: false\n        }, h(component, props, children))\n        const enableLayout = options.enableLayout ?? true;\n        const { canvasElement, app } = await bootstrapCanvas(root, comp, {\n            enableLayout,\n            ...(enableLayout ? { layout: { throttle: 0 } } : {})\n        })\n        app.render()\n        TestBed.lastApp = app as Application;\n        return canvasElement.props.children?.[0]\n    }\n}\n"
  },
  {
    "path": "packages/core/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"declaration\": true,\n    \"emitDeclarationOnly\": false,\n    \"declarationMap\": true,\n    \"rootDir\": \"src\",\n    \"module\": \"ESNext\"\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\"\n  ]\n} \n"
  },
  {
    "path": "packages/core/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { resolve } from 'path'\nimport dts from 'vite-plugin-dts'\n\nexport default defineConfig({\n  plugins: [dts()],\n  build: {\n    lib: {\n      entry: resolve(__dirname, 'src/index.ts'),\n      name: 'CanvasEngine'\n    },\n    rollupOptions: {\n      external: ['pixi.js'],\n      output: [\n        // ESM build\n        {\n          format: 'es',\n          dir: 'dist',\n          entryFileNames: 'index.js'\n        },\n        // IIFE build for global usage\n        {\n          format: 'iife',\n          dir: 'dist',\n          entryFileNames: 'index.global.js',\n          name: 'CanvasEngine',\n          globals: {\n            'pixi.js': 'PIXI'\n          },\n        }\n      ]\n    },\n    minify: true,\n    sourcemap: true\n  },\n  define: {\n    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')\n  }\n}) "
  },
  {
    "path": "packages/presets/package.json",
    "content": "{\n  \"name\": \"@canvasengine/presets\",\n  \"version\": \"2.0.0-beta.58\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"dev\": \"vite build --watch\"\n  },\n  \"peerDependencies\": {\n    \"canvasengine\": \"^2.0.0-beta.45\",\n    \"pixi.js\": \"^8.9.2\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^6.0.3\",\n    \"vite\": \"^8.0.10\",\n    \"vite-plugin-dts\": \"^4.5.4\"\n  },\n  \"author\": \"Samuel Ronce\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://canvasengine.net\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/RSamaium/CanvasEngine.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/RSamaium/CanvasEngine/issues\"\n  },\n  \"keywords\": [\n    \"canvas\",\n    \"pixijs\",\n    \"reactive\",\n    \"html5\",\n    \"presets\"\n  ],\n  \"dependencies\": {\n    \"@canvasengine/tiled\": \"workspace:*\",\n    \"@canvasengine/tilemap\": \"^5.0.1\",\n    \"rxjs\": \"^7.8.2\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n"
  },
  {
    "path": "packages/presets/src/Bar.ts",
    "content": "import { Graphics, h, useProps } from \"canvasengine\";\nimport * as PIXI from \"pixi.js\";\n\ninterface BarProps {\n  backgroundColor?: string;\n  foregroundColor?: string;\n  value: number;\n  maxValue: number;\n  width: number;\n  height: number;\n  border?: any;\n  innerMargin?: number;\n  borderRadius?: number;\n}\n\nfunction componentToHex(c) {\n  var hex = c.toString(16);\n  return hex.length == 1 ? \"0\" + hex : hex;\n}\n\nfunction rgbToHex(r, g, b) {\n  return \"#\" + componentToHex(r) + componentToHex(g) + componentToHex(b);\n}\n\nexport function Bar(opts: BarProps) {\n  const {\n    width,\n    height,\n    value,\n    maxValue,\n    backgroundColor,\n    foregroundColor,\n    border,\n    innerMargin,\n    borderRadius,\n  } = useProps(opts, {\n    backgroundColor: \"#000000\",\n    foregroundColor: \"#FFFFFF\",\n    innerMargin: 0,\n    borderRadius: 0,\n  });\n\n  return h(\n    Graphics,\n    {\n      ...opts,\n      width,\n      height,\n      draw(graphics: any) {\n        if (borderRadius()) {\n          graphics.roundRect(0, 0, width(), height(), borderRadius());\n        } else {\n          graphics.rect(0, 0, width(), height());\n        }\n        if (border) {\n          graphics.stroke(border);\n        }\n        graphics.fill(backgroundColor());\n      },\n    },\n    h(Graphics, {\n      width,\n      height,\n      draw(graphics: any) {\n        const margin = innerMargin();\n        const _borderRadius = borderRadius();\n        const w = Math.max(\n          0,\n          Math.min(\n            width() - 2 * margin,\n            (value() / maxValue()) * (width() - 2 * margin)\n          )\n        );\n        const h = height() - 2 * margin;\n        if (borderRadius) {\n          graphics.roundRect(margin, margin, w, h, _borderRadius);\n        } else {\n          graphics.rect(margin, margin, w, h);\n        }\n        const color = foregroundColor();\n        if (color.startsWith(\"rgba\")) {\n          const [r, g, b, a] = color.match(/\\d+(\\.\\d+)?/g).map(Number);\n          graphics.fill({ color: rgbToHex(r, g, b), alpha: a });\n        } else {\n          graphics.fill(color);\n        }\n      },\n    })\n  );\n}\n"
  },
  {
    "path": "packages/presets/src/Button.ts",
    "content": ""
  },
  {
    "path": "packages/presets/src/FogOfWar.ts",
    "content": "import { h, signal, Sprite, tick, useProps } from \"canvasengine\";\nimport { Texture } from \"pixi.js\";\n\ntype FogColor = [number, number, number, number];\ntype FogVisibilityState = \"visible\" | \"explored\" | \"unknown\";\n\ntype VisionSource = {\n  x: number | (() => number);\n  y: number | (() => number);\n  radius: number | (() => number);\n  enabled?: boolean | (() => boolean);\n};\n\ntype ResolvedVisionSource = {\n  x: number;\n  y: number;\n  radius: number;\n  enabled: boolean;\n};\n\ntype FogOfWarColors = {\n  unknown?: FogColor;\n  explored?: FogColor;\n};\n\ntype FogOfWarProps = {\n  mapWidth: number | (() => number);\n  mapHeight: number | (() => number);\n  tileSize?: number | (() => number);\n  smooth?: boolean | (() => boolean);\n  renderScale?: number | (() => number);\n  edgeSoftness?: number | (() => number);\n  visionSources?: VisionSource[] | (() => VisionSource[]);\n  colors?: FogOfWarColors | (() => FogOfWarColors);\n  updateHz?: number | (() => number);\n  initialExplored?: boolean | (() => boolean);\n  controller?: FogOfWarController | (() => FogOfWarController);\n  obstacleMap?: unknown;\n  [key: string]: unknown;\n};\n\ntype FogSample = {\n  clarity: number;\n  explored: boolean;\n};\n\ntype FogSampler = (x: number, y: number) => FogSample;\n\ntype FogControllerInternals = {\n  setSampler: (sampler: FogSampler) => void;\n  notifyUpdate: () => void;\n};\n\nexport type FogOfWarController = {\n  version: () => number;\n  clarityAt: (x: number, y: number) => number;\n  isVisibleAt: (x: number, y: number, threshold?: number) => boolean;\n  isExploredAt: (x: number, y: number) => boolean;\n  stateAt: (x: number, y: number, clearThreshold?: number) => FogVisibilityState;\n};\n\nconst DEFAULT_UNKNOWN: FogColor = [0, 0, 0, 1];\nconst DEFAULT_EXPLORED: FogColor = [0, 0, 0, 0.55];\nconst DEFAULT_SAMPLE: FogSample = { clarity: 0, explored: false };\nconst defaultSampler: FogSampler = () => DEFAULT_SAMPLE;\nconst fogControllerRegistry = new WeakMap<FogOfWarController, FogControllerInternals>();\n\nconst clamp = (value: number, min: number, max: number) =>\n  Math.max(min, Math.min(max, value));\n\nconst smoothstep = (edge0: number, edge1: number, x: number) => {\n  if (edge1 <= edge0) return x >= edge1 ? 1 : 0;\n  const t = clamp((x - edge0) / (edge1 - edge0), 0, 1);\n  return t * t * (3 - 2 * t);\n};\n\nconst resolveValue = (value: any): any => {\n  if (typeof value === \"function\") return value();\n  return value;\n};\n\nexport function createFogOfWarController(): FogOfWarController {\n  const revision = signal(0);\n  let sampler: FogSampler = defaultSampler;\n\n  const readSample = (x: number, y: number): FogSample => {\n    revision();\n    if (!Number.isFinite(x) || !Number.isFinite(y)) return DEFAULT_SAMPLE;\n    return sampler(x, y);\n  };\n\n  const controller: FogOfWarController = {\n    version: () => revision(),\n    clarityAt: (x, y) => clamp(readSample(x, y).clarity, 0, 1),\n    isVisibleAt: (x, y, threshold = 0.65) =>\n      readSample(x, y).clarity >= clamp(threshold, 0, 1),\n    isExploredAt: (x, y) => {\n      const sample = readSample(x, y);\n      return sample.explored || sample.clarity > 0;\n    },\n    stateAt: (x, y, clearThreshold = 0.65) => {\n      const sample = readSample(x, y);\n      if (sample.clarity >= clamp(clearThreshold, 0, 1)) return \"visible\";\n      if (sample.explored || sample.clarity > 0) return \"explored\";\n      return \"unknown\";\n    },\n  };\n\n  fogControllerRegistry.set(controller, {\n    setSampler(nextSampler) {\n      sampler = typeof nextSampler === \"function\" ? nextSampler : defaultSampler;\n    },\n    notifyUpdate() {\n      revision.update((value: number) => value + 1);\n    },\n  });\n\n  return controller;\n}\n\nconst toColorBytes = (input: FogColor, fallback: FogColor) => {\n  const value = Array.isArray(input) ? input : fallback;\n  const [r, g, b, a] = value;\n  const normalize = (n: number, alpha = false) => {\n    if (!Number.isFinite(n)) return alpha ? 255 : 0;\n    if (n >= 0 && n <= 1) return Math.round(n * 255);\n    return clamp(Math.round(n), 0, 255);\n  };\n  return {\n    r: normalize(r),\n    g: normalize(g),\n    b: normalize(b),\n    a: normalize(a, true),\n  };\n};\n\nconst resolveSources = (input: VisionSource[] | (() => VisionSource[])) => {\n  const raw = resolveValue(input);\n  if (!Array.isArray(raw)) return [];\n  return raw;\n};\n\nexport function FogOfWar(options: FogOfWarProps) {\n  const {\n    mapWidth,\n    mapHeight,\n    tileSize = signal(32),\n    smooth = signal(true),\n    renderScale = signal(2),\n    edgeSoftness = signal(22),\n    visionSources = signal([]),\n    colors = signal({}),\n    updateHz = signal(15),\n    initialExplored = signal(false),\n    controller = undefined,\n    obstacleMap = undefined,\n    ...spriteProps\n  } = useProps(options);\n\n  // Placeholder for phase 2 LOS support with blocking tiles.\n  void obstacleMap;\n\n  let fogCanvas: HTMLCanvasElement;\n  let fogCtx: CanvasRenderingContext2D | null = null;\n  let fogTexture: Texture = Texture.WHITE;\n  let imageData: ImageData | null = null;\n  let pixelData: Uint8ClampedArray | null = null;\n  let visibilityNow = new Float32Array(0);\n  let explored = new Uint8Array(0);\n  let gridWidth = 1;\n  let gridHeight = 1;\n  let cellCount = 1;\n  let cachedMapWidth = 1;\n  let cachedMapHeight = 1;\n  let cachedTileSize = 1;\n  let cachedCellSize = 1;\n  let cachedRenderScale = 1;\n  let accumulatorMs = 0;\n  let forceRefresh = true;\n  let activeController: FogOfWarController | null = null;\n  let activeControllerInternals: FogControllerInternals | null = null;\n  let previousSourcesSnapshot: number[] = [];\n\n  const createFogCanvas = () => {\n    if (typeof document === \"undefined\") {\n      throw new Error(\"FogOfWar: document is undefined, canvas cannot be created.\");\n    }\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = 1;\n    canvas.height = 1;\n    return canvas;\n  };\n\n  fogCanvas = createFogCanvas();\n  fogCtx = fogCanvas.getContext(\"2d\", { willReadFrequently: true });\n  if (!fogCtx) {\n    throw new Error(\"FogOfWar: unable to create 2D context for fog canvas.\");\n  }\n  fogTexture = Texture.from(fogCanvas);\n\n  const resolveRenderScale = () => {\n    const smoothEnabled = resolveValue(smooth) !== false;\n    const fallback = smoothEnabled ? 2 : 1;\n    const value = Number(resolveValue(renderScale));\n    if (!Number.isFinite(value)) return fallback;\n    return clamp(Math.round(value), 1, 8);\n  };\n\n  const resolveEdgeSoftness = () => {\n    if (resolveValue(smooth) === false) return 0;\n    const value = Number(resolveValue(edgeSoftness));\n    if (!Number.isFinite(value)) return Math.max(cachedCellSize * 0.9, 2);\n    return Math.max(0, value);\n  };\n\n  const resolveController = () => {\n    const value = resolveValue(controller);\n    return value && typeof value === \"object\"\n      ? (value as FogOfWarController)\n      : undefined;\n  };\n\n  const resolveVisionSources = (): ResolvedVisionSource[] => {\n    const sources = resolveSources(visionSources);\n    const resolved: ResolvedVisionSource[] = [];\n    for (let i = 0; i < sources.length; i++) {\n      const source = sources[i];\n      resolved.push({\n        x: Number(resolveValue(source.x)),\n        y: Number(resolveValue(source.y)),\n        radius: Number(resolveValue(source.radius)),\n        enabled: resolveValue(source.enabled) !== false,\n      });\n    }\n    return resolved;\n  };\n\n  const didSourcesChange = (sources: ResolvedVisionSource[]) => {\n    const snapshot = new Array(sources.length * 4);\n    let index = 0;\n    for (let i = 0; i < sources.length; i++) {\n      const source = sources[i];\n      snapshot[index++] = source.x;\n      snapshot[index++] = source.y;\n      snapshot[index++] = source.radius;\n      snapshot[index++] = source.enabled ? 1 : 0;\n    }\n\n    let changed = snapshot.length !== previousSourcesSnapshot.length;\n    if (!changed) {\n      for (let i = 0; i < snapshot.length; i++) {\n        const next = snapshot[i];\n        const prev = previousSourcesSnapshot[i];\n        if (Number.isNaN(next) !== Number.isNaN(prev) || Math.abs(next - prev) > 0.01) {\n          changed = true;\n          break;\n        }\n      }\n    }\n\n    previousSourcesSnapshot = snapshot;\n    return changed;\n  };\n\n  const sampleFog = (worldX: number, worldY: number): FogSample => {\n    if (\n      !Number.isFinite(worldX) ||\n      !Number.isFinite(worldY) ||\n      cellCount <= 0 ||\n      gridWidth <= 0 ||\n      gridHeight <= 0\n    ) {\n      return DEFAULT_SAMPLE;\n    }\n\n    const safeX = clamp(worldX, 0, Math.max(0, cachedMapWidth - 1));\n    const safeY = clamp(worldY, 0, Math.max(0, cachedMapHeight - 1));\n    const cellX = Math.min(gridWidth - 1, Math.max(0, Math.floor(safeX / cachedCellSize)));\n    const cellY = Math.min(gridHeight - 1, Math.max(0, Math.floor(safeY / cachedCellSize)));\n    const index = cellY * gridWidth + cellX;\n\n    return {\n      clarity: clamp(visibilityNow[index] ?? 0, 0, 1),\n      explored: explored[index] === 1,\n    };\n  };\n\n  const syncController = (notify: boolean) => {\n    const nextController = resolveController() ?? null;\n    if (nextController !== activeController) {\n      if (activeControllerInternals) {\n        activeControllerInternals.setSampler(defaultSampler);\n      }\n      activeController = nextController;\n      activeControllerInternals = activeController\n        ? fogControllerRegistry.get(activeController) ?? null\n        : null;\n      if (activeControllerInternals) {\n        activeControllerInternals.setSampler(sampleFog);\n      }\n      notify = true;\n    }\n    if (notify && activeControllerInternals) {\n      activeControllerInternals.notifyUpdate();\n    }\n  };\n\n  const applyTextureScaleMode = () => {\n    const source = (fogTexture as any).source;\n    if (!source) return;\n    source.scaleMode = resolveValue(smooth) === false ? \"nearest\" : \"linear\";\n  };\n\n  const resizeFogBuffers = (\n    nextMapWidth: number,\n    nextMapHeight: number,\n    nextTileSize: number,\n    nextRenderScale: number\n  ) => {\n    cachedMapWidth = Math.max(1, Math.floor(nextMapWidth));\n    cachedMapHeight = Math.max(1, Math.floor(nextMapHeight));\n    cachedTileSize = Math.max(1, Math.floor(nextTileSize));\n    cachedRenderScale = clamp(nextRenderScale, 1, 8);\n    cachedCellSize = Math.max(1, cachedTileSize / cachedRenderScale);\n    gridWidth = Math.max(1, Math.ceil(cachedMapWidth / cachedCellSize));\n    gridHeight = Math.max(1, Math.ceil(cachedMapHeight / cachedCellSize));\n    cellCount = gridWidth * gridHeight;\n\n    if (\"width\" in fogCanvas) {\n      (fogCanvas as any).width = gridWidth;\n      (fogCanvas as any).height = gridHeight;\n    }\n\n    visibilityNow = new Float32Array(cellCount);\n    explored = new Uint8Array(cellCount);\n    if (resolveValue(initialExplored)) explored.fill(1);\n\n    imageData = fogCtx?.createImageData(gridWidth, gridHeight) ?? null;\n    pixelData = imageData?.data ?? null;\n    applyTextureScaleMode();\n    forceRefresh = true;\n  };\n\n  const drawVisionCircle = (source: ResolvedVisionSource, featherCells: number) => {\n    if (\n      source.enabled === false ||\n      !Number.isFinite(source.x) ||\n      !Number.isFinite(source.y) ||\n      !Number.isFinite(source.radius) ||\n      source.radius <= 0\n    ) {\n      return;\n    }\n\n    const x = source.x;\n    const y = source.y;\n    const radius = source.radius;\n    const radiusInCells = radius / cachedCellSize;\n    const innerRadius = Math.max(0, radiusInCells - featherCells);\n    const outerRadius = Math.max(radiusInCells, radiusInCells + featherCells);\n    const innerRadiusSq = innerRadius * innerRadius;\n    const outerRadiusSq = outerRadius * outerRadius;\n\n    const minX = Math.max(0, Math.floor(x / cachedCellSize - outerRadius));\n    const maxX = Math.min(gridWidth - 1, Math.ceil(x / cachedCellSize + outerRadius));\n    const minY = Math.max(0, Math.floor(y / cachedCellSize - outerRadius));\n    const maxY = Math.min(gridHeight - 1, Math.ceil(y / cachedCellSize + outerRadius));\n\n    for (let ty = minY; ty <= maxY; ty++) {\n      for (let tx = minX; tx <= maxX; tx++) {\n        const centerX = (tx + 0.5) * cachedCellSize;\n        const centerY = (ty + 0.5) * cachedCellSize;\n        const dx = centerX - x;\n        const dy = centerY - y;\n        const distanceSq = (dx * dx + dy * dy) / (cachedCellSize * cachedCellSize);\n        if (distanceSq > outerRadiusSq) continue;\n\n        let clarity = 1;\n        if (outerRadius > innerRadius && distanceSq > innerRadiusSq) {\n          const distance = Math.sqrt(distanceSq);\n          const fade = smoothstep(innerRadius, outerRadius, distance);\n          clarity = 1 - fade;\n        }\n        if (clarity <= 0.001) continue;\n\n        const index = ty * gridWidth + tx;\n        if (clarity > visibilityNow[index]) {\n          visibilityNow[index] = clarity;\n        }\n        if (clarity > 0.02) explored[index] = 1;\n      }\n    }\n  };\n\n  const rasterizeFog = (resolvedSources?: ResolvedVisionSource[]) => {\n    if (!imageData || !pixelData || !fogCtx) return;\n\n    const rawColors = resolveValue(colors) || {};\n    const unknown = toColorBytes(rawColors.unknown, DEFAULT_UNKNOWN);\n    const known = toColorBytes(rawColors.explored, DEFAULT_EXPLORED);\n\n    visibilityNow.fill(0);\n    const sources = resolvedSources ?? resolveVisionSources();\n    const featherCells = resolveEdgeSoftness() / cachedCellSize;\n    for (let i = 0; i < sources.length; i++) {\n      drawVisionCircle(sources[i], featherCells);\n    }\n\n    for (let i = 0; i < cellCount; i++) {\n      const p = i * 4;\n      const clarity = clamp(visibilityNow[i], 0, 1);\n      const isExplored = explored[i] === 1;\n      const fogColor = isExplored ? known : unknown;\n      pixelData[p] = fogColor.r;\n      pixelData[p + 1] = fogColor.g;\n      pixelData[p + 2] = fogColor.b;\n      pixelData[p + 3] = Math.round(fogColor.a * (1 - clarity));\n    }\n\n    fogCtx.putImageData(imageData, 0, 0);\n    const source = (fogTexture as any).source;\n    if (source && typeof source.update === \"function\") source.update();\n    else if (typeof (fogTexture as any).update === \"function\") (fogTexture as any).update();\n    syncController(true);\n  };\n\n  const initialMapWidth = Number(resolveValue(mapWidth)) || 1;\n  const initialMapHeight = Number(resolveValue(mapHeight)) || 1;\n  const initialTileSize = Number(resolveValue(tileSize)) || 32;\n  const initialRenderScale = resolveRenderScale();\n  resizeFogBuffers(initialMapWidth, initialMapHeight, initialTileSize, initialRenderScale);\n  rasterizeFog();\n\n  tick(({ deltaTime }) => {\n    if (!fogCtx) return;\n\n    const mw = Math.max(1, Number(resolveValue(mapWidth)) || 1);\n    const mh = Math.max(1, Number(resolveValue(mapHeight)) || 1);\n    const ts = Math.max(1, Number(resolveValue(tileSize)) || 32);\n    const rs = resolveRenderScale();\n    if (\n      mw !== cachedMapWidth ||\n      mh !== cachedMapHeight ||\n      ts !== cachedTileSize ||\n      rs !== cachedRenderScale\n    ) {\n      resizeFogBuffers(mw, mh, ts, rs);\n    }\n    applyTextureScaleMode();\n    syncController(false);\n    const resolvedSources = resolveVisionSources();\n    const sourcesChanged = didSourcesChange(resolvedSources);\n    if (sourcesChanged) {\n      // Keep vision movement visually smooth even with low updateHz.\n      forceRefresh = true;\n    }\n\n    const hz = Math.max(1, Number(resolveValue(updateHz)) || 15);\n    const intervalMs = 1000 / hz;\n    accumulatorMs += deltaTime;\n\n    if (forceRefresh || sourcesChanged || accumulatorMs >= intervalMs) {\n      accumulatorMs = 0;\n      forceRefresh = false;\n      rasterizeFog(resolvedSources);\n    }\n  });\n\n  return h(Sprite, {\n    ...spriteProps,\n    texture: fogTexture,\n    x: 0,\n    y: 0,\n    width: Math.max(1, Number(resolveValue(mapWidth)) || 1),\n    height: Math.max(1, Number(resolveValue(mapHeight)) || 1),\n    roundPixels: true,\n  });\n}\n"
  },
  {
    "path": "packages/presets/src/Footprints.ts",
    "content": "import { Container, h, mount, useProps } from \"canvasengine\";\nimport {\n  BlurFilter,\n  Container as PixiContainer,\n  Graphics,\n  Sprite as PixiSprite,\n  Texture,\n} from \"pixi.js\";\n\ntype ReactiveValue<T> = T | (() => T);\ntype PointLike = { x: number; y: number };\ntype ColorInput = string | number;\ntype FootSide = \"left\" | \"right\";\n\ntype ResolvedSurfaceProfile = {\n  lifetimeMs: number;\n  startAlpha: number;\n  endAlpha: number;\n  tint: number;\n  blendMode: any;\n  scale: number;\n  blurStart: number;\n  blurEnd: number;\n  erosionStart: number;\n  depth: number;\n  rimStrength: number;\n};\n\ntype ResolvedCaster = {\n  footAnchor: PointLike;\n  leftOffset: PointLike;\n  rightOffset: PointLike;\n  minStepDistance: number;\n  minSpeed: number;\n  stepIntervalMs: number;\n  size: number;\n  alpha: number;\n  blur: number;\n  surface: string;\n  angleOffset: number;\n  jitter: number;\n};\n\ntype ManagedCasterState = {\n  lastPoint: PointLike | null;\n  lastUpdateMs: number;\n  distanceSinceStep: number;\n  lastStepMs: number;\n  nextFoot: FootSide;\n  heading: number;\n};\n\ntype ManagedFootprint = {\n  baseSprite: PixiSprite;\n  depthSprite: PixiSprite;\n  rimSprite: PixiSprite;\n  baseBlurFilter: BlurFilter;\n  depthBlurFilter: BlurFilter;\n  rimBlurFilter: BlurFilter;\n  bornAt: number;\n  lifetimeMs: number;\n  startAlpha: number;\n  endAlpha: number;\n  baseScaleX: number;\n  baseScaleY: number;\n  blurStart: number;\n  blurEnd: number;\n  erosionStart: number;\n  depth: number;\n  rimStrength: number;\n};\n\nexport type FootprintSurfaceProfile = {\n  lifetimeMs?: ReactiveValue<number>;\n  startAlpha?: ReactiveValue<number>;\n  endAlpha?: ReactiveValue<number>;\n  tint?: ReactiveValue<ColorInput>;\n  blendMode?: ReactiveValue<any>;\n  scale?: ReactiveValue<number>;\n  blurStart?: ReactiveValue<number>;\n  blurEnd?: ReactiveValue<number>;\n  erosionStart?: ReactiveValue<number>;\n  depth?: ReactiveValue<number>;\n  rimStrength?: ReactiveValue<number>;\n};\n\nexport type FootprintCasterOptions = {\n  enabled?: ReactiveValue<boolean>;\n  footAnchor?: ReactiveValue<PointLike>;\n  leftOffset?: ReactiveValue<PointLike>;\n  rightOffset?: ReactiveValue<PointLike>;\n  minStepDistance?: ReactiveValue<number>;\n  minSpeed?: ReactiveValue<number>;\n  stepIntervalMs?: ReactiveValue<number>;\n  size?: ReactiveValue<number>;\n  alpha?: ReactiveValue<number>;\n  blur?: ReactiveValue<number>;\n  surface?: ReactiveValue<string>;\n  angleOffset?: ReactiveValue<number>;\n  jitter?: ReactiveValue<number>;\n};\n\nexport type FootprintsProps = {\n  profiles?: ReactiveValue<Record<string, FootprintSurfaceProfile>>;\n  defaultSurface?: ReactiveValue<string>;\n  maxFootprints?: ReactiveValue<number>;\n  updateHz?: ReactiveValue<number>;\n};\n\nconst FOOTPRINT_MANAGED_MARK = \"__footprintManaged\";\nconst DEFAULT_SURFACE = \"default\";\nconst DEFAULT_UPDATE_HZ = 30;\nconst DEFAULT_MAX_FOOTPRINTS = 260;\n\nconst DEFAULT_CASTER: ResolvedCaster = {\n  footAnchor: { x: 0.5, y: 1 },\n  leftOffset: { x: -10, y: 1 },\n  rightOffset: { x: 10, y: 1 },\n  minStepDistance: 18,\n  minSpeed: 36,\n  stepIntervalMs: 85,\n  size: 1,\n  alpha: 1,\n  blur: 0,\n  surface: DEFAULT_SURFACE,\n  angleOffset: 0,\n  jitter: 8,\n};\n\nconst BASE_PROFILE: ResolvedSurfaceProfile = {\n  lifetimeMs: 1800,\n  startAlpha: 0.32,\n  endAlpha: 0,\n  tint: 0x2d2a26,\n  blendMode: \"multiply\",\n  scale: 1,\n  blurStart: 0.45,\n  blurEnd: 1.9,\n  erosionStart: 0.54,\n  depth: 0.58,\n  rimStrength: 0.14,\n};\n\nconst BUILTIN_PROFILES: Record<string, ResolvedSurfaceProfile> = {\n  [DEFAULT_SURFACE]: BASE_PROFILE,\n  sand: {\n    lifetimeMs: 1650,\n    startAlpha: 0.31,\n    endAlpha: 0,\n    tint: 0x8e6d46,\n    blendMode: \"multiply\",\n    scale: 1,\n    blurStart: 0.35,\n    blurEnd: 1.5,\n    erosionStart: 0.62,\n    depth: 0.54,\n    rimStrength: 0.12,\n  },\n  snow: {\n    lifetimeMs: 2550,\n    startAlpha: 0.24,\n    endAlpha: 0,\n    tint: 0x7d8fa3,\n    blendMode: \"multiply\",\n    scale: 1.05,\n    blurStart: 0.6,\n    blurEnd: 2.25,\n    erosionStart: 0.45,\n    depth: 0.72,\n    rimStrength: 0.28,\n  },\n};\n\nconst clamp = (value: number, min: number, max: number) =>\n  Math.max(min, Math.min(max, value));\n\nconst lerp = (start: number, end: number, t: number) => start + (end - start) * t;\n\nconst smoothstep = (edge0: number, edge1: number, x: number) => {\n  const t = clamp((x - edge0) / Math.max(0.0001, edge1 - edge0), 0, 1);\n  return t * t * (3 - 2 * t);\n};\n\nconst isFiniteNumber = (value: unknown): value is number =>\n  typeof value === \"number\" && Number.isFinite(value);\n\nconst toggleFoot = (foot: FootSide): FootSide => (foot === \"left\" ? \"right\" : \"left\");\n\nconst degToRad = (degrees: number) => (degrees * Math.PI) / 180;\n\nconst resolveReactiveValue = <T>(value: ReactiveValue<T> | undefined): T | undefined => {\n  if (\n    value &&\n    typeof value === \"object\" &&\n    \"value\" in (value as Record<string, unknown>) &&\n    Object.keys(value as Record<string, unknown>).length <= 2\n  ) {\n    return (value as Record<string, T>).value;\n  }\n  if (typeof value === \"function\") {\n    try {\n      return (value as () => T)();\n    } catch {\n      return undefined;\n    }\n  }\n  return value;\n};\n\nconst parseColorToNumber = (color: ColorInput | undefined, fallback: number): number => {\n  if (typeof color === \"number\" && Number.isFinite(color)) {\n    return Math.max(0, Math.floor(color)) & 0xffffff;\n  }\n  if (typeof color === \"string\") {\n    const cleaned = color.trim().replace(/^#/, \"\");\n    const normalized =\n      cleaned.length === 3\n        ? `${cleaned[0]}${cleaned[0]}${cleaned[1]}${cleaned[1]}${cleaned[2]}${cleaned[2]}`\n        : cleaned;\n    const parsed = parseInt(normalized, 16);\n    if (Number.isFinite(parsed)) {\n      return parsed & 0xffffff;\n    }\n  }\n  return fallback;\n};\n\nconst darkenColor = (color: number, amount: number): number => {\n  const normalized = clamp(amount, 0, 1);\n  const r = Math.round(((color >> 16) & 0xff) * (1 - normalized));\n  const g = Math.round(((color >> 8) & 0xff) * (1 - normalized));\n  const b = Math.round((color & 0xff) * (1 - normalized));\n  return (r << 16) | (g << 8) | b;\n};\n\nconst lightenColor = (color: number, amount: number): number => {\n  const normalized = clamp(amount, 0, 1);\n  const r = Math.round(((color >> 16) & 0xff) + (255 - ((color >> 16) & 0xff)) * normalized);\n  const g = Math.round(((color >> 8) & 0xff) + (255 - ((color >> 8) & 0xff)) * normalized);\n  const b = Math.round((color & 0xff) + (255 - (color & 0xff)) * normalized);\n  return (r << 16) | (g << 8) | b;\n};\n\nconst resolvePoint = (value: ReactiveValue<PointLike> | undefined, fallback: PointLike): PointLike => {\n  const resolved = resolveReactiveValue(value);\n  const x = Number((resolved as PointLike | undefined)?.x);\n  const y = Number((resolved as PointLike | undefined)?.y);\n  return {\n    x: isFiniteNumber(x) ? x : fallback.x,\n    y: isFiniteNumber(y) ? y : fallback.y,\n  };\n};\n\nconst toGlobalPoint = (container: any, point: PointLike): PointLike => {\n  if (container && typeof container.toGlobal === \"function\") {\n    const globalPoint = container.toGlobal(point);\n    if (isFiniteNumber(globalPoint?.x) && isFiniteNumber(globalPoint?.y)) {\n      return { x: globalPoint.x, y: globalPoint.y };\n    }\n  }\n  return point;\n};\n\nconst toLocalPoint = (container: any, point: PointLike): PointLike => {\n  if (container && typeof container.toLocal === \"function\") {\n    const localPoint = container.toLocal(point);\n    if (isFiniteNumber(localPoint?.x) && isFiniteNumber(localPoint?.y)) {\n      return { x: localPoint.x, y: localPoint.y };\n    }\n  }\n  return point;\n};\n\nconst resolveProfileInput = (\n  source: FootprintSurfaceProfile | undefined,\n  fallback: ResolvedSurfaceProfile\n): ResolvedSurfaceProfile => {\n  const lifetimeMs = Number(resolveReactiveValue(source?.lifetimeMs));\n  const startAlpha = Number(resolveReactiveValue(source?.startAlpha));\n  const endAlpha = Number(resolveReactiveValue(source?.endAlpha));\n  const scale = Number(resolveReactiveValue(source?.scale));\n  const blurStart = Number(resolveReactiveValue(source?.blurStart));\n  const blurEnd = Number(resolveReactiveValue(source?.blurEnd));\n  const erosionStart = Number(resolveReactiveValue(source?.erosionStart));\n  const depth = Number(resolveReactiveValue(source?.depth));\n  const rimStrength = Number(resolveReactiveValue(source?.rimStrength));\n  const tintInput = resolveReactiveValue(source?.tint);\n  const blendInput = resolveReactiveValue(source?.blendMode);\n\n  return {\n    lifetimeMs: isFiniteNumber(lifetimeMs) ? Math.max(120, lifetimeMs) : fallback.lifetimeMs,\n    startAlpha: isFiniteNumber(startAlpha) ? clamp(startAlpha, 0, 1.5) : fallback.startAlpha,\n    endAlpha: isFiniteNumber(endAlpha) ? clamp(endAlpha, 0, 1.5) : fallback.endAlpha,\n    tint: parseColorToNumber(tintInput, fallback.tint),\n    blendMode: blendInput ?? fallback.blendMode,\n    scale: isFiniteNumber(scale) ? Math.max(0.05, scale) : fallback.scale,\n    blurStart: isFiniteNumber(blurStart) ? Math.max(0, blurStart) : fallback.blurStart,\n    blurEnd: isFiniteNumber(blurEnd) ? Math.max(0, blurEnd) : fallback.blurEnd,\n    erosionStart: isFiniteNumber(erosionStart)\n      ? clamp(erosionStart, 0.05, 0.95)\n      : fallback.erosionStart,\n    depth: isFiniteNumber(depth) ? clamp(depth, 0, 1) : fallback.depth,\n    rimStrength: isFiniteNumber(rimStrength)\n      ? clamp(rimStrength, 0, 1)\n      : fallback.rimStrength,\n  };\n};\n\nconst resolveProfilesMap = (\n  value: ReactiveValue<Record<string, FootprintSurfaceProfile>> | undefined\n): Record<string, ResolvedSurfaceProfile> => {\n  const userProfiles = resolveReactiveValue(value) ?? {};\n  const resolved: Record<string, ResolvedSurfaceProfile> = {};\n\n  for (const [name, profile] of Object.entries(BUILTIN_PROFILES)) {\n    resolved[name] = resolveProfileInput((userProfiles as any)[name], profile);\n  }\n\n  for (const [name, profile] of Object.entries(userProfiles)) {\n    if (resolved[name]) continue;\n    resolved[name] = resolveProfileInput(profile, BASE_PROFILE);\n  }\n\n  if (!resolved[DEFAULT_SURFACE]) {\n    resolved[DEFAULT_SURFACE] = BASE_PROFILE;\n  }\n\n  return resolved;\n};\n\nconst resolveCasterOptions = (\n  rawValue: unknown,\n  defaultSurface: string\n): ResolvedCaster | null => {\n  if (rawValue === false || rawValue === null || rawValue === undefined) return null;\n  const source: FootprintCasterOptions =\n    rawValue === true || typeof rawValue !== \"object\"\n      ? {}\n      : (rawValue as FootprintCasterOptions);\n\n  const enabled = resolveReactiveValue(source.enabled);\n  if (enabled === false) return null;\n\n  const minStepDistance = Number(resolveReactiveValue(source.minStepDistance));\n  const minSpeed = Number(resolveReactiveValue(source.minSpeed));\n  const stepIntervalMs = Number(resolveReactiveValue(source.stepIntervalMs));\n  const size = Number(resolveReactiveValue(source.size));\n  const alpha = Number(resolveReactiveValue(source.alpha));\n  const blur = Number(resolveReactiveValue(source.blur));\n  const angleOffset = Number(resolveReactiveValue(source.angleOffset));\n  const jitter = Number(resolveReactiveValue(source.jitter));\n  const surfaceRaw = resolveReactiveValue(source.surface);\n\n  return {\n    footAnchor: resolvePoint(source.footAnchor, DEFAULT_CASTER.footAnchor),\n    leftOffset: resolvePoint(source.leftOffset, DEFAULT_CASTER.leftOffset),\n    rightOffset: resolvePoint(source.rightOffset, DEFAULT_CASTER.rightOffset),\n    minStepDistance: isFiniteNumber(minStepDistance)\n      ? Math.max(2, minStepDistance)\n      : DEFAULT_CASTER.minStepDistance,\n    minSpeed: isFiniteNumber(minSpeed) ? Math.max(0, minSpeed) : DEFAULT_CASTER.minSpeed,\n    stepIntervalMs: isFiniteNumber(stepIntervalMs)\n      ? Math.max(0, stepIntervalMs)\n      : DEFAULT_CASTER.stepIntervalMs,\n    size: isFiniteNumber(size) ? Math.max(0.1, size) : DEFAULT_CASTER.size,\n    alpha: isFiniteNumber(alpha) ? clamp(alpha, 0, 2) : DEFAULT_CASTER.alpha,\n    blur: isFiniteNumber(blur) ? Math.max(0, blur) : DEFAULT_CASTER.blur,\n    surface:\n      typeof surfaceRaw === \"string\" && surfaceRaw.trim().length > 0\n        ? surfaceRaw.trim()\n        : defaultSurface,\n    angleOffset: isFiniteNumber(angleOffset) ? angleOffset : DEFAULT_CASTER.angleOffset,\n    jitter: isFiniteNumber(jitter) ? Math.max(0, jitter) : DEFAULT_CASTER.jitter,\n  };\n};\n\nconst resolveCasterFromInstance = (\n  instance: any,\n  defaultSurface: string\n): ResolvedCaster | null => {\n  if (!instance || instance[FOOTPRINT_MANAGED_MARK]) return null;\n  const element = typeof instance.getElement === \"function\" ? instance.getElement() : null;\n  const rawFootprintCaster =\n    resolveReactiveValue((instance as any).footprintCaster) ??\n    resolveReactiveValue((instance as any).fullProps?.footprintCaster) ??\n    resolveReactiveValue(element?.props?.footprintCaster) ??\n    resolveReactiveValue(element?.propObservables?.footprintCaster as any);\n  if (rawFootprintCaster === undefined) return null;\n  return resolveCasterOptions(rawFootprintCaster, defaultSurface);\n};\n\nconst collectFootprintCasters = (\n  root: any,\n  defaultSurface: string\n): Array<{ instance: any; caster: ResolvedCaster }> => {\n  const collected: Array<{ instance: any; caster: ResolvedCaster }> = [];\n  const stack: any[] = [root];\n\n  while (stack.length > 0) {\n    const node = stack.pop();\n    const children = Array.isArray(node?.children) ? node.children : [];\n\n    for (let i = 0; i < children.length; i++) {\n      const child = children[i];\n      if (!child || child[FOOTPRINT_MANAGED_MARK]) continue;\n\n      const caster = resolveCasterFromInstance(child, defaultSurface);\n      if (caster && child.parent) {\n        collected.push({ instance: child, caster });\n      }\n\n      if (Array.isArray(child.children) && child.children.length > 0) {\n        stack.push(child);\n      }\n    }\n  }\n\n  return collected;\n};\n\nconst resolveRenderer = (context: any): any => {\n  const appSignal = context?.app;\n  if (typeof appSignal === \"function\") {\n    try {\n      const app = appSignal();\n      if (app?.renderer && typeof app.renderer.generateTexture === \"function\") {\n        return app.renderer;\n      }\n    } catch {\n      // Ignore and use fallback.\n    }\n  }\n  const globalRenderer = (globalThis as any).__PIXI_RENDERER__;\n  if (globalRenderer && typeof globalRenderer.generateTexture === \"function\") {\n    return globalRenderer;\n  }\n  return null;\n};\n\nconst createFootprintTexture = (renderer: any): Texture => {\n  const graphics = new Graphics();\n\n  graphics.ellipse(0, 10, 8.4, 6.1).fill(0xffffff);\n  graphics.ellipse(0, -1.4, 6.8, 9.4).fill(0xffffff);\n  graphics.circle(-4.7, -12.8, 2).fill(0xffffff);\n  graphics.circle(-1.5, -14.6, 1.9).fill(0xffffff);\n  graphics.circle(1.5, -15.3, 1.75).fill(0xffffff);\n  graphics.circle(4.5, -14.1, 1.45).fill(0xffffff);\n\n  const texture = renderer.generateTexture(graphics);\n  graphics.destroy();\n\n  return texture;\n};\n\nconst resolveCasterBasePoint = (\n  caster: any,\n  parent: PixiContainer,\n  casterConfig: ResolvedCaster\n): PointLike => {\n  const bounds = typeof caster.getBounds === \"function\" ? caster.getBounds() : null;\n  const width = Math.max(\n    1,\n    Math.abs(Number(caster.width)) || Math.abs(Number(bounds?.width)) || 1\n  );\n  const height = Math.max(\n    1,\n    Math.abs(Number(caster.height)) || Math.abs(Number(bounds?.height)) || 1\n  );\n\n  const anchorXRaw = Number(caster.anchor?.x);\n  const anchorYRaw = Number(caster.anchor?.y);\n  const anchorX = isFiniteNumber(anchorXRaw) ? clamp(anchorXRaw, 0, 1) : 0.5;\n  const anchorY = isFiniteNumber(anchorYRaw) ? clamp(anchorYRaw, 0, 1) : 1;\n\n  const local = {\n    x: (casterConfig.footAnchor.x - anchorX) * width,\n    y: (casterConfig.footAnchor.y - anchorY) * height,\n  };\n\n  const global = toGlobalPoint(caster, local);\n  return toLocalPoint(parent, global);\n};\n\nconst placeBelowCaster = (\n  managed: ManagedFootprint,\n  caster: any,\n  parent: PixiContainer\n) => {\n  const casterZIndex = isFiniteNumber(caster?.zIndex) ? caster.zIndex : 0;\n  managed.rimSprite.zIndex = casterZIndex - 0.2;\n  managed.baseSprite.zIndex = casterZIndex - 0.18;\n  managed.depthSprite.zIndex = casterZIndex - 0.16;\n\n  if ((parent as any).sortableChildren) return;\n  if (!Array.isArray(parent.children)) return;\n  if (!parent.children.includes(caster)) return;\n\n  const ordered = [managed.rimSprite, managed.baseSprite, managed.depthSprite];\n  for (let i = 0; i < ordered.length; i++) {\n    const sprite = ordered[i];\n    if (!parent.children.includes(sprite)) continue;\n    const casterIndex = parent.getChildIndex(caster);\n    const targetIndex = Math.max(0, casterIndex - 1);\n    if (parent.getChildIndex(sprite) !== targetIndex) {\n      parent.setChildIndex(sprite, targetIndex);\n    }\n  }\n};\n\n/**\n * Footprints preset\n *\n * Adds fading footprints behind moving sprites tagged with `footprintCaster`.\n * Footprints are generated procedurally (no image required) and can be tuned\n * per surface profile (for example `sand` and `snow`).\n */\nexport function Footprints(options: FootprintsProps = {}) {\n  const props = useProps(options);\n\n  mount((element) => {\n    const context = element.props.context;\n    const viewport = context?.viewport;\n    const target: any = viewport ?? element.parent?.componentInstance;\n    if (!target || typeof target.addChild !== \"function\") return;\n    const tickSignal = context?.tick;\n\n    const casterState = new Map<any, ManagedCasterState>();\n    const activeFootprints: ManagedFootprint[] = [];\n    const freeFootprints: ManagedFootprint[] = [];\n\n    let accumulatorMs = 0;\n    let elapsedMs = 0;\n    let forceRefresh = true;\n    let tickSubscription: any = null;\n    let footprintTexture: Texture | null = null;\n\n    const ensureTexture = (): Texture | null => {\n      if (footprintTexture && !footprintTexture.destroyed) return footprintTexture;\n      const renderer = resolveRenderer(context);\n      if (!renderer) return null;\n      footprintTexture = createFootprintTexture(renderer);\n      return footprintTexture;\n    };\n\n    const releaseFootprint = (managed: ManagedFootprint) => {\n      const sprites = [managed.baseSprite, managed.depthSprite, managed.rimSprite];\n      for (let i = 0; i < sprites.length; i++) {\n        const sprite = sprites[i];\n        sprite.visible = false;\n        sprite.alpha = 0;\n        if (sprite.parent) {\n          sprite.parent.removeChild(sprite);\n        }\n      }\n      freeFootprints.push(managed);\n    };\n\n    const destroyFootprint = (managed: ManagedFootprint) => {\n      const sprites = [managed.baseSprite, managed.depthSprite, managed.rimSprite];\n      for (let i = 0; i < sprites.length; i++) {\n        const sprite = sprites[i];\n        if (sprite.parent) {\n          sprite.parent.removeChild(sprite);\n        }\n        sprite.destroy();\n      }\n    };\n\n    const acquireFootprint = (texture: Texture): ManagedFootprint => {\n      let managed = freeFootprints.pop();\n      if (!managed) {\n        const baseSprite = new PixiSprite(texture);\n        const depthSprite = new PixiSprite(texture);\n        const rimSprite = new PixiSprite(texture);\n\n        const baseBlurFilter = new BlurFilter({ strength: 0, quality: 1 });\n        const depthBlurFilter = new BlurFilter({ strength: 0, quality: 1 });\n        const rimBlurFilter = new BlurFilter({ strength: 0, quality: 1 });\n\n        const sprites = [baseSprite, depthSprite, rimSprite];\n        for (let i = 0; i < sprites.length; i++) {\n          const sprite = sprites[i];\n          sprite.anchor.set(0.5, 0.84);\n          sprite.roundPixels = true;\n          sprite.eventMode = \"none\";\n          sprite.visible = false;\n          (sprite as any)[FOOTPRINT_MANAGED_MARK] = true;\n        }\n\n        baseSprite.filters = [baseBlurFilter];\n        depthSprite.filters = [depthBlurFilter];\n        rimSprite.filters = [rimBlurFilter];\n        depthSprite.blendMode = \"multiply\" as any;\n        rimSprite.blendMode = \"screen\" as any;\n\n        managed = {\n          baseSprite,\n          depthSprite,\n          rimSprite,\n          baseBlurFilter,\n          depthBlurFilter,\n          rimBlurFilter,\n          bornAt: 0,\n          lifetimeMs: BASE_PROFILE.lifetimeMs,\n          startAlpha: BASE_PROFILE.startAlpha,\n          endAlpha: BASE_PROFILE.endAlpha,\n          baseScaleX: 1,\n          baseScaleY: 1,\n          blurStart: BASE_PROFILE.blurStart,\n          blurEnd: BASE_PROFILE.blurEnd,\n          erosionStart: BASE_PROFILE.erosionStart,\n          depth: BASE_PROFILE.depth,\n          rimStrength: BASE_PROFILE.rimStrength,\n        };\n      } else {\n        managed.baseSprite.texture = texture;\n        managed.depthSprite.texture = texture;\n        managed.rimSprite.texture = texture;\n      }\n\n      return managed;\n    };\n\n    const trimOverflow = (maxFootprints: number) => {\n      while (activeFootprints.length > maxFootprints) {\n        const oldest = activeFootprints.shift();\n        if (!oldest) break;\n        releaseFootprint(oldest);\n      }\n    };\n\n    const updateActiveFootprints = (nowMs: number) => {\n      for (let i = activeFootprints.length - 1; i >= 0; i--) {\n        const managed = activeFootprints[i];\n        const baseSprite = managed.baseSprite;\n        const depthSprite = managed.depthSprite;\n        const rimSprite = managed.rimSprite;\n\n        if (\n          !baseSprite ||\n          !depthSprite ||\n          !rimSprite ||\n          baseSprite.destroyed ||\n          depthSprite.destroyed ||\n          rimSprite.destroyed\n        ) {\n          activeFootprints.splice(i, 1);\n          continue;\n        }\n\n        const t = clamp((nowMs - managed.bornAt) / Math.max(1, managed.lifetimeMs), 0, 1);\n        const fade = 1 - smoothstep(0, 1, t);\n        const erosion =\n          t <= managed.erosionStart ? 1 : 1 - smoothstep(managed.erosionStart, 1, t);\n        const alpha = clamp(lerp(managed.startAlpha, managed.endAlpha, t) * fade * erosion, 0, 1.5);\n\n        if (t >= 1 || alpha <= 0.001) {\n          activeFootprints.splice(i, 1);\n          releaseFootprint(managed);\n          continue;\n        }\n\n        const spread = 1 + t * 0.08;\n        const depthSpread = 1 + t * 0.05;\n        const rimSpread = 1 + t * 0.12;\n        const depthScaleMul = 0.78 - managed.depth * 0.1;\n        const rimScaleMul = 1.05 + managed.depth * 0.12;\n\n        baseSprite.scale.set(managed.baseScaleX * spread, managed.baseScaleY * spread);\n        depthSprite.scale.set(\n          managed.baseScaleX * depthScaleMul * depthSpread,\n          managed.baseScaleY * depthScaleMul * depthSpread\n        );\n        rimSprite.scale.set(\n          managed.baseScaleX * rimScaleMul * rimSpread,\n          managed.baseScaleY * rimScaleMul * rimSpread\n        );\n\n        baseSprite.alpha = alpha;\n        depthSprite.alpha = clamp(alpha * (0.58 + managed.depth * 0.34), 0, 1.2);\n        rimSprite.alpha = clamp(alpha * managed.rimStrength, 0, 0.65);\n\n        managed.baseBlurFilter.strength = lerp(managed.blurStart, managed.blurEnd, t);\n        managed.depthBlurFilter.strength = lerp(\n          managed.blurStart * (0.45 + (1 - managed.depth) * 0.25),\n          managed.blurEnd * (0.72 + (1 - managed.depth) * 0.22),\n          t\n        );\n        managed.rimBlurFilter.strength = lerp(\n          managed.blurStart * 0.8,\n          managed.blurEnd * (1.28 + managed.depth * 0.24),\n          t\n        );\n\n        baseSprite.visible = true;\n        depthSprite.visible = true;\n        rimSprite.visible = rimSprite.alpha > 0.001;\n      }\n    };\n\n    const emitFootprint = (\n      casterInstance: any,\n      casterConfig: ResolvedCaster,\n      state: ManagedCasterState,\n      profile: ResolvedSurfaceProfile,\n      nowMs: number,\n      maxFootprints: number\n    ) => {\n      const texture = ensureTexture();\n      const parent = casterInstance.parent as PixiContainer | null;\n      if (!texture || !parent || parent.destroyed) return;\n\n      const basePoint = resolveCasterBasePoint(casterInstance, parent, casterConfig);\n      const offset = state.nextFoot === \"left\" ? casterConfig.leftOffset : casterConfig.rightOffset;\n\n      const heading = state.heading;\n      const rightX = -Math.sin(heading);\n      const rightY = Math.cos(heading);\n      const forwardX = Math.cos(heading);\n      const forwardY = Math.sin(heading);\n\n      const x = basePoint.x + rightX * offset.x + forwardX * offset.y;\n      const y = basePoint.y + rightY * offset.x + forwardY * offset.y;\n\n      const managed = acquireFootprint(texture);\n      const sprites = [managed.rimSprite, managed.baseSprite, managed.depthSprite];\n      for (let i = 0; i < sprites.length; i++) {\n        const sprite = sprites[i];\n        if (sprite.parent && sprite.parent !== parent) {\n          sprite.parent.removeChild(sprite);\n        }\n        if (!sprite.parent) {\n          parent.addChild(sprite);\n        }\n      }\n\n      const jitterRad = degToRad(casterConfig.jitter);\n      const randomJitter = (Math.random() * 2 - 1) * jitterRad;\n      const angleOffsetRad = degToRad(casterConfig.angleOffset);\n      const rotation = heading - Math.PI / 2 + angleOffsetRad + randomJitter;\n      const profileScale = profile.scale * casterConfig.size;\n      const scaleX = (state.nextFoot === \"left\" ? 1 : -1) * Math.max(0.01, profileScale);\n      const scaleY = Math.max(0.01, profileScale);\n      const baseAlpha = clamp(profile.startAlpha * casterConfig.alpha, 0, 1.5);\n      const depthTint = darkenColor(profile.tint, 0.38 + profile.depth * 0.26);\n      const rimTint = lightenColor(profile.tint, 0.22 + profile.depth * 0.38);\n\n      managed.baseSprite.position.set(x, y);\n      managed.depthSprite.position.set(x, y);\n      managed.rimSprite.position.set(x, y);\n      managed.baseSprite.rotation = rotation;\n      managed.depthSprite.rotation = rotation;\n      managed.rimSprite.rotation = rotation;\n      managed.baseSprite.scale.set(scaleX, scaleY);\n      managed.depthSprite.scale.set(scaleX * 0.82, scaleY * 0.82);\n      managed.rimSprite.scale.set(scaleX * 1.08, scaleY * 1.08);\n      managed.baseSprite.tint = profile.tint;\n      managed.depthSprite.tint = depthTint;\n      managed.rimSprite.tint = rimTint;\n      managed.baseSprite.blendMode = profile.blendMode as any;\n      managed.baseSprite.alpha = baseAlpha;\n      managed.depthSprite.alpha = clamp(baseAlpha * (0.58 + profile.depth * 0.34), 0, 1.2);\n      managed.rimSprite.alpha = clamp(baseAlpha * profile.rimStrength, 0, 0.65);\n      managed.baseSprite.visible = true;\n      managed.depthSprite.visible = true;\n      managed.rimSprite.visible = managed.rimSprite.alpha > 0.001;\n\n      placeBelowCaster(managed, casterInstance, parent);\n\n      managed.bornAt = nowMs;\n      managed.lifetimeMs = profile.lifetimeMs;\n      managed.startAlpha = baseAlpha;\n      managed.endAlpha = clamp(profile.endAlpha * casterConfig.alpha, 0, 1.5);\n      managed.baseScaleX = scaleX;\n      managed.baseScaleY = scaleY;\n      managed.blurStart = Math.max(0, profile.blurStart + casterConfig.blur);\n      managed.blurEnd = Math.max(managed.blurStart, profile.blurEnd + casterConfig.blur);\n      managed.depth = profile.depth;\n      managed.rimStrength = profile.rimStrength;\n      managed.erosionStart = clamp(\n        profile.erosionStart + (Math.random() * 2 - 1) * 0.11,\n        0.05,\n        0.95\n      );\n      managed.baseBlurFilter.strength = managed.blurStart;\n      managed.depthBlurFilter.strength = managed.blurStart * (0.45 + (1 - profile.depth) * 0.25);\n      managed.rimBlurFilter.strength = managed.blurStart * 0.8;\n\n      activeFootprints.push(managed);\n      trimOverflow(maxFootprints);\n\n      state.nextFoot = toggleFoot(state.nextFoot);\n      state.lastStepMs = nowMs;\n      state.distanceSinceStep = Math.max(0, state.distanceSinceStep - casterConfig.minStepDistance);\n    };\n\n    const sync = (nowMs: number) => {\n      const defaultSurfaceRaw = resolveReactiveValue(props.defaultSurface as ReactiveValue<string> | undefined);\n      const defaultSurface =\n        typeof defaultSurfaceRaw === \"string\" && defaultSurfaceRaw.trim().length > 0\n          ? defaultSurfaceRaw.trim()\n          : DEFAULT_SURFACE;\n\n      const profileMap = resolveProfilesMap(\n        props.profiles as ReactiveValue<Record<string, FootprintSurfaceProfile>> | undefined\n      );\n\n      const maxFootprintsRaw = Number(\n        resolveReactiveValue(props.maxFootprints as ReactiveValue<number> | undefined)\n      );\n      const maxFootprints = clamp(\n        isFiniteNumber(maxFootprintsRaw) ? maxFootprintsRaw : DEFAULT_MAX_FOOTPRINTS,\n        10,\n        1200\n      );\n\n      const casters = collectFootprintCasters(target, defaultSurface);\n      const activeCasters = new Set<any>();\n\n      for (let i = 0; i < casters.length; i++) {\n        const { instance: casterInstance, caster } = casters[i];\n        if (!casterInstance || casterInstance.destroyed || !casterInstance.parent) continue;\n\n        activeCasters.add(casterInstance);\n\n        let state = casterState.get(casterInstance);\n        if (!state) {\n          state = {\n            lastPoint: null,\n            lastUpdateMs: nowMs,\n            distanceSinceStep: 0,\n            lastStepMs: -Infinity,\n            nextFoot: \"left\",\n            heading: Number(casterInstance.rotation) || 0,\n          };\n          casterState.set(casterInstance, state);\n        }\n\n        const parent = casterInstance.parent as PixiContainer;\n        const basePoint = resolveCasterBasePoint(casterInstance, parent, caster);\n\n        if (!state.lastPoint) {\n          state.lastPoint = basePoint;\n          state.lastUpdateMs = nowMs;\n          continue;\n        }\n\n        const deltaMs = Math.max(1, nowMs - state.lastUpdateMs);\n        const dx = basePoint.x - state.lastPoint.x;\n        const dy = basePoint.y - state.lastPoint.y;\n        const distance = Math.hypot(dx, dy);\n\n        if (distance > 0.0001) {\n          state.heading = Math.atan2(dy, dx);\n        }\n\n        state.distanceSinceStep += distance;\n        const speed = (distance * 1000) / deltaMs;\n        const profile = profileMap[caster.surface] ?? profileMap[defaultSurface] ?? BASE_PROFILE;\n\n        if (\n          speed >= caster.minSpeed &&\n          state.distanceSinceStep >= caster.minStepDistance &&\n          nowMs - state.lastStepMs >= caster.stepIntervalMs\n        ) {\n          emitFootprint(casterInstance, caster, state, profile, nowMs, maxFootprints);\n        }\n\n        state.lastPoint = basePoint;\n        state.lastUpdateMs = nowMs;\n      }\n\n      for (const [casterInstance] of casterState.entries()) {\n        if (!activeCasters.has(casterInstance) || casterInstance?.destroyed) {\n          casterState.delete(casterInstance);\n        }\n      }\n\n      updateActiveFootprints(nowMs);\n    };\n\n    tickSubscription = tickSignal?.observable?.subscribe((tickArgs: any) => {\n      const tickValue = tickArgs?.value ?? tickArgs;\n      const deltaTime = Number(tickValue?.deltaTime);\n      const frameMs = isFiniteNumber(deltaTime) ? deltaTime : 16.67;\n\n      elapsedMs += frameMs;\n      accumulatorMs += frameMs;\n\n      const updateHzRaw = Number(resolveReactiveValue(props.updateHz as ReactiveValue<number> | undefined));\n      const updateHz = clamp(isFiniteNumber(updateHzRaw) ? updateHzRaw : DEFAULT_UPDATE_HZ, 1, 120);\n      const intervalMs = 1000 / updateHz;\n\n      if (forceRefresh || accumulatorMs >= intervalMs) {\n        accumulatorMs = 0;\n        forceRefresh = false;\n        sync(elapsedMs);\n      }\n    });\n\n    sync(0);\n\n    return () => {\n      tickSubscription?.unsubscribe?.();\n\n      for (let i = 0; i < activeFootprints.length; i++) {\n        destroyFootprint(activeFootprints[i]);\n      }\n      for (let i = 0; i < freeFootprints.length; i++) {\n        destroyFootprint(freeFootprints[i]);\n      }\n\n      activeFootprints.length = 0;\n      freeFootprints.length = 0;\n      casterState.clear();\n\n      if (footprintTexture && !footprintTexture.destroyed) {\n        footprintTexture.destroy(true);\n      }\n      footprintTexture = null;\n    };\n  });\n\n  return h(Container);\n}\n"
  },
  {
    "path": "packages/presets/src/Loading.ts",
    "content": "import { Graphics, Container, h, useProps, tick, signal, effect, mount } from \"canvasengine\";\nimport * as PIXI from \"pixi.js\";\n\n/**\n * Loading Component Props\n */\nexport interface LoadingProps {\n  /**\n   * Size of the loading spinner (radius in pixels)\n   * @default 30\n   */\n  size?: number;\n  /**\n   * Color of the spinner segments\n   * @default \"#3498db\"\n   */\n  color?: string;\n  /**\n   * Background color of the spinner (optional)\n   */\n  backgroundColor?: string;\n  /**\n   * Rotation speed in degrees per second\n   * @default 180\n   */\n  speed?: number;\n  /**\n   * Number of segments in the spinner\n   * @default 8\n   */\n  segments?: number;\n  /**\n   * Width of each segment\n   * @default 3\n   */\n  segmentWidth?: number;\n  /**\n   * Alpha value for inactive segments (0-1)\n   * @default 0.15\n   */\n  inactiveAlpha?: number;\n}\n\n/**\n * Loading Component\n * \n * Creates an animated circular loading spinner with customizable appearance and rotation speed.\n * The spinner consists of multiple segments that rotate continuously, creating a smooth loading indicator.\n * \n * ## Design\n * \n * The component uses a Graphics element to draw multiple segments arranged in a circle:\n * - **Segments**: Multiple radial segments that create a circular pattern\n * - **Rotation animation**: Continuous rotation using the tick system for smooth animation\n * - **Alpha variation**: Active segments are fully opaque while inactive segments have reduced opacity\n * - **Customizable**: Size, color, speed, and number of segments can be adjusted\n * \n * @param {LoadingProps} opts - Configuration options for the loading spinner\n * \n * @example\n * ```tsx\n * // Basic usage with default settings\n * <Loading />\n * \n * // Custom size and color\n * <Loading \n *   size={50}\n *   color=\"#e74c3c\"\n * />\n * \n * // Fast spinning loader\n * <Loading \n *   speed={360}\n *   segments={12}\n * />\n * \n * // Large loader with background\n * <Loading \n *   size={80}\n *   color=\"#2ecc71\"\n *   backgroundColor=\"#ecf0f1\"\n *   segmentWidth={5}\n * />\n * \n * // Using signals for dynamic control\n * const loaderSize = signal(30);\n * const loaderSpeed = signal(180);\n * \n * <Loading \n *   size={loaderSize}\n *   speed={loaderSpeed}\n * />\n * ```\n * \n * @returns {JSX.Element} A container with an animated loading spinner\n */\nexport function Loading(opts: LoadingProps = {}) {\n  const {\n    size = 30,\n    color = \"#3498db\",\n    backgroundColor,\n    speed = 180,\n    segments = 8,\n    segmentWidth = 3,\n    inactiveAlpha = 0.15,\n  } = useProps(opts, {\n    size: 30,\n    color: \"#3498db\",\n    speed: 180,\n    segments: 8,\n    segmentWidth: 3,\n    inactiveAlpha: 0.15,\n  });\n\n  const rotation = signal(0);\n\n  // Animation loop using tick\n  tick(({ deltaTime }) => {\n    const speedValue = typeof speed === \"function\" ? speed() : speed;\n    const rotationIncrement = (speedValue * deltaTime) / 1000;\n    rotation.set(rotation() + rotationIncrement);\n  });\n\n  const draw = (graphics: PIXI.Graphics) => {\n    const sizeValue = typeof size === \"function\" ? size() : size;\n    const colorValue = typeof color === \"function\" ? color() : color;\n    const backgroundColorValue = backgroundColor\n      ? typeof backgroundColor === \"function\"\n        ? backgroundColor()\n        : backgroundColor\n      : null;\n    const segmentsValue = typeof segments === \"function\" ? segments() : segments;\n    const segmentWidthValue =\n      typeof segmentWidth === \"function\" ? segmentWidth() : segmentWidth;\n    const inactiveAlphaValue =\n      typeof inactiveAlpha === \"function\" ? inactiveAlpha() : inactiveAlpha;\n    const rotationValue = rotation();\n\n    // Draw background circle if specified\n    if (backgroundColorValue) {\n      graphics.circle(0, 0, sizeValue).fill(backgroundColorValue);\n    }\n\n    // Draw spinner segments with fade effect\n    const angleStep = 360 / segmentsValue;\n    const innerRadius = sizeValue * 0.4; // Inner radius of the spinner\n    const outerRadius = sizeValue; // Outer radius of the spinner\n\n    for (let i = 0; i < segmentsValue; i++) {\n      const segmentBaseAngle = i * angleStep;\n      \n      // Calculate opacity based on how close this segment is to the rotation point\n      // The rotation point acts as the \"bright spot\" that fades out\n      const normalizedRotation = ((rotationValue % 360) + 360) % 360;\n      let angleDiff = Math.abs(normalizedRotation - segmentBaseAngle);\n      \n      // Handle wrap-around (shorter distance)\n      if (angleDiff > 180) {\n        angleDiff = 360 - angleDiff;\n      }\n      \n      // Create distinct fade effect: segments near rotation point are bright,\n      // fading out quickly for more contrast\n      const fadeRange = 120; // Reduced range for sharper fade\n      let fadeProgress = angleDiff / fadeRange;\n      \n      // Apply stronger easing for more distinct opacity difference (cubic ease-out)\n      fadeProgress = Math.min(1, fadeProgress);\n      fadeProgress = fadeProgress * fadeProgress * fadeProgress; // Cubic easing for sharper contrast\n      \n      const opacity = inactiveAlphaValue + (1 - fadeProgress) * (1 - inactiveAlphaValue);\n\n      // Draw segment at fixed position (not rotating with the spinner)\n      const angle = segmentBaseAngle * (Math.PI / 180);\n      const segmentAngle = angleStep * (Math.PI / 180);\n      const startAngle = angle - segmentAngle / 2;\n      const endAngle = angle + segmentAngle / 2;\n\n      // Draw segment from inner to outer radius\n      graphics\n        .arc(0, 0, innerRadius, startAngle, endAngle)\n        .arc(0, 0, outerRadius, endAngle, startAngle, true)\n        .fill({ color: colorValue, alpha: opacity });\n    }\n  };\n\n  // Calculate width and height based on size (diameter)\n  const sizeValue = typeof size === \"function\" ? size() : size;\n  const diameter = sizeValue * 2;\n  const widthSignal = typeof size === \"function\" \n    ? signal(diameter)\n    : signal(diameter);\n  const heightSignal = typeof size === \"function\"\n    ? signal(diameter)\n    : signal(diameter);\n\n  // Update width/height when size changes\n  if (typeof size === \"function\") {\n    effect(() => {\n      const s = size();\n      widthSignal.set(s * 2);\n      heightSignal.set(s * 2);\n    });\n  }\n\n  return h(Container, opts as any, [\n    h(Graphics, {\n      draw\n    }),\n  ]);\n}\n"
  },
  {
    "path": "packages/presets/src/NightAmbiant.ts",
    "content": "import { Filter } from \"pixi.js\";\nimport { Container, effect, h, mount, useProps } from \"canvasengine\";\nimport fragmentShader from './shaders/nightSpot.frag.glsl?raw';\nimport vertexShader from './shaders/defaultFilter.vert.glsl?raw';\n\nconst MAX_SPOTS = 24;\nconst SPOT_RADIUS_PX = 180;\n/** Darkness outside the spot (0 = no darkening, 1 = black). */\nconst DARKNESS = 0.75;\n/** Fog: distance from player (0-1) where fog starts. */\nconst FOG_RADIUS = 0.5;\n/** Fog: width of the fog transition (smoothstep). */\nconst FOG_SOFTNESS = 0.35;\n/** Fog color (RGB, linear 0-1). Dark blue-gray for night. */\nconst FOG_COLOR = new Float32Array([0.08, 0.08, 0.14]);\n\ntype PointLike = { x: number; y: number };\ntype BoundsLike = { x: number; y: number; width: number; height: number };\ntype ScreenPointLike = { x: number; y: number };\ntype ReactiveValue<T> = T | (() => T);\ntype ViewportLike = {\n  getVisibleBounds?: () => BoundsLike | null | undefined;\n  toScreen?: (x: number, y: number) => ScreenPointLike;\n};\nexport type NightSpot = PointLike & {\n  radius?: number;\n  intensity?: number;\n  flicker?: boolean;\n  flickerSpeed?: number;\n  pulse?: boolean;\n  pulseSpeed?: number;\n  phase?: number;\n};\n\nexport type NightSpotInput = {\n  x: ReactiveValue<number>;\n  y: ReactiveValue<number>;\n  radius?: ReactiveValue<number>;\n  intensity?: ReactiveValue<number>;\n  flicker?: ReactiveValue<boolean>;\n  flickerSpeed?: ReactiveValue<number>;\n  pulse?: ReactiveValue<boolean>;\n  pulseSpeed?: ReactiveValue<number>;\n  phase?: ReactiveValue<number>;\n};\n\n/**\n * Color input type supporting hex string, number, or RGB array.\n * \n * @example\n * ```ts\n * // Hex string\n * const color1: ColorInput = \"#0a1020\";\n * // Number\n * const color2: ColorInput = 0x0a1020;\n * // RGB tuple (0-255)\n * const color3: ColorInput = [10, 16, 32];\n * // Normalized RGB (0-1)\n * const color4: ColorInput = [0.04, 0.06, 0.12];\n * ```\n */\nexport type ColorInput = string | number | [number, number, number];\n\nexport type NightAmbiantProps = {\n  /** Main reactive list of light spots. */\n  lightSpots?: ReactiveValue<Array<NightSpotInput | NightSpot>>;\n  /** Alias for `lightSpots` for compatibility. */\n  spots?: ReactiveValue<Array<NightSpotInput | NightSpot>>;\n  /** Darkness intensity outside light spots (0 = no darkening, 1 = full black). Default: 0.75 */\n  darkness?: ReactiveValue<number>;\n  /** Tint color applied in dark zones. Default: \"#000000\" */\n  darkColor?: ReactiveValue<ColorInput>;\n  /** Fog color around light spots. Default: \"#141424\" */\n  fogColor?: ReactiveValue<ColorInput>;\n  /** Distance from light center where fog starts (0-1). Default: 0.5 */\n  fogRadius?: ReactiveValue<number>;\n  /** Width of the fog transition. Default: 0.35 */\n  fogSoftness?: ReactiveValue<number>;\n};\n\nexport type NightFilter = Filter & {\n  setLightWorldPosition: (position: PointLike | null) => void;\n  getLightWorldPosition: () => PointLike | null;\n  setSpots: (spots: NightSpot[]) => void;\n  getSpots: () => NightSpot[];\n  syncLightToViewport: () => void;\n  setDarkness: (value: number) => void;\n  setDarkColor: (color: ColorInput) => void;\n  setFogColor: (color: ColorInput) => void;\n  setFogRadius: (value: number) => void;\n  setFogSoftness: (value: number) => void;\n};\n\n/**\n * Parses a color input (hex string, number, or RGB array) into a normalized Float32Array [r, g, b].\n * \n * @param color - The color input to parse\n * @returns A Float32Array with normalized RGB values (0-1)\n * \n * @example\n * ```ts\n * parseColor(\"#ff0000\");      // Float32Array [1, 0, 0]\n * parseColor(0x00ff00);       // Float32Array [0, 1, 0]\n * parseColor([0, 0, 255]);    // Float32Array [0, 0, 1]\n * parseColor([0.5, 0.5, 0.5]); // Float32Array [0.5, 0.5, 0.5]\n * ```\n */\nconst parseColor = (color: ColorInput): Float32Array => {\n  if (typeof color === \"string\") {\n    // Parse hex string (#RGB, #RRGGBB)\n    let hex = color.replace(/^#/, \"\");\n    if (hex.length === 3) {\n      hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];\n    }\n    const num = parseInt(hex, 16);\n    return new Float32Array([\n      ((num >> 16) & 0xff) / 255,\n      ((num >> 8) & 0xff) / 255,\n      (num & 0xff) / 255,\n    ]);\n  }\n  if (typeof color === \"number\") {\n    return new Float32Array([\n      ((color >> 16) & 0xff) / 255,\n      ((color >> 8) & 0xff) / 255,\n      (color & 0xff) / 255,\n    ]);\n  }\n  if (Array.isArray(color) && color.length >= 3) {\n    // If values are > 1, assume 0-255 range\n    const isNormalized = color.every((c) => c <= 1);\n    return new Float32Array(\n      isNormalized ? color : color.map((c) => c / 255)\n    );\n  }\n  return new Float32Array([0, 0, 0]);\n};\n\n/**\n * Creates a night filter with configurable light spots, darkness, and fog effects.\n * \n * The filter renders a dark overlay with circular light spots that illuminate areas.\n * It supports multiple spots with individual intensity, radius, flicker, and pulse effects.\n * \n * @param viewport - Optional viewport for world-to-screen coordinate conversion\n * @param options - Configuration options for the filter\n * @returns A NightFilter instance with methods to control the effect\n * \n * @example\n * ```ts\n * const filter = createNightFilter(viewport, {\n *   spots: [{ x: 100, y: 100, radius: 200, intensity: 1.0 }],\n *   darkness: 0.8,\n *   darkColor: \"#0a1020\",\n *   fogColor: \"#141a2a\",\n * });\n * container.filters = [filter];\n * ```\n */\nexport function createNightFilter(\n  viewport?: ViewportLike,\n  options?: {\n    lightWorldPosition?: PointLike | null;\n    spots?: NightSpot[];\n    getBounds?: () => BoundsLike | null | undefined;\n    darkness?: number;\n    darkColor?: ColorInput;\n    fogColor?: ColorInput;\n    fogRadius?: number;\n    fogSoftness?: number;\n  }\n): NightFilter {\n  const uSpots = new Float32Array(MAX_SPOTS * 4);\n  const uSpotsUniform = { value: uSpots, type: 'vec4<f32>' as const, size: MAX_SPOTS };\n  const uDarkness = { value: options?.darkness ?? DARKNESS, type: 'f32' as const };\n  const uFogColor = { value: options?.fogColor ? parseColor(options.fogColor) : FOG_COLOR, type: 'vec3<f32>' as const };\n  const uFogRadius = { value: options?.fogRadius ?? FOG_RADIUS, type: 'f32' as const };\n  const uFogSoftness = { value: options?.fogSoftness ?? FOG_SOFTNESS, type: 'f32' as const };\n  const uDarkColor = { value: options?.darkColor ? parseColor(options.darkColor) : new Float32Array([0, 0, 0]), type: 'vec3<f32>' as const };\n  \n  let customSpots: NightSpot[] = options?.spots ? [...options.spots] : [];\n  let lightWorldPosition: PointLike | null = options?.lightWorldPosition ?? null;\n\n  const nightFilter = Filter.from({\n    gl: {\n      vertex: vertexShader,\n      fragment: fragmentShader,\n    },\n    resources: {\n      nightUniforms: {\n        uSpots: uSpotsUniform,\n        uDarkness,\n        uDarkColor,\n        uFogColor,\n        uFogRadius,\n        uFogSoftness,\n      },\n    },\n  });\n\n  const clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n  const nowSeconds = () => Date.now() / 1000;\n\n  const getActiveSpots = (): NightSpot[] => {\n    if (!lightWorldPosition) return customSpots;\n    return [{ x: lightWorldPosition.x, y: lightWorldPosition.y }, ...customSpots];\n  };\n\n  const syncLightToViewport = () => {\n    const activeSpots = getActiveSpots();\n    const spotCount = Math.min(activeSpots.length, MAX_SPOTS);\n    const bounds = viewport?.getVisibleBounds?.() ?? options?.getBounds?.();\n    const hasBounds = !!bounds && bounds.width > 0 && bounds.height > 0;\n    const toScreen = viewport?.toScreen?.bind(viewport);\n    const canUseViewportScreen = hasBounds && typeof toScreen === \"function\";\n    let viewportOriginX = 0;\n    let viewportOriginY = 0;\n    if (canUseViewportScreen) {\n      const origin = toScreen(bounds.x, bounds.y);\n      if (isFiniteNumber(origin?.x) && isFiniteNumber(origin?.y)) {\n        viewportOriginX = origin.x;\n        viewportOriginY = origin.y;\n      }\n    }\n    const time = nowSeconds();\n\n    uSpots.fill(0);\n    for (let i = 0; i < spotCount; i++) {\n      const spot = activeSpots[i];\n      const radiusPx = spot.radius ?? SPOT_RADIUS_PX;\n      const intensityBase = clamp(spot.intensity ?? 1, 0, 2);\n      const phase = spot.phase ?? i * 0.7;\n      let intensity = intensityBase;\n\n      if (spot.flicker) {\n        const flickerSpeed = spot.flickerSpeed ?? 12;\n        intensity *= 0.88 + 0.12 * Math.sin(time * flickerSpeed + phase);\n      }\n      if (spot.pulse) {\n        const pulseSpeed = spot.pulseSpeed ?? 2;\n        intensity *= 0.8 + 0.2 * Math.sin(time * pulseSpeed + phase);\n      }\n\n      let x = spot.x;\n      let y = spot.y;\n      let radius = radiusPx;\n\n      if (canUseViewportScreen) {\n        const point = toScreen!(spot.x, spot.y);\n        x = point.x - viewportOriginX;\n        y = point.y - viewportOriginY;\n      } else if (hasBounds) {\n        x = spot.x - bounds.x;\n        y = spot.y - bounds.y;\n      }\n\n      const base = i * 4;\n      uSpots[base] = x;\n      uSpots[base + 1] = y;\n      uSpots[base + 2] = radius;\n      uSpots[base + 3] = clamp(intensity, 0, 2);\n    }\n\n    uSpotsUniform.value = uSpots;\n  };\n\n  const originalApply = nightFilter.apply.bind(nightFilter);\n  nightFilter.apply = ((...args: any[]) => {\n    // Keep the spot anchored in world space while the viewport moves/zooms.\n    syncLightToViewport();\n    return originalApply(...args);\n  }) as typeof nightFilter.apply;\n\n  const extendedFilter = nightFilter as NightFilter;\n  extendedFilter.setLightWorldPosition = (position: PointLike | null) => {\n    lightWorldPosition = position;\n    syncLightToViewport();\n  };\n  extendedFilter.getLightWorldPosition = () => lightWorldPosition;\n  extendedFilter.setSpots = (spots: NightSpot[]) => {\n    customSpots = [...spots];\n    syncLightToViewport();\n  };\n  extendedFilter.getSpots = () => getActiveSpots().map((spot) => ({ ...spot }));\n  extendedFilter.syncLightToViewport = syncLightToViewport;\n  extendedFilter.setDarkness = (value: number) => {\n    uDarkness.value = value;\n  };\n  extendedFilter.setDarkColor = (color: ColorInput) => {\n    uDarkColor.value = parseColor(color);\n  };\n  extendedFilter.setFogColor = (color: ColorInput) => {\n    uFogColor.value = parseColor(color);\n  };\n  extendedFilter.setFogRadius = (value: number) => {\n    uFogRadius.value = value;\n  };\n  extendedFilter.setFogSoftness = (value: number) => {\n    uFogSoftness.value = value;\n  };\n\n  syncLightToViewport();\n\n  return extendedFilter;\n}\n\nconst resolveReactiveValue = <T>(value: ReactiveValue<T> | undefined): T | undefined => {\n  if (typeof value === \"function\") return (value as () => T)();\n  return value;\n};\n\nconst isFiniteNumber = (value: unknown): value is number =>\n  typeof value === \"number\" && Number.isFinite(value);\n\nconst resolveSpot = (spot: NightSpotInput | NightSpot): NightSpot | null => {\n  const source = resolveReactiveValue(spot as ReactiveValue<NightSpotInput | NightSpot>);\n  if (!source) return null;\n\n  const x = resolveReactiveValue(source.x as ReactiveValue<number> | undefined);\n  const y = resolveReactiveValue(source.y as ReactiveValue<number> | undefined);\n  if (!isFiniteNumber(x) || !isFiniteNumber(y)) return null;\n\n  const radius = resolveReactiveValue(source.radius as ReactiveValue<number> | undefined);\n  const intensity = resolveReactiveValue(source.intensity as ReactiveValue<number> | undefined);\n  const flickerSpeed = resolveReactiveValue(source.flickerSpeed as ReactiveValue<number> | undefined);\n  const pulseSpeed = resolveReactiveValue(source.pulseSpeed as ReactiveValue<number> | undefined);\n  const phase = resolveReactiveValue(source.phase as ReactiveValue<number> | undefined);\n\n  return {\n    x,\n    y,\n    radius: isFiniteNumber(radius) ? radius : undefined,\n    intensity: isFiniteNumber(intensity) ? intensity : undefined,\n    flicker: !!resolveReactiveValue(source.flicker as ReactiveValue<boolean> | undefined),\n    flickerSpeed: isFiniteNumber(flickerSpeed) ? flickerSpeed : undefined,\n    pulse: !!resolveReactiveValue(source.pulse as ReactiveValue<boolean> | undefined),\n    pulseSpeed: isFiniteNumber(pulseSpeed) ? pulseSpeed : undefined,\n    phase: isFiniteNumber(phase) ? phase : undefined,\n  };\n};\n\nconst resolveSpots = (\n  spots: ReactiveValue<Array<NightSpotInput | NightSpot>> | undefined\n): NightSpot[] => {\n  const list = resolveReactiveValue(spots);\n  if (!Array.isArray(list)) return [];\n  return list.map(resolveSpot).filter((spot): spot is NightSpot => !!spot);\n};\n\nconst toBoundsLike = (target: any): BoundsLike | null => {\n  if (!target) return null;\n  if (typeof target.getVisibleBounds === \"function\") {\n    const bounds = target.getVisibleBounds();\n    if (bounds) return bounds;\n  }\n  if (typeof target.getLocalBounds === \"function\") {\n    const bounds = target.getLocalBounds();\n    if (bounds) return bounds;\n  }\n  if (isFiniteNumber(target.width) && isFiniteNumber(target.height)) {\n    return { x: 0, y: 0, width: target.width, height: target.height };\n  }\n  return null;\n};\n\n/**\n * Night ambiance component that adds a dark overlay with dynamic light spots.\n * \n * This component creates a night-time atmosphere with configurable darkness,\n * fog effects, and multiple light sources. It automatically attaches to a\n * Viewport if present in context, otherwise to the parent container.\n * \n * All props are reactive and support signal/function values.\n * \n * @param options - Configuration options for the night ambiance effect\n * \n * @example\n * ```html\n * <Viewport worldWidth={2048} worldHeight={2048} screen>\n *   <NightAmbiant\n *     lightSpots={lightSpots}\n *     darkness={0.8}\n *     darkColor=\"#0a1020\"\n *     fogColor=\"#141a2a\"\n *   />\n * </Viewport>\n * ```\n */\nexport function NightAmbiant(options: NightAmbiantProps = {}) {\n  const props = useProps(options);\n  const spotsSource = () =>\n    (props.lightSpots as ReactiveValue<Array<NightSpotInput | NightSpot>> | undefined) ??\n    (props.spots as ReactiveValue<Array<NightSpotInput | NightSpot>> | undefined);\n\n  mount((element) => {\n    const context = element.props.context;\n    const viewport = context?.viewport as ViewportLike | undefined;\n    const target: any = viewport ?? element.parent?.componentInstance;\n    if (!target) return;\n    const canvasSizeSignal = context?.canvasSize as (() => { width: number; height: number }) | undefined;\n\n    const resolveFilterBounds = (): BoundsLike | null => {\n      // Outside a Viewport, use the reactive canvas size to avoid stale fixed widths.\n      if (!viewport && typeof canvasSizeSignal === \"function\") {\n        const size = canvasSizeSignal();\n        if (size && isFiniteNumber(size.width) && isFiniteNumber(size.height) && size.width > 0 && size.height > 0) {\n          return { x: 0, y: 0, width: size.width, height: size.height };\n        }\n      }\n      return toBoundsLike(target);\n    };\n\n    // Resolve initial values for filter options\n    const initialDarkness = resolveReactiveValue(props.darkness as ReactiveValue<number> | undefined);\n    const initialDarkColor = resolveReactiveValue(props.darkColor as ReactiveValue<ColorInput> | undefined);\n    const initialFogColor = resolveReactiveValue(props.fogColor as ReactiveValue<ColorInput> | undefined);\n    const initialFogRadius = resolveReactiveValue(props.fogRadius as ReactiveValue<number> | undefined);\n    const initialFogSoftness = resolveReactiveValue(props.fogSoftness as ReactiveValue<number> | undefined);\n\n    const nightFilter = createNightFilter(viewport, {\n      spots: resolveSpots(spotsSource()),\n      getBounds: resolveFilterBounds,\n      darkness: isFiniteNumber(initialDarkness) ? initialDarkness : undefined,\n      darkColor: initialDarkColor ?? undefined,\n      fogColor: initialFogColor ?? undefined,\n      fogRadius: isFiniteNumber(initialFogRadius) ? initialFogRadius : undefined,\n      fogSoftness: isFiniteNumber(initialFogSoftness) ? initialFogSoftness : undefined,\n    });\n\n    const currentFilters = Array.isArray(target.filters) ? target.filters : [];\n    if (!currentFilters.includes(nightFilter)) {\n      target.filters = [...currentFilters, nightFilter];\n    }\n\n    // Reactive effect for spots\n    effect(() => {\n      nightFilter.setSpots(resolveSpots(spotsSource()));\n    });\n\n    // Reactive effect for darkness\n    effect(() => {\n      const value = resolveReactiveValue(props.darkness as ReactiveValue<number> | undefined);\n      if (isFiniteNumber(value)) {\n        nightFilter.setDarkness(value);\n      }\n    });\n\n    // Reactive effect for dark color\n    effect(() => {\n      const value = resolveReactiveValue(props.darkColor as ReactiveValue<ColorInput> | undefined);\n      if (value !== undefined) {\n        nightFilter.setDarkColor(value);\n      }\n    });\n\n    // Reactive effect for fog color\n    effect(() => {\n      const value = resolveReactiveValue(props.fogColor as ReactiveValue<ColorInput> | undefined);\n      if (value !== undefined) {\n        nightFilter.setFogColor(value);\n      }\n    });\n\n    // Reactive effect for fog radius\n    effect(() => {\n      const value = resolveReactiveValue(props.fogRadius as ReactiveValue<number> | undefined);\n      if (isFiniteNumber(value)) {\n        nightFilter.setFogRadius(value);\n      }\n    });\n\n    // Reactive effect for fog softness\n    effect(() => {\n      const value = resolveReactiveValue(props.fogSoftness as ReactiveValue<number> | undefined);\n      if (isFiniteNumber(value)) {\n        nightFilter.setFogSoftness(value);\n      }\n    });\n\n    return () => {\n      const filters = Array.isArray(target.filters) ? target.filters : [];\n      const nextFilters = filters.filter((filter) => filter !== nightFilter);\n      target.filters = nextFilters.length > 0 ? nextFilters : null;\n    };\n  });\n\n  return h(Container);\n}\n"
  },
  {
    "path": "packages/presets/src/Particle.ts",
    "content": "import { Fx } from \"./fx\";\n\nexport function Particle(options) {\n  const { emit, ...props } = options;\n  return Fx({\n    ...props,\n    trigger: props.trigger ?? emit,\n  });\n}\n"
  },
  {
    "path": "packages/presets/src/SpriteShadows.ts",
    "content": "import { Container, h, mount, useProps } from \"canvasengine\";\nimport {\n  BlurFilter,\n  Container as PixiContainer,\n  Filter,\n  Sprite as PixiSprite,\n} from \"pixi.js\";\nimport fragmentShader from \"./shaders/shadowGradient.frag.glsl?raw\";\nimport vertexShader from \"./shaders/defaultFilter.vert.glsl?raw\";\n\ntype ReactiveValue<T> = T | (() => T);\ntype PointLike = { x: number; y: number };\ntype ColorInput = string | number;\n\nexport type ShadowLight = {\n  x: number;\n  y: number;\n  z?: number;\n  radius?: number;\n  intensity?: number;\n  shadowWeight?: number;\n  enabled?: boolean;\n};\n\nexport type ShadowLightInput = {\n  x: ReactiveValue<number>;\n  y: ReactiveValue<number>;\n  z?: ReactiveValue<number>;\n  radius?: ReactiveValue<number>;\n  intensity?: ReactiveValue<number>;\n  shadowWeight?: ReactiveValue<number>;\n  enabled?: ReactiveValue<boolean>;\n};\n\nexport type ShadowCasterOptions = {\n  enabled?: ReactiveValue<boolean>;\n  height?: ReactiveValue<number>;\n  footOffset?: ReactiveValue<PointLike>;\n  footAnchor?: ReactiveValue<PointLike>;\n  alpha?: ReactiveValue<number>;\n  blur?: ReactiveValue<number>;\n  gradientPower?: ReactiveValue<number>;\n  hardness?: ReactiveValue<number>;\n  minLength?: ReactiveValue<number>;\n  maxLength?: ReactiveValue<number>;\n  contactAlpha?: ReactiveValue<number>;\n  contactScale?: ReactiveValue<number>;\n  anchorX?: ReactiveValue<number>;\n};\n\ntype ShadowMode = \"strongest\" | \"blend2\";\n\nexport type SpriteShadowsProps = {\n  lights?: ReactiveValue<Array<ShadowLightInput | ShadowLight>>;\n  sources?: ReactiveValue<Array<ShadowLightInput | ShadowLight>>;\n  mode?: ReactiveValue<ShadowMode>;\n  updateHz?: ReactiveValue<number>;\n  shadowColor?: ReactiveValue<ColorInput>;\n};\n\ntype ResolvedCaster = {\n  height: number;\n  footOffset: PointLike;\n  footAnchor: PointLike;\n  alpha: number;\n  blur: number;\n  gradientPower: number;\n  hardness: number;\n  minLength: number;\n  maxLength: number;\n  contactAlpha: number;\n  contactScale: number;\n  anchorX?: number;\n};\n\ntype ResolvedLight = {\n  x: number;\n  y: number;\n  globalX: number;\n  globalY: number;\n  z: number;\n  radius: number;\n  intensity: number;\n  shadowWeight: number;\n};\n\ntype LightCandidate = {\n  dirX: number;\n  dirY: number;\n  influence: number;\n  length: number;\n};\n\ntype GradientFilter = Filter & {\n  setGradient: (power: number, floor: number) => void;\n};\n\ntype ManagedShadow = {\n  caster: any;\n  parent: PixiContainer;\n  near: PixiSprite;\n  far: PixiSprite;\n  contact: PixiSprite;\n  nearBlur: BlurFilter;\n  farBlur: BlurFilter;\n  contactBlur: BlurFilter;\n  nearGradient: GradientFilter;\n  farGradient: GradientFilter;\n  dirX: number;\n  dirY: number;\n  length: number;\n};\n\nconst SHADOW_MANAGED_MARK = \"__spriteShadowManaged\";\nconst DEFAULT_LIGHT_Z = 220;\nconst DEFAULT_LIGHT_RADIUS = 360;\nconst DEFAULT_LIGHT_INTENSITY = 1;\nconst DEFAULT_MODE: ShadowMode = \"strongest\";\nconst DEFAULT_UPDATE_HZ = 30;\nconst DEFAULT_SHADOW_COLOR = 0x000000;\nconst DEFAULT_CASTER: ResolvedCaster = {\n  height: 72,\n  footOffset: { x: 0, y: 0 },\n  footAnchor: { x: 0.5, y: 1 },\n  alpha: 0.56,\n  blur: 3.5,\n  gradientPower: 2,\n  hardness: 0.42,\n  minLength: 10,\n  maxLength: 280,\n  contactAlpha: 0.28,\n  contactScale: 0.28,\n};\n\nconst clamp = (value: number, min: number, max: number) =>\n  Math.max(min, Math.min(max, value));\n\nconst isFiniteNumber = (value: unknown): value is number =>\n  typeof value === \"number\" && Number.isFinite(value);\n\nconst resolveReactiveValue = <T>(value: ReactiveValue<T> | undefined): T | undefined => {\n  if (\n    value &&\n    typeof value === \"object\" &&\n    \"value\" in (value as Record<string, unknown>) &&\n    Object.keys(value as Record<string, unknown>).length <= 2\n  ) {\n    return (value as Record<string, T>).value;\n  }\n  if (typeof value === \"function\") {\n    try {\n      return (value as () => T)();\n    } catch {\n      return undefined;\n    }\n  }\n  return value;\n};\n\nconst parseColorToNumber = (color: ColorInput | undefined): number => {\n  if (typeof color === \"number\" && Number.isFinite(color)) {\n    return Math.max(0, Math.floor(color)) & 0xffffff;\n  }\n  if (typeof color === \"string\") {\n    const cleaned = color.trim().replace(/^#/, \"\");\n    const normalized =\n      cleaned.length === 3\n        ? `${cleaned[0]}${cleaned[0]}${cleaned[1]}${cleaned[1]}${cleaned[2]}${cleaned[2]}`\n        : cleaned;\n    const parsed = parseInt(normalized, 16);\n    if (Number.isFinite(parsed)) return parsed & 0xffffff;\n  }\n  return DEFAULT_SHADOW_COLOR;\n};\n\nconst resolvePoint = (\n  value: ReactiveValue<PointLike> | undefined,\n  fallback: PointLike\n): PointLike => {\n  const resolved = resolveReactiveValue(value);\n  const x = Number((resolved as PointLike | undefined)?.x);\n  const y = Number((resolved as PointLike | undefined)?.y);\n  return {\n    x: isFiniteNumber(x) ? x : fallback.x,\n    y: isFiniteNumber(y) ? y : fallback.y,\n  };\n};\n\nconst toGlobalPoint = (\n  container: any,\n  point: PointLike\n): PointLike => {\n  if (container && typeof container.toGlobal === \"function\") {\n    const globalPoint = container.toGlobal(point);\n    if (isFiniteNumber(globalPoint?.x) && isFiniteNumber(globalPoint?.y)) {\n      return { x: globalPoint.x, y: globalPoint.y };\n    }\n  }\n  return point;\n};\n\nconst toLocalPoint = (\n  container: any,\n  point: PointLike\n): PointLike => {\n  if (container && typeof container.toLocal === \"function\") {\n    const localPoint = container.toLocal(point);\n    if (isFiniteNumber(localPoint?.x) && isFiniteNumber(localPoint?.y)) {\n      return { x: localPoint.x, y: localPoint.y };\n    }\n  }\n  return point;\n};\n\nconst createGradientFilter = (\n  power = 2,\n  floor = 0.06\n): GradientFilter => {\n  const uPower = { value: power, type: \"f32\" as const };\n  const uFloor = { value: floor, type: \"f32\" as const };\n  const filter = Filter.from({\n    gl: {\n      vertex: vertexShader,\n      fragment: fragmentShader,\n    },\n    resources: {\n      shadowGradientUniforms: {\n        uPower,\n        uFloor,\n      },\n    },\n  }) as GradientFilter;\n\n  filter.setGradient = (nextPower: number, nextFloor: number) => {\n    uPower.value = isFiniteNumber(nextPower) ? Math.max(0.001, nextPower) : 2;\n    uFloor.value = isFiniteNumber(nextFloor) ? clamp(nextFloor, 0, 1) : 0.06;\n  };\n\n  return filter;\n};\n\nconst resolveCasterOptions = (rawValue: unknown): ResolvedCaster | null => {\n  if (rawValue === false || rawValue === null || rawValue === undefined) return null;\n  const source: ShadowCasterOptions =\n    rawValue === true || typeof rawValue !== \"object\"\n      ? {}\n      : (rawValue as ShadowCasterOptions);\n\n  const enabled = resolveReactiveValue(source.enabled);\n  if (enabled === false) return null;\n\n  const height = Number(resolveReactiveValue(source.height));\n  const alpha = Number(resolveReactiveValue(source.alpha));\n  const blur = Number(resolveReactiveValue(source.blur));\n  const gradientPower = Number(resolveReactiveValue(source.gradientPower));\n  const hardness = Number(resolveReactiveValue(source.hardness));\n  const minLength = Number(resolveReactiveValue(source.minLength));\n  const maxLength = Number(resolveReactiveValue(source.maxLength));\n  const contactAlpha = Number(resolveReactiveValue(source.contactAlpha));\n  const contactScale = Number(resolveReactiveValue(source.contactScale));\n  const anchorX = Number(resolveReactiveValue(source.anchorX));\n\n  return {\n    height: isFiniteNumber(height) ? Math.max(2, height) : DEFAULT_CASTER.height,\n    footOffset: resolvePoint(source.footOffset, DEFAULT_CASTER.footOffset),\n    footAnchor: resolvePoint(source.footAnchor, DEFAULT_CASTER.footAnchor),\n    alpha: isFiniteNumber(alpha) ? clamp(alpha, 0, 1.5) : DEFAULT_CASTER.alpha,\n    blur: isFiniteNumber(blur) ? Math.max(0, blur) : DEFAULT_CASTER.blur,\n    gradientPower: isFiniteNumber(gradientPower)\n      ? clamp(gradientPower, 0.2, 8)\n      : DEFAULT_CASTER.gradientPower,\n    hardness: isFiniteNumber(hardness) ? clamp(hardness, 0, 1) : DEFAULT_CASTER.hardness,\n    minLength: isFiniteNumber(minLength) ? Math.max(0, minLength) : DEFAULT_CASTER.minLength,\n    maxLength: isFiniteNumber(maxLength)\n      ? Math.max(2, maxLength)\n      : DEFAULT_CASTER.maxLength,\n    contactAlpha: isFiniteNumber(contactAlpha)\n      ? clamp(contactAlpha, 0, 1)\n      : DEFAULT_CASTER.contactAlpha,\n    contactScale: isFiniteNumber(contactScale)\n      ? Math.max(0.05, contactScale)\n      : DEFAULT_CASTER.contactScale,\n    anchorX: isFiniteNumber(anchorX) ? clamp(anchorX, 0, 1) : undefined,\n  };\n};\n\nconst resolveCasterFromInstance = (instance: any): ResolvedCaster | null => {\n  if (!instance || instance[SHADOW_MANAGED_MARK]) return null;\n  const element = typeof instance.getElement === \"function\" ? instance.getElement() : null;\n  const rawShadowCaster =\n    resolveReactiveValue((instance as any).shadowCaster) ??\n    resolveReactiveValue((instance as any).fullProps?.shadowCaster) ??\n    resolveReactiveValue(element?.props?.shadowCaster) ??\n    resolveReactiveValue(element?.propObservables?.shadowCaster as any);\n  if (rawShadowCaster === undefined) return null;\n  return resolveCasterOptions(rawShadowCaster);\n};\n\nconst collectShadowCasters = (root: any): Array<{ instance: any; caster: ResolvedCaster }> => {\n  const collected: Array<{ instance: any; caster: ResolvedCaster }> = [];\n  const stack: any[] = [root];\n\n  while (stack.length > 0) {\n    const node = stack.pop();\n    const children = Array.isArray(node?.children) ? node.children : [];\n    for (let i = 0; i < children.length; i++) {\n      const child = children[i];\n      if (!child || child[SHADOW_MANAGED_MARK]) continue;\n\n      const caster = resolveCasterFromInstance(child);\n      if (caster && child.parent) {\n        collected.push({ instance: child, caster });\n      }\n\n      if (Array.isArray(child.children) && child.children.length > 0) {\n        stack.push(child);\n      }\n    }\n  }\n\n  return collected;\n};\n\nconst resolveLights = (\n  source: ReactiveValue<Array<ShadowLightInput | ShadowLight>> | undefined,\n  lightSpace: any\n): ResolvedLight[] => {\n  const raw = resolveReactiveValue(source);\n  if (!Array.isArray(raw)) return [];\n  const resolved: ResolvedLight[] = [];\n\n  for (let i = 0; i < raw.length; i++) {\n    const light = raw[i] as ShadowLightInput | ShadowLight;\n    const enabled = resolveReactiveValue((light as ShadowLightInput).enabled);\n    if (enabled === false) continue;\n\n    const x = Number(resolveReactiveValue((light as ShadowLightInput).x));\n    const y = Number(resolveReactiveValue((light as ShadowLightInput).y));\n    if (!isFiniteNumber(x) || !isFiniteNumber(y)) continue;\n\n    const z = Number(resolveReactiveValue((light as ShadowLightInput).z));\n    const radius = Number(resolveReactiveValue((light as ShadowLightInput).radius));\n    const intensity = Number(resolveReactiveValue((light as ShadowLightInput).intensity));\n    const shadowWeight = Number(resolveReactiveValue((light as ShadowLightInput).shadowWeight));\n    const global = toGlobalPoint(lightSpace, { x, y });\n\n    resolved.push({\n      x,\n      y,\n      globalX: global.x,\n      globalY: global.y,\n      z: isFiniteNumber(z) ? Math.max(2, z) : DEFAULT_LIGHT_Z,\n      radius: isFiniteNumber(radius) ? Math.max(1, radius) : DEFAULT_LIGHT_RADIUS,\n      intensity: isFiniteNumber(intensity)\n        ? clamp(intensity, 0, 2)\n        : DEFAULT_LIGHT_INTENSITY,\n      shadowWeight: isFiniteNumber(shadowWeight) ? clamp(shadowWeight, 0, 4) : 1,\n    });\n  }\n\n  return resolved;\n};\n\nconst blendCandidates = (\n  candidates: LightCandidate[],\n  mode: ShadowMode\n): LightCandidate | null => {\n  if (candidates.length === 0) return null;\n  candidates.sort((a, b) => b.influence - a.influence);\n\n  if (mode === \"strongest\" || candidates.length === 1) {\n    return candidates[0];\n  }\n\n  const picked = candidates.slice(0, 2);\n  let weightedDirX = 0;\n  let weightedDirY = 0;\n  let weightedLength = 0;\n  let weightTotal = 0;\n\n  for (let i = 0; i < picked.length; i++) {\n    const candidate = picked[i];\n    const weight = Math.max(0.001, candidate.influence);\n    weightedDirX += candidate.dirX * weight;\n    weightedDirY += candidate.dirY * weight;\n    weightedLength += candidate.length * weight;\n    weightTotal += weight;\n  }\n\n  if (weightTotal <= 0) return null;\n  const norm = Math.hypot(weightedDirX, weightedDirY);\n  if (norm <= 0.0001) return null;\n\n  return {\n    dirX: weightedDirX / norm,\n    dirY: weightedDirY / norm,\n    length: weightedLength / weightTotal,\n    influence: clamp(weightTotal / picked.length, 0, 2),\n  };\n};\n\nconst hideManagedShadow = (managed: ManagedShadow) => {\n  managed.near.visible = false;\n  managed.far.visible = false;\n  managed.contact.visible = false;\n};\n\nconst destroyManagedShadow = (managed: ManagedShadow) => {\n  managed.near.destroy();\n  managed.far.destroy();\n  managed.contact.destroy();\n};\n\nconst createManagedShadow = (\n  caster: any,\n  parent: PixiContainer,\n  shadowColor: number\n): ManagedShadow => {\n  const near = new PixiSprite();\n  const far = new PixiSprite();\n  const contact = new PixiSprite();\n  const nearBlur = new BlurFilter({ strength: 2.5, quality: 2 });\n  const farBlur = new BlurFilter({ strength: 4.2, quality: 3 });\n  const contactBlur = new BlurFilter({ strength: 2.8, quality: 2 });\n  const nearGradient = createGradientFilter(2, 0.08);\n  const farGradient = createGradientFilter(2.8, 0.02);\n\n  near.filters = [nearGradient, nearBlur];\n  far.filters = [farGradient, farBlur];\n  contact.filters = [contactBlur];\n\n  near.tint = shadowColor;\n  far.tint = shadowColor;\n  contact.tint = shadowColor;\n  near.blendMode = \"multiply\" as any;\n  far.blendMode = \"multiply\" as any;\n  contact.blendMode = \"multiply\" as any;\n  near.eventMode = \"none\";\n  far.eventMode = \"none\";\n  contact.eventMode = \"none\";\n  near.roundPixels = true;\n  far.roundPixels = true;\n  contact.roundPixels = true;\n  near.visible = false;\n  far.visible = false;\n  contact.visible = false;\n  near.alpha = 0;\n  far.alpha = 0;\n\n  (near as any)[SHADOW_MANAGED_MARK] = true;\n  (far as any)[SHADOW_MANAGED_MARK] = true;\n  (contact as any)[SHADOW_MANAGED_MARK] = true;\n\n  parent.addChild(contact);\n  parent.addChild(far);\n  parent.addChild(near);\n\n  return {\n    caster,\n    parent,\n    near,\n    far,\n    contact,\n    nearBlur,\n    farBlur,\n    contactBlur,\n    nearGradient,\n    farGradient,\n    dirX: 0,\n    dirY: 1,\n    length: 0,\n  };\n};\n\nconst placeBelowCaster = (managed: ManagedShadow) => {\n  const { caster, parent, near, far, contact } = managed;\n  if (!caster || caster.destroyed || !parent) return;\n\n  const casterZIndex = isFiniteNumber(caster.zIndex) ? caster.zIndex : 0;\n  contact.zIndex = casterZIndex - 0.32;\n  far.zIndex = casterZIndex - 0.26;\n  near.zIndex = casterZIndex - 0.22;\n\n  if ((parent as any).sortableChildren) return;\n  if (!Array.isArray(parent.children) || !parent.children.includes(caster)) return;\n\n  const setBeforeCaster = (item: any) => {\n    if (!item || item.destroyed || !parent.children.includes(item)) return;\n    const casterIndex = parent.getChildIndex(caster);\n    const targetIndex = Math.max(0, casterIndex - 1);\n    if (parent.getChildIndex(item) !== targetIndex) {\n      parent.setChildIndex(item, targetIndex);\n    }\n  };\n\n  setBeforeCaster(contact);\n  setBeforeCaster(far);\n  setBeforeCaster(near);\n};\n\nconst updateManagedShadow = (\n  managed: ManagedShadow,\n  casterConfig: ResolvedCaster,\n  lights: ResolvedLight[],\n  mode: ShadowMode,\n  shadowColor: number\n) => {\n  const caster = managed.caster;\n  const parent = managed.parent;\n  if (!caster || caster.destroyed || !parent || parent.destroyed) {\n    hideManagedShadow(managed);\n    return;\n  }\n\n  if (caster.visible === false || (isFiniteNumber(caster.worldAlpha) && caster.worldAlpha <= 0.001)) {\n    hideManagedShadow(managed);\n    return;\n  }\n\n  const bounds = typeof caster.getBounds === \"function\" ? caster.getBounds() : null;\n  const hasBounds =\n    !!bounds &&\n    isFiniteNumber(bounds.x) &&\n    isFiniteNumber(bounds.y) &&\n    isFiniteNumber(bounds.width) &&\n    isFiniteNumber(bounds.height) &&\n    bounds.width > 0 &&\n    bounds.height > 0;\n  if (!hasBounds) {\n    hideManagedShadow(managed);\n    return;\n  }\n\n  const casterWidth = Math.max(\n    1,\n    Math.abs(Number(caster.width)) || Math.abs(bounds.width)\n  );\n  const casterHeight = Math.max(\n    1,\n    Math.abs(Number(caster.height)) || Math.abs(bounds.height)\n  );\n\n  const casterAnchorXRaw = Number(caster.anchor?.x);\n  const casterAnchorYRaw = Number(caster.anchor?.y);\n  const casterAnchorX = isFiniteNumber(casterAnchorXRaw) ? clamp(casterAnchorXRaw, 0, 1) : 0.5;\n  const casterAnchorY = isFiniteNumber(casterAnchorYRaw) ? clamp(casterAnchorYRaw, 0, 1) : 1;\n\n  const anchorXForShadow = isFiniteNumber(casterConfig.anchorX)\n    ? casterConfig.anchorX\n    : casterAnchorX;\n\n  const localFootPoint: PointLike = {\n    x:\n      (casterConfig.footAnchor.x - casterAnchorX) * casterWidth +\n      casterConfig.footOffset.x,\n    y:\n      (casterConfig.footAnchor.y - casterAnchorY) * casterHeight +\n      casterConfig.footOffset.y,\n  };\n  const footGlobal = toGlobalPoint(caster, localFootPoint);\n  const footLocal = toLocalPoint(parent, footGlobal);\n  const candidates: LightCandidate[] = [];\n\n  for (let i = 0; i < lights.length; i++) {\n    const light = lights[i];\n    if (light.intensity <= 0.001 || light.radius <= 0.001) continue;\n    const lightLocal = toLocalPoint(parent, {\n      x: light.globalX,\n      y: light.globalY,\n    });\n    const dx = footLocal.x - lightLocal.x;\n    const dy = footLocal.y - lightLocal.y;\n    const distance = Math.hypot(dx, dy);\n    const falloff = clamp(1 - distance / light.radius, 0, 1);\n    const zWeight = clamp(DEFAULT_LIGHT_Z / Math.max(12, light.z), 0.35, 2.4);\n    const influence = clamp(\n      falloff * falloff * light.intensity * light.shadowWeight * zWeight,\n      0,\n      2.2\n    );\n    if (influence <= 0.001) continue;\n\n    const directionNorm = distance > 0.0001 ? distance : 1;\n    const dirX = dx / directionNorm;\n    const dirY = dy / directionNorm;\n    const projectedLength = clamp(\n      (distance * casterConfig.height) / Math.max(14, light.z),\n      casterConfig.minLength,\n      casterConfig.maxLength\n    );\n\n    candidates.push({\n      dirX: isFiniteNumber(dirX) ? dirX : 0,\n      dirY: isFiniteNumber(dirY) ? dirY : 1,\n      influence,\n      length: isFiniteNumber(projectedLength) ? projectedLength : casterConfig.minLength,\n    });\n  }\n\n  const projection = blendCandidates(candidates, mode);\n  if (!projection) {\n    hideManagedShadow(managed);\n    return;\n  }\n\n  const casterTexture = caster.texture;\n  if (!casterTexture) {\n    hideManagedShadow(managed);\n    return;\n  }\n\n  const directionLerp = 0.34;\n  const lengthLerp = 0.32;\n  const smoothDirX = managed.dirX + (projection.dirX - managed.dirX) * directionLerp;\n  const smoothDirY = managed.dirY + (projection.dirY - managed.dirY) * directionLerp;\n  const smoothNorm = Math.hypot(smoothDirX, smoothDirY);\n  const dirX = smoothNorm > 0.0001 ? smoothDirX / smoothNorm : projection.dirX;\n  const dirY = smoothNorm > 0.0001 ? smoothDirY / smoothNorm : projection.dirY;\n  const length = managed.length + (projection.length - managed.length) * lengthLerp;\n  managed.dirX = dirX;\n  managed.dirY = dirY;\n  managed.length = length;\n\n  const lengthScale = clamp(length / casterHeight, 0.08, 6);\n  const widthScale = clamp(0.62 + lengthScale * 0.08, 0.5, 1.2);\n  const hardness = clamp(casterConfig.hardness, 0, 1);\n  const influenceNorm = clamp(projection.influence, 0, 1.35);\n  const alphaBase = clamp(casterConfig.alpha * influenceNorm, 0, 1);\n  const blurBase = Math.max(0, casterConfig.blur * (1.15 - hardness * 0.55));\n  const gradientPower = clamp(casterConfig.gradientPower + (1 - hardness) * 0.7, 0.2, 8);\n  // With anchor.y=1, the silhouette extends along local -Y; rotate that axis to shadow direction.\n  const rotation = Math.atan2(dirY, dirX) + Math.PI / 2;\n\n  managed.near.texture = casterTexture;\n  managed.far.texture = casterTexture;\n  managed.contact.texture = casterTexture;\n  managed.near.tint = shadowColor;\n  managed.far.tint = shadowColor;\n  managed.contact.tint = shadowColor;\n  managed.near.anchor.set(anchorXForShadow, 1);\n  managed.far.anchor.set(anchorXForShadow, 1);\n  managed.contact.anchor.set(anchorXForShadow, 1);\n\n  managed.near.width = casterWidth * widthScale;\n  managed.near.height = casterHeight * Math.max(0.12, lengthScale * 1.06);\n  managed.far.width = managed.near.width * 1.02;\n  managed.far.height = managed.near.height * 1.22;\n\n  managed.near.position.set(footLocal.x, footLocal.y);\n  managed.far.position.set(\n    footLocal.x + dirX * length * 0.34,\n    footLocal.y + dirY * length * 0.34\n  );\n  managed.contact.position.set(\n    footLocal.x + dirX * Math.min(4, length * 0.06),\n    footLocal.y + dirY * Math.min(4, length * 0.06)\n  );\n  managed.near.rotation = rotation;\n  managed.far.rotation = rotation;\n  managed.contact.rotation = rotation;\n\n  managed.near.alpha = clamp(alphaBase * (0.74 + hardness * 0.2), 0, 1);\n  managed.far.alpha = clamp(alphaBase * (0.3 + (1 - hardness) * 0.2), 0, 1);\n  managed.near.visible = managed.near.alpha > 0.001;\n  managed.far.visible = managed.far.alpha > 0.001;\n\n  managed.nearBlur.strength = blurBase * (0.72 + (1 - influenceNorm) * 0.45);\n  managed.farBlur.strength = blurBase * (1.45 + (1 - influenceNorm) * 1.1);\n  managed.nearGradient.setGradient(gradientPower, 0.08);\n  managed.farGradient.setGradient(gradientPower + 0.65, 0.03);\n\n  const contactAlpha = clamp(casterConfig.contactAlpha * influenceNorm * 0.85, 0, 1);\n  const contactWidth = Math.max(\n    4,\n    casterWidth * clamp(casterConfig.contactScale * 1.8, 0.25, 1.3)\n  );\n  const contactHeight = Math.max(\n    2,\n    casterHeight * clamp(casterConfig.contactScale * 0.62, 0.08, 0.56)\n  );\n  managed.contact.width = contactWidth * (0.92 + lengthScale * 0.18);\n  managed.contact.height = contactHeight;\n  managed.contact.alpha = clamp(contactAlpha * (0.6 + hardness * 0.2), 0, 1);\n  managed.contactBlur.strength = blurBase * (0.85 + (1 - hardness) * 0.25);\n  managed.contact.visible = managed.contact.alpha > 0.001;\n\n  placeBelowCaster(managed);\n};\n\n/**\n * SpriteShadows preset\n *\n * Adds RPG-style projected shadows for sprites tagged with `shadowCaster`.\n * The shadow direction is automatically opposite to the dominant light source.\n *\n * Usage:\n * - Add `<SpriteShadows lights={lights} />` in your scene (preferably inside `Viewport`).\n * - Add `shadowCaster` on any sprite that should cast a shadow.\n */\nexport function SpriteShadows(options: SpriteShadowsProps = {}) {\n  const props = useProps(options);\n  const lightsSource = () =>\n    (props.lights as ReactiveValue<Array<ShadowLightInput | ShadowLight>> | undefined) ??\n    (props.sources as ReactiveValue<Array<ShadowLightInput | ShadowLight>> | undefined);\n\n  mount((element) => {\n    const context = element.props.context;\n    const viewport = context?.viewport;\n    const target: any = viewport ?? element.parent?.componentInstance;\n    if (!target || typeof target.addChild !== \"function\") return;\n    const tickSignal = context?.tick;\n\n    const managedByCaster = new Map<any, ManagedShadow>();\n    let accumulatorMs = 0;\n    let forceRefresh = true;\n    let tickSubscription: any = null;\n\n    const sync = () => {\n      const shadowColor = parseColorToNumber(\n        resolveReactiveValue(props.shadowColor as ReactiveValue<ColorInput> | undefined)\n      );\n      const modeRaw = resolveReactiveValue(props.mode as ReactiveValue<ShadowMode> | undefined);\n      const mode: ShadowMode = modeRaw === \"blend2\" ? \"blend2\" : DEFAULT_MODE;\n      const lights = resolveLights(lightsSource(), target);\n      const casters = collectShadowCasters(target);\n      const activeCasters = new Set<any>();\n\n      for (let i = 0; i < casters.length; i++) {\n        const { instance: casterInstance, caster } = casters[i];\n        if (!casterInstance || !casterInstance.parent || casterInstance.destroyed) continue;\n        activeCasters.add(casterInstance);\n\n        let managed = managedByCaster.get(casterInstance);\n        if (!managed || managed.parent !== casterInstance.parent) {\n          if (managed) destroyManagedShadow(managed);\n          managed = createManagedShadow(casterInstance, casterInstance.parent, shadowColor);\n          managedByCaster.set(casterInstance, managed);\n        }\n\n        updateManagedShadow(managed, caster, lights, mode, shadowColor);\n      }\n\n      for (const [casterInstance, managed] of managedByCaster.entries()) {\n        if (\n          !activeCasters.has(casterInstance) ||\n          !casterInstance ||\n          casterInstance.destroyed\n        ) {\n          destroyManagedShadow(managed);\n          managedByCaster.delete(casterInstance);\n        }\n      }\n    };\n\n    tickSubscription = tickSignal?.observable?.subscribe((tickArgs: any) => {\n      const tickValue = tickArgs?.value ?? tickArgs;\n      const deltaTime = Number(tickValue?.deltaTime);\n      const frameMs = isFiniteNumber(deltaTime) ? deltaTime : 16.67;\n      const updateHzRaw = Number(\n        resolveReactiveValue(props.updateHz as ReactiveValue<number> | undefined)\n      );\n      const updateHz = clamp(\n        isFiniteNumber(updateHzRaw) ? updateHzRaw : DEFAULT_UPDATE_HZ,\n        1,\n        120\n      );\n      const intervalMs = 1000 / updateHz;\n      accumulatorMs += frameMs;\n\n      if (forceRefresh || accumulatorMs >= intervalMs) {\n        accumulatorMs = 0;\n        forceRefresh = false;\n        sync();\n      }\n    });\n\n    sync();\n\n    return () => {\n      tickSubscription?.unsubscribe?.();\n      for (const managed of managedByCaster.values()) {\n        destroyManagedShadow(managed);\n      }\n      managedByCaster.clear();\n    };\n  });\n\n  return h(Container);\n}\n"
  },
  {
    "path": "packages/presets/src/Tilemap/Tile.ts",
    "content": "import { CompositeTilemap } from \"@pixi/tilemap\";\nimport { Tile as TiledTileClass } from '@rpgjs/tiled';\nimport { AnimatedSprite, Texture, groupD8 } from \"pixi.js\";\nimport { TileSet } from \"./TileSet\";\n\nexport class Tile extends AnimatedSprite {\n    static getTextures(tile: TiledTileClass, tileSet: TileSet) {\n        const textures: Texture[] = [];\n\n        if (tile.animations && tile.animations.length) {\n            tile.animations.forEach(frame => {\n                textures.push(tileSet.textures[frame.tileid])\n            });\n        } else {\n            textures.push(tileSet.textures[tile.gid - tileSet.firstgid])\n        }\n\n        return textures;\n    }\n\n    animations: { tileid: number, duration: number }[] = []\n    _x: number = 0\n    _y: number = 0\n    pointsBufIndex: number\n    properties: any = {}\n\n    constructor(\n        private tile: TiledTileClass,\n        private tileSet: TileSet\n    ) {\n        super(Tile.getTextures(tile, tileSet));\n        this.animations = tile.animations || []\n        this.properties = tile.properties\n        this.textures = Tile.getTextures(tile, tileSet)\n        this.texture = this.textures[0] as Texture\n        this.flip()\n    }\n\n    get z() {\n        return this.properties.z ?? 0\n    }\n\n    get gid() {\n        return this.tile.gid\n    }\n\n    setAnimation(frame: CompositeTilemap) {\n        const size = this.animations.length\n        if (size > 1) {\n            const offset = (this.animations[1].tileid - this.animations[0].tileid) * this.width\n            frame.tileAnimX(offset, size)\n        }\n    }\n\n    flip() {\n        let symmetry\n        let i = 0\n        const add = (symmetrySecond) => {\n            i++\n            if (symmetry) symmetry = groupD8.add(symmetry, symmetrySecond)\n            else symmetry = symmetrySecond\n        }\n\n        if (this.tile.horizontalFlip) {\n            add(groupD8.MIRROR_HORIZONTAL)\n        }\n\n        if (this.tile.verticalFlip) {\n            add(groupD8.MIRROR_VERTICAL)\n        }\n\n        if (this.tile.diagonalFlip) {\n            if (i % 2 == 0) {\n                add(groupD8.MAIN_DIAGONAL)\n            }\n            else {\n                add(groupD8.REVERSE_DIAGONAL)\n            }\n        }\n\n        //if (symmetry) this.texture.rotate = symmetry\n    }\n}"
  },
  {
    "path": "packages/presets/src/Tilemap/TileGroup.ts",
    "content": "interface TileOptions {\n    tilesetIndex?: number\n    tileId: number\n    x: number\n    y: number\n}\n\ninterface TilesGroupOptions {\n    ignore?: boolean\n    probability?: number\n    baseHeight?: number\n    baseWidth?: number\n    rectMargin?: number\n    baseOffsetX?: number\n    baseOffsetY?: number\n}\n\nexport class TileInfo {\n    tilesetIndex?: number\n    tileId: number\n    flags: Map<string, any> = new Map()\n    id: number = Math.random()\n\n    constructor(obj: TileOptions) {\n        this.tilesetIndex = obj.tilesetIndex ?? 0\n        this.tileId = obj.tileId\n    }\n\n    addFlag(key: string, value: any) {\n        this.flags.set(key, value)\n    }\n}\n\nexport class TilesGroup {\n    tiles: (TileInfo | null)[][] = []\n    width: number\n    height: number\n    ignore: boolean = false\n    probability: number = 1\n    baseHeight: number = 1\n    baseWidth?: number\n    baseOffsetX: number = 0\n    baseOffsetY: number = 0\n    rectMargin: number = 0\n\n    constructor(tiles: TileOptions[], public tilesetIndex: number = 0, options: TilesGroupOptions = {}) {\n        const pointsX = tiles.map(tile => tile.x)\n        const pointsY = tiles.map(tile => tile.y)\n        const offsetX = Math.min(...pointsX)\n        const offsetY = Math.min(...pointsY)\n        this.width = Math.max(...pointsX) - offsetX + 1\n        this.height = Math.max(...pointsY) - offsetY + 1\n        this.ignore = !!options.ignore\n        this.probability = options.probability ?? 1\n        this.baseHeight = options.baseHeight ?? 1\n        this.baseWidth = options.baseWidth\n        this.rectMargin = options.rectMargin ?? 0\n        this.baseOffsetX = options.baseOffsetX ?? 0\n        this.baseOffsetY = options.baseOffsetY ?? 0\n        this.fillTiles()\n        for (let tile of tiles) {\n            this.addTile(tile.x - offsetX, tile.y - offsetY, tile)\n        }\n    }\n\n    getRect(x: number, y: number): { minX: number, minY: number, maxX: number, maxY: number } {\n        const margin = this.rectMargin\n        return {\n            minX: x - margin + this.baseOffsetX,\n            minY: y - this.tilesBaseHeight - margin - this.baseOffsetY,\n            maxX: x + this.tilesBaseWidth + margin,\n            maxY: y + margin\n        }\n    }\n\n    get tilesBase() {\n        return this.tiles[this.tiles.length - 1]\n    }\n\n    get tilesBaseWidth(): number {\n        return this.baseWidth ?? this.tilesBase.length\n    }\n\n    get tilesBaseHeight(): number {\n        return this.baseHeight\n    }\n\n    forEach(cb: (tileInfo: TileInfo | null, x: number, y: number) => void) {\n        for (let i = 0; i < this.tiles.length; i++) {\n            for (let j = 0; j < this.tiles[i].length; j++) {\n                cb(this.tiles[i][j], j, i)\n            }\n        }\n    }\n\n    find(cb: (tileInfo: TileInfo | null, x: number, y: number) => boolean): TileInfo | null {\n        let found: TileInfo | null = null\n        this.forEach((tileInfo, x, y) => {\n            const bool = cb(tileInfo, x, y)\n            if (bool) found = tileInfo\n        })\n        return found\n    }\n\n    getOffsetY(): number {\n        const tilesBase = this.tilesBase\n        let offset = 0\n        this.forEach((tile, x, y) => {\n            if (tile?.tileId == (tilesBase?.[0]?.tileId)) {\n                offset = y\n            }\n        })\n        return offset\n    }\n\n    fillTiles() {\n        for (let i = 0; i < this.height; i++) {\n            this.tiles[i] = []\n            for (let j = 0; j < this.width; j++) {\n                this.tiles[i][j] = null\n            }\n        }\n    }\n\n    shiftToTopLeft(): void {\n        const matrix = this.tiles\n\n        // Find the first non-undefined element and its position\n        const foundFirst = () => {\n            let firstElementRow = -1;\n            let firstElementColumn = -1;\n\n            for (let col = 0; col < matrix.length; col++) {\n                if (!matrix[col]) matrix[col] = []\n                for (let row = 0; row < matrix[col].length; row++) {\n                    if (matrix[col][row] !== undefined) {\n                        firstElementRow = row;\n                        firstElementColumn = col;\n                        return {\n                            firstElementRow,\n                            firstElementColumn\n                        };\n                    }\n                }\n            }\n\n            return {\n                firstElementRow,\n                firstElementColumn\n            }\n        }\n\n        const { firstElementRow, firstElementColumn } = foundFirst()\n\n        // If no non-undefined element is found, return the original matrix\n        if (firstElementRow === -1) {\n            return;\n        }\n\n        // Shift the matrix elements\n        const newMatrix: (TileInfo | null)[][] = [];\n        for (let col = firstElementColumn; col < matrix.length; col++) {\n            const newRow: (TileInfo | null)[] = [];\n            for (let row = firstElementRow; row < matrix[col].length; row++) {\n                newRow.push(matrix[col][row]);\n            }\n            newMatrix.push(newRow);\n        }\n\n        this.tiles = newMatrix;\n\n        this.width = this.tiles[0].length\n        this.height = this.tiles.length\n    }\n\n    addTile(x: number, y: number, tileOptions: TileOptions) {\n        if (!this.tiles[y]) this.tiles[y] = []\n        this.tiles[y][x] = new TileInfo(tileOptions)\n    }\n\n    addTileFlag(x: number, y: number, key: string, value: any) {\n        this.getTile(x, y)?.addFlag(key, value)\n    }\n\n    getTile(x: number, y: number): TileInfo | null {\n        return this.tiles[y]?.[x]\n    }\n\n    getTilesByFlag(key: string, value: any): { tileInfo: TileInfo, x: number, y: number }[] {\n        const array: any = []\n        this.forEach((tileInfo, x, y) => {\n            const flag = tileInfo?.flags.get(key)\n            if (flag && flag == value) {\n                array.push({\n                    tileInfo,\n                    x,\n                    y\n                })\n            }\n        })\n        return array\n    }\n\n    isTileBase(tileInfo: TileInfo): boolean {\n        return !!this.tilesBase.find(tile => tile?.id == tileInfo.id)\n    }\n}"
  },
  {
    "path": "packages/presets/src/Tilemap/TileLayer.ts",
    "content": "import {\n  CompositeTilemap,\n  POINT_STRUCT_SIZE,\n  Tilemap,\n  settings,\n} from \"@canvasengine/tilemap\";\nimport { Layer, Tile as TileClass } from \"@canvasengine/tiled\";\nimport {\n  createComponent,\n  registerComponent,\n  DisplayObject,\n  Signal,\n} from \"canvasengine\";\nimport { Tile } from \"./Tile\";\nimport { TileSet } from \"./TileSet\";\nimport { Subscription } from \"rxjs\";\n\nsettings.use32bitIndex = true;\n\nexport class CanvasTileLayer extends DisplayObject(CompositeTilemap) {\n  private _tiles: any = {};\n  tiles: (TileClass | null)[];\n  private _layer: any; // TODO: fix this, remove any. replace with Layer\n  private frameTile: number = 0;\n  private frameRateAnimation: number = 10;\n  private subscriptionTick: Subscription;\n\n  static findTileSet(gid: number, tileSets: TileSet[]) {\n    let tileset: TileSet | undefined;\n    for (let i = tileSets.length - 1; i >= 0; i--) {\n      tileset = tileSets[i];\n      if (tileset.firstgid && tileset.firstgid <= gid) {\n        break;\n      }\n    }\n    return tileset;\n  }\n\n  /** @internal */\n  createTile(x: number, y: number, options: any = {}): Tile | undefined {\n    const { real, filter } = options;\n    const { tilewidth, tileheight, width } = this._layer;\n    if (real) {\n      x = Math.floor(x / tilewidth);\n      y = Math.floor(y / tileheight);\n    }\n    const i = x + y * width;\n    const tiledTile = this._layer.getTileByIndex(i);\n\n    if (!tiledTile || (tiledTile && tiledTile.gid == 0)) return;\n\n    const tileset = CanvasTileLayer.findTileSet(tiledTile.gid, this.tileSets);\n\n    if (!tileset) return;\n\n    const tile = new Tile(tiledTile, tileset);\n\n    tile.x = x * tilewidth;\n    tile.y = y * tileheight + (tileheight - tile.texture.height);\n\n    tile._x = x;\n    tile._y = y;\n\n    if (tileset.tileoffset) {\n      tile.x += tileset.tileoffset.x ?? 0;\n      tile.y += tileset.tileoffset.y ?? 0;\n    }\n\n    if (filter) {\n      const ret = filter(tile);\n      if (!ret) return;\n    }\n\n    return tile;\n  }\n\n  private _addFrame(tile: Tile, x: number, y: number) {\n    const frame = this.tile(tile.texture, tile.x, tile.y, {\n      rotate: tile.texture.rotate,\n    });\n    // const pb = this.pointsBuf\n    // if (!pb) return null\n    // tile.pointsBufIndex = pb.length - POINT_STRUCT_SIZE\n    tile.setAnimation(frame);\n    this._tiles[x + \";\" + y] = tile;\n  }\n\n  async onMount(args) {\n    const { props } = args;\n\n    this.tileSets = props.tilesets;\n    this._layer = new Layer(\n      {\n        ...props,\n      },\n      this.tileSets\n    );\n\n    const tick: Signal = props.context.tick;\n\n    this.subscriptionTick = tick.observable.subscribe(({ value }) => {\n        if (value.frame % this.frameRateAnimation == 0) {\n            this.tileAnim = [this.frameTile, this.frameTile];\n            this.frameTile++\n         }\n    });\n\n    super.onMount(args);\n  }\n\n  onUpdate(props) {\n    super.onUpdate(props);\n    if (!this.isMounted) return;\n    if (props.tileheight) this._layer.tileheight = props.tileheight;\n    if (props.tilewidth) this._layer.tilewidth = props.tilewidth;\n    if (props.width) this._layer.width = props.width;\n    if (props.height) this._layer.height = props.height;\n    if (props.parallaxX) this._layer.parallaxX = props.parallaxx;\n    if (props.parallaxY) this._layer.parallaxY = props.parallaxy;\n\n    this.removeChildren();\n\n    for (let y = 0; y < this._layer.height; y++) {\n      for (let x = 0; x < this._layer.width; x++) {\n        const tile = this.createTile(x, y);\n        if (tile) {\n          this._addFrame(tile, x, y);\n        }\n      }\n    }\n  }\n\n  async onDestroy(parent: any) {\n    this.subscriptionTick.unsubscribe();\n    await super.onDestroy(parent);\n  }\n}\n\n// @ts-ignore\nexport interface CanvasTileLayer extends CompositeTilemap {}\n\nregisterComponent(\"CompositeTileLayer\", CanvasTileLayer);\n\nexport function CompositeTileLayer(props) {\n  return createComponent(\"CompositeTileLayer\", props);\n}\n"
  },
  {
    "path": "packages/presets/src/Tilemap/TileSet.ts",
    "content": "import { TiledTileset, Tileset as TiledTilesetClass } from \"@canvasengine/tiled\";\nimport { Assets, Rectangle, Texture } from \"pixi.js\";\n\nexport class TileSet extends TiledTilesetClass {\n  public textures: Texture[] = [];\n  private tileGroups = {};\n\n  constructor(tileSet: TiledTileset) {\n    super(tileSet);\n  }\n\n  loadGroup() {\n    // for (let tile of this.tileset.tiles) {\n    // }\n  }\n\n  /** @internal */\n  async load(image: string) {\n    const texture = await Assets.load(image);\n    for (\n      let y = this.margin;\n      y < this.image.height;\n      y += this.tileheight + this.spacing\n    ) {\n      for (\n        let x = this.margin;\n        x < this.image.width;\n        x += this.tilewidth + this.spacing\n      ) {\n        this.textures.push(\n          new Texture({\n            source: texture.source,\n            frame: new Rectangle(+x, +y, +this.tilewidth, +this.tileheight),\n          })\n        );\n      }\n    }\n    this.loadGroup();\n    return this;\n  }\n}\n"
  },
  {
    "path": "packages/presets/src/Tilemap/index.ts",
    "content": "import { TiledLayer, TiledLayerType, TiledMap, TiledParserFile, TiledTileset } from \"@canvasengine/tiled\"\nimport { loop, h, Container, TilingSprite, useProps, effect, signal } from \"canvasengine\"\nimport { CompositeTileLayer } from \"./TileLayer\"\nimport { TileSet } from \"./TileSet\"\n\n/**\n * Reorganizes tile layers based on the z property of tiles\n * \n * This function analyzes each tile in the layer data and groups them by their z property.\n * If a tile has a z property different from 0, it creates new layers for each z value.\n * \n * @param {TiledLayer[]} originalLayers - The original layers from the tilemap\n * @param {TileSet[]} tilesets - Array of loaded tilesets\n * @param {TiledMap} mapData - The complete map data\n * @returns {TiledLayer[]} - Reorganized layers with tiles grouped by z property\n * \n * @example\n * ```typescript\n * const reorganizedLayers = reorganizeLayersByTileZ(mapData.layers, tilesets, mapData);\n * ```\n */\nfunction reorganizeLayersByTileZ(originalLayers: TiledLayer[], tilesets: TileSet[], mapData: TiledMap): TiledLayer[] {\n    const reorganizedLayers: TiledLayer[] = [];\n    \n    for (const layer of originalLayers) {\n        if (layer.type !== TiledLayerType.Tile) {\n            // Keep non-tile layers as they are\n            reorganizedLayers.push(layer);\n            continue;\n        }\n\n        // Group tiles by their z property\n        const layersByZ = new Map<number, number[]>();\n        \n        // Initialize empty arrays for all z values we'll find\n        // Don't pre-populate with original data anymore\n        \n        // Ensure layer data is number array\n        let layerData: number[];\n        if (Array.isArray(layer.data)) {\n            layerData = layer.data.map(gid => {\n                if (typeof gid === 'number') {\n                    return gid;\n                } else {\n                    return parseInt(String(gid), 10);\n                }\n            });\n        } else {\n            // If data is a string, it might be compressed - for now, skip this layer\n            reorganizedLayers.push(layer);\n            continue;\n        }\n        \n        let tilesProcessed = 0;\n        let tilesWithZ = 0;\n        \n        // Analyze each tile in the layer\n        for (let i = 0; i < layerData.length; i++) {\n            const gid = layerData[i];\n            \n            if (gid === 0) continue; // Empty tile\n            \n            tilesProcessed++;\n            \n            // Find the corresponding tileset\n            let tileset: TileSet | undefined;\n            for (let j = tilesets.length - 1; j >= 0; j--) {\n                if (tilesets[j].firstgid && tilesets[j].firstgid <= gid) {\n                    tileset = tilesets[j];\n                    break;\n                }\n            }\n            \n            if (!tileset) {\n                // If no tileset found, put tile in z=0 layer\n                if (!layersByZ.has(0)) {\n                    layersByZ.set(0, new Array(layerData.length).fill(0));\n                }\n                layersByZ.get(0)![i] = gid;\n                continue;\n            }\n            \n            // Get tile properties from tileset\n            const localTileId = gid - tileset.firstgid;\n            // @ts-ignore\n            const tileProperties = tileset.tileset.tiles?.[localTileId]?.properties;\n            const zValue = tileProperties?.z ?? 0;\n            \n            // Count tiles with explicit z property\n            if (tileProperties?.z !== undefined) {\n                tilesWithZ++;\n            }\n            \n            // Create or get the layer for this z value\n            if (!layersByZ.has(zValue)) {\n                layersByZ.set(zValue, new Array(layerData.length).fill(0));\n            }\n            \n            // Place tile in the appropriate z layer\n            layersByZ.get(zValue)![i] = gid;\n        }\n        \n        // Create layers for each z value, ensuring z=0 comes first\n        const sortedZValues = Array.from(layersByZ.keys()).sort((a, b) => a - b);\n        \n        for (const zValue of sortedZValues) {\n            const layerDataForZ = layersByZ.get(zValue)!;\n            \n            // Only create layer if it has tiles\n            if (layerDataForZ.some(gid => gid !== 0)) {\n                const newLayer = {\n                    ...layer,\n                    name: `${layer.name}_z${zValue}`, // Always add _z suffix\n                    data: layerDataForZ,\n                    properties: {\n                        ...layer.properties,\n                        z: zValue\n                    }\n                };\n                \n                reorganizedLayers.push(newLayer);\n            }\n        }\n    }\n    \n    // Sort final layers to ensure z=0 layers come first, then by z value\n    reorganizedLayers.sort((a, b) => {\n        const zA = a.properties?.z ?? 0.5;\n        const zB = b.properties?.z ?? 0.5;\n        return zA - zB;\n    });\n    \n    return reorganizedLayers;\n}\n\nexport function TiledMap(props) {\n    const { map, basePath, createLayersPerTilesZ } = useProps(props, {\n        createLayersPerTilesZ: false,\n        basePath: ''\n    })\n    const layers = signal<TiledLayer[]>([])\n    const objectLayer = props.objectLayer\n    let tilesets: TileSet[] = []\n    let mapData: TiledMap = {} as TiledMap\n\n    const parseTmx = async (file: string, basePath: string = '') => {\n        if (typeof file !== 'string') {\n            return file\n        }\n        // @ts-ignore\n        const parser = new TiledParserFile(\n            file,\n            {\n                basePath\n            }\n        )\n        const data = await parser.parseFilePromise({\n            getOnlyBasename: false\n        })\n\n        return data\n    }\n\n    effect(async () => {\n        const _map = map()\n        if (_map) {\n            mapData = await parseTmx(_map, basePath())\n            tilesets = [] // Reset tilesets array\n            for (let tileSet of mapData.tilesets) {\n                // @ts-ignore\n                if (tileSet.tile) tileSet.tiles = tileSet.tile\n                if (!tileSet.tiles) tileSet.tiles = []\n                tilesets.push(await new TileSet(tileSet).load(tileSet.image.source))\n            }\n            \n            // Reorganize layers by tile z property if enabled\n            let finalLayers = mapData.layers;\n            if (createLayersPerTilesZ()) {\n                finalLayers = reorganizeLayersByTileZ(mapData.layers, tilesets, mapData);\n            }\n            \n            layers.set(finalLayers)\n        }\n    })\n\n    const createLayer = (layers, props = {}) => {\n        return h(Container, props, loop<any>(layers, (layer) => {\n            switch (layer.type) {\n                case TiledLayerType.Tile:\n                    return h(CompositeTileLayer, {\n                        tilewidth: mapData.tilewidth,\n                        tileheight: mapData.tileheight,\n                        // @ts-ignore\n                        width: mapData.width,\n                        // @ts-ignore\n                        height: mapData.height,\n                        ...layer,\n                        tilesets\n                    })\n                case TiledLayerType.Image:\n                    const { width, height, source } = layer.image\n                    return h(TilingSprite, {\n                        image: source,\n                        ...layer,\n                        width: layer.repeatx ? layer.width * layer.tilewidth : width,\n                        height: layer.repeaty ? layer.height * layer.tileheight : height\n                    })\n                case TiledLayerType.Group:\n                    return createLayer(signal(layer.layers), layer)\n                case TiledLayerType.ObjectGroup:\n                    const child = objectLayer?.(layer)\n                    return h(Container, layer, child)\n                default:\n                    return h(Container)\n            }\n        }))\n    }\n\n    return h(Container, props, createLayer(layers))\n}"
  },
  {
    "path": "packages/presets/src/Weathers/fog.ts",
    "content": "import { GlProgram } from \"pixi.js\";\n\nexport function createFogShader(): GlProgram {\n  const vertexSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 aPosition;\n    in vec2 aUV;\n    out vec2 vUV;\n    uniform mat3 uProjectionMatrix;\n    uniform mat3 uWorldTransformMatrix;\n    uniform mat3 uTransformMatrix;\n    void main(void) {\n      vUV = aUV;\n      mat3 modelViewProjectionMatrix = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n      gl_Position = vec4((modelViewProjectionMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n    }\n  `;\n\n  const fragmentSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 vUV;\n    out vec4 finalColor;\n\n    uniform float uTime;\n    uniform vec2  uResolution;\n    uniform float uSpeed;\n    uniform float uScale;\n    uniform float uDensity;\n    uniform float uHeight;\n    uniform vec2  uViewportOrigin;\n\n    float hash(vec2 p) {\n      return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n    }\n\n    float noise(vec2 p) {\n      vec2 i = floor(p);\n      vec2 f = fract(p);\n      float a = hash(i);\n      float b = hash(i + vec2(1.0, 0.0));\n      float c = hash(i + vec2(0.0, 1.0));\n      float d = hash(i + vec2(1.0, 1.0));\n      vec2 u = f * f * (3.0 - 2.0 * f);\n      return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;\n    }\n\n    float fbm(vec2 p) {\n      float value = 0.0;\n      float amp = 0.5;\n      value += amp * noise(p);\n      p = p * 2.03 + vec2(17.13, 9.37);\n      amp *= 0.55;\n      value += amp * noise(p);\n      p = p * 2.01 + vec2(31.71, 4.23);\n      amp *= 0.55;\n      value += amp * noise(p);\n      p = p * 2.02 + vec2(15.41, 27.19);\n      amp *= 0.55;\n      value += amp * noise(p);\n      return value;\n    }\n\n    void main() {\n      vec2 safeResolution = max(uResolution, vec2(1.0));\n      vec2 rawUv = vUV;\n      vec2 uv = rawUv;\n      float aspect = safeResolution.x / safeResolution.y;\n      uv.x *= aspect;\n      vec2 viewportShift = vec2(\n        (uViewportOrigin.x / safeResolution.x) * aspect,\n        uViewportOrigin.y / safeResolution.y\n      );\n      vec2 worldUv = uv + viewportShift;\n\n      float normalizedDensity = uDensity;\n      if (normalizedDensity > 4.0) {\n        normalizedDensity = normalizedDensity / 120.0;\n      }\n      float density = clamp(normalizedDensity, 0.0, 2.4);\n      float scale = clamp(uScale, 0.25, 4.0);\n      float speed = max(uSpeed * 8.0, 0.18);\n\n      vec2 driftA = vec2(uTime * 0.06 * speed, uTime * 0.02 * speed);\n      vec2 driftB = vec2(-uTime * 0.042 * speed, uTime * 0.016 * speed);\n      vec2 wobble = vec2(\n        sin(uTime * 0.23 * speed + worldUv.y * 4.0) * 0.03,\n        cos(uTime * 0.17 * speed + worldUv.x * 3.2) * 0.018\n      );\n      vec2 flowUv = worldUv + wobble;\n\n      float layerA = fbm(flowUv * scale + driftA);\n      float layerB = fbm(flowUv * (scale * 1.7) + driftB);\n      float layerC = fbm(vec2(flowUv.x * 0.75, flowUv.y * 1.35) * (scale * 1.2) + vec2(driftA.x * 0.6, -driftA.y * 0.8));\n\n      float wisps = smoothstep(0.2, 0.82, layerA);\n      float detail = smoothstep(0.28, 0.9, layerB);\n      float fogPattern = clamp(wisps * 0.55 + detail * 0.3 + layerC * 0.35, 0.0, 1.2);\n\n      float heightControl = clamp(uHeight, 0.0, 1.0);\n      float fullScreen = step(0.99, heightControl);\n      float groundFog = pow(clamp(rawUv.y, 0.0, 1.0), 0.42);\n      float heightFactor = mix(groundFog, 1.0, heightControl);\n      heightFactor = mix(heightFactor, 1.0, fullScreen);\n\n      float breathing = 0.9 + 0.1 * sin(uTime * 0.25 * speed);\n      float fog = fogPattern * density * heightFactor * breathing;\n      float alpha = clamp(fog * 0.82, 0.0, 0.82);\n\n      vec3 baseColor = vec3(0.84, 0.88, 0.94);\n      vec3 brightColor = vec3(0.95, 0.97, 1.0);\n      vec3 fogColor = mix(baseColor, brightColor, detail * 0.45);\n      finalColor = vec4(fogColor * alpha, alpha);\n    }\n  `;\n\n  return new GlProgram({\n    vertex: vertexSrc,\n    fragment: fragmentSrc\n  });\n}\n\nexport function createCloudShader(): GlProgram {\n  const vertexSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 aPosition;\n    in vec2 aUV;\n    out vec2 vUV;\n    uniform mat3 uProjectionMatrix;\n    uniform mat3 uWorldTransformMatrix;\n    uniform mat3 uTransformMatrix;\n    void main(void) {\n      vUV = aUV;\n      mat3 modelViewProjectionMatrix = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n      gl_Position = vec4((modelViewProjectionMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n    }\n  `;\n\n  const fragmentSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 vUV;\n    out vec4 finalColor;\n\n    uniform float uTime;\n    uniform vec2  uResolution;\n    uniform float uSpeed;\n    uniform float uScale;\n    uniform float uDensity;\n    uniform float uHeight;\n    uniform vec2  uViewportOrigin;\n    uniform float uSunIntensity;\n    uniform vec2  uSunDirection;\n    uniform float uRaySpread;\n    uniform float uRayTwinkle;\n    uniform float uRayTwinkleSpeed;\n\n    float hash(vec2 p) {\n      return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n    }\n\n    float noise(vec2 p) {\n      vec2 i = floor(p);\n      vec2 f = fract(p);\n      float a = hash(i);\n      float b = hash(i + vec2(1.0, 0.0));\n      float c = hash(i + vec2(0.0, 1.0));\n      float d = hash(i + vec2(1.0, 1.0));\n      vec2 u = f * f * (3.0 - 2.0 * f);\n      return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;\n    }\n\n    float fbm(vec2 p) {\n      float v = 0.0;\n      float a = 0.7;\n      v += a * noise(p);\n      p *= 2.1;\n      a *= 0.5;\n      v += a * noise(p + 17.0);\n      p *= 2.2;\n      a *= 0.5;\n      v += a * noise(p + 29.0);\n      return v;\n    }\n\n    void main() {\n      vec2 safeResolution = max(uResolution, vec2(1.0));\n      vec2 uv = vUV;\n      float aspect = safeResolution.x / safeResolution.y;\n      uv.x *= aspect;\n      vec2 viewportShift = vec2(\n        (uViewportOrigin.x / safeResolution.x) * aspect,\n        uViewportOrigin.y / safeResolution.y\n      );\n      vec2 worldUv = uv + viewportShift;\n\n      float normalizedDensity = uDensity;\n      if (normalizedDensity > 4.0) {\n        normalizedDensity = normalizedDensity / 100.0;\n      }\n      float density = clamp(normalizedDensity, 0.0, 2.0);\n      float scale = clamp(uScale, 0.2, 4.0);\n      float speed = max(uSpeed * 6.0, 0.12);\n      vec2 driftMain = vec2(uTime * 0.04 * speed, uTime * 0.012 * speed);\n      vec2 driftDetail = vec2(-uTime * 0.028 * speed, uTime * 0.01 * speed);\n      vec2 wobble = vec2(\n        sin(uTime * 0.18 * speed + worldUv.y * 4.8) * 0.035,\n        cos(uTime * 0.16 * speed + worldUv.x * 3.7) * 0.02\n      );\n      vec2 flowUv = worldUv + wobble;\n\n      float cloudNoise = fbm(flowUv * scale + driftMain);\n      float detailNoise = fbm(flowUv * (scale * 2.4) + driftDetail);\n\n      float shape = smoothstep(0.4, 0.93, cloudNoise);\n      float detail = smoothstep(0.36, 0.9, detailNoise);\n      float puff = shape * (0.55 + 0.45 * detail);\n\n      float heightControl = clamp(uHeight, 0.0, 1.0);\n      float fullScreen = step(0.99, heightControl);\n      float skyHeight = pow(clamp(1.0 - vUV.y, 0.0, 1.0), 0.68);\n      float heightFactor = mix(skyHeight, 1.0, heightControl);\n      heightFactor = mix(heightFactor, 1.0, fullScreen);\n      float cloud = puff * density * 0.72 * heightFactor;\n      float cloudAlpha = clamp(cloud, 0.0, 0.68);\n\n      vec2 sunDir = uSunDirection;\n      if (length(sunDir) < 0.0001) {\n        sunDir = vec2(0.55, 1.0);\n      }\n      sunDir = normalize(sunDir);\n      vec2 rayUv = worldUv;\n      float spread = clamp(uRaySpread, 0.35, 2.5);\n      float rayCoord = dot(rayUv, sunDir) * (6.5 / spread);\n      float rayNoise = fbm(vec2(rayCoord, rayUv.y * 0.55));\n      float shafts = smoothstep(0.5, 0.9, rayNoise);\n      float skyFade = pow(clamp(1.0 - vUV.y, 0.0, 1.0), 1.25);\n      float cloudGap = clamp(1.0 - cloudAlpha * 1.05, 0.0, 1.0);\n      float twinkleAmount = clamp(uRayTwinkle, 0.0, 1.5);\n      float twinkleSpeed = max(uRayTwinkleSpeed, 0.01);\n      float twinklePulse = 0.5 + 0.5 * sin(uTime * 1.9 * twinkleSpeed + rayCoord * 1.8);\n      float twinkleNoise = fbm(vec2(rayCoord * 1.35 + 13.7, uTime * 0.1 * twinkleSpeed));\n      float twinkle = mix(\n        1.0,\n        clamp(0.7 + 0.35 * twinklePulse + 0.25 * twinkleNoise, 0.35, 1.55),\n        twinkleAmount\n      );\n      float rayAlpha = shafts * skyFade * cloudGap * clamp(uSunIntensity, 0.0, 2.0) * twinkle * 0.58;\n\n      vec3 cloudDark = vec3(0.82, 0.87, 0.94);\n      vec3 cloudBright = vec3(0.98, 0.99, 1.0);\n      vec3 cloudColor = mix(cloudDark, cloudBright, detail * 0.55);\n      vec3 rayColor = vec3(1.0, 0.95, 0.8);\n\n      float totalAlpha = cloudAlpha + rayAlpha;\n      float alpha = clamp(totalAlpha, 0.0, 0.86);\n      vec3 premulColor = cloudColor * cloudAlpha + rayColor * rayAlpha;\n      if (totalAlpha > 0.0001) {\n        premulColor *= (alpha / totalAlpha);\n      }\n      finalColor = vec4(premulColor, alpha);\n    }\n  `;\n\n  return new GlProgram({\n    vertex: vertexSrc,\n    fragment: fragmentSrc\n  });\n}\n"
  },
  {
    "path": "packages/presets/src/Weathers/index.ts",
    "content": "import {\n  tick,\n  useProps,\n  h,\n  Mesh,\n  signal,\n  mount,\n  effect as watchEffect,\n} from \"canvasengine\";\nimport { Geometry, Shader, UniformGroup } from \"pixi.js\";\nimport { createRainShader } from \"./rain\";\nimport { createSnowShader } from \"./snow\";\nimport { createFogShader, createCloudShader } from \"./fog\";\n\nexport const RAIN_PRESETS = {\n  lightRain: { effect: \"rain\", speed: 0.35, windDirection: 0.1, windStrength: 0.15, density: 110, maxDrops: 90 },\n  steadyRain: { effect: \"rain\", speed: 0.6, windDirection: 0.2, windStrength: 0.3, density: 180, maxDrops: 120 },\n  stormRain: { effect: \"rain\", speed: 1.4, windDirection: 0.7, windStrength: 0.75, density: 300, maxDrops: 150 },\n} as const;\n\nexport const SNOW_PRESETS = {\n  lightSnow: { effect: \"snow\", speed: 0.35, windDirection: 0.1, windStrength: 0.18, density: 90, maxDrops: 100 },\n  winterSnow: { effect: \"snow\", speed: 0.5, windDirection: 0.2, windStrength: 0.28, density: 150, maxDrops: 130 },\n  blizzardSnow: { effect: \"snow\", speed: 1.1, windDirection: 0.8, windStrength: 0.75, density: 290, maxDrops: 160 },\n} as const;\n\nexport const FOG_PRESETS = {\n  rpgMorningMist: { effect: \"fog\", speed: 0.16, density: 0.75, height: 0.45, scale: 1.35 },\n  rpgForestFog: { effect: \"fog\", speed: 0.22, density: 1.0, height: 0.62, scale: 1.75 },\n  rpgSwampFog: { effect: \"fog\", speed: 0.14, density: 1.3, height: 0.55, scale: 2.1 },\n  rpgNightFog: { effect: \"fog\", speed: 0.12, density: 1.15, height: 0.58, scale: 1.9 },\n  rpgHeavyFog: { effect: \"fog\", speed: 0.1, density: 1.7, height: 0.72, scale: 2.3 },\n} as const;\n\nexport const CLOUD_PRESETS = {\n  lightClouds: { effect: \"cloud\", speed: 0.16, density: 0.55, height: 0.72, scale: 1.35, sunIntensity: 1.0, sunAngle: 0.84, raySpread: 0.92, rayTwinkle: 0.25, rayTwinkleSpeed: 0.9 },\n  overcastClouds: { effect: \"cloud\", speed: 0.12, density: 0.95, height: 0.86, scale: 1.85, sunIntensity: 0.4, sunAngle: 0.95, raySpread: 1.15, rayTwinkle: 0.18, rayTwinkleSpeed: 0.7 },\n  stormClouds: { effect: \"cloud\", speed: 0.2, density: 1.25, height: 0.94, scale: 2.2, sunIntensity: 0.12, sunAngle: 1.08, raySpread: 1.35, rayTwinkle: 0.12, rayTwinkleSpeed: 0.6 },\n  goldenHourRays: { effect: \"cloud\", speed: 0.14, density: 0.72, height: 0.82, scale: 1.5, sunIntensity: 1.3, sunAngle: 0.72, raySpread: 0.78, rayTwinkle: 0.78, rayTwinkleSpeed: 1.4 },\n  sunnySoftRays: { effect: \"cloud\", speed: 0.13, density: 0.62, height: 0.76, scale: 1.4, sunIntensity: 1.05, sunAngle: 0.8, raySpread: 0.95, rayTwinkle: 0.35, rayTwinkleSpeed: 0.95 },\n  sunsetTwinkleRays: { effect: \"cloud\", speed: 0.1, density: 0.74, height: 0.84, scale: 1.55, sunIntensity: 1.35, sunAngle: 0.64, raySpread: 0.8, rayTwinkle: 1.0, rayTwinkleSpeed: 1.6 },\n  dramaticCrepuscularRays: { effect: \"cloud\", speed: 0.11, density: 0.9, height: 0.9, scale: 1.9, sunIntensity: 1.5, sunAngle: 0.7, raySpread: 0.68, rayTwinkle: 0.6, rayTwinkleSpeed: 1.2 },\n  morningHazeRays: { effect: \"cloud\", speed: 0.09, density: 0.52, height: 0.7, scale: 1.3, sunIntensity: 0.9, sunAngle: 0.9, raySpread: 1.05, rayTwinkle: 0.42, rayTwinkleSpeed: 0.8 },\n} as const;\n\nexport const WEATHER_PRESETS = {\n  rain: RAIN_PRESETS,\n  snow: SNOW_PRESETS,\n  fog: FOG_PRESETS,\n  cloud: CLOUD_PRESETS,\n} as const;\n\n\n/**\n * Weather Effect Component (optimized)\n */\nexport const WeatherEffect = (options) => {\n  const {\n    effect: effectType = signal('rain'),\n    speed = signal(0.5),\n    windDirection = signal(0.0),\n    windStrength = signal(0.2),\n    density = signal(120.0),  // Reduced default density for better performance\n    maxDrops = signal(80.0),  // Reduced default maxDrops for better performance\n    height = signal(1.0),  // Fog/cloud height parameter (0 = bottom, 1 = full)\n    scale = signal(2.0),  // Fog noise scale parameter\n    sunIntensity = signal(0.85),  // Cloud sunlight shaft intensity\n    sunAngle = signal(0.85),  // Cloud sunlight direction angle in radians\n    raySpread = signal(1.0),  // Cloud sunlight ray spread\n    rayTwinkle = signal(0.45),  // Cloud sunlight twinkle amount\n    rayTwinkleSpeed = signal(1.0),  // Cloud sunlight twinkle speed\n    resolution,\n    ...meshProps\n  } = useProps(options);\n\n  // Auto-detect resolution from canvas if not provided\n  const defaultResolution = signal([1000, 1000]);\n  const viewWidth = signal(defaultResolution()[0]);\n  const viewHeight = signal(defaultResolution()[1]);\n  const originX = signal(0);\n  const originY = signal(0);\n  let viewportRef;\n  const effectSignal =\n    typeof effectType === \"function\" ? effectType : signal(effectType);\n  const resolutionSignal = resolution\n    ? (typeof resolution === \"function\" ? resolution : signal(resolution))\n    : defaultResolution;\n\n  // Try to get canvas size from context if available\n  mount((element) => {\n    const context = element.props.context;\n    let parent = element.parent;\n    let isInsideViewport = false;\n    while (parent) {\n      if (parent.tag === \"Viewport\") {\n        isInsideViewport = true;\n        break;\n      }\n      parent = parent.parent;\n    }\n    viewportRef = isInsideViewport ? context?.viewport : undefined;\n    if (viewportRef?.getVisibleBounds) {\n      const bounds = viewportRef.getVisibleBounds();\n      if (bounds && bounds.width > 0 && bounds.height > 0) {\n        defaultResolution.set([bounds.width, bounds.height]);\n        viewWidth.set(bounds.width);\n        viewHeight.set(bounds.height);\n        originX.set(bounds.x);\n        originY.set(bounds.y);\n      }\n    }\n    if (context?.canvasSize) {\n      watchEffect(() => {\n        const size = context.canvasSize();\n        if (size && size.width > 0 && size.height > 0) {\n          if (!viewportRef?.getVisibleBounds) {\n            defaultResolution.set([size.width, size.height]);\n            viewWidth.set(size.width);\n            viewHeight.set(size.height);\n            originX.set(0);\n            originY.set(0);\n          }\n        }\n      });\n    }\n  });\n\n  const speedSignal = typeof speed === \"function\" ? speed : signal(speed);\n  const windDirectionSignal =\n    typeof windDirection === \"function\" ? windDirection : signal(windDirection);\n  const windStrengthSignal =\n    typeof windStrength === \"function\" ? windStrength : signal(windStrength);\n  const densitySignal =\n    typeof density === \"function\" ? density : signal(density);\n  const maxDropsSignal =\n    typeof maxDrops === \"function\" ? maxDrops : signal(maxDrops);\n  const heightSignal =\n    typeof height === \"function\" ? height : signal(height);\n  const scaleSignal =\n    typeof scale === \"function\" ? scale : signal(scale);\n  const sunIntensitySignal =\n    typeof sunIntensity === \"function\" ? sunIntensity : signal(sunIntensity);\n  const sunAngleSignal =\n    typeof sunAngle === \"function\" ? sunAngle : signal(sunAngle);\n  const raySpreadSignal =\n    typeof raySpread === \"function\" ? raySpread : signal(raySpread);\n  const rayTwinkleSignal =\n    typeof rayTwinkle === \"function\" ? rayTwinkle : signal(rayTwinkle);\n  const rayTwinkleSpeedSignal =\n    typeof rayTwinkleSpeed === \"function\" ? rayTwinkleSpeed : signal(rayTwinkleSpeed);\n\n  const normalizeHeightValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) ? value : 1.0;\n  const normalizeSunIntensityValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) ? Math.max(0, value) : 0.85;\n  const normalizeSunAngleValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) ? value : 0.85;\n  const normalizeRaySpreadValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : 1.0;\n  const normalizeRayTwinkleValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) ? Math.max(0, value) : 0.45;\n  const normalizeRayTwinkleSpeedValue = (value) =>\n    typeof value === \"number\" && Number.isFinite(value) && value > 0 ? value : 1.0;\n  const sunDirectionFromAngle = (angle) => [Math.cos(angle), Math.sin(angle)];\n  const normalizeResolutionValue = (value) => {\n    if (!Array.isArray(value)) return [1, 1];\n    const width =\n      typeof value[0] === \"number\" && Number.isFinite(value[0]) && value[0] > 0\n        ? value[0]\n        : 1;\n    const height =\n      typeof value[1] === \"number\" && Number.isFinite(value[1]) && value[1] > 0\n        ? value[1]\n        : 1;\n    return [width, height];\n  };\n\n  let glProgram;\n  let uniformConfig;\n\n  if (effectSignal() === 'rain') {\n    glProgram = createRainShader();\n    uniformConfig = {\n      uTime: { value: 0, type: \"f32\" },\n      uResolution: { value: normalizeResolutionValue(resolutionSignal()), type: \"vec2<f32>\" },\n      uRainSpeed: { value: speedSignal(), type: \"f32\" },\n      uWindDirection: { value: windDirectionSignal(), type: \"f32\" },\n      uWindStrength: { value: windStrengthSignal(), type: \"f32\" },\n      uRainDensity: { value: densitySignal(), type: \"f32\" },\n      uMaxDrops: { value: maxDropsSignal(), type: \"f32\" },\n    };\n  } else if (effectSignal() === 'snow') {\n    glProgram = createSnowShader();\n    uniformConfig = {\n      uTime: { value: 0, type: \"f32\" },\n      uResolution: { value: normalizeResolutionValue(resolutionSignal()), type: \"vec2<f32>\" },\n      uSnowSpeed: { value: speedSignal(), type: \"f32\" },\n      uWindDirection: { value: windDirectionSignal(), type: \"f32\" },\n      uWindStrength: { value: windStrengthSignal(), type: \"f32\" },\n      uSnowDensity: { value: densitySignal(), type: \"f32\" },\n      uMaxFlakes: { value: maxDropsSignal(), type: \"f32\" },\n    };\n  } else if (effectSignal() === 'fog') {\n    glProgram = createFogShader();\n    uniformConfig = {\n      uTime: { value: 0, type: \"f32\" },\n      uResolution: { value: normalizeResolutionValue(resolutionSignal()), type: \"vec2<f32>\" },\n      uSpeed: { value: speedSignal(), type: \"f32\" },\n      uScale: { value: scaleSignal(), type: \"f32\" },\n      uDensity: { value: densitySignal(), type: \"f32\" },\n      uHeight: { value: normalizeHeightValue(heightSignal()), type: \"f32\" },\n      uViewportOrigin: { value: [originX(), originY()], type: \"vec2<f32>\" },\n    };\n  } else if (effectSignal() === 'cloud') {\n    const initialSunAngle = normalizeSunAngleValue(sunAngleSignal());\n    glProgram = createCloudShader();\n    uniformConfig = {\n      uTime: { value: 0, type: \"f32\" },\n      uResolution: { value: normalizeResolutionValue(resolutionSignal()), type: \"vec2<f32>\" },\n      uSpeed: { value: speedSignal(), type: \"f32\" },\n      uScale: { value: scaleSignal(), type: \"f32\" },\n      uDensity: { value: densitySignal(), type: \"f32\" },\n      uHeight: { value: normalizeHeightValue(heightSignal()), type: \"f32\" },\n      uViewportOrigin: { value: [originX(), originY()], type: \"vec2<f32>\" },\n      uSunIntensity: { value: normalizeSunIntensityValue(sunIntensitySignal()), type: \"f32\" },\n      uSunDirection: { value: sunDirectionFromAngle(initialSunAngle), type: \"vec2<f32>\" },\n      uRaySpread: { value: normalizeRaySpreadValue(raySpreadSignal()), type: \"f32\" },\n      uRayTwinkle: { value: normalizeRayTwinkleValue(rayTwinkleSignal()), type: \"f32\" },\n      uRayTwinkleSpeed: { value: normalizeRayTwinkleSpeedValue(rayTwinkleSpeedSignal()), type: \"f32\" },\n    };\n  } else {\n    throw new Error(`Unknown weather effect: ${effectSignal()}. Supported: rain, snow, fog, cloud`);\n  }\n\n  const uniformGroup = new UniformGroup(uniformConfig);\n\n  const shader = new Shader({\n    glProgram,\n    resources: { uniforms: uniformGroup },\n  });\n\n  const geometry = new Geometry({\n    attributes: {\n      aPosition: [0, 0, 1, 0, 1, 1, 0, 1],\n      aUV: [0, 0, 1, 0, 1, 1, 0, 1],\n    },\n    indexBuffer: [0, 1, 2, 0, 2, 3],\n  });\n\n  // Initialize time with a random offset to prevent initial clustering\n  let timeAccumulator = Math.random() * 10.0;\n  \n  // Cache previous values to avoid unnecessary uniform updates\n  let prevResolution = [...normalizeResolutionValue(resolutionSignal())];\n  let prevWindDirection = windDirectionSignal();\n  let prevWindStrength = windStrengthSignal();\n  let prevSpeed = speedSignal();\n  let prevDensity = densitySignal();\n  let prevMaxDrops = maxDropsSignal();\n  let prevHeight = heightSignal();\n  let prevScale = scaleSignal();\n  let prevSunIntensity = normalizeSunIntensityValue(sunIntensitySignal());\n  let prevSunAngle = normalizeSunAngleValue(sunAngleSignal());\n  let prevRaySpread = normalizeRaySpreadValue(raySpreadSignal());\n  let prevRayTwinkle = normalizeRayTwinkleValue(rayTwinkleSignal());\n  let prevRayTwinkleSpeed = normalizeRayTwinkleSpeedValue(rayTwinkleSpeedSignal());\n  let prevOriginX = originX();\n  let prevOriginY = originY();\n\n  tick(({ deltaTime }) => {\n    if (viewportRef?.getVisibleBounds) {\n      const bounds = viewportRef.getVisibleBounds();\n      if (bounds && bounds.width > 0 && bounds.height > 0) {\n        const nextWidth = bounds.width;\n        const nextHeight = bounds.height;\n        const nextOriginX = bounds.x;\n        const nextOriginY = bounds.y;\n        if (nextWidth !== viewWidth()) viewWidth.set(nextWidth);\n        if (nextHeight !== viewHeight()) viewHeight.set(nextHeight);\n        if (nextOriginX !== originX()) originX.set(nextOriginX);\n        if (nextOriginY !== originY()) originY.set(nextOriginY);\n        const currentResolution = defaultResolution();\n        if (currentResolution[0] !== nextWidth || currentResolution[1] !== nextHeight) {\n          defaultResolution.set([nextWidth, nextHeight]);\n        }\n      }\n    }\n\n    // Always update time (required for animation)\n    timeAccumulator += deltaTime / 600;\n    uniformGroup.uniforms.uTime = timeAccumulator;\n\n    // Only update resolution if it changed\n    const currentResolution = normalizeResolutionValue(resolutionSignal());\n    if (currentResolution[0] !== prevResolution[0] || currentResolution[1] !== prevResolution[1]) {\n      uniformGroup.uniforms.uResolution = currentResolution;\n      prevResolution = [...currentResolution];\n    }\n\n    if (effectSignal() === 'fog' || effectSignal() === 'cloud') {\n      const currentOriginX = originX();\n      const currentOriginY = originY();\n      if (currentOriginX !== prevOriginX || currentOriginY !== prevOriginY) {\n        uniformGroup.uniforms.uViewportOrigin = [currentOriginX, currentOriginY];\n        prevOriginX = currentOriginX;\n        prevOriginY = currentOriginY;\n      }\n    }\n\n    // Only update wind if it changed\n    const currentWindDirection = windDirectionSignal();\n    if (currentWindDirection !== prevWindDirection) {\n      uniformGroup.uniforms.uWindDirection = currentWindDirection;\n      prevWindDirection = currentWindDirection;\n    }\n\n    // Update wind strength only for rain and snow (fog doesn't use it)\n    if (effectSignal() === 'rain' || effectSignal() === 'snow') {\n      const currentWindStrength = windStrengthSignal();\n      if (currentWindStrength !== prevWindStrength) {\n        uniformGroup.uniforms.uWindStrength = currentWindStrength;\n        prevWindStrength = currentWindStrength;\n      }\n    }\n\n    if (effectSignal() === 'rain') {\n      // Only update rain-specific uniforms if they changed\n      const currentSpeed = speedSignal();\n      if (currentSpeed !== prevSpeed) {\n        uniformGroup.uniforms.uRainSpeed = currentSpeed;\n        prevSpeed = currentSpeed;\n      }\n\n      const currentDensity = densitySignal();\n      if (currentDensity !== prevDensity) {\n        uniformGroup.uniforms.uRainDensity = currentDensity;\n        prevDensity = currentDensity;\n      }\n\n      const currentMaxDrops = maxDropsSignal();\n      if (currentMaxDrops !== prevMaxDrops) {\n        uniformGroup.uniforms.uMaxDrops = currentMaxDrops;\n        prevMaxDrops = currentMaxDrops;\n      }\n    } else if (effectSignal() === 'snow') {\n      // Only update snow-specific uniforms if they changed\n      const currentSpeed = speedSignal();\n      if (currentSpeed !== prevSpeed) {\n        uniformGroup.uniforms.uSnowSpeed = currentSpeed;\n        prevSpeed = currentSpeed;\n      }\n\n      const currentDensity = densitySignal();\n      if (currentDensity !== prevDensity) {\n        uniformGroup.uniforms.uSnowDensity = currentDensity;\n        prevDensity = currentDensity;\n      }\n\n      const currentMaxDrops = maxDropsSignal();\n      if (currentMaxDrops !== prevMaxDrops) {\n        uniformGroup.uniforms.uMaxFlakes = currentMaxDrops;\n        prevMaxDrops = currentMaxDrops;\n      }\n    } else if (effectSignal() === 'fog' || effectSignal() === 'cloud') {\n      // Only update fog-specific uniforms if they changed\n      const currentSpeed = speedSignal();\n      if (currentSpeed !== prevSpeed) {\n        uniformGroup.uniforms.uSpeed = currentSpeed;\n        prevSpeed = currentSpeed;\n      }\n\n      const currentScale = scaleSignal();\n      if (currentScale !== prevScale) {\n        uniformGroup.uniforms.uScale = currentScale;\n        prevScale = currentScale;\n      }\n\n      const currentDensity = densitySignal();\n      if (currentDensity !== prevDensity) {\n        uniformGroup.uniforms.uDensity = currentDensity;\n        prevDensity = currentDensity;\n      }\n\n      const currentHeight = normalizeHeightValue(heightSignal());\n      if (currentHeight !== prevHeight) {\n        uniformGroup.uniforms.uHeight = currentHeight;\n        prevHeight = currentHeight;\n      }\n\n      if (effectSignal() === 'cloud') {\n        const currentSunIntensity = normalizeSunIntensityValue(sunIntensitySignal());\n        if (currentSunIntensity !== prevSunIntensity) {\n          uniformGroup.uniforms.uSunIntensity = currentSunIntensity;\n          prevSunIntensity = currentSunIntensity;\n        }\n\n        const currentSunAngle = normalizeSunAngleValue(sunAngleSignal());\n        if (currentSunAngle !== prevSunAngle) {\n          uniformGroup.uniforms.uSunDirection = sunDirectionFromAngle(currentSunAngle);\n          prevSunAngle = currentSunAngle;\n        }\n\n        const currentRaySpread = normalizeRaySpreadValue(raySpreadSignal());\n        if (currentRaySpread !== prevRaySpread) {\n          uniformGroup.uniforms.uRaySpread = currentRaySpread;\n          prevRaySpread = currentRaySpread;\n        }\n\n        const currentRayTwinkle = normalizeRayTwinkleValue(rayTwinkleSignal());\n        if (currentRayTwinkle !== prevRayTwinkle) {\n          uniformGroup.uniforms.uRayTwinkle = currentRayTwinkle;\n          prevRayTwinkle = currentRayTwinkle;\n        }\n\n        const currentRayTwinkleSpeed = normalizeRayTwinkleSpeedValue(rayTwinkleSpeedSignal());\n        if (currentRayTwinkleSpeed !== prevRayTwinkleSpeed) {\n          uniformGroup.uniforms.uRayTwinkleSpeed = currentRayTwinkleSpeed;\n          prevRayTwinkleSpeed = currentRayTwinkleSpeed;\n        }\n      }\n    }\n  });\n\n  return h(Mesh, {\n    ...meshProps,\n    geometry,\n    shader,\n    width: viewWidth,\n    height: viewHeight,\n    x: originX,\n    y: originY,\n  });\n};\n\nexport const Weather = WeatherEffect;\n"
  },
  {
    "path": "packages/presets/src/Weathers/rain.ts",
    "content": "import { GlProgram } from \"pixi.js\";\n\nexport function createRainShader(): GlProgram {\n  const vertexSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 aPosition;\n    in vec2 aUV;\n    out vec2 vUV;\n    uniform mat3 uProjectionMatrix;\n    uniform mat3 uWorldTransformMatrix;\n    uniform mat3 uTransformMatrix;\n    void main(void) {\n      vUV = aUV;\n      mat3 modelViewProjectionMatrix = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n      gl_Position = vec4((modelViewProjectionMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n    }\n  `;\n\n  const fragmentSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 vUV;\n    out vec4 finalColor;\n\n    uniform float uTime;\n    uniform vec2  uResolution;\n    uniform float uRainSpeed;\n    uniform float uWindDirection;\n    uniform float uWindStrength;\n    uniform float uRainDensity;\n    uniform float uMaxDrops;\n\n    float hash(vec2 p) {\n      return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n    }\n\n    float rainLayer(\n      vec2 uv,\n      float t,\n      float scale,\n      float speed,\n      float slant,\n      float density,\n      float width,\n      float length\n    ) {\n      vec2 dir = normalize(vec2(slant, 1.0));\n      vec2 perp = vec2(-dir.y, dir.x);\n\n      float along = dot(uv, dir) * scale - t * speed;\n      float across = dot(uv, perp) * scale;\n\n      vec2 p = vec2(across, along);\n      vec2 cell = floor(p);\n      vec2 f = fract(p);\n\n      float rnd = hash(cell);\n      float rnd2 = hash(cell + 13.17);\n\n      float x = rnd;\n      float dropWidth = width * (0.7 + rnd2 * 0.6);\n      float dropLength = length * (0.5 + rnd * 0.6);\n\n      float line = 1.0 - smoothstep(0.0, dropWidth, abs(f.x - x));\n      float segment = smoothstep(0.0, 0.03, f.y)\n        * (1.0 - smoothstep(dropLength, dropLength + 0.03, f.y));\n\n      float visible = step(rnd, density);\n      float intensity = line * segment * visible;\n      return intensity * (0.6 + 0.4 * rnd2);\n    }\n\n    void main() {\n      vec2 safeResolution = max(uResolution, vec2(1.0));\n      vec2 uv = vUV;\n      float aspect = safeResolution.x / safeResolution.y;\n      uv.x *= aspect;\n\n      float pixelCount = safeResolution.x * safeResolution.y;\n      float resolutionFactor = clamp(pixelCount / 700000.0, 0.7, 1.1);\n\n      float densityFactor = clamp(uRainDensity / 180.0, 0.35, 1.4);\n      float maxDropFactor = clamp(uMaxDrops / 90.0, 0.45, 1.1);\n      float density = clamp(densityFactor * maxDropFactor * resolutionFactor, 0.15, 1.0);\n\n      float slant = uWindDirection * uWindStrength * 0.6;\n      float speed = 1.3 * uRainSpeed + 0.4;\n\n      float rain = 0.0;\n      rain += rainLayer(uv, uTime, 24.0, speed * 1.2, slant, density, 0.026, 0.9);\n      rain += rainLayer(uv, uTime, 36.0, speed * 1.5, slant * 1.2, density * 0.85, 0.02, 0.72);\n      rain += rainLayer(uv, uTime, 52.0, speed * 1.8, slant * 1.4, density * 0.7, 0.016, 0.58);\n\n      float heightFade = mix(0.65, 1.0, uv.y);\n      rain *= heightFade;\n\n      vec3 rainColor = vec3(0.75, 0.85, 1.0);\n      float alpha = clamp(rain * 1.15, 0.0, 0.95);\n      finalColor = vec4(rainColor * alpha, alpha);\n    }\n  `;\n\n  return new GlProgram({ vertex: vertexSrc, fragment: fragmentSrc });\n}\n"
  },
  {
    "path": "packages/presets/src/Weathers/snow.ts",
    "content": "import { GlProgram } from \"pixi.js\";\n\n/**\n * Creates a performant snow shader program.\n * Optimized with early exits, capped loop count, and LOD based on resolution.\n */\nexport function createSnowShader(): GlProgram {\n  const vertexSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 aPosition;\n    in vec2 aUV;\n    out vec2 vUV;\n    uniform mat3 uProjectionMatrix;\n    uniform mat3 uWorldTransformMatrix;\n    uniform mat3 uTransformMatrix;\n    void main(void) {\n      vUV = aUV;\n      mat3 modelViewProjectionMatrix = uProjectionMatrix * uWorldTransformMatrix * uTransformMatrix;\n      gl_Position = vec4((modelViewProjectionMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);\n    }\n  `;\n\n  const fragmentSrc = /* glsl */ `\n    precision mediump float;\n    in vec2 vUV;\n    out vec4 finalColor;\n\n    uniform float uTime;\n    uniform vec2  uResolution;\n    uniform float uSnowSpeed;\n    uniform float uWindDirection;\n    uniform float uWindStrength;\n    uniform float uSnowDensity;\n    uniform float uMaxFlakes;\n\n    float hash(vec2 p) {\n      return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);\n    }\n\n    vec2 hash2(vec2 p) {\n      return vec2(\n        hash(p),\n        hash(p + 19.19)\n      );\n    }\n\n    float snowLayer(\n      vec2 uv,\n      float t,\n      float scale,\n      float speed,\n      float wind,\n      float density,\n      float sizeMin,\n      float sizeMax\n    ) {\n      vec2 p = uv;\n      p.x -= wind * t;\n      p.y -= t * speed;\n\n      p *= scale;\n      vec2 cell = floor(p);\n      vec2 f = fract(p);\n\n      float rnd = hash(cell);\n      if (rnd > density) {\n        return 0.0;\n      }\n\n      vec2 jitter = hash2(cell + 3.7);\n      float wobble = (hash(cell + 9.1) - 0.5) * 0.3;\n      vec2 center = jitter;\n      center.x += sin(t * 0.7 + jitter.y * 6.283) * 0.15 + wobble;\n      center.y += cos(t * 0.5 + jitter.x * 6.283) * 0.12;\n\n      float size = mix(sizeMin, sizeMax, rnd);\n      float dist = length(f - center);\n      float alpha = 1.0 - smoothstep(size * 0.4, size, dist);\n      float twinkle = 0.7 + 0.3 * sin(t * 1.2 + rnd * 6.283);\n      return alpha * twinkle;\n    }\n\n    void main() {\n      vec2 safeResolution = max(uResolution, vec2(1.0));\n      vec2 uv = vUV;\n      float aspect = safeResolution.x / safeResolution.y;\n      uv.x *= aspect;\n\n      float pixelCount = safeResolution.x * safeResolution.y;\n      float resolutionFactor = clamp(pixelCount / 900000.0, 0.6, 1.1);\n\n      float densityFactor = clamp(uSnowDensity / 180.0, 0.25, 1.3);\n      float maxFlakeFactor = clamp(uMaxFlakes / 90.0, 0.4, 1.1);\n      float density = clamp(densityFactor * maxFlakeFactor * resolutionFactor, 0.08, 1.0);\n\n      float wind = uWindDirection * uWindStrength * 0.45;\n      float speed = uSnowSpeed * 0.9 + 0.15;\n\n      float snow = 0.0;\n      snow += snowLayer(uv, uTime, 18.0, speed * 0.5, wind * 0.6, density, 0.1, 0.22) * 0.65;\n      snow += snowLayer(uv, uTime, 28.0, speed * 0.75, wind * 0.9, density * 0.9, 0.075, 0.16) * 0.8;\n      snow += snowLayer(uv, uTime, 40.0, speed, wind, density * 0.75, 0.05, 0.12);\n\n      float heightFade = mix(0.7, 1.0, uv.y);\n      snow *= heightFade;\n\n      vec3 snowColor = vec3(0.92, 0.95, 1.0);\n      float alpha = clamp(snow * 1.1, 0.0, 0.92);\n      finalColor = vec4(snowColor * alpha, alpha);\n    }\n  `;\n\n  return new GlProgram({ vertex: vertexSrc, fragment: fragmentSrc });\n}\n"
  },
  {
    "path": "packages/presets/src/fx/Fx.ts",
    "content": "import { Container, h, mount, on, tick, useProps } from \"canvasengine\";\nimport type { Container as PixiContainer } from \"pixi.js\";\nimport { FX_PRESETS } from \"./presets\";\nimport { FxRuntime } from \"./runtime\";\nimport type { FxPreset } from \"./types\";\n\nconst valueOf = (value) => (typeof value === \"function\" ? value() : value);\n\nfunction resolvePreset(name, preset): FxPreset {\n  const directPreset = valueOf(preset);\n  if (directPreset) return directPreset;\n  const presetName = valueOf(name);\n  const found = FX_PRESETS[presetName];\n  if (!found) {\n    throw new Error(`Unknown Fx preset: ${presetName}`);\n  }\n  return found;\n}\n\nexport function Fx(options) {\n  const {\n    name,\n    preset,\n    trigger,\n    autostart,\n    loop,\n    enabled,\n    x,\n    y,\n    rotation,\n    scale,\n    alpha,\n    seed,\n    maxParticles,\n    timeScale,\n    preload,\n    missingTexture,\n    onStart,\n    onComplete,\n    onParticleSpawn,\n    ...containerProps\n  } = useProps(options, {\n    name: \"hitSpark\",\n    autostart: false,\n    loop: false,\n    enabled: true,\n    x: 0,\n    y: 0,\n    rotation: 0,\n    scale: 1,\n    alpha: 1,\n    timeScale: 1,\n    preload: true,\n    missingTexture: \"shape\",\n  });\n\n  let container: PixiContainer | undefined;\n  let localRuntime = new FxRuntime({\n    seed: valueOf(seed),\n    maxParticles: valueOf(maxParticles),\n  });\n\n  const spawn = async (config = {}) => {\n    if (!container || !valueOf(enabled)) return;\n    const selectedPreset = resolvePreset(name, preset);\n    if (valueOf(preload)) {\n      await localRuntime.preload(selectedPreset);\n    }\n    const instance = localRuntime.spawn(container, selectedPreset, {\n      loop: valueOf(loop),\n      seed: valueOf(seed),\n      maxParticles: valueOf(maxParticles),\n      missingTexture: valueOf(missingTexture),\n      onStart,\n      onComplete,\n      onParticleSpawn,\n      ...config,\n    });\n    return instance;\n  };\n\n  mount((element) => {\n    container = element.componentInstance as unknown as PixiContainer;\n    if (valueOf(autostart) || valueOf(loop)) {\n      spawn();\n    }\n    return () => {\n      localRuntime.clear();\n    };\n  });\n\n  if (trigger?.listen) {\n    on(trigger, async (config) => {\n      await spawn(config);\n    });\n  }\n\n  tick(({ deltaTime }) => {\n    localRuntime.update((deltaTime ?? 16.67) * valueOf(timeScale));\n  });\n\n  return h(Container, {\n    ...containerProps,\n    x,\n    y,\n    rotation,\n    scale,\n    alpha,\n  });\n}\n"
  },
  {
    "path": "packages/presets/src/fx/index.ts",
    "content": "export * from \"./Fx\";\nexport * from \"./presets\";\nexport * from \"./runtime\";\nexport * from \"./types\";\n\n"
  },
  {
    "path": "packages/presets/src/fx/presets.ts",
    "content": "import type { FxPreset } from \"./types\";\n\nexport const FX_PRESETS = {\n  hitSpark: {\n    duration: 180,\n    emitters: [\n      {\n        burst: 18,\n        angle: [0, 360],\n        speed: [120, 340],\n        particle: {\n          shape: \"spark\",\n          lifetime: [160, 340],\n          color: [\"#fff4a8\", \"#ff7a2f\"],\n          alpha: [1, 0],\n          scale: [0.18, 0],\n          rotationSpeed: [-480, 480],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n  slashSpark: {\n    duration: 160,\n    emitters: [\n      {\n        burst: 22,\n        angle: [-12, 12],\n        speed: [180, 430],\n        spreadX: 10,\n        spreadY: 3,\n        particle: {\n          shape: \"spark\",\n          lifetime: [110, 260],\n          color: [\"#ffffff\", \"#ffcf5a\"],\n          alpha: [1, 0],\n          scale: [0.16, 0],\n          rotation: [-8, 8],\n          rotationSpeed: [-260, 260],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n      {\n        burst: 8,\n        angle: [150, 210],\n        speed: [60, 160],\n        particle: {\n          shape: \"star\",\n          lifetime: [140, 320],\n          color: [\"#fff8cc\", \"#ff8f3d\"],\n          alpha: [0.85, 0],\n          scale: [0.12, 0.4],\n          blendMode: \"add\",\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  impactBurst: {\n    duration: 260,\n    emitters: [\n      {\n        burst: 24,\n        angle: [0, 360],\n        speed: [130, 280],\n        particle: {\n          shape: \"spark\",\n          lifetime: [180, 420],\n          color: [\"#fff3ba\", \"#d64d27\"],\n          alpha: [1, 0],\n          scale: [0.2, 0],\n          rotationSpeed: [-360, 360],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n      {\n        burst: 10,\n        angle: [0, 360],\n        speed: [30, 90],\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [220, 520],\n          color: [\"#ffd18a\", \"#6d3a2a\"],\n          alpha: [0.38, 0],\n          scale: [0.28, 1.15],\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  smokePuff: {\n    duration: 260,\n    emitters: [\n      {\n        burst: 16,\n        angle: [-130, -50],\n        speed: [12, 58],\n        spreadX: 10,\n        spreadY: 6,\n        gravity: -10,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [520, 940],\n          color: [\"#8f8f8f\", \"#4f4f4f\"],\n          alpha: [0.38, 0],\n          scale: [0.45, 1.85],\n          rotationSpeed: [-40, 40],\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  dustStep: {\n    duration: 160,\n    emitters: [\n      {\n        burst: 10,\n        angle: [-170, -10],\n        speed: [18, 86],\n        spreadX: 8,\n        spreadY: 3,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [260, 520],\n          color: \"#b99a6a\",\n          alpha: [0.26, 0],\n          scale: [0.22, 0.9],\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  dashDust: {\n    duration: 220,\n    emitters: [\n      {\n        burst: 22,\n        angle: [155, 205],\n        speed: [70, 190],\n        spreadX: 18,\n        spreadY: 5,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [300, 640],\n          color: [\"#cfb07c\", \"#8f744f\"],\n          alpha: [0.34, 0],\n          scale: [0.28, 1.2],\n          ease: \"outCubic\",\n        },\n      },\n      {\n        burst: 9,\n        angle: [168, 192],\n        speed: [150, 330],\n        spreadX: 10,\n        particle: {\n          shape: \"spark\",\n          lifetime: [120, 280],\n          color: \"#d9c08a\",\n          alpha: [0.42, 0],\n          scale: [0.12, 0],\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n  magicBurst: {\n    duration: 360,\n    emitters: [\n      {\n        burst: 32,\n        angle: [0, 360],\n        speed: [70, 220],\n        particle: {\n          shape: \"star\",\n          lifetime: [420, 840],\n          color: [\"#77e5ff\", \"#b970ff\"],\n          alpha: [0.95, 0],\n          scale: [0.18, 0.75],\n          rotationSpeed: [-220, 220],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n  healPulse: {\n    duration: 520,\n    emitters: [\n      {\n        burst: 18,\n        angle: [-120, -60],\n        speed: [28, 86],\n        spreadX: 20,\n        spreadY: 10,\n        gravity: -16,\n        particle: {\n          shape: \"star\",\n          lifetime: [520, 980],\n          color: [\"#d9ffe6\", \"#55e68a\"],\n          alpha: [0.85, 0],\n          scale: [0.18, 0.62],\n          rotationSpeed: [-120, 120],\n          blendMode: \"add\",\n          ease: \"outQuad\",\n        },\n      },\n      {\n        burst: 10,\n        angle: [-105, -75],\n        speed: [12, 42],\n        spreadX: 16,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [620, 1100],\n          color: [\"#9fffc5\", \"#3edc7c\"],\n          alpha: [0.3, 0],\n          scale: [0.3, 1.0],\n          blendMode: \"add\",\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  campfire: {\n    duration: 1000,\n    emitters: [\n      {\n        loop: true,\n        rate: 38,\n        angle: [-110, -70],\n        speed: [16, 54],\n        spreadX: 8,\n        spreadY: 3,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [360, 720],\n          color: [\"#ffd36d\", \"#ff4b1f\"],\n          alpha: [0.8, 0],\n          scale: [0.25, 1.05],\n          blendMode: \"add\",\n          ease: \"outQuad\",\n        },\n      },\n      {\n        loop: true,\n        rate: 12,\n        angle: [-115, -65],\n        speed: [10, 30],\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [620, 1100],\n          color: \"#555555\",\n          alpha: [0.18, 0],\n          scale: [0.35, 1.4],\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  torchFire: {\n    duration: 1000,\n    emitters: [\n      {\n        loop: true,\n        rate: 24,\n        angle: [-104, -76],\n        speed: [12, 42],\n        spreadX: 4,\n        spreadY: 2,\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [280, 560],\n          color: [\"#fff09a\", \"#ff5a22\"],\n          alpha: [0.75, 0],\n          scale: [0.16, 0.72],\n          blendMode: \"add\",\n          ease: \"outQuad\",\n        },\n      },\n      {\n        loop: true,\n        rate: 7,\n        angle: [-112, -68],\n        speed: [8, 26],\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [520, 960],\n          color: \"#4f4f4f\",\n          alpha: [0.13, 0],\n          scale: [0.22, 0.9],\n          ease: \"outQuad\",\n        },\n      },\n    ],\n  },\n  pickup: {\n    duration: 320,\n    emitters: [\n      {\n        burst: 14,\n        angle: [210, 330],\n        speed: [70, 170],\n        particle: {\n          shape: \"star\",\n          lifetime: [260, 620],\n          color: [\"#ffffff\", \"#ffe66d\"],\n          alpha: [1, 0],\n          scale: [0.2, 0.65],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n  levelUp: {\n    duration: 820,\n    emitters: [\n      {\n        burst: 30,\n        angle: [-105, -75],\n        speed: [80, 210],\n        spreadX: 34,\n        spreadY: 10,\n        gravity: -24,\n        particle: {\n          shape: \"star\",\n          lifetime: [620, 1180],\n          color: [\"#ffffff\", \"#ffe870\"],\n          alpha: [1, 0],\n          scale: [0.16, 0.8],\n          rotationSpeed: [-180, 180],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n      {\n        duration: 420,\n        rate: 36,\n        angle: [-98, -82],\n        speed: [90, 180],\n        spreadX: 26,\n        particle: {\n          shape: \"spark\",\n          lifetime: [420, 840],\n          color: [\"#fff8c8\", \"#66d9ff\"],\n          alpha: [0.75, 0],\n          scale: [0.12, 0],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n  explosionSmall: {\n    duration: 280,\n    emitters: [\n      {\n        burst: 28,\n        angle: [0, 360],\n        speed: [120, 300],\n        particle: {\n          shape: \"softCircle\",\n          lifetime: [300, 720],\n          color: [\"#fff1a6\", \"#d34b24\"],\n          alpha: [1, 0],\n          scale: [0.25, 1.15],\n          blendMode: \"add\",\n          ease: \"outCubic\",\n        },\n      },\n    ],\n  },\n} satisfies Record<string, FxPreset>;\n"
  },
  {
    "path": "packages/presets/src/fx/runtime.ts",
    "content": "import { Container, Sprite, Texture } from \"pixi.js\";\nimport type {\n  FxEmitterConfig,\n  FxInstance,\n  FxParticle,\n  FxParticleConfig,\n  FxPreset,\n  FxRuntimeOptions,\n} from \"./types\";\nimport { getParticleTextures, getShapeTexture, preloadPresetTextures } from \"./textures\";\nimport {\n  colorToNumber,\n  createRandom,\n  easeValue,\n  lerp,\n  lerpColor,\n  normalizeAngle,\n  rangeValue,\n} from \"./utils\";\n\ntype RuntimeEmitter = FxEmitterConfig & {\n  elapsed: number;\n  emittedBurst: boolean;\n  carry: number;\n  particles: FxParticle[];\n};\n\ntype RuntimeInstance = FxInstance & {\n  emitters: RuntimeEmitter[];\n  options: FxRuntimeOptions;\n};\n\nexport class FxRuntime {\n  private instances = new Set<RuntimeInstance>();\n  private pool: Sprite[] = [];\n  private random: () => number;\n  private maxParticles: number;\n  private activeCount = 0;\n\n  constructor(options: { seed?: number; maxParticles?: number } = {}) {\n    this.random = createRandom(options.seed);\n    this.maxParticles = options.maxParticles ?? 600;\n  }\n\n  async preload(preset: FxPreset) {\n    await preloadPresetTextures(preset);\n  }\n\n  spawn(container: Container, preset: FxPreset, options: FxRuntimeOptions & { loop?: boolean } = {}): FxInstance {\n    const instance: RuntimeInstance = {\n      container,\n      preset,\n      elapsed: 0,\n      loop: Boolean(options.loop),\n      complete: false,\n      activeParticles: 0,\n      emitters: preset.emitters.map((emitter) => ({\n        ...emitter,\n        elapsed: 0,\n        emittedBurst: false,\n        carry: 0,\n        particles: [],\n      })),\n      options,\n      stop: () => {\n        instance.loop = false;\n        instance.complete = true;\n        instance.emitters.forEach((emitter) => {\n          emitter.duration = 0;\n          emitter.loop = false;\n        });\n      },\n    };\n\n    this.instances.add(instance);\n    options.onStart?.(instance);\n    return instance;\n  }\n\n  update(deltaMs: number) {\n    const delta = Number.isFinite(deltaMs) ? Math.max(0, deltaMs) : 0;\n    for (const instance of Array.from(this.instances)) {\n      this.updateInstance(instance, delta);\n    }\n  }\n\n  clear() {\n    for (const instance of Array.from(this.instances)) {\n      this.recycleInstance(instance);\n    }\n    this.instances.clear();\n  }\n\n  get activeInstances() {\n    return this.instances.size;\n  }\n\n  private updateInstance(instance: RuntimeInstance, deltaMs: number) {\n    instance.elapsed += deltaMs;\n    const delay = instance.preset.delay ?? 0;\n    if (instance.elapsed < delay) return;\n\n    let hasLiveParticles = false;\n    let hasEmitting = false;\n\n    for (const emitter of instance.emitters) {\n      this.updateEmitter(instance, emitter, deltaMs);\n      hasLiveParticles ||= emitter.particles.length > 0;\n      hasEmitting ||= this.isEmitterActive(instance, emitter);\n    }\n\n    instance.activeParticles = instance.emitters.reduce(\n      (count, emitter) => count + emitter.particles.length,\n      0\n    );\n\n    if (!hasEmitting && !hasLiveParticles) {\n      instance.complete = true;\n    }\n\n    if (instance.complete && !hasLiveParticles) {\n      this.instances.delete(instance);\n      instance.options.onComplete?.(instance);\n    }\n  }\n\n  private updateEmitter(instance: RuntimeInstance, emitter: RuntimeEmitter, deltaMs: number) {\n    emitter.elapsed += deltaMs;\n    const delay = emitter.delay ?? 0;\n    if (emitter.elapsed >= delay && this.isEmitterActive(instance, emitter)) {\n      if (emitter.burst && !emitter.emittedBurst) {\n        for (let i = 0; i < emitter.burst; i++) this.spawnParticle(instance, emitter);\n        emitter.emittedBurst = true;\n      }\n\n      if (emitter.rate) {\n        emitter.carry += (emitter.rate * deltaMs) / 1000;\n        const count = Math.floor(emitter.carry);\n        emitter.carry -= count;\n        for (let i = 0; i < count; i++) this.spawnParticle(instance, emitter);\n      }\n    }\n\n    for (let i = emitter.particles.length - 1; i >= 0; i--) {\n      const particle = emitter.particles[i];\n      particle.age += deltaMs;\n      if (particle.age >= particle.lifetime) {\n        this.recycleParticle(instance.container, particle);\n        emitter.particles.splice(i, 1);\n      } else {\n        this.updateParticle(particle, deltaMs);\n      }\n    }\n  }\n\n  private isEmitterActive(instance: RuntimeInstance, emitter: RuntimeEmitter) {\n    if (instance.complete) return false;\n    const delay = emitter.delay ?? 0;\n    const elapsed = emitter.elapsed - delay;\n    if (elapsed < 0) return false;\n    if (emitter.burst && !emitter.emittedBurst) return true;\n    if (instance.loop || emitter.loop) return true;\n    const duration = emitter.duration ?? instance.preset.duration ?? 0;\n    return elapsed <= duration;\n  }\n\n  private spawnParticle(instance: RuntimeInstance, emitter: RuntimeEmitter) {\n    const maxParticles = emitter.maxParticles ?? instance.options.maxParticles ?? this.maxParticles;\n    if (this.activeCount >= maxParticles || emitter.particles.length >= maxParticles) return;\n\n    const particleConfig = emitter.particle ?? {};\n    const textures = getParticleTextures(particleConfig, this.random);\n    if (!textures.length) {\n      if (instance.options.missingTexture === \"skip\") return;\n      if (instance.options.missingTexture === \"error\") {\n        throw new Error(\"Fx particle texture is not loaded\");\n      }\n      textures.push(getShapeTexture(particleConfig.shape));\n    }\n\n    const sprite = this.pool.pop() ?? new Sprite(Texture.WHITE);\n    sprite.texture = textures[0];\n    sprite.visible = true;\n    sprite.anchor.set(particleConfig.anchor?.x ?? 0.5, particleConfig.anchor?.y ?? 0.5);\n    sprite.x = (emitter.x ?? 0) + rangeValue([-(emitter.spreadX ?? 0), emitter.spreadX ?? 0], this.random, 0);\n    sprite.y = (emitter.y ?? 0) + rangeValue([-(emitter.spreadY ?? 0), emitter.spreadY ?? 0], this.random, 0);\n    sprite.rotation = (rangeValue(particleConfig.rotation, this.random, 0) * Math.PI) / 180;\n    sprite.blendMode = (particleConfig.blendMode ?? \"normal\") as any;\n\n    const angle = normalizeAngle(emitter.angle, this.random);\n    const speed = rangeValue(emitter.speed, this.random, 0);\n    const alpha = particleConfig.alpha ?? [1, 0];\n    const scale = particleConfig.scale ?? [1, 0];\n    const tint = particleConfig.tint ?? particleConfig.color ?? 0xffffff;\n    const startTint = colorToNumber(Array.isArray(tint) ? tint[0] : tint);\n    const endTint = colorToNumber(Array.isArray(tint) ? tint[1] : tint, startTint);\n    const startScale = rangeValue(Array.isArray(scale) ? scale[0] : scale, this.random, 1);\n    const endScale = Array.isArray(scale) ? rangeValue(scale[1], this.random, 0) : startScale;\n    const startAlpha = rangeValue(Array.isArray(alpha) ? alpha[0] : alpha, this.random, 1);\n    const endAlpha = Array.isArray(alpha) ? rangeValue(alpha[1], this.random, 0) : startAlpha;\n\n    sprite.alpha = startAlpha;\n    sprite.tint = startTint;\n    sprite.scale.set(startScale);\n    instance.container.addChild(sprite);\n\n    const particle: FxParticle = {\n      sprite,\n      age: 0,\n      lifetime: rangeValue(particleConfig.lifetime, this.random, 600),\n      vx: Math.cos(angle) * speed,\n      vy: Math.sin(angle) * speed,\n      ax: emitter.accelerationX ?? 0,\n      ay: emitter.accelerationY ?? 0,\n      gravity: emitter.gravity ?? 0,\n      startAlpha,\n      endAlpha,\n      startScale,\n      endScale,\n      startTint,\n      endTint,\n      rotationSpeed: (rangeValue(particleConfig.rotationSpeed, this.random, 0) * Math.PI) / 180,\n      frameRate: particleConfig.frameRate ?? 12,\n      frames: textures,\n      ease: particleConfig.ease ?? \"linear\",\n    };\n    emitter.particles.push(particle);\n    this.activeCount++;\n    instance.options.onParticleSpawn?.(particle);\n  }\n\n  private updateParticle(particle: FxParticle, deltaMs: number) {\n    const seconds = deltaMs / 1000;\n    const progress = particle.age / particle.lifetime;\n    const eased = easeValue(particle.ease, progress);\n    particle.vx += particle.ax * seconds;\n    particle.vy += (particle.ay + particle.gravity) * seconds;\n    particle.sprite.x += particle.vx * seconds;\n    particle.sprite.y += particle.vy * seconds;\n    particle.sprite.rotation += particle.rotationSpeed * seconds;\n    particle.sprite.alpha = lerp(particle.startAlpha, particle.endAlpha, eased);\n    particle.sprite.scale.set(lerp(particle.startScale, particle.endScale, eased));\n    particle.sprite.tint = lerpColor(particle.startTint, particle.endTint, eased);\n\n    if (particle.frames.length > 1) {\n      const frame = Math.min(\n        particle.frames.length - 1,\n        Math.floor((particle.age / 1000) * particle.frameRate) % particle.frames.length\n      );\n      particle.sprite.texture = particle.frames[frame];\n    }\n  }\n\n  private recycleParticle(container: Container, particle: FxParticle) {\n    container.removeChild(particle.sprite);\n    particle.sprite.visible = false;\n    particle.sprite.alpha = 1;\n    particle.sprite.tint = 0xffffff;\n    particle.sprite.scale.set(1);\n    this.pool.push(particle.sprite);\n    this.activeCount = Math.max(0, this.activeCount - 1);\n  }\n\n  private recycleInstance(instance: RuntimeInstance) {\n    for (const emitter of instance.emitters) {\n      for (const particle of emitter.particles) {\n        this.recycleParticle(instance.container, particle);\n      }\n      emitter.particles = [];\n    }\n  }\n\n}\n"
  },
  {
    "path": "packages/presets/src/fx/textures.ts",
    "content": "import { Assets, Texture } from \"pixi.js\";\nimport type { FxParticleConfig, FxShape } from \"./types\";\n\nconst shapeTextures = new Map<FxShape, Texture>();\nconst imageTextures = new Map<string, Promise<Texture> | Texture>();\n\nexport function getShapeTexture(shape: FxShape = \"softCircle\"): Texture {\n  if (!shapeTextures.has(shape)) {\n    shapeTextures.set(shape, createShapeTexture(shape));\n  }\n  return shapeTextures.get(shape)!;\n}\n\nfunction createShapeTexture(shape: FxShape): Texture {\n  if (typeof document === \"undefined\") return Texture.WHITE;\n\n  const canvas = document.createElement(\"canvas\");\n  canvas.width = shape === \"spark\" ? 64 : 48;\n  canvas.height = shape === \"spark\" ? 16 : 48;\n  const context = canvas.getContext(\"2d\");\n  if (!context) return Texture.WHITE;\n\n  context.clearRect(0, 0, canvas.width, canvas.height);\n  context.fillStyle = \"#ffffff\";\n  context.strokeStyle = \"#ffffff\";\n\n  if (shape === \"spark\") {\n    const gradient = context.createLinearGradient(0, 0, canvas.width, 0);\n    gradient.addColorStop(0, \"rgba(255,255,255,0)\");\n    gradient.addColorStop(0.22, \"rgba(255,255,255,1)\");\n    gradient.addColorStop(1, \"rgba(255,255,255,0)\");\n    context.strokeStyle = gradient;\n    context.lineWidth = 4;\n    context.lineCap = \"round\";\n    context.beginPath();\n    context.moveTo(3, canvas.height / 2);\n    context.lineTo(canvas.width - 3, canvas.height / 2);\n    context.stroke();\n  } else if (shape === \"square\") {\n    context.fillRect(8, 8, 32, 32);\n  } else if (shape === \"star\") {\n    drawStar(context, 24, 24, 5, 20, 8);\n  } else if (shape === \"circle\") {\n    context.beginPath();\n    context.arc(24, 24, 18, 0, Math.PI * 2);\n    context.fill();\n  } else {\n    const gradient = context.createRadialGradient(24, 24, 2, 24, 24, 22);\n    gradient.addColorStop(0, \"rgba(255,255,255,1)\");\n    gradient.addColorStop(0.45, \"rgba(255,255,255,0.72)\");\n    gradient.addColorStop(1, \"rgba(255,255,255,0)\");\n    context.fillStyle = gradient;\n    context.fillRect(0, 0, canvas.width, canvas.height);\n  }\n\n  return Texture.from(canvas);\n}\n\nfunction drawStar(\n  context: CanvasRenderingContext2D,\n  x: number,\n  y: number,\n  points: number,\n  outerRadius: number,\n  innerRadius: number\n) {\n  context.beginPath();\n  for (let i = 0; i < points * 2; i++) {\n    const radius = i % 2 === 0 ? outerRadius : innerRadius;\n    const angle = (i * Math.PI) / points - Math.PI / 2;\n    const px = x + Math.cos(angle) * radius;\n    const py = y + Math.sin(angle) * radius;\n    if (i === 0) context.moveTo(px, py);\n    else context.lineTo(px, py);\n  }\n  context.closePath();\n  context.fill();\n}\n\nexport async function preloadParticleTextures(config: FxParticleConfig = {}) {\n  const loads: Promise<any>[] = [];\n  if (config.image && !imageTextures.has(config.image)) {\n    const promise = Assets.load(config.image) as Promise<Texture>;\n    imageTextures.set(config.image, promise);\n    loads.push(\n      promise.then((texture) => {\n        imageTextures.set(config.image!, texture);\n      })\n    );\n  }\n  if (config.spritesheet) {\n    loads.push(Promise.resolve(Assets.load(config.spritesheet)));\n  }\n  await Promise.all(loads);\n}\n\nexport async function preloadPresetTextures(preset) {\n  await Promise.all(\n    (preset?.emitters ?? []).map((emitter) => preloadParticleTextures(emitter.particle))\n  );\n}\n\nexport function getParticleTextures(config: FxParticleConfig = {}, random = Math.random): Texture[] {\n  if (config.texture) return [config.texture];\n  if (config.frames?.length) {\n    const frames = config.frames.map((frame) => Texture.from(frame));\n    if (config.frameMode === \"random\") {\n      return [frames[Math.floor(random() * frames.length)] ?? frames[0]];\n    }\n    return frames;\n  }\n  if (config.frame) return [Texture.from(config.frame)];\n  if (config.image) {\n    const cached = imageTextures.get(config.image);\n    if (cached && !(cached instanceof Promise)) return [cached];\n    return [];\n  }\n  return [getShapeTexture(config.shape)];\n}\n"
  },
  {
    "path": "packages/presets/src/fx/types.ts",
    "content": "import type { Container, Texture } from \"pixi.js\";\n\nexport type FxSignal<T> = T | (() => T);\nexport type FxRange = number | [number, number];\nexport type FxColor = string | number;\nexport type FxColorRange = FxColor | [FxColor, FxColor];\nexport type FxShape = \"circle\" | \"softCircle\" | \"spark\" | \"square\" | \"star\";\nexport type FxFrameMode = \"first\" | \"random\" | \"animated\";\nexport type FxBlendMode = \"normal\" | \"add\" | \"multiply\" | \"screen\" | string;\n\nexport interface FxParticleConfig {\n  image?: string;\n  texture?: Texture;\n  spritesheet?: string;\n  frame?: string;\n  frames?: string[];\n  frameMode?: FxFrameMode;\n  frameRate?: number;\n  shape?: FxShape;\n  lifetime?: FxRange;\n  color?: FxColorRange;\n  tint?: FxColorRange;\n  alpha?: FxRange;\n  scale?: FxRange;\n  rotation?: FxRange;\n  rotationSpeed?: FxRange;\n  blendMode?: FxBlendMode;\n  anchor?: { x: number; y: number };\n  ease?: \"linear\" | \"outQuad\" | \"outCubic\" | \"inQuad\";\n}\n\nexport interface FxEmitterConfig {\n  name?: string;\n  delay?: number;\n  duration?: number;\n  loop?: boolean;\n  burst?: number;\n  rate?: number;\n  maxParticles?: number;\n  x?: number;\n  y?: number;\n  spreadX?: number;\n  spreadY?: number;\n  angle?: FxRange;\n  speed?: FxRange;\n  accelerationX?: number;\n  accelerationY?: number;\n  gravity?: number;\n  particle?: FxParticleConfig;\n}\n\nexport interface FxPreset {\n  duration?: number;\n  delay?: number;\n  emitters: FxEmitterConfig[];\n}\n\nexport interface FxParticle {\n  sprite: any;\n  age: number;\n  lifetime: number;\n  vx: number;\n  vy: number;\n  ax: number;\n  ay: number;\n  gravity: number;\n  startAlpha: number;\n  endAlpha: number;\n  startScale: number;\n  endScale: number;\n  startTint: number;\n  endTint: number;\n  rotationSpeed: number;\n  frameRate: number;\n  frames: Texture[];\n  ease: NonNullable<FxParticleConfig[\"ease\"]>;\n}\n\nexport interface FxInstance {\n  container: Container;\n  preset: FxPreset;\n  elapsed: number;\n  loop: boolean;\n  complete: boolean;\n  activeParticles: number;\n  stop: () => void;\n}\n\nexport interface FxRuntimeOptions {\n  seed?: number;\n  maxParticles?: number;\n  missingTexture?: \"skip\" | \"shape\" | \"error\";\n  onStart?: (instance: FxInstance) => void;\n  onComplete?: (instance: FxInstance) => void;\n  onParticleSpawn?: (particle: FxParticle) => void;\n}\n\n"
  },
  {
    "path": "packages/presets/src/fx/utils.ts",
    "content": "import type { FxColor, FxRange } from \"./types\";\n\nexport function resolveValue<T>(value: T | (() => T)): T {\n  return typeof value === \"function\" ? (value as () => T)() : value;\n}\n\nexport function createRandom(seed = Date.now()) {\n  let state = seed >>> 0;\n  return () => {\n    state = (state * 1664525 + 1013904223) >>> 0;\n    return state / 4294967296;\n  };\n}\n\nexport function rangeValue(value: FxRange | undefined, random: () => number, fallback: number): number {\n  if (value === undefined) return fallback;\n  if (Array.isArray(value)) {\n    return value[0] + (value[1] - value[0]) * random();\n  }\n  return value;\n}\n\nexport function normalizeAngle(value: FxRange | undefined, random: () => number): number {\n  return (rangeValue(value, random, 0) * Math.PI) / 180;\n}\n\nexport function colorToNumber(value: FxColor | undefined, fallback = 0xffffff): number {\n  if (value === undefined) return fallback;\n  if (typeof value === \"number\") return value;\n  const hex = value.trim().replace(\"#\", \"\");\n  if (hex.length === 3) {\n    return parseInt(hex.split(\"\").map((char) => char + char).join(\"\"), 16);\n  }\n  return parseInt(hex, 16);\n}\n\nexport function lerp(start: number, end: number, progress: number): number {\n  return start + (end - start) * progress;\n}\n\nexport function lerpColor(start: number, end: number, progress: number): number {\n  const sr = (start >> 16) & 255;\n  const sg = (start >> 8) & 255;\n  const sb = start & 255;\n  const er = (end >> 16) & 255;\n  const eg = (end >> 8) & 255;\n  const eb = end & 255;\n  const r = Math.round(lerp(sr, er, progress));\n  const g = Math.round(lerp(sg, eg, progress));\n  const b = Math.round(lerp(sb, eb, progress));\n  return (r << 16) + (g << 8) + b;\n}\n\nexport function easeValue(name: string | undefined, progress: number): number {\n  const t = Math.max(0, Math.min(1, progress));\n  if (name === \"outQuad\") return 1 - (1 - t) * (1 - t);\n  if (name === \"outCubic\") return 1 - Math.pow(1 - t, 3);\n  if (name === \"inQuad\") return t * t;\n  return t;\n}\n\n"
  },
  {
    "path": "packages/presets/src/index.ts",
    "content": "export * from './Bar'\nexport * from './Particle'\nexport * from './fx'\nexport * from './NightAmbiant'\nexport * from './Loading'\nexport * from './Tilemap'\nexport * from './Weathers'\nexport * from './FogOfWar'\nexport * from './SpriteShadows'\nexport * from './Footprints'\n"
  },
  {
    "path": "packages/presets/src/shaders/defaultFilter.vert.glsl",
    "content": "/**\n * Default Pixi filter vertex shader.\n * Outputs vTextureCoord (0-1) for sampling the input texture in fragment shader.\n */\nin vec2 aPosition;\nout vec2 vTextureCoord;\n\nuniform highp vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nvec4 filterVertexPosition(void) {\n  vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n  position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n  position.y = position.y * (2.0 * uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n  return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord(void) {\n  return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvoid main(void) {\n  gl_Position = filterVertexPosition();\n  vTextureCoord = filterTextureCoord();\n}\n"
  },
  {
    "path": "packages/presets/src/shaders/nightSpot.frag.glsl",
    "content": "/**\n * Night + spot light + fog fragment shader.\n * - Supports multiple circular spots (uSpots) in screen-pixel space.\n * - Each spot is vec4(xPx, yPx, radiusPx, intensity).\n * - Fog is based on the nearest light source so illuminated areas stay readable.\n * - Dark zones are tinted with uDarkColor for colored night effects.\n */\nprecision highp float;\nprecision highp int;\n\nin vec2 vTextureCoord;\n\nout vec4 finalColor;\n\nuniform sampler2D uTexture;\nuniform highp vec4 uInputSize;\nuniform vec4 uSpots[24];\nuniform float uDarkness;\nuniform vec3 uDarkColor;\nuniform vec3 uFogColor;\nuniform float uFogRadius;\nuniform float uFogSoftness;\n\nvoid main() {\n  vec4 color = texture(uTexture, vTextureCoord);\n  float light = 0.0;\n  float nearestDist = 1.0;\n  vec2 fragPx = vTextureCoord * uInputSize.xy;\n  float minInputDim = max(min(uInputSize.x, uInputSize.y), 1.0);\n\n  for (int i = 0; i < 24; i++) {\n    vec4 spotData = uSpots[i];\n    vec2 lightPosPx = spotData.xy;\n    float radiusPx = max(spotData.z, 0.0001);\n    float intensity = max(spotData.w, 0.0);\n    if (intensity <= 0.0001) continue;\n\n    vec2 deltaPx = fragPx - lightPosPx;\n    float distPx = length(deltaPx);\n    float spot = (1.0 - smoothstep(0.0, radiusPx, distPx)) * intensity;\n    light = clamp(light + spot, 0.0, 1.0);\n    nearestDist = min(nearestDist, distPx / minInputDim);\n  }\n\n  // Night: full brightness where light is strong, darker elsewhere.\n  // Apply dark color tint in unlit areas.\n  float factor = mix(1.0 - uDarkness, 1.0, light);\n  vec3 darkened = color.rgb * factor;\n  // Blend towards dark color in unlit areas (when factor < 1)\n  float darkTint = (1.0 - factor) * uDarkness;\n  color.rgb = mix(darkened, uDarkColor, darkTint);\n\n  // Fog fades in with distance to nearest light, but less inside lit areas.\n  float fogFactor = smoothstep(uFogRadius, uFogRadius + uFogSoftness, nearestDist);\n  fogFactor *= (1.0 - light * 0.7);\n  color.rgb = mix(color.rgb, uFogColor, clamp(fogFactor, 0.0, 1.0));\n\n  finalColor = color;\n}\n"
  },
  {
    "path": "packages/presets/src/shaders/shadowGradient.frag.glsl",
    "content": "/**\n * Gradient alpha for projected sprite shadows.\n * Strong alpha near the caster's feet (vTextureCoord.y ~ 1),\n * softer alpha at the shadow tip (vTextureCoord.y ~ 0).\n */\nprecision highp float;\nprecision highp int;\n\nin vec2 vTextureCoord;\nout vec4 finalColor;\n\nuniform sampler2D uTexture;\nuniform float uPower;\nuniform float uFloor;\n\nvoid main() {\n  vec4 color = texture(uTexture, vTextureCoord);\n  float gradient = pow(clamp(vTextureCoord.y, 0.0, 1.0), max(0.001, uPower));\n  float alphaMul = mix(clamp(uFloor, 0.0, 1.0), 1.0, gradient);\n  finalColor = vec4(color.rgb, color.a * alphaMul);\n}\n"
  },
  {
    "path": "packages/presets/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"declaration\": true,\n    \"emitDeclarationOnly\": false,\n    \"declarationMap\": true,\n    \"rootDir\": \"src\"\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\"\n  ]\n} "
  },
  {
    "path": "packages/presets/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport { resolve } from 'path'\nimport dts from 'vite-plugin-dts'\n\nexport default defineConfig({\n  plugins: [dts()],\n  build: {\n    lib: {\n      entry: resolve(__dirname, 'src/index.ts'),\n      name: 'CanvasEnginePresets'\n    },\n    rollupOptions: {\n      external: ['canvasengine', 'pixi.js'],\n      output: [\n        // ESM build with externals\n        {\n          format: 'es',\n          dir: 'dist',\n          entryFileNames: 'index.js'\n        },\n        // IIFE build that extends global CanvasEngine\n        {\n          format: 'iife',\n          dir: 'dist',\n          entryFileNames: 'index.global.js',\n          name: 'CanvasEnginePresets',\n          globals: {\n            'canvasengine': 'CanvasEngine',\n            'pixi.js': 'PIXI'\n          },\n        }\n      ]\n    },\n    minify: true,\n    sourcemap: true\n  },\n  define: {\n    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')\n  }\n}) "
  },
  {
    "path": "packages/testing/package.json",
    "content": "{\n  \"name\": \"@canvasengine/testing\",\n  \"version\": \"2.0.0-beta.58\",\n  \"description\": \"Testing utilities and mocks for CanvasEngine\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"files\": [\n    \"dist\"\n  ],\n  \"scripts\": {\n    \"build\": \"tsup\",\n    \"dev\": \"tsup --watch\"\n  },\n  \"peerDependencies\": {\n    \"canvasengine\": \"workspace:*\",\n    \"vitest\": \"*\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^25.6.0\",\n    \"tsup\": \"^8.5.1\",\n    \"typescript\": \"^6.0.3\"\n  },\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"keywords\": [\n    \"canvas\",\n    \"pixijs\",\n    \"testing\",\n    \"mocks\"\n  ],\n  \"author\": \"Samuel Ronce\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://canvasengine.net\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/RSamaium/CanvasEngine.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/RSamaium/CanvasEngine/issues\"\n  },\n  \"dependencies\": {\n    \"rxjs\": \"^7.8.2\"\n  }\n}\n"
  },
  {
    "path": "packages/testing/src/helpers/createMockComponentInstance.ts",
    "content": "import { ComponentInstance } from 'canvasengine';\nimport { MockContainer, MockSprite, MockText, MockGraphics, MockMesh, MockTilingSprite, MockNineSlicePlane, MockDOMElement, MockDOMContainer, MockTexture } from '../mocks/pixi-base';\n\n/**\n * Creates a mock ComponentInstance based on the component type\n * \n * This helper function creates appropriate mock instances for different component types.\n * It's useful when you need a ComponentInstance but don't want to use the real PixiJS implementation.\n * \n * @param componentType - The type of component to create a mock for\n * @returns A mock ComponentInstance appropriate for the component type\n * \n * @example\n * ```typescript\n * const containerInstance = createMockComponentInstance('Container');\n * const spriteInstance = createMockComponentInstance('Sprite');\n * ```\n */\nexport function createMockComponentInstance(componentType: string): ComponentInstance {\n  switch (componentType.toLowerCase()) {\n    case 'container':\n      return new MockContainer() as any;\n    case 'sprite':\n      return new MockSprite() as any;\n    case 'text':\n      return new MockText() as any;\n    case 'graphics':\n    case 'rect':\n    case 'circle':\n    case 'ellipse':\n    case 'triangle':\n    case 'svg':\n      return new MockGraphics() as any;\n    case 'mesh':\n      return new MockMesh() as any;\n    case 'tilingsprite':\n      return new MockTilingSprite(new MockTexture()) as any;\n    case 'nineslicesprite':\n      return new MockNineSlicePlane(new MockTexture()) as any;\n    case 'domelement':\n      return new MockDOMElement() as any;\n    case 'domcontainer':\n      return new MockDOMContainer() as any;\n    default:\n      // Default to Container for unknown types\n      return new MockContainer() as any;\n  }\n}\n"
  },
  {
    "path": "packages/testing/src/helpers/createMockElement.ts",
    "content": "import { Element, Props } from 'canvasengine';\nimport { ComponentInstance } from 'canvasengine';\nimport { Subject } from 'rxjs';\nimport { createMockComponentInstance } from './createMockComponentInstance';\n\n/**\n * Creates a mock Element with all required properties\n * \n * This function creates a complete mock Element that can be used in tests.\n * The element includes a mock componentInstance (PixiJS instance) that can be spied upon.\n * \n * @param tag - The tag name of the element (e.g., 'Container', 'Sprite')\n * @param props - Optional props to assign to the element\n * @param componentInstance - Optional custom componentInstance. If not provided, a default mock will be created\n * @returns A complete mock Element with all required properties\n * \n * @example\n * ```typescript\n * // Create a basic element with default mock\n * const element = createMockElement('Container', { x: 100, y: 50 });\n * \n * // Create an element with custom componentInstance\n * const customInstance = new MockSprite();\n * const spriteElement = createMockElement('Sprite', { image: 'hero.png' }, customInstance);\n * \n * // Access and spy on componentInstance\n * expect(element.componentInstance.x).toBe(100);\n * ```\n */\nexport function createMockElement<T extends ComponentInstance = ComponentInstance>(\n  tag: string,\n  props: Props = {},\n  componentInstance?: T\n): Element<T> {\n  const instance = componentInstance || (createMockComponentInstance(tag) as T);\n\n  // Apply props to componentInstance if they are standard PixiJS properties\n  if (instance && typeof instance === 'object') {\n    Object.keys(props).forEach(key => {\n      if (key in instance && !['children', 'context'].includes(key)) {\n        (instance as any)[key] = props[key];\n      }\n    });\n  }\n\n  const element: Element<T> = {\n    tag,\n    props: { ...props },\n    componentInstance: instance,\n    propSubscriptions: [],\n    propObservables: undefined,\n    parent: null,\n    context: undefined,\n    directives: {},\n    destroy: () => {\n      // Mock destroy implementation\n      element.propSubscriptions.forEach(sub => sub.unsubscribe());\n      element.effectSubscriptions.forEach(sub => sub.unsubscribe());\n      element.effectUnmounts.forEach(fn => {\n        if (typeof fn === 'function') {\n          fn();\n        }\n      });\n    },\n    allElements: new Subject(),\n    isFrozen: false,\n    effectSubscriptions: [],\n    effectMounts: [],\n    effectUnmounts: [],\n  };\n\n  return element;\n}\n"
  },
  {
    "path": "packages/testing/src/helpers/spyOnElement.ts",
    "content": "import { vi } from 'vitest';\nimport { Element, ComponentInstance } from 'canvasengine';\n\n/**\n * Creates a spy on a property or method of an element's componentInstance\n * \n * This helper makes it easy to spy on the PixiJS instance (componentInstance) of an element.\n * It's a convenience wrapper around vi.spyOn that targets element.componentInstance.\n * \n * @param element - The element whose componentInstance should be spied upon\n * @param property - The property or method name to spy on\n * @returns A Vitest spy object\n * \n * @example\n * ```typescript\n * const element = createMockElement('Container', { x: 100 });\n * \n * // Spy on a property getter/setter\n * const xSpy = spyOnElement(element, 'x');\n * element.componentInstance.x = 200;\n * expect(xSpy).toHaveBeenCalled();\n * \n * // Spy on a method\n * const addChildSpy = spyOnElement(element, 'addChild');\n * element.componentInstance.addChild(new MockContainer());\n * expect(addChildSpy).toHaveBeenCalled();\n * ```\n */\nexport function spyOnElement<T extends ComponentInstance>(\n  element: Element<T>,\n  property: keyof T | string\n): ReturnType<typeof vi.spyOn> {\n  if (!element.componentInstance) {\n    throw new Error('Element componentInstance is not defined');\n  }\n\n  return vi.spyOn(element.componentInstance as any, property as string);\n}\n\n/**\n * Creates spies on multiple properties or methods of an element's componentInstance\n * \n * This helper allows you to spy on multiple properties/methods at once.\n * \n * @param element - The element whose componentInstance should be spied upon\n * @param properties - Array of property or method names to spy on\n * @returns An object with spy objects keyed by property name\n * \n * @example\n * ```typescript\n * const element = createMockElement('Container');\n * const spies = spyOnElementMultiple(element, ['addChild', 'removeChild', 'destroy']);\n * \n * element.componentInstance.addChild(new MockContainer());\n * expect(spies.addChild).toHaveBeenCalled();\n * ```\n */\nexport function spyOnElementMultiple<T extends ComponentInstance>(\n  element: Element<T>,\n  properties: (keyof T | string)[]\n): Record<string, ReturnType<typeof vi.spyOn>> {\n  const spies: Record<string, ReturnType<typeof vi.spyOn>> = {};\n  \n  properties.forEach(property => {\n    spies[property as string] = spyOnElement(element, property);\n  });\n  \n  return spies;\n}\n"
  },
  {
    "path": "packages/testing/src/index.ts",
    "content": "/**\n * @canvasengine/testing\n * \n * Testing utilities and mocks for CanvasEngine\n * \n * This package provides comprehensive mocks for PixiJS classes and helpers\n * for creating mock elements that can be used in tests without requiring\n * a full PixiJS environment or jsdom setup.\n */\n\n// Export all PixiJS mocks\nexport {\n  MockContainer,\n  MockSprite,\n  MockText,\n  MockGraphics,\n  MockMesh,\n  MockTilingSprite,\n  MockNineSlicePlane,\n  MockDOMElement,\n  MockDOMContainer,\n  MockApplication,\n  MockTexture,\n  MockRectangle,\n  MockObservablePoint,\n  MockVideoResource,\n} from './mocks/pixi-base';\n\n// Import mocks for the mapping\nimport {\n  MockContainer,\n  MockSprite,\n  MockText,\n  MockGraphics,\n  MockMesh,\n  MockTilingSprite,\n  MockNineSlicePlane,\n  MockDOMElement,\n  MockDOMContainer,\n} from './mocks/pixi-base';\n\n// Export helpers\nexport {\n  createMockElement,\n} from './helpers/createMockElement';\n\nexport {\n  createMockComponentInstance,\n} from './helpers/createMockComponentInstance';\n\nexport {\n  spyOnElement,\n  spyOnElementMultiple,\n} from './helpers/spyOnElement';\n\n// Re-export types from canvasengine for convenience\nexport type {\n  Element,\n  Props,\n  ComponentInstance,\n} from 'canvasengine';\n\n/**\n * Mapping of CanvasEngine component names to their corresponding mock classes.\n * \n * This object can be used with bootstrapCanvas() to register mock components for testing.\n * \n * @example\n * ```typescript\n * import { mockComponents } from '@canvasengine/testing';\n * \n * await bootstrapCanvas(rootElement, MyComponent, {\n *   components: mockComponents,\n *   autoRegister: false\n * });\n * ```\n * \n * @example\n * ```typescript\n * // Use specific mocks only\n * import { mockComponents, MockSprite } from '@canvasengine/testing';\n * \n * await bootstrapCanvas(rootElement, MyComponent, {\n *   components: {\n *     Sprite: MockSprite,\n *     Container: mockComponents.Container\n *   }\n * });\n * ```\n */\nexport const mockComponents = {\n  Canvas: MockContainer,\n  Container: MockContainer,\n  Sprite: MockSprite,\n  Text: MockText,\n  Graphics: MockGraphics,\n  Rect: MockGraphics,\n  Circle: MockGraphics,\n  Ellipse: MockGraphics,\n  Triangle: MockGraphics,\n  Svg: MockGraphics,\n  Mesh: MockMesh,\n  TilingSprite: MockTilingSprite,\n  NineSliceSprite: MockNineSlicePlane,\n  DOMContainer: MockDOMContainer,\n  DOMElement: MockDOMElement,\n  Viewport: MockContainer, // Viewport extends Container\n  ParticlesEmitter: MockContainer, // ParticlesEmitter extends Container\n} as const;\n"
  },
  {
    "path": "packages/testing/src/mocks/pixi-base.ts",
    "content": "import { vi } from 'vitest';\n\n/**\n * Base class for creating mock event emitters\n * Provides event handling functionality similar to PixiJS EventEmitter\n */\nclass MockEventEmitter {\n  #eventListeners: Map<string, Function[]> = new Map();\n\n  on(event: string, handler: Function) {\n    if (!this.#eventListeners.has(event)) {\n      this.#eventListeners.set(event, []);\n    }\n    this.#eventListeners.get(event)!.push(handler);\n    return this;\n  }\n\n  off(event: string, handler?: Function) {\n    if (!this.#eventListeners.has(event)) return this;\n    if (handler) {\n      const handlers = this.#eventListeners.get(event)!;\n      const index = handlers.indexOf(handler);\n      if (index > -1) {\n        handlers.splice(index, 1);\n      }\n    } else {\n      this.#eventListeners.delete(event);\n    }\n    return this;\n  }\n\n  emit(event: string, data?: any) {\n    if (this.#eventListeners.has(event)) {\n      this.#eventListeners.get(event)!.forEach(handler => handler(data));\n    }\n    return this;\n  }\n\n  once(event: string, handler: Function) {\n    const onceHandler = (...args: any[]) => {\n      handler(...args);\n      this.off(event, onceHandler);\n    };\n    return this.on(event, onceHandler);\n  }\n\n  removeAllListeners(event?: string) {\n    if (event) {\n      this.#eventListeners.delete(event);\n    } else {\n      this.#eventListeners.clear();\n    }\n    return this;\n  }\n}\n\n/**\n * Mock for PixiJS ObservablePoint\n * Represents a point that can be observed for changes\n */\nexport class MockObservablePoint {\n  x: number;\n  y: number;\n  cb?: (point: MockObservablePoint) => void;\n\n  constructor(x = 0, y = 0, cb?: (point: MockObservablePoint) => void) {\n    this.x = x;\n    this.y = y;\n    this.cb = cb;\n  }\n\n  set(x: number, y: number) {\n    this.x = x;\n    this.y = y;\n    this.cb?.(this);\n    return this;\n  }\n\n  copyFrom(point: { x: number; y: number }) {\n    this.x = point.x;\n    this.y = point.y;\n    this.cb?.(this);\n    return this;\n  }\n\n  copyTo(point: { x: number; y: number }) {\n    point.x = this.x;\n    point.y = this.y;\n    return point;\n  }\n\n  equals(point: { x: number; y: number }) {\n    return this.x === point.x && this.y === point.y;\n  }\n}\n\n/**\n * Mock for PixiJS Rectangle\n */\nexport class MockRectangle {\n  x: number;\n  y: number;\n  width: number;\n  height: number;\n\n  constructor(x = 0, y = 0, width = 0, height = 0) {\n    this.x = x;\n    this.y = y;\n    this.width = width;\n    this.height = height;\n  }\n\n  contains = vi.fn((x: number, y: number) => {\n    return x >= this.x && x <= this.x + this.width &&\n           y >= this.y && y <= this.y + this.height;\n  });\n\n  clone = vi.fn(() => {\n    return new MockRectangle(this.x, this.y, this.width, this.height);\n  });\n}\n\n/**\n * Mock for PixiJS Texture\n */\nexport class MockTexture {\n  width: number;\n  height: number;\n  baseTexture: any;\n  frame: MockRectangle;\n  valid: boolean = true;\n\n  constructor(width = 100, height = 100) {\n    this.width = width;\n    this.height = height;\n    this.frame = new MockRectangle(0, 0, width, height);\n    this.baseTexture = {\n      width,\n      height,\n      valid: true,\n    };\n  }\n\n  destroy = vi.fn();\n  update = vi.fn();\n  clone = vi.fn(() => new MockTexture(this.width, this.height));\n}\n\n/**\n * Mock for PixiJS Container\n * Base class for all display objects that can contain children\n */\nexport class MockContainer extends MockEventEmitter {\n  x: number = 0;\n  y: number = 0;\n  width: number = 0;\n  height: number = 0;\n  alpha: number = 1;\n  visible: boolean = true;\n  rotation: number = 0;\n  scale: MockObservablePoint = new MockObservablePoint(1, 1);\n  anchor: MockObservablePoint = new MockObservablePoint(0, 0);\n  pivot: MockObservablePoint = new MockObservablePoint(0, 0);\n  skew: MockObservablePoint = new MockObservablePoint(0, 0);\n  tint: number = 0xffffff;\n  blendMode: number = 0;\n  filters: any[] = [];\n  mask: any = null;\n  parent: MockContainer | null = null;\n  children: MockContainer[] = [];\n  eventMode: string = 'auto';\n  destroyed: boolean = false;\n  zIndex: number = 0;\n  sortableChildren: boolean = false;\n  sortDirty: boolean = false;\n\n  addChild = vi.fn(function<T extends MockContainer>(this: MockContainer, child: T): T {\n    if (child.parent) {\n      child.parent.removeChild(child);\n    }\n    child.parent = this;\n    this.children.push(child);\n    return child;\n  });\n\n  addChildAt = vi.fn(function<T extends MockContainer>(this: MockContainer, child: T, index: number): T {\n    if (child.parent) {\n      child.parent.removeChild(child);\n    }\n    child.parent = this;\n    this.children.splice(index, 0, child);\n    return child;\n  });\n\n  removeChild = vi.fn(function<T extends MockContainer>(this: MockContainer, child: T): T {\n    const index = this.children.indexOf(child);\n    if (index > -1) {\n      this.children.splice(index, 1);\n      child.parent = null;\n    }\n    return child;\n  });\n\n  removeChildAt = vi.fn(function(this: MockContainer, index: number): MockContainer {\n    const child = this.children[index];\n    if (child) {\n      this.children.splice(index, 1);\n      child.parent = null;\n    }\n    return child;\n  });\n\n  removeChildren = vi.fn(function(this: MockContainer, beginIndex = 0, endIndex = this.children.length): MockContainer[] {\n    const removed = this.children.splice(beginIndex, endIndex - beginIndex);\n    removed.forEach(child => { child.parent = null; });\n    return removed;\n  });\n\n  getChildAt = vi.fn(function(this: MockContainer, index: number): MockContainer {\n    return this.children[index];\n  });\n\n  getChildIndex = vi.fn(function(this: MockContainer, child: MockContainer): number {\n    return this.children.indexOf(child);\n  });\n\n  setChildIndex = vi.fn(function(this: MockContainer, child: MockContainer, index: number): void {\n    const currentIndex = this.children.indexOf(child);\n    if (currentIndex > -1) {\n      this.children.splice(currentIndex, 1);\n      this.children.splice(index, 0, child);\n    }\n  });\n\n  swapChildren = vi.fn(function(this: MockContainer, child: MockContainer, child2: MockContainer): void {\n    const index1 = this.children.indexOf(child);\n    const index2 = this.children.indexOf(child2);\n    if (index1 > -1 && index2 > -1) {\n      [this.children[index1], this.children[index2]] = [this.children[index2], this.children[index1]];\n    }\n  });\n\n  destroy = vi.fn(function(this: MockContainer, options?: any): void {\n    this.destroyed = true;\n    this.removeChildren();\n    this.removeAllListeners();\n  });\n\n  updateTransform = vi.fn();\n  render = vi.fn();\n  calculateBounds = vi.fn();\n  getLocalBounds = vi.fn(() => new MockRectangle(0, 0, this.width, this.height));\n  getBounds = vi.fn(() => new MockRectangle(this.x, this.y, this.width, this.height));\n  toLocal = vi.fn((point: { x: number; y: number }) => ({ x: point.x - this.x, y: point.y - this.y }));\n  toGlobal = vi.fn((point: { x: number; y: number }) => ({ x: point.x + this.x, y: point.y + this.y }));\n}\n\n/**\n * Mock for PixiJS Graphics\n */\nexport class MockGraphics extends MockContainer {\n  geometry: any = null;\n\n  clear = vi.fn(() => this);\n  rect = vi.fn(() => this);\n  circle = vi.fn(() => this);\n  ellipse = vi.fn(() => this);\n  polygon = vi.fn(() => this);\n  lineTo = vi.fn(() => this);\n  moveTo = vi.fn(() => this);\n  beginFill = vi.fn(() => this);\n  endFill = vi.fn(() => this);\n  lineStyle = vi.fn(() => this);\n  drawRect = vi.fn(() => this);\n  drawCircle = vi.fn(() => this);\n  drawEllipse = vi.fn(() => this);\n  drawPolygon = vi.fn(() => this);\n}\n\n/**\n * Mock for PixiJS Sprite\n */\nexport class MockSprite extends MockContainer {\n  texture: MockTexture;\n  anchor: MockObservablePoint = new MockObservablePoint(0.5, 0.5);\n\n  constructor(texture?: MockTexture) {\n    super();\n    this.texture = texture || new MockTexture(100, 100);\n    this.width = this.texture.width;\n    this.height = this.texture.height;\n  }\n\n  static from = vi.fn((source: string | MockTexture) => {\n    if (typeof source === 'string') {\n      return new MockSprite(new MockTexture(100, 100));\n    }\n    return new MockSprite(source);\n  });\n}\n\n/**\n * Mock for PixiJS Text\n */\nexport class MockText extends MockContainer {\n  text: string = '';\n  style: any = {};\n  canvas: HTMLCanvasElement | null = null;\n  context: CanvasRenderingContext2D | null = null;\n  resolution: number = 1;\n\n  constructor(text = '', style?: any) {\n    super();\n    this.text = text;\n    this.style = style || {};\n  }\n\n  updateText = vi.fn((respectDirty = true) => {});\n  updateTransform = vi.fn();\n}\n\n/**\n * Mock for PixiJS Mesh\n */\nexport class MockMesh extends MockContainer {\n  geometry: any = null;\n  shader: any = null;\n  texture: MockTexture | null = null;\n\n  constructor(geometry?: any, shader?: any, texture?: MockTexture) {\n    super();\n    this.geometry = geometry;\n    this.shader = shader;\n    this.texture = texture || null;\n  }\n}\n\n/**\n * Mock for PixiJS TilingSprite\n */\nexport class MockTilingSprite extends MockContainer {\n  texture: MockTexture;\n  tilePosition: MockObservablePoint = new MockObservablePoint(0, 0);\n  tileScale: MockObservablePoint = new MockObservablePoint(1, 1);\n\n  constructor(texture: MockTexture, width = 100, height = 100) {\n    super();\n    this.texture = texture;\n    this.width = width;\n    this.height = height;\n  }\n}\n\n/**\n * Mock for PixiJS NineSlicePlane\n */\nexport class MockNineSlicePlane extends MockContainer {\n  texture: MockTexture;\n  leftWidth: number = 10;\n  topHeight: number = 10;\n  rightWidth: number = 10;\n  bottomHeight: number = 10;\n\n  constructor(texture: MockTexture, leftWidth = 10, topHeight = 10, rightWidth = 10, bottomHeight = 10) {\n    super();\n    this.texture = texture;\n    this.leftWidth = leftWidth;\n    this.topHeight = topHeight;\n    this.rightWidth = rightWidth;\n    this.bottomHeight = bottomHeight;\n  }\n}\n\n/**\n * Mock for PixiJS DOMElement\n */\nexport class MockDOMElement extends MockContainer {\n  element: HTMLElement | null = null;\n\n  constructor(element?: HTMLElement | string) {\n    super();\n    if (typeof element === 'string') {\n      this.element = document.createElement(element);\n    } else {\n      this.element = element || null;\n    }\n  }\n}\n\n/**\n * Mock for PixiJS DOMContainer\n */\nexport class MockDOMContainer extends MockContainer {\n  constructor() {\n    super();\n  }\n}\n\n/**\n * Mock for PixiJS Application\n */\nexport class MockApplication extends MockEventEmitter {\n  stage: MockContainer = new MockContainer();\n  screen: MockRectangle = new MockRectangle(800, 600);\n  view: HTMLCanvasElement;\n  destroyed: boolean = false;\n  renderer: any = {\n    width: 800,\n    height: 600,\n    resolution: 1,\n    plugins: {},\n    render: vi.fn(),\n    destroy: vi.fn(),\n    resize: vi.fn(),\n    clear: vi.fn(),\n  };\n  ticker: any = {\n    add: vi.fn(),\n    remove: vi.fn(),\n    start: vi.fn(),\n    stop: vi.fn(),\n  };\n  loader: any = {\n    add: vi.fn(),\n    load: vi.fn(),\n  };\n\n  constructor(options?: any) {\n    super();\n    const canvas = document.createElement('canvas');\n    canvas.width = options?.width || 800;\n    canvas.height = options?.height || 600;\n    this.view = canvas;\n    this.screen.width = options?.width || 800;\n    this.screen.height = options?.height || 600;\n  }\n\n  render = vi.fn(() => {});\n  destroy = vi.fn((removeView = false) => {\n    this.destroyed = true;\n    if (removeView && this.view.parentNode) {\n      this.view.parentNode.removeChild(this.view);\n    }\n  });\n  resize = vi.fn((width: number, height: number) => {\n    this.screen.width = width;\n    this.screen.height = height;\n    this.view.width = width;\n    this.view.height = height;\n  });\n}\n\n/**\n * Mock for PixiJS VideoResource (for Video component)\n */\nexport class MockVideoResource {\n  source: HTMLVideoElement | null = null;\n  width: number = 0;\n  height: number = 0;\n  valid: boolean = false;\n\n  constructor(source?: HTMLVideoElement) {\n    this.source = source || null;\n    if (source) {\n      this.width = source.videoWidth || 0;\n      this.height = source.videoHeight || 0;\n      this.valid = true;\n    }\n  }\n\n  load = vi.fn(() => Promise.resolve(this));\n  destroy = vi.fn();\n}\n"
  },
  {
    "path": "packages/testing/tsconfig.json",
    "content": "{\n  \"extends\": \"../../tsconfig.json\",\n  \"compilerOptions\": {\n    \"outDir\": \"dist\",\n    \"declaration\": true,\n    \"emitDeclarationOnly\": false,\n    \"declarationMap\": true,\n    \"ignoreDeprecations\": \"6.0\",\n    \"rootDir\": \"src\",\n    \"types\": [\"vitest/globals\", \"node\"]\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"exclude\": [\n    \"dist\",\n    \"node_modules\"\n  ]\n}\n"
  },
  {
    "path": "packages/testing/tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nexport default defineConfig({\n  format: ['esm'],\n  target: 'node20',\n  splitting: true,\n  clean: true,\n  shims: false,\n  dts: true,\n  sourcemap: true,\n  entry: ['src/index.ts'],\n  outDir: 'dist',\n  external: ['canvasengine', 'vitest'],\n})\n"
  },
  {
    "path": "packages/tiled/package.json",
    "content": "{\n  \"name\": \"@canvasengine/tiled\",\n  \"version\": \"2.0.0-beta.58\",\n  \"description\": \"\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"publishConfig\": {\n    \"access\": \"public\"\n  },\n  \"scripts\": {\n    \"build\": \"vite build\",\n    \"dev\": \"vite build --watch\",\n    \"test\": \"vitest\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@types/node\": \"^25.6.0\",\n    \"typescript\": \"^6.0.3\",\n    \"vite\": \"^8.0.10\",\n    \"vite-plugin-dts\": \"^4.5.4\",\n    \"vitest\": \"^4.1.5\"\n  },\n  \"dependencies\": {\n    \"buffer\": \"^6.0.3\",\n    \"xml-js\": \"^1.6.11\",\n    \"xmlbuilder\": \"^15.1.1\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "packages/tiled/readme.md",
    "content": "Time was saved on writing the types. Thanks to  https://github.com/excaliburjs/excalibur-tiled/blob/main/src"
  },
  {
    "path": "packages/tiled/src/classes/Gid.ts",
    "content": "import { TiledProperties } from \"./Properties\"\n\nconst FLIPPED_HORIZONTALLY_FLAG = 0x80000000\nconst FLIPPED_VERTICALLY_FLAG   = 0x40000000\nconst FLIPPED_DIAGONALLY_FLAG   = 0x20000000\nconst ROTATED_HEXAGONAL_120_FLAG = 0x10000000\n\nexport class TileGid extends TiledProperties {\n    private _gid: number \n\n    constructor(public obj?) {\n        super(obj)\n        this._gid = obj?.gid\n    }\n\n    static getRealGid(gid: number): number {\n        return gid & ~(FLIPPED_HORIZONTALLY_FLAG |\n            FLIPPED_VERTICALLY_FLAG |\n            FLIPPED_DIAGONALLY_FLAG | \n            ROTATED_HEXAGONAL_120_FLAG)\n    }\n\n    get horizontalFlip(): boolean {\n        return !!(this._gid & FLIPPED_HORIZONTALLY_FLAG)\n    }\n\n    get verticalFlip(): boolean {\n        return !!(this._gid & FLIPPED_VERTICALLY_FLAG)\n    }\n\n    get diagonalFlip(): boolean {\n        return !!(this._gid & FLIPPED_DIAGONALLY_FLAG)\n    }\n\n    get rotatedHex120(): boolean {\n        return !!(this._gid & ROTATED_HEXAGONAL_120_FLAG)\n    }\n\n    get gid(): number {\n       return TileGid.getRealGid(this._gid)\n    }\n\n    set gid(val: number) {\n        this._gid = val\n    }\n}"
  },
  {
    "path": "packages/tiled/src/classes/Layer.ts",
    "content": "import { TiledLayer } from \"../types/Layer\";\nimport { TileGid } from \"./Gid\";\nimport { TiledObjectClass } from \"./Object\";\nimport { TiledProperties } from \"./Properties\";\nimport { Tile } from \"./Tile\";\nimport { Tileset } from \"./Tileset\";\n\nexport class Layer extends TiledProperties {\n    cacheTiles: boolean = false\n    tiles: (Tile | undefined)[] = []\n    objects: TiledObjectClass[]\n\n    get size(): number {\n        return this.data.length\n    }\n\n    constructor(layer: TiledLayer, private tilesets: Tileset[], private parent?: Layer) {\n        super(layer)\n        Object.assign(this, layer)\n        this.mapObjects()\n        this.mergePropertiesWithParent()\n        // Caching tiles saves CPU but consumes RAM for large maps\n        this.cacheTiles = this.getProperty<boolean, boolean>('cache-tiles', false)\n        if (this.cacheTiles) this.propertiesTiles()\n    }\n\n    createTile(gid: number, tileIndex: number, layerIndex?: number): Tile | undefined {\n        if (gid == 0) {\n            return\n        }\n        const realGid = TileGid.getRealGid(gid)\n        const tileset = Layer.findTileSet(realGid, this.tilesets)\n        if (!tileset) {\n            return undefined\n        }\n        const tile = tileset.getTile(realGid - tileset.firstgid)\n        if (tile) {\n            return new Tile({\n                ...tile.tile,\n                gid,\n                index: tileIndex,\n                layerIndex\n            })\n        }\n        return new Tile({\n            gid,\n            index: tileIndex,\n            layerIndex\n        })\n    }\n\n    private mergePropertiesWithParent() {\n        const parent = this.getLayerParent()\n        if (!this.properties) this.properties = {}\n        if (!parent) return\n        for (let key in parent.properties) {\n            const val = parent.properties[key]\n            const valChild = this.properties[key]\n            if (valChild === undefined) {\n                this.properties[key] = val\n            }\n            else {\n                if (key == 'z') {\n                    this.properties[key] += val\n                }\n                else {\n                    continue\n                }\n            }\n        }\n        this.opacity = Math.round((parent.opacity ?? 1) * (this.opacity ?? 1) * 100) / 100\n        this.offsetx = (parent.offsetx ?? 0) + (this.offsetx ?? 0)\n        this.offsety = (parent.offsety ?? 0) + (this.offsety ?? 0)\n        this.locked = parent.locked ?? false\n    }\n\n    private propertiesTiles() {\n        if (!this.data) return\n        const data = this.data as number[]\n        for (let i = 0; i < data.length; i++) {\n            const id = data[i]\n            this.tiles.push(this.createTile(id, i))\n        }\n    }\n\n    private mapObjects() {\n        if (this.objects) {\n            this.objects = this.objects.map(object => {\n                const obj = new TiledObjectClass(object)\n                obj.layerName = this.name\n                return obj\n            })\n        }\n    }\n\n    getTileByIndex(tileIndex: number): Tile | undefined {\n        if (this.cacheTiles) {\n            return this.tiles[tileIndex]\n        }\n        return this.createTile(this.data[tileIndex] as number, tileIndex)\n    }\n\n    static findTileSet(gid: number, tileSets: Tileset[]): Tileset | undefined {\n        let tileset: Tileset | undefined\n        for (let i = tileSets.length - 1; i >= 0; i--) {\n            tileset = tileSets[i]\n            if (tileset.firstgid && tileset.firstgid <= gid) {\n                break;\n            }\n        }\n        return tileset;\n    }\n\n    getLayerParent(): Layer | undefined {\n        return this.parent\n    }\n\n    tilesForEach(cb: (tile: Tile | undefined, index: number) => void) {\n        for (let i = 0; i < this.data.length; i++) {\n            if (this.cacheTiles) {\n                cb(this.tiles[i], i)\n                continue\n            }\n            cb(this.createTile(this.data[i] as number, i) as Tile, i)\n        }\n    }\n\n    setData(tileIndex: number, gid: number): void {\n        (this.data as number[])[tileIndex] = gid\n    }\n}\n\nexport interface Layer extends TiledLayer {\n    objects: TiledObjectClass[]\n}"
  },
  {
    "path": "packages/tiled/src/classes/Map.ts",
    "content": "import { TiledLayer, TiledLayerType } from \"../types/Layer\";\nimport { TiledMap } from \"../types/Map\";\nimport { TiledTileset } from \"../types/Tileset\";\nimport { Layer } from \"./Layer\";\nimport { TiledObjectClass } from \"./Object\";\nimport { TiledProperties } from \"./Properties\";\nimport { Tile } from \"./Tile\";\nimport { Tileset } from \"./Tileset\";\n\nexport interface TileInfo {\n    tiles: Tile[]\n    hasCollision: boolean | undefined\n    isClimbable?: boolean | undefined\n    isOverlay: boolean | undefined\n    objectGroups: TiledObjectClass[],\n    tileIndex: number\n}\n\nexport interface GetTileOptions {\n    populateTiles?: boolean\n}\n\n// Allows you to cache tilesets. Avoid rebuilding for other maps\nexport let bufferTilesets = {}\n\nexport class MapClass extends TiledProperties {\n    /** \n     * @title Data of map\n     * @prop {object} [data]\n     * @readonly\n     * @memberof Map\n     * @memberof RpgSceneMap\n     * */\n    data: TiledMap\n\n    tilesets: Tileset[] = []\n    layers: Layer[] = []\n\n    private tmpLayers: Layer[] = []\n    private tilesIndex: {\n        [zIndex: number]: Uint16Array\n    } = {}\n\n    /**\n     * Allows to define the size of ArrayBuffer to keep in memory the tiles of the map\n     */\n    private allocateMemory: number = 0\n\n    /**\n     * If set to true, the memory allocation will take only one tile (the tile of the last layer)\n     */\n    private lowMemory: boolean = false\n\n    constructor(map?: TiledMap) {\n        super(map ?? {})\n        if (map) this.load(map)\n    }\n\n    load(map: TiledMap) {\n        Object.assign(this, map)\n        if (this.hasProperty('low-memory')) {\n            this.lowMemory = this.getProperty<boolean, boolean>('low-memory', false)\n        }\n        this.tmpLayers = []\n        this.mapTilesets()\n        this.mapLayers(this.layers)\n        this.layers = [...this.tmpLayers]\n        Reflect.deleteProperty(this, 'tmpLayers')\n        this.setTilesIndex()\n        this.data = map  \n    }\n\n    /** \n     * @title Width of the map in pixels\n     * @prop {number} [widthPx]\n     * @readonly\n     * @memberof Map\n     * @memberof RpgSceneMap\n     * */\n\n    get widthPx(): number {\n        return this.width * this.tilewidth\n    }\n\n    /** \n    * @title Height of the map in pixels\n    * @prop {number} [heightPx]\n    * @readonly\n    * @memberof Map\n    * @memberof RpgSceneMap\n    * */\n    get heightPx(): number {\n        return this.height * this.tileheight\n    }\n\n    /** \n     * @title The depth of the map in pixels (this is the height of a tile ;))\n     * @prop {number} map.zTileHeight\n     * @readonly\n     * @memberof Map\n     * @memberof RpgSceneMap\n     * */\n    get zTileHeight(): number {\n        return this.tileheight\n    }\n\n    /**\n     * Find a layer by name. Returns `undefined` is the layer is not found\n\n     * @title Get Layer by name\n     * @method map.getLayerByName(name)\n     * @param {string} name layer name\n     * @returns {LayerInfo | undefined}\n     * @example\n     *  ```ts\n     *  const tiles = map.getLayerByName(0, 0)\n     *  ```\n     * @memberof Map\n     * @memberof RpgSceneMap\n     */\n    getLayerByName(name: string): TiledLayer | undefined {\n        return this.layers.find(layer => layer.name == name)\n    }\n\n    /**\n    * Get the tile index on the tileset\n    * \n    * @title Get index of tile\n    * @method map.getTileIndex(x,y)\n    * @param {number} x Position X\n    * @param {number} x Position Y\n    * @returns {number}\n    * @memberof Map\n    * @memberof RpgSceneMap\n    */\n    getTileIndex(x: number, y: number, [z] = [0]): number {\n        return this.width * Math.floor((y - z) / this.tileheight) + Math.floor(x / this.tilewidth)\n    }\n\n    getTilePosition(index: number): { x: number, y: number } {\n        return {\n            y: Math.floor(index / this.width) * this.tileheight,\n            x: index % (this.width) * this.tilewidth\n        }\n    }\n\n    /**\n     * Find the point of origin (top left) of a tile. Of course, its position depends on the size of the tile\n\n     * @title Get origin position of tile\n     * @method map.getTileOriginPosition(x,y)\n     * @param {number} x Position X\n     * @param {number} x Position Y\n     * @returns { {x: number, y: number }}\n     * @example\n     *  ```ts\n     *  // If the size of a tile is 32x32px\n     *  const position = map.getTileOriginPosition(35, 12)\n     *  console.log(position) // { x: 32, y: 0 }\n     *  ```\n     * @memberof Map\n     * @memberof RpgSceneMap\n     */\n\n    getTileOriginPosition(x: number, y: number): {\n        x: number\n        y: number\n    } {\n        return {\n            x: Math.floor(x / this.tilewidth) * this.tilewidth,\n            y: Math.floor(y / this.tileheight) * this.tileheight\n        }\n    }\n\n    /**\n    * Recover tiles according to a position\n\n    * @title Get tile by position\n    * @method map.getTileByPosition(x,y)\n    * @param {number} x Position X\n    * @param {number} x Position Y\n    * @returns {TileInfo}\n    * @example\n    *  ```ts\n    *  const tiles = map.getTileByPosition(0, 0)\n    *  ```\n    * @memberof Map\n    * @memberof RpgSceneMap\n    */\n    getTileByPosition(x: number, y: number, z: [number, number] = [0, 0], options: GetTileOptions = {}): TileInfo {\n        const tileIndex = this.getTileIndex(x, y, [z[0]])\n        return this.getTileByIndex(tileIndex, z, options)\n    }\n\n    /**\n     * Retrieves tiles according to its index\n\n     * @title Get tile by index\n     * @method map.getTileByIndex(tileIndex)\n     * @param {number} tileIndex tile index\n     * @returns {TileInfo}\n     * @example\n     *  ```ts\n     *  const index = map.getTileIndex(0, 0)\n     *  const tiles = map.getTileByIndex(index)\n     *  ```\n     * @memberof Map\n     * @memberof RpgSceneMap\n     */\n\n    getTileByIndex(\n        tileIndex: number, \n        zPlayer: [number, number] = [0, 0], \n        options: GetTileOptions = {\n            populateTiles: true\n        }\n    ): TileInfo {\n        const zA = Math.floor(zPlayer[0] / this.zTileHeight)\n        const zB = Math.floor(zPlayer[1] / this.zTileHeight)\n        const level = this.tilesIndex[zA]\n        const obj: TileInfo = {\n            tiles: [],\n            hasCollision: false,\n            isOverlay: false,\n            objectGroups: [],\n            tileIndex\n        }\n        if (!level) {\n            return obj\n        }\n        const [layer] = this.layers\n        const getTileByPointer = (pointer = 0) => {\n            const pos = tileIndex * this.realAllocateMemory + pointer\n            const gid = level[pos]\n            if (gid === 0) {\n                return obj\n            }\n            const tile = layer.createTile(gid, tileIndex, level[pos+1])\n            if (tile) obj.tiles.push(tile)\n        }\n        if (options.populateTiles) {\n            for (let i=0 ; i < this.realAllocateMemory ; i += 2) {\n                getTileByPointer(i)\n            }\n        }\n        else {\n            getTileByPointer()\n        }\n        const [tile] = obj.tiles\n        if (tile) {\n            obj.hasCollision = tile.getProperty<boolean, boolean>('collision', false)\n            obj.objectGroups = tile.objects as TiledObjectClass[] ?? []\n        }\n        return obj\n    }\n\n    getAllObjects(): TiledObjectClass[] {\n        return this.layers.reduce((prev: TiledObjectClass[], current: Layer) => {\n            if (!current.objects) return prev\n            return prev.concat(...current.objects)\n        }, [])\n    }\n\n    getData() {\n        return {\n            ...this.data,\n            layers: this.layers\n        }\n    }\n\n    setTile(x: number, y: number, layerFilter: string | ((layer: any) => boolean), tileInfo: any): {\n        x: number,\n        y: number,\n        tiles: {\n            [tileIndex: number]: Tile\n        }\n    } | never {\n        if (this.lowMemory) {\n            throw 'Impossible to change a tile with the lowMemory option'\n        }\n        const tileIndex = this.getTileIndex(x, y)\n        let fnFilter\n        let tilesEdited = {}\n        if (typeof layerFilter == 'string') {\n            fnFilter = (layer) => layer.name == layerFilter\n        }\n        else {\n            fnFilter = layerFilter\n        }\n        for (let i=0 ; i < this.layers.length ; i++) {\n            const layer = this.layers[i]\n            if (!fnFilter(layer)) continue\n            let tile: Tile | undefined\n            const oldTile = this.getTileByIndex(tileIndex)\n            if (tileInfo.gid) {\n                tile = layer.createTile(tileInfo.gid, tileIndex)\n            }\n            if (!tile) continue\n            for (let key in tileInfo) {\n                if (key == 'gid') continue\n                tile[key] = tileInfo[key]\n            }\n            tilesEdited[layer.name] = {\n                gid: tile.gid,\n                properties: tile.properties\n            }\n            this.setTileIndex(layer, oldTile.tiles[0], tile, tileIndex, i)\n            layer.setData(tileIndex, tile.gid)\n        }\n        return {\n            x,\n            y,\n            tiles: tilesEdited\n        }\n    }\n\n    removeCacheTileset(name: string) {\n        delete bufferTilesets[name]\n    }\n\n    clearCacheTilesets() {\n        bufferTilesets = {}\n    }\n\n    private mapTilesets() {\n        this.tilesets = this.tilesets.map(tileset => {\n            if (bufferTilesets[tileset.name]) {\n                const instance = bufferTilesets[tileset.name]\n                instance.firstgid = tileset.firstgid\n                return instance\n            }\n            const _tileset = new Tileset(tileset)\n            bufferTilesets[_tileset.name] = _tileset\n            return _tileset\n        })\n    }\n\n    private mapLayers(layers: TiledLayer[] = [], parent?: Layer) {\n        for (let layer of layers) {\n            const layerInstance = new Layer(layer, this.tilesets, parent)\n            this.tmpLayers.push(layerInstance)\n            if (layer.layers) {\n                this.mapLayers(layer.layers, layerInstance)\n            }\n        }\n        if (this.lowMemory) this.allocateMemory = 1\n        if (!this.allocateMemory) this.allocateMemory = this.layers.length\n    }\n\n    private setTileIndex(layer: Layer, oldTile: Tile, newTile: Tile, tileIndex: number, layerIndex: number) {\n        const startPos = tileIndex * this.realAllocateMemory\n        let pointer = startPos + this.realAllocateMemory - 2\n        const zLayer = layer.getProperty<number, number>('z', 0)\n        const zTile = oldTile.getProperty<number, number>('z', 0)\n        let z = zLayer + zTile\n        while (pointer >= startPos) {\n            const zlayer = this.tilesIndex[z]\n            if (zlayer[pointer] === oldTile.gid && zlayer[pointer+1] === layerIndex) {\n                this.tilesIndex[z][pointer] = newTile.gid\n            }\n            pointer -= 2\n        }\n    }\n\n    /**\n     * We multiply by 2 because 2 entries are stored for a tile: its GID and the Layer Index\n     * \n     * Example If I have 3 layers, The array will have the following form \n     * \n     * [\n     *  GID of Layer 3, \n     *  Layer Index of Layer 3, \n     *  GID of Layer 2, \n     *  Layer Index of Layer 2, \n     *  GID of Layer 1, \n     *  Layer Index of Layer 1,\n     * ... others tiles\n     * ]\n     * \n     * The size in memory of the map is therefore:\n     * \n     * `(map width * map height * number of layers * 4) bytes`\n     * \n     * > We multiply by 4, because an element takes 2 bytes and has 2 elements for a tile is 4 bytes in all\n     * \n     * Example (a 100x100 map with 5 layers)\n     * \n     * `100 * 100 * 5 * 4 = 200000 bytes = ~195 Kb`\n     * \n     * If we define on lowMemory then the calculation is the following\n     * \n     * `(map width * map height * 4) bytes`\n     * \n     * Example\n     * \n     * `100 * 100 * 4 = 40000 bytes = ~39 Kb`\n     */\n    private get realAllocateMemory() {\n        return this.allocateMemory * 2\n    }\n\n    /**\n     * We keep each tile in memory classified by z value. The values are ordered from the end to the beginning so that the first element of the array (when retrieved with getTileByIndex() is the tile on the highest layer. This way, the tile search is very fast for collisions \n     * \n     */\n    private addTileIndex(layer: Layer, tile: Tile | undefined, tileIndex: number, layerIndex: number) {\n        if ((!tile) || (tile && tile.gid == 0)) {\n            return\n        }\n        const zLayer = layer.getProperty<number, number>('z', 0)\n        const zTile = tile.getProperty<number, number>('z', 0)\n        let z = zLayer + zTile\n        if (!this.tilesIndex[z]) {\n            const buffer = new ArrayBuffer(layer.size * this.realAllocateMemory * 2)\n            this.tilesIndex[z] = new Uint16Array(buffer)\n        }\n        const startPos = tileIndex * this.realAllocateMemory\n        let pointer = startPos + this.realAllocateMemory - 2\n\n        while (this.tilesIndex[z][pointer] !== 0 && pointer > startPos) {\n            pointer -= 2\n        }\n\n        this.tilesIndex[z][pointer] = tile.gid\n        this.tilesIndex[z][pointer+1] = layerIndex\n        this.tilesIndex[z][startPos] = tile.gid\n        this.tilesIndex[z][startPos+1] = layerIndex\n    }\n\n    private setTilesIndex() {\n        for (let i=0 ; i < this.layers.length ; i++) {\n            const layer = this.layers[i]\n            if (layer.type != TiledLayerType.Tile) {\n                continue\n            }\n            layer.tilesForEach((tile, index) => {\n                this.addTileIndex(layer, tile, index, i)\n            })\n        }\n    }\n}\n\nexport interface MapClass extends TiledMap { }"
  },
  {
    "path": "packages/tiled/src/classes/Object.ts",
    "content": "import { TiledObject } from \"../types/Objects\";\nimport { TileGid } from \"./Gid\";\n\nexport class TiledObjectClass extends TileGid {\n    layerName?: string = ''\n\n    constructor(object?: TiledObject) {\n        super(object)\n        Object.assign(this, object)\n        if (object?.gid) {\n            this.y -= this.height\n        }\n    }\n}\n\nexport interface TiledObjectClass extends TiledObject {}"
  },
  {
    "path": "packages/tiled/src/classes/Properties.ts",
    "content": "export class TiledProperties {\n    properties: {\n        [key: string]: any\n    } = {}\n    class: string\n\n    constructor(data?: any) {\n        this.properties = data?.properties ?? {}\n    }\n\n    getProperty<P, D = undefined>(name: string, defaultValue?: D): P | D {\n        const val = this.properties[name]\n        if (val === undefined) {\n            return defaultValue as D\n        }\n        return val as any\n    }\n\n    hasProperty(name: string): boolean {\n        return !!this.properties[name]\n    }\n\n    setProperty<T>(name: string, value: T) {\n        this.properties[name] = value\n    }\n\n    getType(): string {\n        return this.class || this['type']\n    }\n }"
  },
  {
    "path": "packages/tiled/src/classes/Tile.ts",
    "content": "import { TilesetTile } from \"../types/Tile\";\nimport { TileGid } from \"./Gid\";\n\ntype TileInfo = TilesetTile & { gid?: number, index: number, layerIndex?: number }\n\nexport class Tile extends TileGid {\n    index: number\n\n    constructor(public tile: TileInfo | { gid: number }) {\n        super(tile)\n        // Store the properties before Object.assign to avoid overwriting them\n        const preservedProperties = this.properties\n        Reflect.deleteProperty(tile, 'gid')\n        Object.assign(this, tile)\n        // Restore properties if they were overwritten by Object.assign\n        if (preservedProperties && Object.keys(preservedProperties).length > 0) {\n            this.properties = { ...preservedProperties, ...this.properties }\n        }\n    } \n}\n\nexport interface Tile extends TileInfo {}"
  },
  {
    "path": "packages/tiled/src/classes/Tileset.ts",
    "content": "import { TilesetTile } from \"../types/Tile\"\nimport { TiledTileset } from \"../types/Tileset\"\nimport { TiledProperties } from \"./Properties\"\nimport { Tile } from \"./Tile\"\n\nexport class Tileset extends TiledProperties {\n    private cacheTileId: Map<number, Tile> = new Map()\n\n    constructor(private tileset: TiledTileset) {\n        super(tileset)\n        Object.assign(this, tileset)\n        this.margin = this.margin ?? 0\n        this.spacing = this.spacing ?? 0\n        // Handle both 'tiles' and 'tile' property names\n        const tilesArray = tileset.tiles || (tileset as any).tile || []\n        for (let tile of tilesArray) {\n            this.addTile(tile)\n        }\n        Reflect.deleteProperty(this, 'tiles')\n        Reflect.deleteProperty(this, 'tile')\n    }\n\n    addTile(tileObj: TilesetTile): Tile {\n        const tile = new Tile(tileObj)\n        this.cacheTileId.set(tile.id, tile)\n        return tile\n    }\n\n    getTile(id: number): Tile | undefined {\n        return this.cacheTileId.get(+id)\n    }\n}\n\nexport interface Tileset extends TiledTileset {}"
  },
  {
    "path": "packages/tiled/src/generate/tileset.ts",
    "content": "import builder from 'xmlbuilder'\nimport { TiledTileset } from '../types/Tileset'\n\nexport class Tileset {\n    constructor(protected nbTilesWidth: number, protected nbTilesHeight: number) {}\n\n    generate(attr: {\n        root: any,\n        image: any\n    }): builder.XMLElement {\n        const root = builder.create('tileset')\n        for (let param in attr.root) {\n            root.att(param, attr.root[param])\n        }\n        root.att('tilecount', this.nbTilesWidth * this.nbTilesHeight)\n        root.att('columns', this.nbTilesWidth)\n        root.ele('image', attr.image)\n        return root\n    }\n\n    createTile(id: number, properties): builder.XMLElement {\n        const tile = builder.create('tile', { headless: true })\n        tile.att('id', id)\n        const elProperties = tile.ele('properties')\n        for (let key in properties) {\n            const value = properties[key]\n            let type\n            if (typeof value == 'boolean') {\n                type = 'bool'\n            }\n            elProperties.ele('property', { name: key, type, value })\n        }\n        return tile\n    }\n}"
  },
  {
    "path": "packages/tiled/src/generate/wangtile.ts",
    "content": "import builder from 'xmlbuilder'\nimport { Tileset } from './tileset'\n\nexport class Autotile extends Tileset {\n    static readonly HEIGHT_TILES: number = 6\n    static readonly WIDTH_TILES: number = 8\n\n    constructor(private nbGroupTilesWidth: number, private nbGroupTilesHeight: number, private nbAnimation: number = 1) {\n        const totalWidth = nbGroupTilesWidth *  Autotile.WIDTH_TILES *  nbAnimation\n        const totalHeight = nbGroupTilesHeight *  Autotile.HEIGHT_TILES\n        super(totalWidth, totalHeight)\n    }\n\n    static getWangTiles(id: number): [number, number, number, number, number, number, number, number][] {\n        return [\n            [0,0,id,0,0,0,0,0],\n            [0,0,id,0,0,0,id,0],\n            [0,0,0,0,0,0,id,0],\n            [0,0,0,0,id,0,0,0],\n            [0,0,id,id,id,0,0,0],\n            [0,0,id,id,id,id,id,0],\n            [0,0,0,0,id,id,id,0],\n            [0,0,id,0,id,0,0,0],\n            [0,0,0,0,id,0,id,0],\n            [id,0,id,0,id,0,0,0],\n            [0,0,id,0,id,0,id,0],\n            [id,0,0,0,id,0,0,0],\n            [id,id,id,id,id,0,0,0],\n            [id,id,id,id,id,id,id,id],\n            [id,0,0,0,id,id,id,id],\n            [id,0,id,0,0,0,0,0],\n            [id,0,0,0,0,0,id,0],\n            [id,0,id,0,0,0,id,0],\n            [id,0,0,0,id,0,id,0],\n            [id,0,0,0,0,0,0,0],\n            [id,id,id,0,0,0,0,0],\n            [id,id,id,0,0,0,id,id],\n            [id,0,0,0,0,0,id,id],\n            [id,id,id,0,id,0,0,0],\n            [id,0,0,0,id,0,id,id],\n            [0,0,id,0,id,id,id,0],\n            [0,0,id,id,id,0,id,0],\n            [id,id,id,0,id,id,id,id],\n            [id,id,id,id,id,0,id,id],\n            [id,0,id,0,id,0,id,id],\n            [id,id,id,0,id,0,id,0],\n            [id,0,id,id,id,0,0,0],\n            [id,0,0,0,id,id,id,0],\n            [id,0,id,0,0,0,id,id],\n            [id,id,id,0,0,0,id,0],\n            [id,0,id,id,id,id,id,id],\n            [id,id,id,id,id,id,id,0],\n            [id,0,id,0,id,id,id,0],\n            [id,0,id,id,id,0,id,0],\n            [id,0,id,id,id,id,id,0],\n            [id,id,id,0,id,0,id,id],\n            [id,0,id,0,id,id,id,id],\n            [id,id,id,id,id,0,id,0],\n            [id,0,id,id,id,0,id,id],\n            [id,id,id,0,id,id,id,0],\n            [id,0,id,0,id,0,id,0]\n        ]\n    }\n\n    static getRandomColor() {\n        const letters = '0123456789ABCDEF'\n        let color = '#';\n        for (var i = 0; i < 6; i++) {\n            color += letters[Math.floor(Math.random() * 16)]\n        }\n        return color\n    }\n\n    get hasAnimation(): boolean {\n        return this.nbAnimation > 1\n    }\n\n    getIndex(x: number, y: number): number {\n        return x + y * this.nbTilesWidth\n    }\n\n    generate(attr: {\n        root: any,\n        image: any,\n        tile: any\n    }): builder.XMLElement {\n        const root = super.generate({\n            root: attr.root,\n            image: attr.image\n        })\n        for (let i=0 ; i < this.nbTilesHeight ; i++) {\n            for (let j=0 ; j < this.nbTilesWidth ; j++) {\n                const tileId = this.getIndex(j, i)\n                const nbProp = Object.keys(attr.tile).length\n                const hasAnimation = this.hasAnimation && j < Autotile.WIDTH_TILES\n                if (nbProp == 0 && !hasAnimation) {\n                    continue\n                }\n                const xmlTile = this.createTile(tileId, attr.tile)\n                if (hasAnimation) {\n                    const xmlAnimation = this.generateAnimationTile(tileId)\n                    xmlTile.importDocument(xmlAnimation)\n                }\n                root.importDocument(xmlTile)\n            }\n        }\n        const xmlWang = this.generateWangTiles()\n        root.importDocument(xmlWang)\n        return root\n    }\n\n    generateAnimationTile(tileId: number): builder.XMLElement {\n        let xml = builder.create('animation', { headless: true })\n        for (let i=0 ; i < this.nbAnimation ; i++) {\n            xml.ele('frame', { tileid: tileId + i * Autotile.WIDTH_TILES, duration: 100 })\n        }\n        return xml\n    }\n\n    generateWangTiles(tileId: number = 0, name = 'Autotile'): builder.XMLElement {\n        let xml = builder.create('wangsets', { headless: true })\n        const xmlWangset = xml.ele('wangset', { name, type: 'mixed', tile: tileId })\n        const getOrigin = (i, j) => i* Autotile.WIDTH_TILES + (j* Autotile.HEIGHT_TILES * this.nbTilesWidth)\n        for (let i=0 ; i < this.nbGroupTilesWidth ; i++) {\n            for (let j=0 ; j < this.nbGroupTilesHeight ; j++) {\n                xmlWangset.ele('wangcolor', { color: Autotile.getRandomColor(), tile: getOrigin(i, j), probability: 1 })\n            }\n        }\n        let k=0\n        for (let i=0 ; i < this.nbGroupTilesWidth ; i++) {\n            for (let j=0 ; j < this.nbGroupTilesHeight ; j++) {\n                const wangTiles = Autotile.getWangTiles(k+1)\n                const origin = getOrigin(i, j)\n                for (let l=0 ; l <= wangTiles.length ; l++) {\n                    const wangTile = wangTiles[l-1]\n                    if (!wangTile) continue\n                    const x = l % Autotile.WIDTH_TILES\n                    const y = Math.floor(l / Autotile.WIDTH_TILES)\n                    const index = this.getIndex(x, y)\n                    const tileId = origin + index\n                    xmlWangset.ele('wangtile', { tileid: tileId, wangid: wangTile.join(',') })\n                }\n                k++\n            }\n        }\n        return xml\n    }\n}\n/*\nconst str = new Autotile(1, 2).generate({\n    root: {\n        version: '1.8',\n        tiledversion: \"1.8.2\",\n        name: \"[A]Wall-Up_pipo\",\n        tilewidth: \"32\",\n        tileheight: \"32\"\n    },\n    image: {\n        source: '../../../client/maps/assets/[A]Wall-Up_pipo.png',\n        width: \"256\",\n        height: \"384\"\n    },\n    tile: {}\n }).end({ pretty: true })\nconsole.log(str)\n*/"
  },
  {
    "path": "packages/tiled/src/index.ts",
    "content": "export type { TiledWorld, TiledWorldMap } from './types/WorldMaps'\nexport type { TiledTileset } from './types/Tileset'\nexport type { TiledObject } from './types/Objects'\nexport type { TiledImage } from './types/Types'\nexport { type TiledLayer, TiledLayerType } from './types/Layer'\nexport type { TiledText } from './types/Text'\nexport type { TiledMap } from './types/Map'\nexport { isTiledFormat } from './utils'\nexport { TiledParser } from './parser/parser'\nexport { TiledProperties } from './classes/Properties'\nexport { Tile } from './classes/Tile'\nexport { Layer } from './classes/Layer'\nexport { Tileset } from './classes/Tileset'\nexport { TiledObjectClass } from './classes/Object'\nexport { TiledParserFile } from './parser/open-file'\nexport { MapClass } from './classes/Map'"
  },
  {
    "path": "packages/tiled/src/parser/open-file.ts",
    "content": "import { TiledParser } from \"./parser\"\nimport { TiledMap } from \"../types/Map\"\nimport { TiledTileset } from \"../types/Tileset\"\nimport { joinPath } from \"../utils\"\n\ntype ParseOptions = { getOnlyBasename?: boolean }\n\n\nexport class TiledParserFile {\n    private basePath: string\n\n    constructor(private file: string, {\n        basePath = '',\n        staticDir = '',\n        relativePath = ''\n    } = {}) {\n        this.basePath = basePath\n    }\n\n    static isBrowser() {\n        // @ts-ignore\n        return (typeof window !== 'undefined' && !window.useFileSystem)\n    }\n\n    static typeOfFile(file: string): {\n        isXml: boolean\n        isObject: boolean\n        isHttp: boolean\n        isPath: boolean\n    } {\n        file = file.trim()\n        const isString = typeof file == 'string'\n        const info = {\n            isXml: isString && file.startsWith('<?xml'),\n            isObject: !!file['version'],\n            isHttp: isString && file.startsWith('http')\n        }\n        return  {\n            ...info,\n            isPath: !info.isXml && !info.isObject && !info.isHttp\n        }\n    }\n\n    private _parseFile<T>(file: string, type: string, cb: Function) {\n        const isXml = content => TiledParserFile.typeOfFile(content).isXml\n\n        const loadContent = (content) => {\n            if (!content) {\n                return cb(null)\n            }\n            if (isXml(content)) {\n                const parser = new TiledParser(content, file, this.basePath)\n                if (type == 'map') {\n                    const json = parser.parseMap() as any\n                    return cb(json)\n                }\n                else if (type == 'tileset') {\n                    const json = parser.parseTileset() as any\n                    return cb(json)\n                }\n            }\n\n            return cb(JSON.parse(content))\n        }\n\n        if (TiledParserFile.typeOfFile(file).isObject) {\n            return cb(file)\n        }\n\n        const { isHttp } = TiledParserFile.typeOfFile(file)\n        if (isXml(file)) {\n            loadContent(file)\n        }\n        else if (isHttp || (TiledParserFile.isBrowser() && process.env.NODE_ENV != 'test')) {\n            let url = isHttp ? file : joinPath(this.basePath, file)\n            // @ts-ignore\n            if (TiledParserFile.isBrowser() && window.urlCache) {\n                // @ts-ignore\n                url = window.urlCache[file]\n            }\n            fetch(url, {\n                headers: {\n                    'Content-Type': 'application/xml'\n                }\n            })\n                .then(response => response.text())\n                .then(loadContent)\n                .catch(err => cb(null, err))\n        }\n    }\n\n    parseFile(cb: Function, options: ParseOptions = {}) {\n        const { getOnlyBasename } = options\n        const basename = path => path.substring(path.lastIndexOf('/') + 1)\n        if (getOnlyBasename) {\n            if (TiledParserFile.typeOfFile(this.file).isPath) {\n                this.file = basename(this.file)\n            }\n        }\n        this._parseFile<TiledMap>(this.file, 'map', (map, err) => {\n            let hasError = false\n            if (err) return cb(null, err)\n            if (map.tilesets) {\n                const parseTileset: TiledTileset[] = []\n                const finish = () => {\n                    loadAll++\n                    if (loadAll == map.tilesets.length && !hasError) {\n                        map.tilesets = parseTileset\n                        cb(map)\n                    }\n                }\n                let loadAll = 0\n                for (let i=0; i <  map.tilesets.length ; i++) {\n                    const tileset = map.tilesets[i]\n                    \n                    // Check if tileset already contains XML child data (tiles, image, etc.)\n                    if (!tileset.source || tileset.tiles || tileset.image || tileset.tile) {\n                        // Tileset already contains data, no need to load from external source\n                        parseTileset[i] = tileset\n                        finish()\n                        continue\n                    }\n                    \n                    if (getOnlyBasename) {\n                        if (TiledParserFile.typeOfFile(tileset.source).isPath) {\n                            tileset.source = basename(tileset.source)\n                        }\n                    }\n\n                    this._parseFile<TiledTileset>(tileset.source, 'tileset', (result, err) => {\n                        if (err) {\n                            hasError = true\n                            return cb(null, err)\n                        }\n                        parseTileset[i] = {\n                            ...result,\n                            firstgid: tileset.firstgid\n                        }\n                        finish()\n                    })\n                }\n                \n            }\n        })\n    }\n\n    parseFilePromise(options: ParseOptions = {}): Promise<TiledMap> {\n        return new Promise((resolve, reject) => {\n            this.parseFile((ret, err) => {\n                if (ret) resolve(ret)\n                else reject(err)\n            }, options)\n        })\n    }\n}"
  },
  {
    "path": "packages/tiled/src/parser/parser.ts",
    "content": "import { xml2js } from 'xml-js'\nimport { TiledMap } from '../types/Map'\nimport { TilesetTile } from '../types/Tile'\nimport { TiledTileset } from '../types/Tileset'\nimport { Buffer } from 'buffer'\nimport { getBaseName, joinPath } from '../utils'\n\nexport class TiledParser {\n  private layers: Map<number, any> = new Map()\n\n  constructor(private xml: string, private filePath: string = '', private basePath: string = '') { \n  }\n\n  static propToNumber = (obj, props: string[]) => {\n    for (let key of props) {\n      if (obj[key] !== undefined) {\n        obj[key] = +obj[key]\n      }\n    }\n    return obj\n  }\n\n  static propToBool = (obj, props: string[]) => {\n    for (let key of props) {\n      if (obj[key] !== undefined) {\n        obj[key] = obj[key] == 'true' || obj[key] == '1'\n      }\n    }\n    return obj\n  }\n\n  static toArray<T>(prop): T[] {\n    if (!prop) return []\n    if (!Array.isArray(prop)) return [prop]\n    return prop\n  }\n\n  getImagePath(image: string) {\n    if (this.filePath.startsWith('http')) return new URL(image, this.filePath).href\n    return joinPath(this.basePath, image)\n  }\n\n  /**\n   * Check if the object is a tileset source reference\n   * Tileset sources should not have their paths transformed with getImagePath\n   */\n  private isTilesetSource(obj: any): boolean {\n    // Check if object has tileset-specific properties\n    return obj.firstgid !== undefined || \n           obj.tilewidth !== undefined || \n           obj.tileheight !== undefined ||\n           obj.tilecount !== undefined ||\n           obj.columns !== undefined\n  }\n\n  transform = (obj) => {\n    if (!obj) return\n    const attr = obj.attributes || obj._attributes\n    if (!attr) return obj\n    let newObj = {\n      ...obj,\n      ...attr,\n      ...TiledParser.propToNumber(attr, [\n        'version',\n        'width',\n        'height',\n        'tilewidth',\n        'tileheight',\n        'nextlayerid',\n        'nextobjectid',\n        'hexsidelength',\n        'opacity',\n        'x',\n        'y',\n        'offsetx',\n        'offsety',\n        'startx',\n        'starty',\n        'id',\n        'firstgid',\n        'imageheight',\n        'imagewidth',\n        'margin',\n        'columns',\n        'rows',\n        'tilecount',\n        'rotation',\n        'gid',\n        'tileid',\n        'duration',\n        'parallaxx',\n        'parallaxy',\n        'repeatx',\n        'repeaty',\n        'pixelsize'\n      ]),\n      ...TiledParser.propToBool(attr, [\n        'visible',\n        'infinite',\n        'locked',\n        'bold',\n        'italic',\n        'kerning',\n        'strikeout',\n        'underline',\n        'wrap'\n      ])\n    }\n    if (newObj.properties) {\n      const properties: any = TiledParser.toArray(newObj.properties.property)\n      const propObj = {}\n      for (let prop of properties) {\n        const attr = prop._attributes\n        if (!attr) continue\n        let val\n        switch (attr.type) {\n          case 'file':\n            val = this.getImagePath(attr.value)\n            break\n          case 'object':\n          case 'float':\n          case 'int':\n            val = +attr.value\n            break\n          case 'bool':\n            val = attr.value == 'true' ? true : false\n            break\n          case 'class':\n            val = {\n              ...(this.transform(prop)?.properties ?? {}),\n              _classname: attr.propertytype\n            }\n            break\n          default:\n            val = attr.value\n        }\n        propObj[attr.name] = val\n      }\n      newObj.properties = propObj\n    }\n    if (newObj.polygon) {\n      newObj.polygon = this.transform(newObj.polygon)\n    }\n    if (newObj.polyline) {\n      newObj.polyline = this.transform(newObj.polyline)\n    }\n    if (newObj.points) {\n      newObj = newObj.points.split(' ').map(point => {\n        const pos = point.split(',')\n        return { x: +pos[0], y: +pos[1] }\n      })\n    }\n    if (newObj.point) {\n      newObj.point = true\n    }\n    if (newObj.ellipse) {\n      newObj.ellipse = true\n    }\n    if (newObj.text) {\n      newObj.text = {\n        text: newObj.text._text,\n        ...this.transform(newObj.text)\n      }\n      delete newObj.text._text\n    }\n    if (newObj.image) {\n      newObj.image = this.transform(newObj.image)\n    }\n    if (newObj.source) {\n      // For tileset source, keep the original path without transformation\n      // The path resolution will be handled in the TiledParserFile class\n      if (!this.isTilesetSource(newObj)) {\n        newObj.source = this.getImagePath(newObj.source)\n      }\n    }\n    const objectgroup = newObj.object || newObj.objectgroup?.object\n    if (objectgroup) {\n      newObj.objects = TiledParser.toArray(objectgroup).map((object: any) => {\n        return this.transform(object)\n      })\n    }\n    delete newObj._attributes\n    delete newObj.attributes\n    delete newObj.object\n    delete newObj.objectgroup\n    return newObj\n  }\n\n  static unpackTileBytes(buffer: Buffer, size: number): number[] | never {\n    const expectedCount = size * 4\n    if (buffer.length !== expectedCount) {\n      throw new Error(\"Expected \" + expectedCount +\n        \" bytes of tile data; received \" + buffer.length)\n    }\n    let tileIndex = 0\n    const array: number[] = []\n    for (let i = 0; i < expectedCount; i += 4) {\n      array[tileIndex] = buffer.readUInt32LE(i)\n      tileIndex++\n    }\n    return array\n  }\n\n  static decode(obj: { encoding: string, data: string }, size: number) {\n    const { encoding, data } = obj\n    if (encoding == 'base64') {\n      return TiledParser.unpackTileBytes(Buffer.from(data.trim(), 'base64'), size)\n    }\n    else if (encoding == 'csv') {\n      return data.trim().split(',').map(x => +x)\n    }\n    return data\n  }\n\n  parseMap(): TiledMap {\n    const json: any = xml2js(this.xml, { compact: true })\n    const jsonNoCompact: any = xml2js(this.xml)\n    //const layer = json.map.layer\n    const tileset = json.map.tileset\n    const group = json.map.group\n\n    const recursiveObjectGroup = (obj) => {\n      const { objectgroup, group, layer, imagelayer } = obj\n      const setLayer = (type) => {\n        if (!type) return\n        TiledParser.toArray(type).forEach((val: any) => {\n          if (this.layers.has(+val._attributes.id)) {\n            throw new Error(`Tiled Parser Error: Layer with id ${val._attributes.id} already exists`)\n          }\n          this.layers.set(+val._attributes.id, val)\n        })\n      }\n      setLayer(objectgroup)\n      setLayer(layer)\n      setLayer(group)\n      setLayer(imagelayer)\n      if (group) {\n        recursiveObjectGroup(group)\n      }\n    }\n\n    recursiveObjectGroup(json.map)\n\n    const recursiveLayer = (elements, array: any = []) => {\n      if (!elements) return array\n      for (let element of elements) {\n        const { name } = element\n        if (!['layer', 'group', 'imagelayer', 'objectgroup'].includes(name)) continue\n        const data = element.elements?.find(el => el.name == 'data')\n        element.layer = this.layers.get(+element.attributes.id)\n        const obj = {\n          ...(this.transform(data) ?? {}),\n          ...this.transform(element),\n          ...this.transform(element.layer),\n          layers: recursiveLayer(element.elements),\n          data: data ? data.elements[0].text : undefined,\n          type: name == 'layer' ? 'tilelayer' : name\n        }\n        delete obj.elements\n        delete obj.layer\n        if (obj.data) obj.data = TiledParser.decode(obj, obj.width * obj.height)\n        array.push(obj)\n      }\n      return array\n    }\n\n    const layers = recursiveLayer(jsonNoCompact.elements[0].elements)\n\n    const tilesets = TiledParser.toArray<TiledTileset>(tileset).map(tileset => {\n      const obj = this.transform(tileset)\n      return obj\n    })\n\n    const ret = {\n      ...this.transform(json.map),\n      layers,\n      tilesets\n    }\n\n    delete ret.layer\n    delete ret.tileset\n    delete ret.group\n    delete ret.imagelayer\n\n    return ret\n  }\n\n  parseTileset(): TiledTileset {\n    const json: any = xml2js(this.xml, { compact: true })\n    const { tileset } = json\n\n    const ret = {\n      ...this.transform(tileset),\n      image: this.transform(tileset.image),\n      tiles: TiledParser.toArray<TilesetTile>(tileset.tile).map((tile: any) => {\n        const ret = this.transform(tile)\n        if (tile.animation) {\n          ret.animations = TiledParser.toArray(tile.animation.frame).map(this.transform)\n        }\n        delete ret.animation\n        return ret\n      })\n    }\n\n    delete ret.tile\n\n    return ret\n  }\n}"
  },
  {
    "path": "packages/tiled/src/types/Layer.ts",
    "content": "import { TiledObject } from \"./Objects\";\nimport { TiledChunk, TiledCompression, TiledEncoding, TiledImage, TiledProperty } from \"./Types\";\n\nexport enum TiledLayerType {\n    Tile = 'tilelayer',\n    ObjectGroup = 'objectgroup',\n    Image = 'imagelayer',\n    Group = 'group'\n}\n\nexport interface TiledLayer {\n    /**\n     * Incremental ID - unique across all layers\n     */\n    id: number;\n    /**\n     * Image used by this layer. imagelayer only.\n     */\n    image: TiledImage;\n    /**\n     * Array of unsigned int (GIDs) or base64-encoded data. tilelayer only.\n     */\n    data: number[] | string;\n    /**\n     * \tArray of chunks (optional). tilelayer only.\n     */\n    chunks: TiledChunk[];\n    /**\n     * Column count. Same as map width for fixed-size maps.\n     */\n    width: number;\n    /**\n     * Row count. Same as map height for fixed-size maps.\n     */\n    height: number;\n    /**\n     * Name assigned to this layer\n     */\n    name: string;\n    /**\n     * From [0, 1]\n     */\n    opacity: number;\n    properties: {\n        [key: string]: any\n    }\n    /**\n     * csv (default) or base64. tilelayer only.\n     */\n    encoding: TiledEncoding;\n    /**\n     * zlib, gzip, zstd (since Tiled 1.3) or empty (default). tilelayer only.\n     */\n    compression?: TiledCompression;\n \n    /**\n     * Type of layer (tilelayer, objectgroup)\n     */\n    type: TiledLayerType;\n\n    /**\n     * @since 1.9\n     */\n    class: string\n\n    /**\n     * Whether layer is shown or hidden in editor\n     */\n    visible: boolean;\n \n    /**\n     * Horizontal layer offset in tiles. Always 0.\n     */\n    x: number;\n    /**\n     * Vertical layer offset in tiles. Always 0.\n     */\n    y: number;\n \n    /**\n     * Layer order in the original Tiled source\n     */\n    order: number;\n    /**\n     * Horizontal layer offset in pixels (default: 0)\n     */\n    offsetx: number;\n    /**\n     * Vertical layer offset in pixels (default: 0)\n     */\n    offsety: number;\n    /**\n     * X coordinate where layer content starts (for infinite maps)\n     */\n    startx: number;\n    /**\n     * Y coordinate where layer content starts (for infinite maps)\n     */\n    starty: number;\n \n    /**\n     * Hex-formatted color (#RRGGBB or #AARRGGBB) that is multiplied with any graphics drawn by this layer or any child layers (optional).\n     */\n    tintcolor: string;\n    /**\n     * Hex-formatted color (#RRGGBB) (optional). imagelayer only.\n     */\n    transparentcolor: string;\n \n    /**\n     * topdown (default) or index. objectgroup only.\n     */\n    draworder: 'topdown' | 'index' | 'objectgroup';\n    /**\n     * Array of objects. objectgroup only.\n     */\n    objects: TiledObject[];\n\n    layers: TiledLayer[]\n\n    parallaxx: number\n    parallaxy: number\n    repeatx: number\n    repeaty: number\n    locked: boolean\n    color: string\n }"
  },
  {
    "path": "packages/tiled/src/types/Map.ts",
    "content": "import { TiledLayer } from \"./Layer\";\nimport { TiledTileset } from \"./Tileset\";\nimport { TiledProperty } from \"./Types\";\n\nexport interface TiledMap {\n    type: 'map';\n\n    version: number;\n \n    width: number;\n    /**\n     * Number of tile rows\n     */\n    height: number;\n    /**\n     * Length of the side of a hex tile in pixels (hexagonal maps only)\n     */\n    hexsidelength: number;\n    /**\n     * Map grid height\n     */\n    tileheight: number;\n    /**\n     * Map grid width\n     */\n    tilewidth: number;\n \n    /**\n     *\tHex-formatted color (#RRGGBB or #AARRGGBB) (optional)\n     */\n    backgroundcolor: string;\n    /**\n     * The compression level to use for tile layer data (defaults to -1, which means to use the algorithm default)\n     */\n    compressionlevel: number;\n    /**\n     * Whether the map has infinite dimensions\n     */\n    infinite: boolean;\n    /**\n     *\tAuto-increments for each layer\n     */\n    nextlayerid: number;\n    /**\n     * Auto-increments for each placed object\n     */\n    nextobjectid: number;\n \n    /**\n     * Map orientation (orthogonal, isometric, staggered or hexagonal)\n     */\n    orientation: 'orthogonal' | 'isometric' | 'staggered' | 'hexagonal';\n \n    layers: TiledLayer[];\n    properties: {\n        [key: string]: any\n    }\n    tilesets: TiledTileset[];\n \n    /**\n     * Render order: right-down (the default), right-up, left-down or left-up (currently only supported for orthogonal maps)\n     */\n    renderorder: 'right-down' | 'right-up' | 'left-down' | 'left-up';\n \n    /**\n     * x or y (staggered / hexagonal maps only)\n     */\n    staggeraxis: 'x' | 'y';\n    /**\n     * odd or even (staggered / hexagonal maps only)\n     */\n    staggerindex: 'odd' | 'even';\n \n    /**\n     * The Tiled version used to save the file\n     */\n    tiledversion: string;\n \n    /**\n     * @since 1.9\n     */\n     class: string\n }"
  },
  {
    "path": "packages/tiled/src/types/Objects.ts",
    "content": "import { TiledText } from \"./Text\";\nimport { TiledPoint, TiledProperty } from \"./Types\";\n\nexport interface TiledObject {\n    id: number;\n \n    /**\n     * Tile object id\n     */\n    gid: number;\n    /**\n     * Used to mark an object as a point\n     */\n    point: boolean;\n    height: number;\n    name: string;\n    properties: {\n        [key: string]: any\n    }\n    /**\n     * Angle in degrees clockwise\n     */\n    rotation: number;\n    type: string;\n    /**\n     * @since 1.9\n     */\n    class: string \n    visible: boolean;\n    width: number;\n    /**\n     * X coordinate in pixels\n     */\n    x: number;\n    /**\n     * Y coordinate in pixels\n     */\n    y: number;\n \n    /**\n     * Reference to a template file, in case object is a template instance\n     */\n    template: string;\n \n    /**\n     *\tOnly used for text objects\n     */\n    text: TiledText;\n \n    /**\n     * Whether or not object is an ellipse\n     */\n    ellipse: boolean;\n \n    /**\n     * Polygon points\n     */\n    polygon: TiledPoint[];\n \n    /**\n     * Polyline points\n     */\n    polyline: TiledPoint[];\n }"
  },
  {
    "path": "packages/tiled/src/types/Text.ts",
    "content": "export interface TiledText {\n    text: string;\n    /**\n     * Whether to use a bold font (default: false)\n     */\n    bold: boolean;\n    /**\n     * Hex-formatted color (#RRGGBB or #AARRGGBB) (default: #000000)\n     */\n    color: string;\n    /**\n     * Font family (default: sans-serif)\n     */\n    fontfamily: string;\n    /**\n     * Horizontal alignment (center, right, justify or left (default))\n     */\n    halign: 'center' | 'right' | 'justify' | 'left';\n    /**\n     * Whether to use an italic font (default: false)\n     */\n    italic: boolean;\n    /**\n     * Whether to use kerning when placing characters (default: true)\n     */\n    kerning: boolean;\n    /**\n     * Pixel size of font (default: 16)\n     */\n    pixelsize: number;\n    /**\n     * Whether to strike out the text (default: false)\n     */\n    strikeout: boolean;\n    /**\n     * Whether to underline the text (default: false)\n     */\n    underline: boolean;\n    /**\n     * Vertical alignment (center, bottom or top (default))\n     */\n    valign: 'center' | 'bottom' | 'top';\n    /**\n     * Whether the text is wrapped within the object bounds (default: false)\n     */\n    wrap: boolean;\n }"
  },
  {
    "path": "packages/tiled/src/types/Tile.ts",
    "content": "import { TiledLayer } from \"./Layer\";\nimport { TiledObject } from \"./Objects\";\nimport { TiledFrame, TiledProperty } from \"./Types\";\n\nexport interface TilesetTile {\n    gid: number\n    id: number;\n    type: string;\n    image: string;\n    imageheight: number;\n    imagewidth: number;\n    animations: TiledFrame[];\n    properties: {\n        [key: string]: any\n    }\n    terrain: number[];\n    objects: TiledObject[];\n    probability: number;\n }"
  },
  {
    "path": "packages/tiled/src/types/Tileset.ts",
    "content": "import { TilesetTile } from \"./Tile\";\nimport { TiledGrid, TiledMapTerrain, TiledProperty, TiledTileOffset, TiledWangSet } from \"./Types\";\n\nexport interface TiledTileset {\n    type: 'tileset';\n    /**\n     * The JSON format version\n     */\n    version: number;\n \n    /**\n     * GID corresponding to the first tile in the set\n     */\n    firstgid: number;\n    /**\n     * Image used for tiles in this set\n     */\n    image: {\n        source: string\n        height: number\n        width: number\n    }\n    /**\n     * Height of source image in pixels\n     */\n    imageheight: number;\n    /**\n     * Width of source image in pixels\n     */\n    imagewidth: number;\n    /**\n     * (optional)\n     */\n    grid: TiledGrid;\n    /**\n     * Buffer between image edge and first tile (pixels)\n     */\n    margin: number;\n    /**\n     * Alignment to use for tile objects (unspecified (default), topleft, top, topright, left, center, right, bottomleft, bottom or bottomright) (since 1.4)\n     */\n    objectalignment: 'unspecified' | 'topleft' | 'top' | 'topright' | 'left' | 'center' | 'right' | 'bottomleft' | 'bottom' | 'bottomright';\n    /**\n     * Refers to external tileset file (should be JSON)\n     */\n    source: string;\n    /**\n     * Spacing between adjacent tiles in image (pixels)\n     */\n    spacing: number;\n \n    columns: number;\n    rows: number;\n    /**\n     * Maximum height of tiles in this set\n     */\n    tileheight: number;\n    tilewidth: number;\n \n    /**\n     * Array of Tiles (optional)\n     */\n    tiles: TilesetTile[];\n \n    name: string;\n    properties: {\n        [key: string]: any\n    }\n    /**\n     * The number of tiles in this tileset\n     */\n    tilecount: number;\n    /**\n     * Optional\n     */\n    tileoffset: TiledTileOffset;\n \n    /**\n     * The Tiled version used to save the file\n     */\n    tiledversion: string;\n    /**\n     * Hex-formatted color (#RRGGBB or #AARRGGBB) (optional)\n     */\n    backgroundcolor: string;\n    /**\n     * Hex-formatted color (#RRGGBB) (optional)\n     */\n    transparentcolor: string;\n    /**\n     * Array of Terrains (optional)\n     */\n    terrains: TiledMapTerrain[];\n \n    /**\n     * Array of Wang sets (since 1.1.5)\n     */\n    wangsets: TiledWangSet[];\n }"
  },
  {
    "path": "packages/tiled/src/types/Types.ts",
    "content": "export interface TiledProperty<T = unknown> {\n    /**\n     * Name of the property\n     */\n    name: string;\n    /**\n     * Type of the property (string (default), int, float, bool, color or file (since 0.16, with color and file added in 0.17))\n     */\n    type: 'string' | 'int' | 'float' | 'bool' | 'color' | 'file';\n    /**\n     * Value of the property\n     */\n    value: T;\n }\n \n export type TiledEncoding = 'csv' | 'base64';\n export type TiledCompression = 'zlib' | 'gzip' | 'zstd';\n \n export interface TiledChunk {\n    /**\n     * Array of unsigned int (GIDs) or base64-encoded data\n     */\n    data: number[] | string;\n    /**\n     * Height in tiles\n     */\n    height: number;\n    /**\n     * Width in tiles\n     */\n    width: number;\n    /**\n     * X coordinate in tiles\n     */\n    x: number;\n    /**\n     * Y coordinate in tiles\n     */\n    y: number;\n }\n \n export interface TiledTileOffset {\n    /**\n     * Horizontal offset in pixels\n     */\n    x: number;\n    /**\n     * Vertical offset in pixels (positive is down)\n     */\n    y: number;\n }\n \n export interface TiledWangSet {\n    /**\n     * Array of Wang colors\n     */\n    cornercolors: TiledWangColor[];\n    /**\n     * Array of Wang colors\n     */\n    edgecolors: TiledWangColor[];\n    name: string;\n    properties: TiledProperty[];\n    /**\n     * Local ID of tile representing the Wang set\n     */\n    tile: number;\n    wangtiles: TiledWangTile[];\n }\n \n export interface TiledWangTile {\n    /**\n     * Array of Wang color indexes (uchar[8]\n     */\n    wangid: number[];\n    /**\n     * Tile is flipped diagonally (default: false)\n     */\n    dflip: boolean;\n    /**\n     * Tile is flipped horizontally (default: false)\n     */\n    hflip: boolean;\n    /**\n     * Local ID of tile\n     */\n    tileid: number;\n    /**\n     * Tile is flipped vertically (default: false)\n     */\n    vflip: boolean;\n }\n \n export interface TiledWangColor {\n    /**\n     * Hex-formatted color (#RRGGBB or #AARRGGBB)\n     */\n    color: string;\n    /**\n     * Name of the Wang color\n     */\n    name: string;\n    /**\n     * Probability used when randomizing\n     */\n    probability: number;\n    /**\n     * Local ID of tile representing the Wang color\n     */\n    tile: number;\n }\n \n export interface TiledGrid {\n    /**\n     *\torthogonal (default) or isometric\n     */\n    orientation: 'orthogonal' | 'isometric';\n    /**\n     * Cell width of tile grid\n     */\n    width: number;\n    /**\n     * Cell height of tile grid\n     */\n    height: number;\n }\n \n export interface TiledFrame {\n    /**\n     * Frame duration in milliseconds\n     */\n    duration: number;\n    /**\n     * \tLocal tile ID representing this frame\n     */\n    tileid: number;\n }\n export interface TiledMapTerrain {\n    name: string;\n    /**\n     * Local ID of tile representing terrain\n     */\n    tile: number;\n    properties: TiledProperty[];\n }\n \n export interface TiledPoint {\n    x: number;\n    y: number;\n }\n\n export interface TiledImage {\n   source: string,\n   width: number, \n   height: number\n   trans?: string\n }"
  },
  {
    "path": "packages/tiled/src/types/WorldMaps.ts",
    "content": "export interface TiledWorldMap {\n    fileName: string\n    height: number\n    width: number\n    x: number\n    y: number\n}\n\nexport interface TiledWorld {\n    maps: TiledWorldMap[]\n    onlyShowAdjacentMaps: boolean,\n    type: 'world'\n}"
  },
  {
    "path": "packages/tiled/src/utils.ts",
    "content": "export function isTiledFormat(val: any): boolean {\n    return typeof val == 'object' && val.version && val.orientation\n}\n/**\n * Join path segments with forward slashes\n * @param {...string} segments - Path segments to join\n * @returns {string} Joined path\n * @example\n * joinPath('base', 'static', 'file.json') // returns 'base/static/file.json'\n */\n\nexport function joinPath(...segments: string[]): string {\n    return segments\n        .filter(segment => segment && segment.length > 0)\n        .join('/')\n        .replace(/\\/+/g, '/') // Replace multiple slashes with single slash\n}\n\n\nexport function getBaseName(path: string): string {\n    return path.substring(0, path.lastIndexOf('/') + 1)\n}"
  },
  {
    "path": "packages/tiled/tests/class.spec.ts",
    "content": "import { TiledParser } from \"../src/parser/parser\"\nimport { tileset, xmlObjectImage, xmlTile } from \"./data\"\nimport { Tileset } from '../src/classes/Tileset'\nimport { Layer, Tile, TiledLayerType, TiledObjectClass } from '../src'\nimport { test, expect, describe, beforeEach } from 'vitest'\n\nlet layer: Layer\n\nfunction setLayer(xml) {\n    const parser = new TiledParser(xml)\n    const map = parser.parseMap()\n    const parserTileset = new TiledParser(tileset)\n    const tilesetData = parserTileset.parseTileset()\n    const tilesetInstance = new Tileset(tilesetData)\n    map.layers[0].properties = {}\n    map.layers[0].properties['cache-tiles'] = true\n    layer = new Layer(map.layers[0], [tilesetInstance])\n}\n\ndescribe('Tests classes', () => {\n\n    beforeEach(() => {\n        setLayer(xmlTile)\n    })\n\n    test('Verify tiles array', () => {\n        expect(layer.tiles).toBeDefined()\n    })\n\n    test('tiles is not empty', () => {\n        expect(layer.tiles).toHaveLength(layer.width * layer.height)\n    })\n\n    test('tile is Tile instance', () => {\n        expect(layer.tiles[0]).toBeInstanceOf(Tile)\n    })\n\n    test('Get Gid', () => {\n        const tile = layer.tiles[0]\n        expect(tile?.gid).toBe(9)\n    })\n\n    test('Get Gid Flip', () => {\n        const tile = layer.tiles[1]\n        expect(tile?.horizontalFlip).toBe(true)\n        expect(tile?.verticalFlip).toBe(false)\n        expect(tile?.diagonalFlip).toBe(true)\n    })\n\n})\n\n\ndescribe('Tests classes for objectgroup', () => {\n\n    beforeEach(() => {\n        setLayer(xmlObjectImage)\n    })\n\n    test('Verify Type', () => {\n       expect(layer.type).toBe(TiledLayerType.ObjectGroup)\n    })\n\n    test('has objects property', () => {\n        expect(layer).toHaveProperty('objects')\n        expect(layer.objects).toHaveLength(1)\n    })\n\n    test('TiledObjectClass instance', () => {\n        const object = layer.objects[0]\n        expect(object).toBeInstanceOf(TiledObjectClass)\n        expect(object).toHaveProperty('x')\n        expect(object).toHaveProperty('y')\n        expect(object).toHaveProperty('width')\n        expect(object).toHaveProperty('height')\n    })\n\n    test('get gid', () => {\n        const object = layer.objects[0]\n        expect(object.gid).toBe(1)\n    })\n\n    test('test flip', () => {\n        const object = layer.objects[0]\n        expect(object?.horizontalFlip).toBe(true)\n        expect(object?.verticalFlip).toBe(false)\n        expect(object?.diagonalFlip).toBe(false)\n    })\n})"
  },
  {
    "path": "packages/tiled/tests/data.ts",
    "content": "const xmlObject = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"3\" nextobjectid=\"2\">\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <objectgroup id=\"2\" name=\"Object Layer 1\">\n  <object id=\"1\" x=\"62.0593\" y=\"24.752\" width=\"19.0124\" height=\"20.0886\"/>\n </objectgroup>\n</map>\n`\n\nconst xml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"5\">\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n  </data>\n </layer>\n <layer id=\"2\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n</map>\n`\n\nconst xmlProperties = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"3\" nextobjectid=\"2\">\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <objectgroup id=\"2\" name=\"Object Layer 1\">\n  <properties>\n   <property name=\"test\" type=\"int\" value=\"0\"/>\n  </properties>\n  <object id=\"1\" x=\"62.0593\" y=\"24.752\" width=\"19.0124\" height=\"20.0886\">\n   <properties>\n    <property name=\"objectprop\" type=\"int\" value=\"0\"/>\n   </properties>\n  </object>\n </objectgroup>\n</map>\n`\n\nconst xmlGroup = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"2\">\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <objectgroup id=\"2\" name=\"Object Layer 1\">\n  <properties>\n   <property name=\"test\" type=\"int\" value=\"0\"/>\n  </properties>\n </objectgroup>\n <group id=\"3\" name=\"Group 1\">\n  <properties>\n   <property name=\"grouptest\" type=\"int\" value=\"0\"/>\n  </properties>\n  <layer id=\"4\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n   <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n  </layer>\n </group>\n</map>\n`\n\nconst xmlImage = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"6\" nextobjectid=\"2\">\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <imagelayer id=\"5\" name=\"Image Layer 1\">\n  <image source=\"assets/test.png\" width=\"1536\" height=\"2112\"/>\n </imagelayer>\n</map>\n`\n\nconst xmlTile = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"9\" nextobjectid=\"3\">\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <layer id=\"8\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n  <data encoding=\"csv\">\n9,2684354569,0,0,0,0,0,0,0,0,\n0,3758096393,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0\n</data>\n </layer>\n</map>\n`\n\nconst tileset = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tileset version=\"1.8\" tiledversion=\"1.8.2\" name=\"[Base]BaseChip_pipo\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"1000\" columns=\"8\">\n <image source=\"../../client/maps/assets/[Base]BaseChip_pipo.png\" width=\"256\" height=\"4000\"/>\n <tile id=\"0\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"1\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"2\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"3\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"4\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"5\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"6\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"7\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"8\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"9\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"10\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"11\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"12\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"13\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"14\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"15\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"16\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"16.9835\" y=\"14.9844\" width=\"15\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"17\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"1.66533e-16\" y=\"15.4545\" width=\"17\" height=\"16.5455\"/>\n  </objectgroup>\n </tile>\n <tile id=\"18\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"19\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"20\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"21\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"22\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"23\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n </tile>\n <tile id=\"24\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"25\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"26\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"27\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"28\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"29\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"30\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"31\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"32\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"33\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"34\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"35\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"36\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"37\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"38\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"39\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"40\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"9.52174\" width=\"31.9565\" height=\"20.4783\"/>\n  </objectgroup>\n </tile>\n <tile id=\"41\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"11.3913\" width=\"32\" height=\"18.913\"/>\n  </objectgroup>\n </tile>\n <tile id=\"42\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"11.4348\" width=\"31.8261\" height=\"18.4348\"/>\n  </objectgroup>\n </tile>\n <tile id=\"43\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.69565\" y=\"19.2174\" width=\"27.2174\" height=\"10.6957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"44\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"45\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"46\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"47\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"48\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"49\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"50\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"51\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"52\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"53\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"54\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"55\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"56\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"57\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"58\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"59\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"60\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"61\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"62\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"63\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"64\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"65\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"66\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"67\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"68\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"69\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"70\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"71\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"72\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"73\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"-0.0869565\" y=\"0.0434783\" width=\"32.087\" height=\"1.86957\"/>\n  </objectgroup>\n </tile>\n <tile id=\"74\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.0434783\">\n    <polygon points=\"0,0 17.7826,0.0869565 31.8261,13.6957 32.1304,31.9565 29.913,31.913 29.5652,14.3913 16.9565,2.04348 -0.0434783,2.04348\"/>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"75\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"76\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"77\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"78\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"79\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"80\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"81\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"82\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"83\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"84\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"85\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"86\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"87\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"88\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"89\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"90\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"91\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"92\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"93\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"94\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"95\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"96\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"97\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"98\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"99\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"100\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"101\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"102\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"103\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"104\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"105\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"106\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"107\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"108\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"109\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"110\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"111\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"112\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"113\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"114\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"115\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"116\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"117\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"118\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"119\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"120\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"121\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"122\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"123\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"124\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"125\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"126\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"127\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"128\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"129\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"130\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"131\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"132\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"133\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"134\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"135\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"136\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"137\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"138\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"139\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"140\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"141\">\n  <properties>\n   <property name=\"climb\" type=\"bool\" value=\"true\"/>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"142\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"143\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"144\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"145\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"146\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"147\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"148\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"149\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"150\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"151\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"152\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"153\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"154\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"155\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"156\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"157\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"158\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"159\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.75\" y=\"-0.25\" width=\"24.5\" height=\"16\"/>\n  </objectgroup>\n </tile>\n <tile id=\"160\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"161\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"162\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"163\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.78261\" y=\"0.0434783\" width=\"18.1304\" height=\"13.2174\"/>\n  </objectgroup>\n </tile>\n <tile id=\"164\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"165\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"166\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.5\" y=\"0.75\" width=\"26.25\" height=\"17\"/>\n  </objectgroup>\n </tile>\n <tile id=\"167\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"2.75\" y=\"0.5\" width=\"24.5\" height=\"16.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"168\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"169\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"170\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"171\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"172\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"173\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.25\" y=\"-0.25\" width=\"23.25\" height=\"15.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"174\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"175\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"176\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8.25\" y=\"-0.25\" width=\"14\" height=\"32\"/>\n  </objectgroup>\n </tile>\n <tile id=\"177\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.5\" y=\"3.5\" width=\"12\" height=\"28.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"178\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.75\" y=\"12.25\" width=\"22\" height=\"19.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"179\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"20.75\" height=\"20\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"180\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"181\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"182\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12.5\" width=\"31.5\" height=\"19.75\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"183\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"184\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"12\" width=\"31.5\" height=\"18\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"185\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"9.25\" y=\"0\" width=\"12.5\" height=\"28.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"186\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"187\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0.25\" width=\"19\" height=\"27.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"188\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.25\" y=\"11.25\" width=\"20\" height=\"16.5\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"189\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.5\" y=\"0.25\" width=\"19.25\" height=\"31.25\"/>\n  </objectgroup>\n </tile>\n <tile id=\"190\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"13.8261\" width=\"20\" height=\"6.17391\"/>\n   <object id=\"2\" x=\"10.3478\" y=\"0.130435\" width=\"10.2174\" height=\"31.7391\"/>\n  </objectgroup>\n </tile>\n <tile id=\"191\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.9565\" y=\"4.43478\" width=\"8\" height=\"24.0435\"/>\n  </objectgroup>\n </tile>\n <tile id=\"192\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"193\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"194\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"195\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"196\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"197\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"198\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"199\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"200\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"201\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"202\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"203\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"204\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"205\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"206\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"207\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"208\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"209\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"210\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"211\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"212\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"213\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"214\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"215\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"216\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"217\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"218\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"219\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"220\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"221\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"222\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"223\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"224\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"225\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"226\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"227\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"228\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"6.75\" y=\"10.75\" width=\"17.25\" height=\"19\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"229\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"230\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"231\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"232\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"233\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"234\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"235\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"236\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"4.18182\" y=\"17.4545\" width=\"23.8182\" height=\"14\"/>\n  </objectgroup>\n </tile>\n <tile id=\"237\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"12.8696\" y=\"20.3913\" width=\"6.21739\" height=\"9.56522\"/>\n  </objectgroup>\n </tile>\n <tile id=\"238\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"3.17391\" y=\"18.9565\" width=\"28.7391\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"239\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"19.5217\" width=\"28.9565\" height=\"11\"/>\n  </objectgroup>\n </tile>\n <tile id=\"240\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"241\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"242\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"243\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"244\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"245\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"246\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"247\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"248\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"249\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"250\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"251\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"252\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"253\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"254\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"255\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"256\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"257\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"258\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"259\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"260\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"261\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"262\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"263\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"264\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"265\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0434783\" y=\"14.0435\" width=\"31.913\" height=\"12.1739\"/>\n  </objectgroup>\n </tile>\n <tile id=\"266\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"267\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.0435\" y=\"16.2609\" width=\"7.43478\" height=\"15.8696\">\n    <properties>\n     <property name=\"overlay\" type=\"bool\" value=\"true\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"268\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"269\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"4\">\n   <object id=\"4\" x=\"14.5272\" y=\"16.125\" width=\"6.28261\" height=\"16.0734\"/>\n  </objectgroup>\n </tile>\n <tile id=\"270\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"271\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"272\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"273\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"274\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"275\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"15\" y=\"0.0869565\" width=\"2.04348\" height=\"31.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"276\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"277\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"14.8261\" y=\"0.0434783\" width=\"2.26087\" height=\"31.8696\"/>\n  </objectgroup>\n </tile>\n <tile id=\"278\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"279\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"280\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"281\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0.0869565\" y=\"14.1304\" width=\"31.7826\" height=\"12.6087\"/>\n  </objectgroup>\n </tile>\n <tile id=\"282\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"283\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.2609\" y=\"0.173913\" width=\"9.21739\" height=\"23.8261\"/>\n  </objectgroup>\n </tile>\n <tile id=\"284\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"285\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"11.4348\" y=\"0.0434783\" width=\"9.17391\" height=\"23.5217\"/>\n  </objectgroup>\n </tile>\n <tile id=\"286\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"0\" y=\"0\" width=\"8.75\" height=\"30.5\"/>\n  </objectgroup>\n </tile>\n <tile id=\"287\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"0\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"21\" y=\"0.5\" width=\"9.5\" height=\"29.75\"/>\n  </objectgroup>\n </tile>\n <tile id=\"288\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"289\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"290\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"291\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"292\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"293\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"294\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"295\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"296\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"297\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"298\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"299\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"300\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"301\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"302\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"303\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"304\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"305\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"306\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"307\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"308\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"309\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"310\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"311\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"312\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"313\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"314\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"315\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"316\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"317\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"318\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"319\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"320\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"321\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"322\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"323\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"324\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"325\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"326\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"327\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"328\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"329\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"330\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"331\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"332\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"333\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"334\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"335\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"336\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"337\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"338\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"339\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"340\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"341\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"342\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"343\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"344\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"345\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"346\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"347\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"348\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"349\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"350\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"351\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"352\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"353\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"354\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"355\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"356\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"357\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"358\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"359\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"360\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"361\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"362\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"363\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"364\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"365\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"366\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"367\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"368\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"369\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"370\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"371\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"372\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"373\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"374\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"375\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"376\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"377\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"378\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"379\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"380\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"381\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"382\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"383\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"384\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"385\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"386\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"387\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"388\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"389\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"390\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"391\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"392\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"393\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"394\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"395\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"396\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"397\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"398\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"399\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"400\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"401\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"402\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"403\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"404\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"405\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"406\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"407\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"408\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"409\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"410\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"411\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"412\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"413\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"414\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"415\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"416\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"417\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"418\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"419\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"420\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"421\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"422\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"423\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"424\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"425\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"426\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"427\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"428\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"429\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"430\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"431\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"432\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"433\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"434\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"435\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"436\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"437\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"438\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"439\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"440\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"441\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"442\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"443\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"444\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"445\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"446\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"447\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"448\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"449\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"450\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"451\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"452\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"453\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"454\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"455\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"456\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"457\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"458\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"459\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"460\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"461\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"462\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"463\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"464\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"465\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"466\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"467\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"468\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"469\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"470\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"471\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"472\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"473\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"474\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"475\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"476\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"477\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"478\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"479\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"480\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"481\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"482\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"483\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"484\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"485\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"486\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"487\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"488\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"489\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"490\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"491\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"492\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"493\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"494\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"495\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"496\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"497\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"498\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"499\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"500\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"501\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"502\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"503\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"504\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"505\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"506\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"507\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"508\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"509\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"510\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"511\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"512\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"513\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"514\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"515\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"516\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"517\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"518\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"519\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"520\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"521\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"522\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"523\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"524\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"525\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"526\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"527\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"528\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"529\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"530\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"531\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"532\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"533\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"534\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"535\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"536\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"537\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"538\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"539\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"540\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"541\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"542\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"543\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"544\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"545\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"546\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"547\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"548\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"549\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"550\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"551\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"552\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"553\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"554\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"555\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"556\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"557\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"558\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"559\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"560\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"561\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"562\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"563\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"564\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"565\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"566\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"567\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"568\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"569\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"570\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"571\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"572\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"573\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"574\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"575\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"576\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"577\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"578\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"579\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"580\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"581\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"582\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"583\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"584\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"585\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"586\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"587\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"588\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"589\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"590\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"591\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"592\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"593\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"594\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"595\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"596\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"597\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"598\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"599\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"600\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"601\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"602\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"603\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"604\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"605\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"606\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"607\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"608\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"609\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"610\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"611\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"612\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"613\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"614\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"615\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"616\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"617\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"618\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"619\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"620\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"621\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"622\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"623\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"624\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"625\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"626\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"627\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"628\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"629\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"630\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"631\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"632\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"633\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"634\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"635\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"636\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"637\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"638\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"639\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"640\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"641\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"642\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"643\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"644\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"645\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"646\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"647\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"648\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"649\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"650\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"651\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"652\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"653\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"654\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"655\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"656\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"657\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"658\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"659\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"660\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"661\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"662\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"663\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"664\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"665\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"666\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"667\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"668\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"669\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"670\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"671\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"672\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"673\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"674\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"675\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"676\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"677\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"678\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"679\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"680\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"681\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"682\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"683\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"684\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"685\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"686\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"687\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"688\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"689\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"690\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"691\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"692\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"693\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"694\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"695\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"696\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"697\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"698\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"699\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"700\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"701\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"702\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"703\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"704\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"705\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"706\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"707\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"708\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"709\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"710\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"711\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"712\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"713\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"714\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"715\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"716\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"717\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"718\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"719\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"720\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"721\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"722\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"723\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"724\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"725\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"726\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"727\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"728\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"729\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"730\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"731\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"732\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"733\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"734\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"735\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"736\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"737\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"738\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"739\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"740\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"741\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"742\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"743\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"744\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"745\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"746\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"747\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"748\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"749\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"750\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"751\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"752\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"753\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"754\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"755\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"756\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"757\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"758\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"759\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"760\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"761\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"762\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"763\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"764\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"765\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"766\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"767\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"768\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"769\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"770\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"771\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"772\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"773\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"774\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"775\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"776\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"777\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"778\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"779\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"780\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"781\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"782\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"783\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"784\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"785\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"786\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"787\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"788\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"789\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"790\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"791\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"792\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"793\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"794\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"795\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"796\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"797\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"798\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"799\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"800\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"801\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"802\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"803\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"804\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"805\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"806\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"807\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"808\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"809\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"810\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"811\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"812\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"813\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"814\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"815\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"816\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"817\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"818\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"819\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"820\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"821\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"822\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"823\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"824\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"825\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"826\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"827\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"828\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"829\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"830\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"831\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"832\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"833\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"834\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"835\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"836\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"837\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"838\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"839\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"840\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"841\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"842\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"843\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"844\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"845\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"846\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"847\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"848\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"849\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"850\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"851\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"852\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"853\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"854\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"855\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"856\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"857\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"858\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"859\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"860\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"861\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"862\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"863\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"864\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"865\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"866\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"867\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"868\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"869\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"870\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"871\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"872\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"873\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"874\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"875\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"876\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"877\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"878\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"879\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"880\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"881\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"882\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"883\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"884\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"885\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"886\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"887\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"888\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"889\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"890\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"891\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"892\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"893\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"894\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"895\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"896\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"897\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"898\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"899\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"900\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"901\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"902\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"903\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"904\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"905\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"906\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"907\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"908\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"909\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"910\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"911\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"912\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"913\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"914\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"915\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"916\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"917\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"918\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"919\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"920\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"921\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"922\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"923\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"924\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"925\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"926\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"927\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"928\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"929\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"930\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"931\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"932\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"933\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"934\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"2\"/>\n  </properties>\n </tile>\n <tile id=\"935\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n  </properties>\n </tile>\n <tile id=\"936\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"937\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"938\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"939\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"940\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"941\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"942\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"z\" type=\"int\" value=\"1\"/>\n  </properties>\n </tile>\n <tile id=\"943\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"944\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"945\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"946\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"947\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"948\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"949\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"8\" y=\"11.2727\" width=\"15.4545\" height=\"18.7273\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"950\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n  <objectgroup draworder=\"index\" id=\"2\">\n   <object id=\"1\" x=\"10.1818\" y=\"12.9091\" width=\"12\" height=\"15.6364\">\n    <properties>\n     <property name=\"z\" type=\"int\" value=\"0\"/>\n    </properties>\n   </object>\n  </objectgroup>\n </tile>\n <tile id=\"951\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"952\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"953\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"954\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"955\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"956\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"957\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"958\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"959\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"960\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"961\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"962\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"963\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"964\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"965\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"966\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"967\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"968\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"969\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"970\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"971\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"972\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"973\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"974\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"975\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"976\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"977\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"978\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"979\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"980\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"981\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"982\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"983\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"984\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"985\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"986\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"987\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"988\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"989\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"990\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"991\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"992\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"993\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"994\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"995\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"996\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"997\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"998\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n <tile id=\"999\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n  </properties>\n </tile>\n</tileset>\n`\n\nconst xmlObjectImage = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"11\" nextobjectid=\"4\">\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <objectgroup id=\"10\" name=\"Object Layer 1\">\n  <object id=\"3\" gid=\"2147483649\" x=\"134.631\" y=\"85.2599\" width=\"32\" height=\"32\" rotation=\"296.503\"/>\n </objectgroup>\n</map>\n`\n\nconst xmlText= `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"12\" nextobjectid=\"5\">\n <objectgroup id=\"11\" name=\"Object Layer 1\">\n  <object id=\"4\" x=\"109.781\" y=\"133.5\" width=\"91.4375\" height=\"19\">\n   <text wrap=\"1\">Hello World</text>\n  </object>\n </objectgroup>\n</map>\n`\n\nconst xmlDeepProperties = `\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"13\" nextobjectid=\"5\">\n <properties>\n   <property name=\"test\" type=\"class\" propertytype=\"Event\">\n    <properties>\n     <property name=\"hp\" type=\"int\" value=\"5\"/>\n     <property name=\"mode\" propertytype=\"Enum0\" value=\"scenario\"/>\n    </properties>\n   </property>\n  </properties>\n</map>\n\n`\n\nexport {\n    xmlObject,\n    xmlObjectImage,\n    xml,\n    xmlProperties,\n    xmlGroup,\n    xmlImage,\n    xmlTile,\n    tileset,\n    xmlText,\n    xmlDeepProperties\n}"
  },
  {
    "path": "packages/tiled/tests/parser.spec.ts",
    "content": "import { TiledParser } from '../src/parser/parser'\nimport { TiledLayerType } from '../src/types/Layer'\nimport { xml, xmlDeepProperties, xmlGroup, xmlImage, xmlObject, xmlProperties, xmlText, xmlTile } from './data'\nimport { test, expect } from 'vitest'\n\ntest('propToNumber() method', () => {\n    const ret = TiledParser.propToNumber({\n        test: '1',\n        other: '2'\n    }, ['test'])\n    expect(ret.test).toBe(1)\n    expect(ret.other).toBe('2')\n})\n\ntest('propToBool() method', () => {\n    const ret = TiledParser.propToBool({\n        test: 'true',\n        other: 'false',\n        foo: 'false'\n    }, ['test', 'other'])\n    expect(ret.test).toBe(true)\n    expect(ret.other).toBe(false)\n    expect(ret.foo).toBe('false')\n})\n\ntest('toArray() method', () => {\n    const ret = TiledParser.toArray({ test: 1 })\n    expect(ret).toMatchObject([ { test: 1 }])\n})\n\ntest('parseMap() method', () => {\n   const parser = new TiledParser(xml)\n   const map = parser.parseMap()\n   expect(map.version).toBe(1.8)\n   expect(map.width).toBe(10)\n   expect(map.layers).toHaveLength(2)\n   const layer = map.layers[0]\n   expect(layer).toHaveProperty('name', 'Tile Layer 1')\n   expect(layer).toHaveProperty('encoding', 'base64')\n   expect(layer).toHaveProperty('data')\n})\n\ntest('parseMap() method - test data', () => {\n    const parser = new TiledParser(xml)\n    const map = parser.parseMap()\n    const data = map.layers[0].data\n    expect(data).toHaveLength(map.width * map.height)\n    expect(data[0]).toBe(1)\n})\n\ntest('parseMap() method - test objectgroup', () => {\n    const parser = new TiledParser(xmlObject)\n    const map = parser.parseMap()\n    const layer = map.layers[1]\n    expect(layer.type).toBe(TiledLayerType.ObjectGroup)\n    expect(layer.objects).toHaveLength(1)\n    expect(layer.objects[0]).toMatchObject({ id: 1, x: 62.0593, y: 24.752, width: 19.0124, height: 20.0886 })\n})\n\ntest('parseMap() method - test properties', () => {\n    const parser = new TiledParser(xmlProperties)\n    const map = parser.parseMap()\n    const layer = map.layers[1]\n    expect(layer.properties).toMatchObject({ test: 0 })\n    expect(layer.objects[0].properties).toMatchObject({ objectprop: 0 })\n})\n\ntest('parseMap() method - test properties', () => {\n    const parser = new TiledParser(xmlDeepProperties)\n    const map = parser.parseMap()\n    const properties: any = map.properties\n    expect(properties.test).toHaveProperty('hp', 5)\n    expect(properties.test).toHaveProperty('mode', 'scenario')\n    expect(properties.test).toHaveProperty('_classname', 'Event')\n})\n\ntest('parseMap() method - test group', () => {\n    const parser = new TiledParser(xmlGroup)\n    const map = parser.parseMap()\n    const layer = map.layers[2]\n    expect(layer.type).toBe(TiledLayerType.Group)\n    expect(layer.layers).toHaveLength(1)\n    expect(layer.properties).toMatchObject({ grouptest: 0 })\n})\n\ntest('parseMap() method - test image', () => {\n    const parser = new TiledParser(xmlImage)\n    const map = parser.parseMap()\n    const layer = map.layers[1]\n    expect(layer.type).toBe(TiledLayerType.Image)\n    expect(layer).toHaveProperty('image')\n    expect(layer.image).toMatchObject({ source: 'assets/test.png', width: 1536, height: 2112 })\n})\n\ntest('parseMap() method - test tileset', () => {\n    const parser = new TiledParser(xmlTile)\n    const map = parser.parseMap()\n    expect(map).toHaveProperty('tilesets')\n    expect(map.tilesets).toHaveLength(1)\n    const tileset = map.tilesets[0]\n    expect(tileset).toHaveProperty('firstgid', 1)\n    expect(tileset).toHaveProperty('source', '[Base]BaseChip_pipo.tsx')\n})\n\ntest('parseMap() method - test text object', () => {\n    const parser = new TiledParser(xmlText)\n    const map = parser.parseMap()\n    const layer = map.layers[0].objects[0]\n    expect(layer).toHaveProperty('text')\n    expect(layer.text).toHaveProperty('text', 'Hello World')\n    expect(layer.text).toHaveProperty('wrap', true)\n})"
  },
  {
    "path": "packages/tiled/tests/tile-properties.spec.ts",
    "content": "import { test, expect } from 'vitest'\nimport { TiledParser } from \"../src/parser/parser\"\nimport { MapClass } from '../src'\n\nconst xmlWithTileProperties = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"2\" height=\"2\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"2\" nextobjectid=\"1\">\n <tileset firstgid=\"1\" name=\"test\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"4\" columns=\"2\">\n  <image source=\"test.png\" width=\"64\" height=\"64\"/>\n  <tile id=\"0\">\n   <properties>\n    <property name=\"collision\" type=\"bool\" value=\"true\"/>\n    <property name=\"damage\" type=\"int\" value=\"10\"/>\n   </properties>\n  </tile>\n  <tile id=\"1\">\n   <properties>\n    <property name=\"collision\" type=\"bool\" value=\"false\"/>\n    <property name=\"heal\" type=\"int\" value=\"5\"/>\n   </properties>\n  </tile>\n </tileset>\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"2\" height=\"2\">\n  <data encoding=\"csv\">\n1,2,\n3,4\n</data>\n </layer>\n</map>`\n\nconst tileset = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<tileset version=\"1.9\" tiledversion=\"1.9.2\" name=\"test\" tilewidth=\"32\" tileheight=\"32\" tilecount=\"4\" columns=\"2\">\n <image source=\"test.png\" width=\"64\" height=\"64\"/>\n <tile id=\"0\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"true\"/>\n   <property name=\"damage\" type=\"int\" value=\"10\"/>\n  </properties>\n </tile>\n <tile id=\"1\">\n  <properties>\n   <property name=\"collision\" type=\"bool\" value=\"false\"/>\n   <property name=\"heal\" type=\"int\" value=\"5\"/>\n  </properties>\n </tile>\n</tileset>`\n\nfunction getMap(xml: string): MapClass {\n    const parser = new TiledParser(xml)\n    const mapData = parser.parseMap()\n    mapData.tilesets = mapData.tilesets.map(source => {\n        const parserTileset = new TiledParser(tileset)\n        const tilesetData = parserTileset.parseTileset()\n        return {\n            ...source,\n            ...tilesetData\n        }\n    })\n    return new MapClass(mapData)\n}\n\ntest('Tile properties should be preserved after creation', () => {\n    const map = getMap(xmlWithTileProperties)\n    \n    // Get tile at position (0, 0) which should be tile ID 1 (firstgid=1, so tile 0 from tileset)\n    const tileInfo = map.getTileByPosition(0, 0)\n    const [tile] = tileInfo.tiles\n    \n    expect(tile).toBeDefined()\n    expect(tile.properties).toBeDefined()\n    expect(Object.keys(tile.properties)).toHaveLength(2)\n    expect(tile.getProperty('collision')).toBe(true)\n    expect(tile.getProperty('damage')).toBe(10)\n})\n\ntest('Multiple tiles should have their own properties', () => {\n    const map = getMap(xmlWithTileProperties)\n    \n    // Get tile at position (32, 0) which should be tile ID 2 (tile 1 from tileset)\n    const tileInfo = map.getTileByPosition(32, 0)\n    const [tile] = tileInfo.tiles\n    \n    expect(tile).toBeDefined()\n    expect(tile.properties).toBeDefined()\n    expect(Object.keys(tile.properties)).toHaveLength(2)\n    expect(tile.getProperty('collision')).toBe(false)\n    expect(tile.getProperty('heal')).toBe(5)\n})\n\ntest('Tiles without properties should have empty properties object', () => {\n    const map = getMap(xmlWithTileProperties)\n    \n    // Get tile at position (0, 32) which should be tile ID 3 (tile 2 from tileset, no properties defined)\n    const tileInfo = map.getTileByPosition(0, 32)\n    const [tile] = tileInfo.tiles\n    \n    expect(tile).toBeDefined()\n    expect(tile.properties).toBeDefined()\n    expect(Object.keys(tile.properties)).toHaveLength(0)\n}) "
  },
  {
    "path": "packages/tiled/tests/tiledmap-multi-layers.spec.ts",
    "content": "import { TiledParser } from \"../src/parser/parser\"\nimport { tileset } from \"./data\"\nimport { MapClass } from '../src'\nimport { test, expect, describe, beforeEach } from 'vitest'\n\nconst getXmlMap = (properties = '') => `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"5\">\n ${properties}\n <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n  </data>\n </layer>\n <layer id=\"2\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n <layer id=\"3\" name=\"Tile Layer 3\" width=\"10\" height=\"10\">\n  <data encoding=\"base64\">\n   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n  </data>\n </layer>\n</map>\n`\n\nconst xml = getXmlMap()\nconst xmlLowMemory = getXmlMap(`\n    <properties>\n        <property name=\"low-memory\" value=\"true\" type=\"bool\"  />\n    </properties>\n`)\n\nfunction getMap(xml) {\n    const parser = new TiledParser(xml)\n    const mapData = parser.parseMap()\n    mapData.tilesets = mapData.tilesets.map(source => {\n        const parserTileset = new TiledParser(tileset)\n        const tilesetData = parserTileset.parseTileset()\n        return {\n            ...source,\n            ...tilesetData\n        }\n    })\n    return new MapClass(mapData)\n}\n\ntest('Has 3 Layers', () => {\n    const map = getMap(xml)\n    expect(map.layers).toHaveLength(3)\n})\n\ntest('Test Allocate memory Size', () => {\n    const map = getMap(xml)\n    expect(map['allocateMemory']).toBe(3)\n})\n\ndescribe('Get Tile In Memory', () => {\n    test('3 tiles found', () => {\n        const map = getMap(xml)\n        const { tiles } = map.getTileByIndex(44)\n        expect(tiles).toHaveLength(3)\n    })\n\n    test('3 tiles found', () => {\n        const map = getMap(xml)\n        const { tiles } = map.getTileByIndex(44)\n        expect(tiles[0].id).toBe(41)\n        expect(tiles[0].layerIndex).toBe(2)\n        expect(tiles[1].id).toBe(41)\n        expect(tiles[1].layerIndex).toBe(1)\n        expect(tiles[2].id).toBe(0)\n        expect(tiles[2].layerIndex).toBe(0)\n    })\n})\n\ndescribe('Memory Optimization', () => {\n    let map: MapClass\n\n    beforeEach(() => {\n        map = getMap(xmlLowMemory)\n    })\n\n    test('Test Allocate memory Size', () => {\n        expect(map['allocateMemory']).toBe(1)\n    })\n\n    test('1 tile only found', () => {\n        const { tiles } = map.getTileByIndex(44)\n        expect(tiles).toHaveLength(1)\n    })\n\n    test('1 tile only found', () => {\n        const { tiles } = map.getTileByIndex(44)\n        expect(tiles[0].id).toBe(41)\n        expect(tiles[0].layerIndex).toBe(2)\n    })\n})"
  },
  {
    "path": "packages/tiled/tests/tiledmap.spec.ts",
    "content": "import { TiledParser } from \"../src/parser/parser\"\nimport { tileset, xml, xmlGroup, xmlObjectImage, xmlTile } from \"./data\"\nimport { Tileset } from '../src/classes/Tileset'\nimport { Layer, MapClass, Tile, TiledLayerType, TiledObjectClass } from '../src'\nimport { test, expect, describe } from 'vitest'\n\nfunction getMap(xml) {\n    const parser = new TiledParser(xml)\n    const mapData = parser.parseMap()\n    mapData.tilesets = mapData.tilesets.map(source => {\n        const parserTileset = new TiledParser(tileset)\n        const tilesetData = parserTileset.parseTileset()\n        return {\n            ...source,\n            ...tilesetData\n        }\n    })\n    return new MapClass(mapData)\n}\n\n\ntest('Map is loaded', () => {\n    const map = getMap(xml)\n    expect(map).toBeDefined()\n    expect(map.tilesets[0]).toBeInstanceOf(Tileset)\n    expect(map.layers[0]).toBeInstanceOf(Layer)\n})\n\ntest('Map Tile Size', () => {\n    const map = getMap(xml)\n    expect(map.tileheight).toBe(32)\n    expect(map.tilewidth).toBe(32)\n})\n\ntest('Layers', () => {\n    const map = getMap(xmlGroup)\n    expect(map.layers).toHaveLength(4)\n    expect(map.layers[2].type).toBe(TiledLayerType.Group)\n})\n\ntest('Group Properties', () => {\n    const map = getMap(xmlGroup)\n    const layerGroup = map.layers[2]\n    const prop = layerGroup.getProperty<number>('grouptest')\n    expect(prop).toBe(0)\n})\n\ntest('Layers Properties has parent', () => {\n    const map = getMap(xmlGroup)\n    const layer = map.layers[3]\n    const parent = layer.getLayerParent()\n    expect(parent).toBeInstanceOf(Layer)\n    expect(parent?.name).toBe('Group 1')\n})\n\ntest('Layers Properties same properties of group parent', () => {\n    const map = getMap(xmlGroup)\n    const layerGroup = map.layers[3]\n    const prop = layerGroup.getProperty<number>('grouptest')\n    expect(prop).toBe(0)\n})\n\ntest('Layers Properties same properties of group parent (incrementation z value)', () => {\n    const map = getMap(`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"2\">\n     <group id=\"3\" name=\"Group 1\">\n      <properties>\n       <property name=\"z\" type=\"int\" value=\"2\"/>\n      </properties>\n      <layer id=\"4\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n       <data encoding=\"base64\">\n       AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n      </data>\n      <properties>\n       <property name=\"z\" type=\"int\" value=\"3\"/>\n      </properties>\n      </layer>\n     </group>\n    </map>\n    `)\n    const layerGroup = map.layers[1]\n    const prop = layerGroup.getProperty<number>('z')\n    expect(prop).toBe(5)\n})\n\ntest('Layers Properties same properties of group parent (erase parent value)', () => {\n    const map = getMap(`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"2\">\n     <group id=\"3\" name=\"Group 1\">\n      <properties>\n       <property name=\"test\" type=\"int\" value=\"2\"/>\n      </properties>\n      <layer id=\"4\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n       <data encoding=\"base64\">\n       AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n      </data>\n      <properties>\n       <property name=\"test\" type=\"int\" value=\"3\"/>\n      </properties>\n      </layer>\n     </group>\n    </map>\n    `)\n    const layerGroup = map.layers[1]\n    const prop = layerGroup.getProperty<number>('test')\n    expect(prop).toBe(3)\n})\n\ntest('Opacity', () => {\n    const map = getMap(`<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <map version=\"1.8\" tiledversion=\"1.8.6\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"14\" nextobjectid=\"8\">\n     <group id=\"13\" name=\"Group 1\" opacity=\"0.9\">\n      <layer id=\"12\" name=\"Tile Layer 1\" width=\"10\" height=\"10\" opacity=\"0.56\">\n       <data encoding=\"base64\">\n       AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n      </data>\n      </layer>\n     </group>\n    </map>\n    \n    `)\n    const layer1 = map.layers[0]\n    const layer2 = map.layers[1]\n    expect(layer1.opacity).toBe(0.9)\n    expect(layer2.opacity).toBe(0.5)\n})\n\ndescribe('Test Tiles Index', () => {\n    const xmlZ = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <map version=\"1.8\" tiledversion=\"1.8.2\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"5\" nextobjectid=\"5\">\n     <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n     <layer id=\"1\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n      <data encoding=\"base64\">\n       AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n      </data>\n      <properties>\n            <property name=\"z\" type=\"int\" value=\"1\"/>\n        </properties>\n     </layer>\n     <layer id=\"2\" name=\"Tile Layer 2\" width=\"10\" height=\"10\">\n      <data encoding=\"base64\">\n       AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA==\n      </data>\n        <properties>\n            <property name=\"z\" type=\"int\" value=\"2\"/>\n        </properties>\n     </layer>\n    </map>\n    `\n\n    test('getTileIndex()', () => {\n        const map = getMap(xml)\n        const { width } = map\n        expect(map.getTileIndex(32, 32)).toEqual(width + 1)\n    })\n\n    test('getTilePosition() #1', () => {\n        const map = getMap(xml)\n        expect(map.getTilePosition(85)).toMatchObject({\n            x: 5 * 32,\n            y: 8 * 32\n        })\n        expect(map.getTilePosition(11)).toMatchObject({\n            x: 1 * 32,\n            y: 1 * 32\n        })\n        expect(map.getTilePosition(9)).toMatchObject({\n            x: 9 * 32,\n            y: 0 * 32\n        })\n        expect(map.getTilePosition(99)).toMatchObject({\n            x: 9 * 32,\n            y: 9 * 32\n        })\n    })\n\n    test('Tiles Index', () => {\n        const map = getMap(xml)\n        const tileInfo = map.getTileByIndex(0)\n        expect(tileInfo.tiles).toHaveLength(2)\n        expect(tileInfo.hasCollision).toBe(false)\n    })\n\n    test('Tiles Index, Not found layer', () => {\n        const map = getMap(xmlZ)\n        const tileInfo = map.getTileByIndex(0)\n        expect(tileInfo.tiles).toHaveLength(0)\n        expect(tileInfo.hasCollision).toBe(false)\n    })\n\n    test('Tiles Index, Z=1', () => {\n        const map = getMap(xmlZ)\n        const tileInfo = map.getTileByIndex(0, [32, 64])\n        expect(tileInfo.tiles).toHaveLength(2)\n        expect(tileInfo.hasCollision).toBe(false)\n    })\n\n    test('Tiles Index, Z=2', () => {\n        const map = getMap(xmlZ)\n        const tileInfo = map.getTileByIndex(0, [64, 64+32])\n        expect(tileInfo.tiles).toHaveLength(2)\n        expect(tileInfo.hasCollision).toBe(false)\n    })\n\n    const xmlFlipTiled = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n    <map version=\"1.8\" tiledversion=\"1.8.6\" orientation=\"orthogonal\" renderorder=\"right-down\" width=\"10\" height=\"10\" tilewidth=\"32\" tileheight=\"32\" infinite=\"0\" nextlayerid=\"14\" nextobjectid=\"8\">\n     <tileset firstgid=\"1\" source=\"[Base]BaseChip_pipo.tsx\"/>\n     <layer id=\"12\" name=\"Tile Layer 1\" width=\"10\" height=\"10\">\n     <data encoding=\"base64\">\n     KQAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==\n    </data>\n    </layer>\n    </map>\n    `\n\n    test('Get Flip Tile', () => {\n        const map = getMap(xmlFlipTiled)\n        const tileInfo = map.getTileByIndex(0)\n        const tile = tileInfo.tiles[0]\n        expect(tile.gid).toBe(41)\n        expect(tileInfo.hasCollision).toBe(true)\n    })\n})\n"
  },
  {
    "path": "packages/tiled/tsconfig.json",
    "content": "{\n    \"compilerOptions\": {\n      \"target\": \"ES2020\",\n      \"lib\": [\"dom\", \"esnext\"],\n      \"module\": \"ES2020\",\n      \"outDir\": \"./lib\",\n      \"rootDir\": \"./src\",\n      \"strict\": true,\n      \"sourceMap\": true,\n      \"strictNullChecks\": true,\n      \"strictPropertyInitialization\": false,\n      \"moduleResolution\": \"node\",\n      \"esModuleInterop\": true,\n      \"removeComments\": false,\n      \"noUnusedParameters\": false,\n      \"noUnusedLocals\": false,\n      \"noImplicitThis\": false,\n      \"noImplicitAny\": false,\n      \"noImplicitReturns\": false,\n      \"declaration\": true,\n      \"experimentalDecorators\": true, \n      \"emitDecoratorMetadata\": true,\n      \"stripInternal\": true\n    },\n    \"include\": [\n        \"src\"\n    ]\n  }"
  },
  {
    "path": "packages/tiled/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport dts from 'vite-plugin-dts'\n\nexport default defineConfig({\n  plugins: [\n    dts({ \n      include: ['src/**/*.ts'],\n      outDir: 'dist'\n    })\n  ],\n  build: {\n    target: 'esnext',\n    sourcemap: true,\n    minify: false,\n    lib: {\n      entry: 'src/index.ts',\n      formats: ['es'],\n      fileName: 'index'\n    }\n  },\n})"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/**'"
  },
  {
    "path": "sample/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Canvas Engine</title>\n    <style>\n      body, #root {\n        margin: 0;\n        padding: 0;\n        width: 100vw;\n        overflow: hidden;\n        height: 100vh;\n      }\n\n      .red {\n        color: red;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "sample/package.json",
    "content": "{\n  \"name\": \"sample\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"test\": \"vitest\",\n    \"test:run\": \"vitest run\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"path-browserify\": \"^1.0.1\",\n    \"pixi.js\": \"^8.18.1\",\n    \"vite\": \"^8.0.10\"\n  },\n  \"devDependencies\": {\n    \"@pixi/layout\": \"^3.2.0\",\n    \"@canvasengine/testing\": \"workspace:*\",\n    \"vitest\": \"^4.1.5\",\n    \"vitest-webgl-canvas-mock\": \"^1.1.0\"\n  },\n  \"type\": \"module\"\n}\n"
  },
  {
    "path": "sample/src/app.ce",
    "content": "\n<Canvas>\n  <Container  x y>\n    <Sprite image=\"https://pixijs.com/assets/flowerTop.png\"  />\n   \n  </Container>\n  <DOMContainer>\n    <button click={() => {\n      console.log('button clicked')\n    }}>Click me</button>\n  </DOMContainer>\n\n  <Container>\n    <Child />\n  </Container>\n</Canvas>\n\n<style scoped>\n  button {\n    background-color: red;\n  }\n</style>\n\n<script>\n  import { TiledMap } from '@canvasengine/presets'\n  import { signal } from 'canvasengine'\n  import Child from './child.ce'\n  \n  let map = signal({})\n  \n  const x = signal(0)\n  const y = signal(0)\n\n  setInterval(() => {\n    x.update(x => x + 1)\n    y.update(y => y + 1)\n  }, 16)\n</script>\n      "
  },
  {
    "path": "sample/src/benchmark.ce",
    "content": "<Canvas backgroundColor=\"#1a1a1a\">\n  <Container x={20} y={20}>\n    <Text \n      text={statsText} \n      size=\"14\"\n      color=\"#ffffff\"\n      fontFamily=\"monospace\"\n    />\n  </Container>\n  \n  <Viewport \n    worldWidth={worldWidth} \n    worldHeight={worldHeight} \n    drag={true}\n    clamp={clamp}\n  >\n    <Container>\n      @for (item of items) {\n        <Sprite \n          image=\"https://pixijs.com/assets/flowerTop.png\"\n          x={@item.x}\n          y={@item.y}\n        />\n      }\n    </Container>\n  </Viewport>\n  \n  <Container x={20} y={160}>\n    <Text \n      text={controlsText} \n      size=\"12\"\n      color=\"#00ff00\"\n      fontFamily=\"monospace\"\n    />\n  </Container>\n</Canvas>\n\n<script>\n  import { signal, computed, effect, tick, mount } from \"canvasengine\";\n  \n  // ============================================\n  // PERFORMANCE OPTIMIZATION MODES\n  // ============================================\n  // Mode 0: Naive (all signals, update all every frame) - SLOW\n  // Mode 1: Imperative animation (no animated signals, direct Pixi access) - FAST\n  // Mode 2: Throttled updates (animate every N frames) - MEDIUM\n  // Mode 3: LOD (reduced animation complexity at high counts) - ADAPTIVE\n  \n  const optimizationMode = signal(1); // Start with optimized mode\n  const elementCount = signal(5000);\n  const isAnimating = signal(true);\n  const animationSpeed = signal(1);\n  const clamp = { direction: 'all' };\n  const throttleFrames = signal(2); // For mode 2: animate every N frames\n  \n  // Stats tracking\n  const lastFpsTime = signal(performance.now());\n  const fps = signal(60);\n  const avgUpdateTime = signal(0);\n  const signalUpdatesPerFrame = signal(0);\n  \n  // Store sprite references for imperative mode\n  let spriteRefs = [];\n  let updateTimes = [];\n  let frameCounter = 0;\n  \n  // World dimensions based on element count\n  const worldWidth = computed(() => {\n    const count = elementCount();\n    const cols = Math.ceil(Math.sqrt(count));\n    return cols * 100;\n  });\n  \n  const worldHeight = computed(() => {\n    const count = elementCount();\n    const cols = Math.ceil(Math.sqrt(count));\n    return cols * 100;\n  });\n  \n  // ============================================\n  // OPTIMIZED ITEM GENERATION\n  // No signals for animated properties - only static positions\n  // ============================================\n  function generateItems(count) {\n    const items = [];\n    const cols = Math.ceil(Math.sqrt(count));\n    \n    for (let i = 0; i < count; i++) {\n      const col = i % cols;\n      const row = Math.floor(i / cols);\n      \n      // Only x and y as signals (for loop reactivity)\n      // Animation data is plain values - NO SIGNALS\n      items.push({\n        id: i,\n        x: signal(col * 100 + 50),\n        y: signal(row * 100 + 50),\n        // Animation parameters (non-reactive)\n        baseRotation: Math.random() * Math.PI * 2,\n        baseAlpha: 0.5 + Math.random() * 0.5,\n        baseScale: 0.8 + Math.random() * 0.4,\n        rotationSpeed: (Math.random() - 0.5) * 0.05,\n        alphaSpeed: (Math.random() - 0.5) * 0.02,\n        scaleSpeed: (Math.random() - 0.5) * 0.01,\n      });\n    }\n    \n    return items;\n  }\n  \n  const items = signal(generateItems(elementCount()));\n  \n  // Update items when count changes - INCREMENTAL approach\n  effect(() => {\n    const targetCount = elementCount();\n    const currentItems = items();\n    const currentCount = currentItems.length;\n    \n    if (targetCount === currentCount) return;\n    \n    const startTime = performance.now();\n    \n    if (targetCount > currentCount) {\n      // ADD elements incrementally\n      const cols = Math.ceil(Math.sqrt(targetCount));\n      const newItems = [...currentItems];\n      \n      for (let i = currentCount; i < targetCount; i++) {\n        const col = i % cols;\n        const row = Math.floor(i / cols);\n        \n        newItems.push({\n          id: i,\n          x: signal(col * 100 + 50),\n          y: signal(row * 100 + 50),\n          baseRotation: Math.random() * Math.PI * 2,\n          baseAlpha: 0.5 + Math.random() * 0.5,\n          baseScale: 0.8 + Math.random() * 0.4,\n          rotationSpeed: (Math.random() - 0.5) * 0.05,\n          alphaSpeed: (Math.random() - 0.5) * 0.02,\n          scaleSpeed: (Math.random() - 0.5) * 0.01,\n        });\n      }\n      \n      items.set(newItems);\n    } else {\n      // REMOVE elements from the end\n      items.set(currentItems.slice(0, targetCount));\n    }\n    \n    // Reset sprite refs cache\n    spriteRefs = [];\n    \n    const updateTime = performance.now() - startTime;\n    console.log(`Adjusted to ${targetCount} items in ${updateTime.toFixed(2)}ms`);\n  });\n  \n  // ============================================\n  // ANIMATION LOOP - IMPERATIVE APPROACH\n  // Direct manipulation of Pixi objects instead of signal updates\n  // ============================================\n  tick((tickValue, element) => {\n    if (!isAnimating()) return;\n    \n    const startTime = performance.now();\n    const mode = optimizationMode();\n    const speed = animationSpeed();\n    const currentItems = items();\n    const frame = tickValue.frame;\n    let signalUpdates = 0;\n    \n    // Get viewport container with sprites\n    const viewportContainer = element.componentInstance?.children?.[1]?.children?.[0];\n    \n    // Mode 2: Throttling - skip frames\n    if (mode === 2 && frame % throttleFrames() !== 0) {\n      // Skip this frame but still calculate FPS\n      updateFpsStats(startTime);\n      return;\n    }\n    \n    // Cache sprite references for faster access\n    if (spriteRefs.length !== currentItems.length && viewportContainer) {\n      spriteRefs = viewportContainer.children || [];\n    }\n    \n    // LOD threshold for mode 3\n    const count = currentItems.length;\n    const useLOD = mode === 3 && count > 2000;\n    const animateAlpha = !useLOD || count < 5000;\n    const animateScale = !useLOD || count < 3000;\n    \n    // Animate sprites\n    currentItems.forEach((item, index) => {\n      const sprite = spriteRefs[index];\n      if (!sprite) return;\n      \n      // Calculate new values\n      const newRotation = item.baseRotation + frame * item.rotationSpeed * speed;\n      \n      if (mode === 0) {\n        // MODE 0: NAIVE - Use signals (expensive!)\n        // This would require signals for rotation/alpha/scale which we removed\n        // Just do direct manipulation but count as if we did signal updates\n        sprite.rotation = newRotation;\n        signalUpdates += 3;\n        \n        if (animateAlpha) {\n          sprite.alpha = Math.max(0.3, Math.min(1, item.baseAlpha + Math.sin(frame * item.alphaSpeed * speed) * 0.3));\n        }\n        if (animateScale) {\n          const scale = Math.max(0.5, Math.min(1.5, item.baseScale + Math.sin(frame * item.scaleSpeed * speed) * 0.2));\n          sprite.scale.set(scale);\n        }\n      } else {\n        // MODE 1, 2, 3: IMPERATIVE - Direct Pixi manipulation (fast!)\n        sprite.rotation = newRotation;\n        \n        if (animateAlpha) {\n          sprite.alpha = Math.max(0.3, Math.min(1, item.baseAlpha + Math.sin(frame * item.alphaSpeed * speed) * 0.3));\n        }\n        if (animateScale) {\n          const scale = Math.max(0.5, Math.min(1.5, item.baseScale + Math.sin(frame * item.scaleSpeed * speed) * 0.2));\n          sprite.scale.set(scale);\n        }\n      }\n    });\n    \n    signalUpdatesPerFrame.set(signalUpdates);\n    updateFpsStats(startTime);\n  });\n  \n  function updateFpsStats(startTime) {\n    frameCounter++;\n    const currentTime = performance.now();\n    const deltaTime = currentTime - lastFpsTime();\n    \n    if (deltaTime >= 1000) {\n      const currentFps = (frameCounter * 1000) / deltaTime;\n      fps.set(Math.round(currentFps));\n      frameCounter = 0;\n      lastFpsTime.set(currentTime);\n    }\n    \n    const updateTime = currentTime - startTime;\n    updateTimes.push(updateTime);\n    if (updateTimes.length > 60) {\n      updateTimes.shift();\n    }\n    const avgTime = updateTimes.reduce((a, b) => a + b, 0) / updateTimes.length;\n    avgUpdateTime.set(avgTime);\n  }\n  \n  // Mode descriptions\n  const modeNames = {\n    0: 'Naive (simulate signal overhead)',\n    1: 'Imperative (direct Pixi)',\n    2: 'Throttled (skip frames)',\n    3: 'LOD (adaptive complexity)',\n  };\n  \n  // Stats text\n  const statsText = computed(() => {\n    const count = elementCount();\n    const currentFps = fps();\n    const avgTime = avgUpdateTime().toFixed(2);\n    const worldW = worldWidth();\n    const worldH = worldHeight();\n    const mode = optimizationMode();\n    const throttle = throttleFrames();\n    \n    // Estimate signal count reduction\n    const naiveSignals = count * 5; // x, y, rotation, alpha, scale\n    const optimizedSignals = count * 2; // only x, y\n    const reduction = Math.round((1 - optimizedSignals / naiveSignals) * 100);\n    \n    return `\nPERFORMANCE BENCHMARK\n=====================\nMode: [${mode}] ${modeNames[mode]}\nElements: ${count}\nFPS: ${currentFps}\nAvg Update Time: ${avgTime}ms\nWorld Size: ${worldW}x${worldH}\nAnimating: ${isAnimating() ? 'Yes' : 'No'}\nSpeed: ${animationSpeed().toFixed(2)}x\n${mode === 2 ? `Throttle: every ${throttle} frames` : ''}\n---------------------\nSignal reduction: ${reduction}% (${naiveSignals} -> ${optimizedSignals})\n    `.trim();\n  });\n  \n  // Controls text\n  const controlsText = computed(() => {\n    return `\nCONTROLS\n========\n[1-4] Switch optimization mode\n[Q/E] Elements -/+10\n[W/R] Elements -/+100\n[A] Toggle animation\n[S/D] Speed -/+\n[T/Y] Throttle -/+ (mode 2)\n[0] 100 elements\n[9] 1000 elements\n[8] 5000 elements\n[7] 10000 elements\n    `.trim();\n  });\n  \n  // Keyboard controls\n  mount((element) => {\n    const handleKeyDown = (e) => {\n      switch(e.key.toLowerCase()) {\n        case '1':\n          optimizationMode.set(0);\n          console.log('Mode: Naive (simulated signal overhead)');\n          break;\n        case '2':\n          optimizationMode.set(1);\n          console.log('Mode: Imperative (direct Pixi manipulation)');\n          break;\n        case '3':\n          optimizationMode.set(2);\n          console.log('Mode: Throttled updates');\n          break;\n        case '4':\n          optimizationMode.set(3);\n          console.log('Mode: LOD (adaptive complexity)');\n          break;\n        case 'q':\n          elementCount.update(count => Math.max(1, count - 10));\n          break;\n        case 'e':\n          elementCount.update(count => count + 10);\n          break;\n        case 'w':\n          elementCount.update(count => Math.max(1, count - 100));\n          break;\n        case 'r':\n          elementCount.update(count => count + 100);\n          break;\n        case 'a':\n          isAnimating.update(animating => !animating);\n          break;\n        case 's':\n          animationSpeed.update(speed => Math.max(0.1, speed - 0.1));\n          break;\n        case 'd':\n          animationSpeed.update(speed => Math.min(5, speed + 0.1));\n          break;\n        case 't':\n          throttleFrames.update(t => Math.max(1, t - 1));\n          break;\n        case 'y':\n          throttleFrames.update(t => Math.min(10, t + 1));\n          break;\n        case '0':\n          elementCount.set(100);\n          break;\n        case '9':\n          elementCount.set(1000);\n          break;\n        case '8':\n          elementCount.set(5000);\n          break;\n        case '7':\n          elementCount.set(10000);\n          break;\n      }\n    };\n    \n    window.addEventListener('keydown', handleKeyDown);\n    \n    return () => {\n      window.removeEventListener('keydown', handleKeyDown);\n    };\n  });\n  \n  console.log('Benchmark initialized with OPTIMIZED mode.');\n  console.log('Press [1-4] to switch optimization modes.');\n</script>\n"
  },
  {
    "path": "sample/src/box.ce",
    "content": "<Canvas>\n  <Container justifyContent=\"center\" alignItems=\"center\" width=\"100%\" height=\"100%\">\n    <Container\n      ref=\"dialogbox\"\n      scale={{ x: scaleX }}\n      anchor={[0.5, 0.5]}\n      width={700}\n      height\n      positionType=\"absolute\"\n      bottom={10}\n    >\n    <Rect width={700} height={250} color=\"#1a1a2e\" />\n      <Rect\n        x={0}\n        y={0}\n        width={700}\n        height\n        color=\"#1a1a2e\"\n        alpha={0.9}\n        borderRadius={10}\n        border\n        shadow\n      />\n        <Container\n          flexDirection=\"row\"\n          width={700}\n          height\n          alpha={contentOpacity}\n        >\n          <Container flexDirection=\"column\">\n            <Text\n              text=\"Hello\"\n              color=\"#fff\"\n              fontSize={18}\n              margin={40}\n              style={textStyle}\n            />\n          </Container>\n      </Container>\n  </Container>  \n  \n    \n  </Container>\n\n\n</Canvas>\n  <script>\n\n    import {\n      animatedSignal,\n      computed,\n      effect,\n      signal,\n      trigger,\n      mount\n    } from \"canvasengine\";\n    import Child  from \"./child.ce\";\n  \n    let isDestroyed = false;\n  \n    const texts = ['Hello']\n    const height = signal(250);\n    const isTextCompleted = signal(false);\n    const display1 = signal(false);\n    const display2 = signal(true);\n  \n    const border = signal({ width: 5, color: \"#595971\" });\n    const shadow = signal({ color: \"#000\", blur: 10, offsetX: 10, offsetY: 10 });\n  \n    const contentOpacity = animatedSignal(0, {\n      duration: 1000,\n    });\n  \n    const scaleX = animatedSignal(0, {\n      duration: 500,\n    });\n  \n    scaleX.set(1);\n    contentOpacity.set(1);\n    \n    const textStyle = {\n      wordWrap: true,\n      wordWrapWidth: 700 - 256 - 80\n    }\n  \n     setTimeout(() => {\n      display1.set(true);\n     }, 1000);\n  </script>"
  },
  {
    "path": "sample/src/child.ce",
    "content": "<DOMContainer x={100} y={100} class=\"child\">\n    <button click={() => {\n        console.log('button clicked')\n    }}>Click me</button>\n</DOMContainer>\n\n<style scoped>\n    button {\n        background-color: blue;\n    }\n</style>\n\n<script>\n    import { tick, mount } from 'canvasengine'\n\n    mount((element) => {\n        console.log(element)\n    })\n\n    console.log('child')\n</script>"
  },
  {
    "path": "sample/src/control.ce",
    "content": "<script>\n  import { signal } from \"canvasengine\";\n\n  enum Direction {\n      Up,\n      Down,\n      Left,\n      Right\n  }\n\n  const x = signal(0);\n  const y = signal(0);\n  const speed = signal(10);\n  const direction = signal(Direction.Down);\n  const boot = signal(false);\n\n  const controls = signal({\n      down: {\n        repeat: true,\n        bind: [\"down\", 'bottom_right', 'bottom_left'],\n        keyDown() {\n          y.update((y) => y + speed());\n          direction.set(Direction.Down);\n        },\n      },\n      up: {\n        repeat: true,\n        bind: ['up', 'top_left', 'top_right'],\n        keyDown() {\n          y.update((y) => y - speed());\n          direction.set(Direction.Up);\n        },\n      },\n      left: {\n        repeat: true,\n        bind: \"left\",\n        keyDown() {\n          x.update((x) => x - speed());\n          direction.set(Direction.Left);\n        },\n      },\n      right: {\n        repeat: true,\n        bind: \"right\",\n        keyDown() {\n          x.update((x) => x + speed());\n          direction.set(Direction.Right);\n        },\n      },\n      action: {\n        bind: \"space\",\n        keyDown() {\n          console.log(\"action\");\n        },\n      },\n    });\n</script>\n\n<Canvas backgroundColor=\"white\">\n  <Container>\n    <DOMContainer>  \n        <button click={() => boot.set(!boot())}>Boot</button>\n    </DOMContainer>\n    @if (boot) {\n     <Container>\n        <Rect color=\"red\" width={100} height={100} controls x y />  \n     </Container>\n    }\n  </Container>\n</Canvas>\n"
  },
  {
    "path": "sample/src/controls-buttons.ce",
    "content": "<Canvas backgroundColor=\"#2c3e50\">\n  <Container>\n    <!-- Rectangle with controls -->\n    <Rect \n      color=\"#3498db\" \n      width={60} \n      height={60} \n      borderRadius={8}\n      controls={controls}\n      x={x}\n      y={y}\n    />\n    \n    <!-- Joystick container below the canvas -->\n    <Container y={400} x={200}>\n      <Joystick \n        controls={controlsInstance}\n        outerColor=\"#34495e\"\n        innerColor=\"#3498db\"\n      />\n    </Container>\n    \n    <!-- Gamepad buttons A and B (right side) -->\n    <Container x={600} y={200}>\n      <!-- Button B (top) -->\n      <Button \n        text=\"B\"\n        shape=\"circle\"\n        width={70}\n        height={70}\n        controls={controlsInstance}\n        controlName=\"buttonB\"\n        style={{\n          backgroundColor: {\n            normal: \"#e74c3c\",\n            hover: \"#c0392b\",\n            pressed: \"#a93226\",\n            disabled: \"#7f8c8d\"\n          },\n          text: {\n            fontSize: 24,\n            fontFamily: \"Arial Bold\",\n            color: \"#ffffff\"\n          }\n        }}\n      />\n      \n      <!-- Button A (bottom) -->\n      <Button \n        text=\"A\"\n        shape=\"circle\"\n        width={70}\n        height={70}\n        y={90}\n        controls={controlsInstance}\n        controlName=\"buttonA\"\n        style={{\n          backgroundColor: {\n            normal: \"#2ecc71\",\n            hover: \"#27ae60\",\n            pressed: \"#229954\",\n            disabled: \"#7f8c8d\"\n          },\n          text: {\n            fontSize: 24,\n            fontFamily: \"Arial Bold\",\n            color: \"#ffffff\"\n          }\n        }}\n      />\n    </Container>\n    \n    <!-- Instructions -->\n    <Text \n      text=\"Use the joystick below to move the rectangle, or use arrow keys. Click buttons A/B or press Space/Enter\"\n      x={10}\n      y={10}\n      color=\"#ecf0f1\"\n      size=\"14\"\n      fontFamily=\"Arial\"\n    />\n    \n    <!-- Action feedback text -->\n    <Text \n      text={actionText}\n      x={10}\n      y={30}\n      color=\"#f39c12\"\n      size=\"16\"\n      fontFamily=\"Arial Bold\"\n    />\n  </Container>\n</Canvas>\n\n<script>\n  import { signal, mount } from \"canvasengine\"\n  // Rectangle position\n  const x = signal(200);\n  const y = signal(200);\n  \n  // Movement speed\n  const speed = signal(10);\n  \n  // Action feedback text\n  const actionText = signal(\"\");\n\n  // Controls configuration with joystick integration\n  const controls = signal({\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        x.update((x) => Math.max(0, x - speed()));\n      },\n    },\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown() {\n        x.update((x) => x + speed());\n      },\n    },\n    up: {\n      repeat: true,\n      bind: \"up\",\n      keyDown() {\n        y.update((y) => Math.max(0, y - speed()));\n      },\n    },\n    down: {\n      repeat: true,\n      bind: \"down\",\n      keyDown() {\n        y.update((y) => y + speed());\n      },\n    },\n    // Button A action (green button)\n    buttonA: {\n      bind: [\"space\", \"enter\"],\n      keyDown() {\n        actionText.set(\"Button A pressed! (Jump/Action)\");\n        // Add your action logic here (e.g., jump, interact)\n        setTimeout(() => {\n          actionText.set(\"\");\n        }, 1000);\n      },\n    },\n    // Button B action (red button)\n    buttonB: {\n      bind: [\"shift\", \"x\"],\n      keyDown() {\n        actionText.set(\"Button B pressed! (Cancel/Secondary)\");\n        // Add your action logic here (e.g., cancel, secondary action)\n        setTimeout(() => {\n          actionText.set(\"\");\n        }, 1000);\n      },\n    },\n    // Joystick configuration - automatically handles joystick events\n    // Uses default direction mapping\n    joystick: {\n      enabled: true,\n      moveInterval: 50,\n      threshold: 0.1\n    }\n  });\n\n  // Store the controls directive instance to pass to the Joystick\n  const controlsInstance = signal(null);\n\n  // Get the controls directive from the Rect element\n  mount((element) => {\n    // Find the Rect element with controls directive\n    function findElementWithControls(el) {\n      if (el.directives && el.directives.controls) {\n        return el;\n      }\n      if (el.props && el.props.children) {\n        for (const child of el.props.children) {\n          if (child) {\n            const found = findElementWithControls(child);\n            if (found) return found;\n          }\n        }\n      }\n      return null;\n    }\n\n    const rectElement = findElementWithControls(element);\n    if (rectElement && rectElement.directives.controls) {\n      controlsInstance.set(rectElement.directives.controls);\n    }\n  });\n</script>\n\n"
  },
  {
    "path": "sample/src/controls-rect.ce",
    "content": "<Canvas backgroundColor=\"#2c3e50\">\n  <Container>\n    <Rect \n      color=\"#3498db\" \n      width={60} \n      height={60} \n      borderRadius={8}\n      controls \n      x \n      y \n    />\n    \n    <!-- Display gamepad status -->\n    <Text \n      text={gamepadStatus}\n      x={10}\n      y={10}\n      color=\"#ecf0f1\"\n      size=\"16\"\n      fontFamily=\"Arial\"\n    />\n    \n    <!-- Instructions -->\n    <Text \n      text=\"Use arrow keys or a gamepad to move the rectangle\"\n      x={10}\n      y={40}\n      color=\"#95a5a6\"\n      size=\"12\"\n      fontFamily=\"Arial\"\n    />\n  </Container>\n</Canvas>\n\n<script>\n  import { signal, computed, effect } from \"canvasengine\";\n\n  // Rectangle position\n  const x = signal(200);\n  const y = signal(200);\n  \n  // Movement speed\n  const speed = signal(5);\n\n  // Gamepad connection status signal\n  const gamepadConnected = signal(false);\n  \n  // Gamepad status text (reactive, updated when gamepadConnected changes)\n  const gamepadStatus = computed(() => \n    gamepadConnected() ? \"Gamepad: Connected ✅\" : \"Gamepad: Not connected\"\n  );\n\n  effect(() => {\n    console.log(gamepadConnected());\n  });\n\n  // Controls configuration\n  const controls = signal({\n    up: {\n      repeat: true,\n      bind: \"up\",\n      keyDown(_, payload) {\n        y.update((y) => Math.max(0, y - speed()));\n      },\n    },\n    down: {\n      repeat: true,\n      bind: \"down\",\n      keyDown() {\n        y.update((y) => y + speed());\n      },\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        x.update((x) => Math.max(0, x - speed()));\n      },\n    },\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown() {\n        x.update((x) => x + speed());\n      },\n    },\n    // Gamepad configuration with callbacks and signal\n    gamepad: {\n      enabled: true,\n      // Default mappings will be used if joypad.js is available\n      // button_0 -> action, button_1 -> back\n      // Left stick axes will be mapped to up/down/left/right directions\n      \n      // Signal to track connection status (automatically updated)\n      gamepadConnected: gamepadConnected,\n      \n      // Optional callbacks\n      onConnect() {\n        console.log(\"Gamepad connected!\");\n      },\n      onDisconnect() {\n        console.log(\"Gamepad disconnected!\");\n      }\n    }\n  });\n</script>\n"
  },
  {
    "path": "sample/src/dependencies.ce",
    "content": "<Canvas>\n  <Container \n    flexDirection=\"column\" \n    justifyContent=\"center\" \n    alignItems=\"center\" \n    width=\"100%\" \n    height=\"100%\"\n  >\n    <!-- Component that waits for userData signal -->\n    <child dependencies />\n  </Container>\n</Canvas>\n\n<script>\n  import { signal, mount } from 'canvasengine';\n  import child from './child.ce';\n\n\n  // Start with undefined dependencies\n  const userData = signal(undefined);\n  const config = signal(undefined);\n  \n  // Create a promise that resolves after a delay\n  const assetsPromise = new Promise((resolve) => {\n    setTimeout(() => {\n      resolve({ sprites: ['sprite1', 'sprite2', 'sprite3'] });\n    }, 2000);\n  });\n\n  // Loading text that updates based on dependencies\n  const loadingText = signal('Loading user data...');\n\n  // Simulate loading user data asynchronously\n  setTimeout(() => {\n    userData.set({ \n      name: 'Player One', \n      score: 1250, \n      level: 5 \n    });\n    loadingText.set('Loading config...');\n  }, 6000);\n\n  // Simulate loading config\n  setTimeout(() => {\n    config.set({ theme: 'dark', difficulty: 'hard' });\n    loadingText.set('All dependencies loaded!');\n  }, 3000);\n\n  // Log when components mount\n  mount((element) => {\n    console.log('Component mounted:', element.tag);\n  });\n\n  const dependencies = [userData];\n</script>\n\n"
  },
  {
    "path": "sample/src/flash.ce",
    "content": "<Canvas>\n    <Container>\n        <!-- Instructions -->\n        <Text text=\"Click the rectangles to flash them!\" x={10} y={10} color=\"#ecf0f1\" size=\"18\" fontFamily=\"Arial\" />\n        <Text text=\"Different flash configurations are demonstrated below\" x={10} y={35} color=\"#95a5a6\" size=\"14\" fontFamily=\"Arial\" />\n    </Container>\n\n    <!-- Basic alpha flash example -->\n    <Container x={100} y={100}>\n        <Text text=\"Alpha Flash\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n        controls\n            color=\"#e74c3c\" \n            width={80} \n            height={80} \n            borderRadius={8} \n            flash={alphaFlashConfig}\n            click={() => alphaFlashTrigger.start()}\n        />\n    </Container>\n\n    <!-- Tint flash example -->\n    <Container x={250} y={100}>\n        <Text text=\"Tint Flash\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n            color=\"#3498db\" \n            width={80} \n            height={80} \n            borderRadius={8} \n            flash={tintFlashConfig}\n            click={() => tintFlashTrigger.start()}\n        />\n    </Container>\n\n    <!-- Both flash example -->\n    <Container x={400} y={100}>\n        <Text text=\"Both Flash\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n            color=\"#2ecc71\" \n            width={80} \n            height={80} \n            borderRadius={8} \n            flash={bothFlashConfig}\n            click={() => bothFlashTrigger.start()}\n        />\n    </Container>\n\n    <!-- Multiple cycles flash -->\n    <Container x={550} y={100}>\n        <Text text=\"Multi Cycle\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n            color=\"#f39c12\" \n            width={80} \n            height={80} \n            borderRadius={8} \n            flash={multiCycleFlashConfig}\n            click={() => multiCycleFlashTrigger.start()}\n        />\n    </Container>\n\n    <!-- Flash with callbacks -->\n    <Container x={100} y={250}>\n        <Text text=\"With Callbacks\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n            color=\"#9b59b6\" \n            width={80} \n            height={80} \n            borderRadius={8} \n            flash={callbackFlashConfig}\n            click={() => callbackFlashTrigger.start()}\n        />\n        <Text text={statusText} x={0} y={100} color=\"#2ecc71\" size=\"12\" fontFamily=\"Arial\" />\n    </Container>\n\n    <!-- Flash sprite example -->\n    <Container x={300} y={250}>\n        <Text text=\"Sprite Flash\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            sheet={{\n                definition,\n                playing: \"default\"\n            }}\n            flash={spriteFlashConfig}\n            click={() => spriteFlashTrigger.start()}\n        />\n    </Container>\n\n    <!-- Multiple elements flash together -->\n    <Container x={500} y={250}>\n        <Text text=\"Group Flash\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Rect \n            color=\"#e67e22\" \n            width={60} \n            height={60} \n            borderRadius={8} \n            x={0}\n            y={0}\n            flash={{ trigger: groupFlashTrigger }}\n            click={() => groupFlashTrigger.start()}\n        />\n        <Rect \n            color=\"#e67e22\" \n            width={60} \n            height={60} \n            borderRadius={8} \n            x={70}\n            y={0}\n            flash={{ trigger: groupFlashTrigger }}\n        />\n        <Rect \n            color=\"#e67e22\" \n            width={60} \n            height={60} \n            borderRadius={8} \n            x={35}\n            y={70}\n            flash={{ trigger: groupFlashTrigger }}\n        />\n    </Container>\n</Canvas>\n\n<script>\n    import { trigger, signal, on } from 'canvasengine';\n\n    // Alpha flash trigger\n    const alphaFlashTrigger = trigger();\n    const alphaFlashConfig = {\n        trigger: alphaFlashTrigger,\n        type: 'alpha',\n        alpha: 0.2,\n        duration: 300\n    };\n\n    // Tint flash trigger\n    const tintFlashTrigger = trigger();\n    const tintFlashConfig = {\n        trigger: tintFlashTrigger,\n        type: 'tint',\n        tint: 0xff0000,  // Red flash\n        duration: 300\n    };\n\n    // Both flash trigger\n    const bothFlashTrigger = trigger();\n    const bothFlashConfig = {\n        trigger: bothFlashTrigger,\n        type: 'both',\n        alpha: 0.5,\n        tint: 0x00ff00,  // Green flash\n        duration: 400\n    };\n\n    // Multi-cycle flash trigger\n    const multiCycleFlashTrigger = trigger();\n    const multiCycleFlashConfig = {\n        trigger: multiCycleFlashTrigger,\n        type: 'alpha',\n        cycles: 3,\n        duration: 600\n    };\n\n    // Callback flash trigger\n    const callbackFlashTrigger = trigger();\n    const statusText = signal('Click to flash');\n    const callbackFlashConfig = {\n        trigger: callbackFlashTrigger,\n        type: 'alpha',\n        alpha: 0.3,\n        duration: 300,\n        onStart() {\n            console.log('Flash started!');\n            statusText.set('Flash started!');\n        },\n        onComplete() {\n            console.log('Flash completed!');\n            statusText.set('Flash completed!');\n        }\n    };\n\n    // Sprite flash trigger\n    const spriteFlashTrigger = trigger();\n    const spriteFlashConfig = {\n        trigger: spriteFlashTrigger,\n        type: 'tint',\n        tint: 0xff0000,  // Yellow flash\n        duration: 250\n    };\n\n    // Group flash trigger (multiple elements flash together)\n    const groupFlashTrigger = trigger();\n\n    const definition = {\n    id: \"explosion\",\n    image: \"./exp.png\",\n    width: 1024,\n    height: 1024,\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n        default: {\n             animations: () => [\n                [ \n                    { time: 0, frameX: 0, frameY: 0 },\n                    { time: 10, frameX: 1, frameY: 0 },\n                    { time: 20, frameX: 2, frameY: 0 },\n                    { time: 30, frameX: 3, frameY: 0 },\n                    { time: 40, frameX: 0, frameY: 1 },\n                    { time: 50, frameX: 1, frameY: 1 },\n                    { time: 60, frameX: 2, frameY: 1 },     \n                    { time: 70, frameX: 3, frameY: 1 },\n                    { time: 80, frameX: 0, frameY: 2 },\n                    { time: 90, frameX: 1, frameY: 2 },\n                    { time: 100, frameX: 2, frameY: 2 },\n                    { time: 110, frameX: 3, frameY: 2 },\n                    { time: 120, frameX: 0, frameY: 3 },\n                    { time: 130, frameX: 1, frameY: 3 },\n                    { time: 140, frameX: 2, frameY: 3 },\n                    { time: 150, frameX: 3, frameY: 3 },\n                ]\n             ]\n        }\n    }\n}\n\nconst controls = signal({\n    up: {\n        bind: \"up\",\n        keyDown() {\n            alphaFlashTrigger.start();\n        }\n    }\n});\n</script>\n\n"
  },
  {
    "path": "sample/src/flex.ce",
    "content": "\n<Canvas backgroundColor=\"#2c3e50\">\n    <Container flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" width=\"100%\" height=\"100%\" gap={30} anchor={[0.5, 0.5]}>\n        <Text text=\"Click the rectangles to flash them!\" color=\"white\" size={24} />\n        \n        <Container flexDirection=\"row\" gap={30}>\n            <Container flexDirection=\"column\" alignItems=\"center\">\n                <Text text=\"Alpha Flash\" color=\"#ecf0f1\" size={14} />\n                <Triangle color=\"red\" width={50} height={50}  />\n                \n            </Container>\n           \n        </Container>\n    </Container>\n</Canvas>\n\n<script>\nimport { trigger } from 'canvasengine';\n\n// Alpha flash - changes opacity\nconst alphaFlashTrigger = trigger();\nconst alphaFlashConfig = {\n    trigger: alphaFlashTrigger,\n    type: 'alpha',\n    alpha: 0.2,\n    duration: 300\n};\n\n// Tint flash - changes color\nconst tintFlashTrigger = trigger();\nconst tintFlashConfig = {\n    trigger: tintFlashTrigger,\n    type: 'tint',\n    tint: 0xff0000,  // Red flash\n    duration: 300\n};\n\n// Both flash - changes opacity and color\nconst bothFlashTrigger = trigger();\nconst bothFlashConfig = {\n    trigger: bothFlashTrigger,\n    type: 'both',\n    alpha: 0.5,\n    tint: 0x00ff00,  // Green flash\n    duration: 400\n};\n\n// Multi-cycle flash - flashes multiple times\nconst multiCycleFlashTrigger = trigger();\nconst multiCycleFlashConfig = {\n    trigger: multiCycleFlashTrigger,\n    type: 'alpha',\n    cycles: 3,\n    duration: 600\n};\n</script>\n\n        "
  },
  {
    "path": "sample/src/focus-navigation-dom.ce",
    "content": "<Canvas backgroundColor=\"#2c3e50\">\n  <Container x={400} y={300}>\n    <Text \n      text=\"Focus Navigation DOM Example\" \n      x={0} \n      y={-250} \n      style={{ fontSize: 32, fill: \"#ecf0f1\" }}\n    />\n    \n   \n      <DOMContainer>\n        <div class=\"button-container\">\n        <Navigation \n            tabindex={tabindex} \n            controls={controls}\n          >\n              <div>\n                <Navigation tabindex={tabindex2} controls={controls2}>\n                  <div>\n                    <button tabindex={0}>Button 1</button>\n                    <button tabindex={1}>Button 2</button>\n                    <button tabindex={2}>Button 3</button>\n                  </div>\n                </Navigation>\n                  <div>\n                      @for (item of items) {\n                          <button tabindex={item.id}>{item.label}</button>\n                        }\n                  </div>\n              </div>\n          </Navigation>\n        </div>\n      </DOMContainer>\n   \n  </Container>\n</Canvas>\n\n<style scoped>\n  .button-container {\n    display: flex;\n    flex-direction: column;\n    gap: 10px;\n    padding: 20px;\n    background: rgba(255, 255, 255, 0.1);\n    border-radius: 8px;\n    overflow: hidden;\n    height: 300px;\n  }\n  button {\n    padding: 10px 20px;\n    font-size: 18px;\n    cursor: pointer;\n    background: #34495e;\n    color: white;\n    border: 2px solid transparent;\n    border-radius: 4px;\n    transition: all 0.2s;\n  }\n  button:focus {\n    background: #3498db;\n    border-color: white;\n    outline: none;\n    transform: scale(1.05);\n  }\n</style>\n\n<script>\n  import { signal, effect, createTabindexNavigator } from \"canvasengine\";\n\n  const tabindex = signal(0);\n  const tabindex2 = signal(0);\n  const nav2 = createTabindexNavigator(\n    tabindex2,\n    { count: () => 3 },\n    \"wrap\"\n  );\n  const controls2 = signal({\n    right: {\n      repeat: true,\n      bind: \"right\",\n      throttle: 150,\n      keyDown() {\n        nav2.next(-1);\n      }\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      throttle: 150,\n      keyDown() {\n        nav2.next(1);\n      }\n    }\n  });\n\n  effect(() => {\n    console.log(\"Selected index:\", tabindex());\n  });\n\n  const items100 = new Array(20).fill(0).map((_, index) => ({ id: index, label: `Item ${index + 1}` }));\n  const items = signal(items100);\n\n  const nav = createTabindexNavigator(\n    tabindex,\n    { count: () => items().length },\n    \"wrap\"\n  );\n  \n\n  const controls = signal({\n    up: {\n      repeat: true,\n      bind: \"up\",\n      throttle: 150,\n      keyDown() {\n        nav.next(-1);\n      }\n    },\n    down: {\n      repeat: true,\n      bind: \"down\",\n      throttle: 150,\n      keyDown() {\n        nav.next(1);\n      }\n    },\n    action: {\n      bind: [\"space\", \"enter\"]\n    },\n    gamepad: {\n      enabled: true\n    }\n  });\n</script>\n  \n"
  },
  {
    "path": "sample/src/focus-navigation.ce",
    "content": "<Canvas backgroundColor=\"#2c3e50\">\n  <Container x={400} y={300}>\n    <Text \n      text=\"Focus Navigation Example\" \n      x={0} \n      y={-250} \n      style={{ fontSize: 32, fill: \"#ecf0f1\" }}\n    />\n    \n    <Text \n      text=\"Use Up/Down arrows or gamepad to navigate\" \n      x={0} \n      y={-200} \n      style={{ fontSize: 16, fill: \"#bdc3c7\" }}\n    />\n    \n    <Text \n      text=\"Press Space/Enter to select\" \n      x={0} \n      y={-170} \n      style={{ fontSize: 16, fill: \"#bdc3c7\" }}\n    />\n\n    <Viewport screenHeight={300} worldWidth={2000} worldHeight={8000} clamp={ {direction: 'all'} }>\n      <FocusContainer \n      tabindex={selectedIndex} \n      controls={controls}\n      onFocusChange={onFocusChange}\n    >\n      <Container>\n        <Rect\n        width={320}\n        height={80}\n        x={0}\n        y={selectedIndex * 80}\n        color=\"#ffffff\"\n        alpha={0.2}\n        viewportFollow={true}\n      />\n        @for (item of items) {\n          <Container y={@item.@id * 80}  tabindex={@item.@id}>\n            <Rect\n             \n              width={300}\n              height={60}\n              x={0}\n              y={0}\n              color={@item.@color}\n              alpha={0.5}\n            />\n            <Text\n              text={@item.@label}\n              x={0}\n              y={0}\n              style={{ fontSize: 24, fill: \"#ffffff\" }}\n            />\n          \n               \n              \n          </Container>\n        }\n      </Container>\n    </FocusContainer>\n    </Viewport>\n  </Container>\n</Canvas>\n\n<script>\n    import { signal, computed, useFocusChange, mount, effect } from \"canvasengine\";\n\n    const selectedIndex = signal(0);\n\n    const onFocusChange = (index, element) => {\n      console.log('Focus changed to index:', index, element);\n    }\n\n    const items100 = new Array(20).fill(0).map((_, index) => ({ id: index, label: `Item ${index + 1}` }));\n\n    const items = signal(items100);\n  \n    const controls = signal({\n      up: {\n        repeat: true,\n        bind: \"up\",\n        keyDown() {\n          console.log(\"Up pressed\");\n        }\n      },\n      down: {\n        repeat: true,\n        bind: \"down\",\n        keyDown() {\n          console.log(\"Down pressed\");\n        }\n      },\n      action: {\n        bind: [\"space\", \"enter\"],\n        keyDown() {\n          console.log(\"Action pressed on item\", selectedIndex());\n        }\n      },\n      gamepad: {\n        enabled: true\n      }\n    });\n  </script>\n"
  },
  {
    "path": "sample/src/fogofwar.ce",
    "content": "<Canvas backgroundColor=\"#1b2430\">\n  <Viewport worldWidth={worldWidth} worldHeight={worldHeight} clamp={clamp} sortableChildren={true}>\n    <Sprite image=\"back.png\" />\n\n    <!-- Objet normal: reste visible comme aujourd'hui (atténué par le fog) -->\n    <Rect x={relicX} y={relicY} width={34} height={34} color=\"#ffd166\" zIndex={2} />\n\n    <!-- Objet strict: visible seulement dans la zone très claire -->\n    <Rect\n      x={enemyX}\n      y={enemyY}\n      width={34}\n      height={34}\n      color=\"#5ee7ff\"\n      zIndex={3}\n      fogVisibility={enemyFogVisibility}\n    />\n\n    <Graphics\n      x={playerX}\n      y={playerY}\n      zIndex={10}\n      draw={(g) => {\n        g.clear();\n        g.beginFill(0xffcc00);\n        g.drawCircle(0, 0, 20);\n        g.endFill();\n      }}\n      controls\n      viewportFollow={true}\n    />\n\n    <FogOfWar\n      mapWidth={worldWidth}\n      mapHeight={worldHeight}\n      tileSize={tileSize}\n      smooth={true}\n      renderScale={4}\n      edgeSoftness={26}\n      visionSources={visionSources}\n      controller={fogController}\n      updateHz={60}\n      colors={fogColors}\n      zIndex={1000}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { computed, signal } from 'canvasengine'\n  import { FogOfWar, createFogOfWarController } from '@canvasengine/presets'\n\n  const worldWidth = 2048\n  const worldHeight = 2048\n  const tileSize = 32\n  const clamp = { direction: 'all' }\n\n  const playerX = signal(360)\n  const playerY = signal(320)\n  const allyX = signal(760)\n  const allyY = signal(520)\n  const enemyX = signal(1080)\n  const enemyY = signal(690)\n  const relicX = 118\n  const relicY = 128\n\n  const fogController = createFogOfWarController()\n\n  const fogColors = {\n    unknown: [8, 12, 22, 0.95],\n    explored: [0, 0, 0, 0.45],\n  }\n\n  const visionSources = computed(() => [\n    { x: playerX(), y: playerY(), radius: 240, enabled: true },\n    { x: allyX(), y: allyY(), radius: 170, enabled: true },\n  ])\n\n  const enemyFogVisibility = {\n    controller: fogController,\n    mode: 'visible',\n    threshold: 0.72,\n    point: {\n      x: computed(() => enemyX() + 17),\n      y: computed(() => enemyY() + 17),\n    },\n  }\n\n  const controls = signal({\n    right: {\n      repeat: true,\n      bind: 'right',\n      keyDown() {\n        playerX.update((x) => Math.min(x + 12, worldWidth - 12))\n      },\n    },\n    left: {\n      repeat: true,\n      bind: 'left',\n      keyDown() {\n        playerX.update((x) => Math.max(x - 12, 12))\n      },\n    },\n    up: {\n      repeat: true,\n      bind: 'up',\n      keyDown() {\n        playerY.update((y) => Math.max(y - 12, 12))\n      },\n    },\n    down: {\n      repeat: true,\n      bind: 'down',\n      keyDown() {\n        playerY.update((y) => Math.min(y + 12, worldHeight - 12))\n      },\n    },\n  })\n</script>\n"
  },
  {
    "path": "sample/src/footprints.ce",
    "content": "<Canvas backgroundColor=\"#0d1424\">\n  <Viewport\n    worldWidth={worldWidth}\n    worldHeight={worldHeight}\n    sortableChildren={true}\n    clamp={viewportClamp}\n  >\n    <Graphics zIndex={0} draw={drawTerrain} />\n\n    <Footprints\n      profiles={surfaceProfiles}\n      defaultSurface=\"sand\"\n      updateHz={45}\n      maxFootprints={320}\n    />\n\n    <Sprite\n      x={heroX}\n      y={heroY}\n      width={88}\n      height={88}\n      zIndex={30}\n      viewportFollow={true}\n      controls={heroControls}\n      sheet={heroSheet}\n      footprintCaster={heroFootprintCaster}\n    />\n\n    <Text\n      x={26}\n      y={24}\n      zIndex={100}\n      text=\"Footprints demo: move with arrows. Rules change by terrain zone (snow/sand/mud/rock).\"\n      style={labelStyle}\n    />\n\n    <Text\n      x={26}\n      y={58}\n      zIndex={100}\n      text={surfaceLabel}\n      style={surfaceStyle}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { computed, signal } from \"canvasengine\";\n  import { Footprints } from \"@canvasengine/presets\";\n\n  const worldWidth = 2048;\n  const worldHeight = 1280;\n  const viewportClamp = { direction: \"all\" };\n  const moveSpeed = 10;\n\n  const labelStyle = {\n    fill: \"#f3f4ff\",\n    fontSize: 18,\n    fontFamily: \"Courier New\",\n    wordWrap: true,\n    wordWrapWidth: 980,\n  };\n\n  const surfaceStyle = {\n    fill: \"#dfe8ff\",\n    fontSize: 16,\n    fontFamily: \"Courier New\",\n  };\n\n  const heroX = signal(420);\n  const heroY = signal(840);\n\n  const zones = [\n    {\n      name: \"mud-pit\",\n      x1: 860,\n      y1: 760,\n      x2: 1260,\n      y2: 980,\n      surface: \"mud\",\n      enabled: true,\n      minStepDistance: 13,\n      minSpeed: 28,\n      alpha: 0.46,\n      blur: 0.25,\n      size: 0.78,\n    },\n    {\n      name: \"rock-platform\",\n      x1: 1460,\n      y1: 840,\n      x2: 1880,\n      y2: 1100,\n      surface: \"rock\",\n      enabled: false,\n      minStepDistance: 20,\n      minSpeed: 80,\n      alpha: 0,\n      blur: 0,\n      size: 0.76,\n    },\n    {\n      name: \"snow-field\",\n      x1: 0,\n      y1: 0,\n      x2: worldWidth,\n      y2: 560,\n      surface: \"snow\",\n      enabled: true,\n      minStepDistance: 14,\n      minSpeed: 36,\n      alpha: 0.28,\n      blur: 0.2,\n      size: 0.72,\n    },\n    {\n      name: \"sand-dune\",\n      x1: 0,\n      y1: 560,\n      x2: worldWidth,\n      y2: worldHeight,\n      surface: \"sand\",\n      enabled: true,\n      minStepDistance: 18,\n      minSpeed: 44,\n      alpha: 0.34,\n      blur: 0.1,\n      size: 0.7,\n    },\n  ];\n\n  const inZone = (x, y, zone) =>\n    x >= zone.x1 && x <= zone.x2 && y >= zone.y1 && y <= zone.y2;\n\n  const fallbackZone = zones[zones.length - 1];\n\n  const zoneAt = (x, y) => {\n    for (let i = 0; i < zones.length; i++) {\n      const zone = zones[i];\n      if (inZone(x, y, zone)) return zone;\n    }\n    return fallbackZone;\n  };\n\n  const currentZone = computed(() => zoneAt(heroX(), heroY()));\n\n  const heroControls = signal({\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown() {\n        heroX.update((x) => Math.min(x + moveSpeed, worldWidth - 32));\n      },\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        heroX.update((x) => Math.max(x - moveSpeed, 32));\n      },\n    },\n    up: {\n      repeat: true,\n      bind: \"up\",\n      keyDown() {\n        heroY.update((y) => Math.max(y - moveSpeed, 32));\n      },\n    },\n    down: {\n      repeat: true,\n      bind: \"down\",\n      keyDown() {\n        heroY.update((y) => Math.min(y + moveSpeed, worldHeight - 32));\n      },\n    },\n  });\n\n  const heroSheetDefinition = {\n    id: \"footprints-hero\",\n    image: \"./exp.png\",\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n      loop: {\n        animations: () => [\n          [\n            { time: 0, frameX: 0, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 8, frameX: 1, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 16, frameX: 2, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 24, frameX: 3, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 32, frameX: 0, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 40, frameX: 1, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 48, frameX: 2, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 56, frameX: 3, frameY: 1, anchor: [0.5, 0.86] },\n          ],\n        ],\n      },\n    },\n  };\n\n  const heroSheet = {\n    definition: heroSheetDefinition,\n    playing: \"loop\",\n  };\n\n  const heroFootprintCaster = {\n    enabled: () => currentZone().enabled,\n    surface: () => currentZone().surface,\n    minStepDistance: () => currentZone().minStepDistance,\n    minSpeed: () => currentZone().minSpeed,\n    alpha: () => currentZone().alpha,\n    blur: () => currentZone().blur,\n    size: () => currentZone().size,\n    stepIntervalMs: 70,\n    leftOffset: { x: -8, y: 1 },\n    rightOffset: { x: 8, y: 1 },\n    angleOffset: 180,\n    jitter: 11,\n  };\n\n  const surfaceLabel = computed(() => {\n    const zone = currentZone();\n    const mode = zone.enabled ? \"footprints ON\" : \"footprints OFF\";\n    return `Zone: ${zone.name} | surface: ${zone.surface} | ${mode} | x=${Math.round(heroX())}, y=${Math.round(heroY())}`;\n  });\n\n  const surfaceProfiles = {\n    sand: {\n      tint: \"#7f5d34\",\n      startAlpha: 0.34,\n      endAlpha: 0,\n      lifetimeMs: 1800,\n      blurStart: 0.35,\n      blurEnd: 1.6,\n      erosionStart: 0.62,\n      blendMode: \"multiply\",\n      depth: 0.58,\n      rimStrength: 0.12,\n    },\n    snow: {\n      tint: \"#889db6\",\n      startAlpha: 0.26,\n      endAlpha: 0,\n      lifetimeMs: 2600,\n      blurStart: 0.62,\n      blurEnd: 2.35,\n      erosionStart: 0.43,\n      blendMode: \"multiply\",\n      depth: 0.74,\n      rimStrength: 0.3,\n    },\n    mud: {\n      tint: \"#4e3421\",\n      startAlpha: 0.42,\n      endAlpha: 0,\n      lifetimeMs: 3000,\n      blurStart: 0.24,\n      blurEnd: 1.1,\n      erosionStart: 0.78,\n      blendMode: \"multiply\",\n      scale: 1.06,\n      depth: 0.88,\n      rimStrength: 0.08,\n    },\n    rock: {\n      tint: \"#5f646b\",\n      startAlpha: 0.1,\n      endAlpha: 0,\n      lifetimeMs: 900,\n      blurStart: 0.2,\n      blurEnd: 0.5,\n      erosionStart: 0.35,\n      blendMode: \"normal\",\n      depth: 0.34,\n      rimStrength: 0.05,\n    },\n  };\n\n  const drawTerrain = (graphics) => {\n    graphics.clear();\n\n    graphics.rect(0, 0, worldWidth, 560);\n    graphics.fill({ color: 0xeaf3fb, alpha: 1 });\n\n    graphics.rect(0, 560, worldWidth, worldHeight - 560);\n    graphics.fill({ color: 0xd6b17b, alpha: 1 });\n\n    graphics.rect(860, 760, 400, 220);\n    graphics.fill({ color: 0x6e4b2f, alpha: 0.85 });\n\n    graphics.rect(1460, 840, 420, 260);\n    graphics.fill({ color: 0x69717b, alpha: 0.9 });\n\n    graphics.rect(0, 552, worldWidth, 16);\n    graphics.fill({ color: 0xffffff, alpha: 0.22 });\n\n    for (let i = 0; i < 7; i++) {\n      const y = 72 + i * 68;\n      graphics.rect(0, y, worldWidth, 2);\n      graphics.fill({ color: 0xc8d8e7, alpha: 0.18 });\n    }\n\n    for (let i = 0; i < 8; i++) {\n      const y = 620 + i * 74;\n      graphics.rect(0, y, worldWidth, 2);\n      graphics.fill({ color: 0xaf8452, alpha: 0.2 });\n    }\n  };\n</script>\n"
  },
  {
    "path": "sample/src/freeze.ce",
    "content": "<Canvas>\n    <Container>\n        <!-- Instructions -->\n        <Text text=\"Freeze System Demo\" x={10} y={10} color=\"#ecf0f1\" size=\"24\" fontFamily=\"Arial\" />\n        <Text text=\"Click the button to freeze/unfreeze the sprite\" x={10} y={40} color=\"#95a5a6\" size=\"14\" fontFamily=\"Arial\" />\n        <Text text=\"When frozen: no updates, no controls, no events\" x={10} y={60} color=\"#95a5a6\" size=\"14\" fontFamily=\"Arial\" />\n    </Container>\n\n    <!-- Freeze button -->\n    <Container x={100} y={100}>\n        <Text text=\"Toggle Freeze\" x={0} y={-30} color=\"#ecf0f1\" size=\"16\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            width={150}\n            height={50}\n            borderRadius={8}\n            click={() => {\n                freezeSignal.set(!freezeSignal())\n                console.log('Freeze toggled:', freezeSignal())\n            }}\n        />\n    </Container>\n\n    <!-- Sprite with freeze prop (Signal) -->\n    <Container x={100} y={200}>\n        <Text text=\"Frozen Sprite (Signal)\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Text text={freezeSignal ? \"FROZEN\" : \"ACTIVE\"} x={0} y={-50} color={freezeSignal ? \"#e74c3c\" : \"#2ecc71\"} size=\"12\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            width={200}\n            height={200}\n            borderRadius={8}\n            freeze={freezeSignal}\n            x={xSignal}\n            y={ySignal}\n            controls={controlsConfig1}\n            click={handleSpriteClick}\n        />\n    </Container>\n\n    <!-- Sprite with freeze prop (boolean) -->\n    <Container x={400} y={200}>\n        <Text text=\"Always Frozen Sprite (boolean)\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Text text={freezeSignal2 ? \"FROZEN\" : \"ACTIVE\"} x={0} y={-50} color={freezeSignal2 ? \"#e74c3c\" : \"#2ecc71\"} size=\"12\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            width={200}\n            height={200}\n            borderRadius={8}\n            freeze={freezeSignal2}\n            x={xSignal2}\n            y={ySignal2}\n            controls={controlsConfig2}\n            click={handleFrozenSpriteClick}\n        />\n    </Container>\n\n    <!-- Animated sprite to show updates are blocked -->\n    <Container x={100} y={450}>\n        <Text text=\"Animated Sprite (updates blocked when frozen)\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            width={100}\n            height={100}\n            borderRadius={8}\n            freeze={freezeSignal}\n            x={animatedX}\n            y={200}\n            click={handleAnimatedSpriteClick}\n        />\n    </Container>\n\n    <!-- Spritesheet animation example -->\n    <Container x={300} y={450}  freeze={freezeSignal}>\n        <Text text=\"Spritesheet Animation (blocked when frozen)\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            sheet={{\n                definition: spritesheetDefinition,\n                playing: \"default\"\n            }}\n           \n            click={handleAnimatedSpriteClick}\n        />\n        <Child />\n    </Container>\n\n    \n</Canvas>\n\n<script>\n    import { signal, animatedSignal, mount } from 'canvasengine';\n    import Child from './child.ce';\n\n    // Freeze state signal\n    const freezeSignal = signal(false);\n    const freezeSignal2 = signal(false);\n\n    // Position signals for first sprite\n    const xSignal = signal(0);\n    const ySignal = signal(0);\n\n    // Position signals for second sprite (always frozen)\n    const xSignal2 = signal(0);\n    const ySignal2 = signal(0);\n\n    // Animated position signal\n    const animatedX = animatedSignal(0, { duration: 2000, repeat: true });\n\n    mount((element) => {\n        animatedX.set(300);\n    })\n    \n\n    // Controls configuration for first sprite (arrow keys)\n    const controlsConfig1 = {\n        up: {\n            bind: 'up',\n            repeat: true,\n            keyDown: () => {\n                ySignal.set(ySignal() - 10);\n                console.log('Up pressed, y:', ySignal());\n            }\n        },\n        down: {\n            bind: 'down',\n            repeat: true,\n            keyDown: () => {\n                ySignal.set(ySignal() + 10);\n                console.log('Down pressed, y:', ySignal());\n            }\n        },\n        left: {\n            bind: 'left',\n            repeat: true,\n            keyDown: () => {\n                xSignal.set(xSignal() - 10);\n                console.log('Left pressed, x:', xSignal());\n            }\n        },\n        right: {\n            bind: 'right',\n            repeat: true,\n            keyDown: () => {\n                xSignal.set(xSignal() + 10);\n                console.log('Right pressed, x:', xSignal());\n            }\n        }\n    };\n\n    // Controls configuration for second sprite (WASD keys)\n    const controlsConfig2 = {\n        up: {\n            bind: 'up',\n            repeat: true,\n            keyDown: () => {\n                ySignal2.set(ySignal2() - 10);\n                console.log('W pressed, y2:', ySignal2());\n            }\n        },\n        down: {\n            bind: 'down',\n            repeat: true,\n            keyDown: () => {\n                ySignal2.set(ySignal2() + 10);\n                console.log('S pressed, y2:', ySignal2());\n            }\n        },\n        left: {\n            bind: 'left',\n            repeat: true,\n            keyDown: () => {\n                xSignal2.set(xSignal2() - 10);\n                console.log('A pressed, x2:', xSignal2());\n            }\n        },\n        right: {\n            bind: 'right',\n            repeat: true,\n            keyDown: () => {\n                xSignal2.set(xSignal2() + 10);\n                console.log('D pressed, x2:', xSignal2());\n            }\n        }\n    };\n\n    // Event handlers\n    const handleSpriteClick = () => {\n        console.log('Sprite clicked!');\n    };\n\n    const handleFrozenSpriteClick = () => {\n        console.log('Frozen sprite clicked! (should not work)');\n        freezeSignal2.set(!freezeSignal2());\n    };\n\n    const handleAnimatedSpriteClick = () => {\n        console.log('Animated sprite clicked!');\n    };\n\n    // Spritesheet definition for animation\n    const spritesheetDefinition = {\n        id: \"explosion\",\n        image: \"./exp.png\",\n        width: 1024,\n        height: 1024,\n        framesWidth: 4,\n        framesHeight: 4,\n        textures: {\n            default: {\n                animations: () => [\n                    [ \n                        { time: 0, frameX: 0, frameY: 0 },\n                        { time: 10, frameX: 1, frameY: 0 },\n                        { time: 20, frameX: 2, frameY: 0 },\n                        { time: 30, frameX: 3, frameY: 0 },\n                        { time: 40, frameX: 0, frameY: 1 },\n                        { time: 50, frameX: 1, frameY: 1 },\n                        { time: 60, frameX: 2, frameY: 1 },     \n                        { time: 70, frameX: 3, frameY: 1 },\n                        { time: 80, frameX: 0, frameY: 2 },\n                        { time: 90, frameX: 1, frameY: 2 },\n                        { time: 100, frameX: 2, frameY: 2 },\n                        { time: 110, frameX: 3, frameY: 2 },\n                        { time: 120, frameX: 0, frameY: 3 },\n                        { time: 130, frameX: 1, frameY: 3 },\n                        { time: 140, frameX: 2, frameY: 3 },\n                        { time: 150, frameX: 3, frameY: 3 },\n                    ]\n                ]\n            }\n        }\n    };\n    \n</script>\n"
  },
  {
    "path": "sample/src/fx.ce",
    "content": "<Canvas backgroundColor=\"#151922\">\n  <Container sortableChildren={true}>\n    <Text text=\"Fx preset sample\" x={24} y={20} color=\"#ffffff\" size=\"22\" />\n    <Text text=\"Click anywhere to spawn hit sparks\" x={24} y={52} color=\"#b9c0cc\" size=\"14\" />\n\n    <Rect\n      x={0}\n      y={0}\n      width={900}\n      height={620}\n      color=\"rgba(0,0,0,0)\"\n      click={spawnAtPointer}\n    />\n\n    <Fx name=\"slashSpark\" trigger={slashTrigger} x={210} y={185} zIndex={2} />\n    <Fx name=\"impactBurst\" trigger={impactTrigger} x={335} y={185} zIndex={2} />\n    <Fx name=\"healPulse\" trigger={healTrigger} x={210} y={315} zIndex={2} />\n    <Fx name=\"levelUp\" trigger={levelTrigger} x={335} y={315} zIndex={2} />\n    <Fx name=\"magicBurst\" trigger={magicTrigger} x={470} y={250} zIndex={2} />\n    <Fx name=\"dashDust\" trigger={dashTrigger} x={470} y={425} zIndex={2} />\n    <Fx name=\"campfire\" x={620} y={360} loop zIndex={1} />\n    <Fx name=\"torchFire\" x={700} y={360} loop zIndex={1} />\n    <Fx name=\"hitSpark\" trigger={hitTrigger} x={sparkX} y={sparkY} zIndex={3} />\n    <Fx preset={imageSpark} trigger={imageTrigger} x={770} y={250} zIndex={4} />\n\n    <Text text=\"slash\" x={190} y={225} color=\"#ffd36d\" size=\"13\" />\n    <Text text=\"impact\" x={310} y={225} color=\"#ffd36d\" size=\"13\" />\n    <Text text=\"heal\" x={190} y={365} color=\"#9fffc5\" size=\"13\" />\n    <Text text=\"level\" x={315} y={365} color=\"#ffe870\" size=\"13\" />\n    <Text text=\"magic\" x={445} y={305} color=\"#b970ff\" size=\"13\" />\n    <Text text=\"dash dust\" x={435} y={462} color=\"#d9c08a\" size=\"13\" />\n    <Text text=\"loops\" x={635} y={410} color=\"#ffd36d\" size=\"13\" />\n    <Text text=\"image\" x={748} y={305} color=\"#9fd7ff\" size=\"13\" />\n  </Container>\n</Canvas>\n\n<script>\n  import { Fx } from '@canvasengine/presets'\n  import { signal, trigger } from 'canvasengine'\n\n  const hitTrigger = trigger()\n  const slashTrigger = trigger()\n  const impactTrigger = trigger()\n  const healTrigger = trigger()\n  const levelTrigger = trigger()\n  const dashTrigger = trigger()\n  const magicTrigger = trigger()\n  const imageTrigger = trigger()\n  const sparkX = signal(260)\n  const sparkY = signal(250)\n\n  const imageSpark = {\n    duration: 360,\n    emitters: [\n      {\n        burst: 18,\n        angle: [0, 360],\n        speed: [80, 220],\n        particle: {\n          image: 'https://pixijs.com/assets/flowerTop.png',\n          lifetime: [360, 720],\n          alpha: [0.95, 0],\n          scale: [0.18, 0.55],\n          rotationSpeed: [-180, 180],\n          blendMode: 'add',\n          ease: 'outCubic',\n        },\n      },\n    ],\n  }\n\n  function spawnAtPointer(event) {\n    sparkX.set(event.global.x)\n    sparkY.set(event.global.y)\n    hitTrigger.start()\n  }\n\n  setInterval(() => {\n    slashTrigger.start()\n    impactTrigger.start()\n    healTrigger.start()\n    levelTrigger.start()\n    dashTrigger.start()\n    magicTrigger.start()\n  }, 1400)\n\n  setInterval(() => {\n    imageTrigger.start()\n  }, 1800)\n</script>\n"
  },
  {
    "path": "sample/src/light.ce",
    "content": "<Canvas>\n    <Container x={100} y={100}>\n        <Graphics draw={drawHalo}  />\n    </Container>\n</Canvas>\n  \n  <script>\n  import { computed, signal, tick, mount, effect } from \"canvasengine\";\n  import { BlurFilter } from \"pixi.js\";\n  \n  const { \n    baseRadius,\n    radiusVariation,\n    baseOpacity,\n    opacityVariation,\n    sizeSpeed,\n    opacitySpeed,\n    lightColor\n  } = defineProps();\n  \n  // ====================\n  // Props with default values\n  // ====================\n  \n  const getBaseRadius = computed(() => baseRadius?.() ?? 30);\n  const getRadiusVariation = computed(() => radiusVariation?.() ?? 10);\n  const getBaseOpacity = computed(() => baseOpacity?.() ?? 0.6);\n  const getOpacityVariation = computed(() => opacityVariation?.() ?? 0.3);\n  const getSizeSpeed = computed(() => sizeSpeed?.() ?? 0.002);\n  const getOpacitySpeed = computed(() => opacitySpeed?.() ?? 0.003);\n  const getLightColor = computed(() => lightColor?.() ?? 0xffffaa);\n  \n  // ====================\n  // Animation state\n  // ====================\n  \n  /** Time counter for animations */\n  const time = signal(0);\n\n  /**\n   * Current radius of the halo with pulsing animation\n   * Uses multiple sine waves for more organic movement\n   */\n  const currentRadius = computed(() => {\n    const t = time();\n    const base = getBaseRadius();\n    const variation = getRadiusVariation();\n    const speed = getSizeSpeed();\n    \n    // Combine two sine waves for less predictable pulsing\n    const pulse1 = Math.sin(t * speed);\n    const pulse2 = Math.sin(t * speed * 1.5) * 0.5;\n    const combinedPulse = (pulse1 + pulse2) / 1.5;\n    \n    return base + (combinedPulse * variation);\n  });\n  \n  /**\n   * Current opacity of the halo with fading animation\n   * Includes a subtle flicker effect\n   */\n  const currentOpacity = computed(() => {\n    const t = time();\n    const base = getBaseOpacity();\n    const variation = getOpacityVariation();\n    const speed = getOpacitySpeed();\n    \n    // Main breathing cycle\n    const fade = Math.sin(t * speed);\n    \n    // Subtle high-frequency flicker (candle-like)\n    const flicker = (Math.random() - 0.5) * 0.1;\n    \n    return Math.max(0, Math.min(1, base + (fade * variation) + flicker));\n  });\n  \n  // ====================\n  // Position calculations\n  // ====================\n\n  const position = computed(() => ({\n    x: 100,\n    y: 100\n  }));\n  \n  // ====================\n  // Drawing function\n  // ====================\n  \n  // Create filters once to avoid recreation on every frame\n  const blurFilter = new BlurFilter({ strength: 20, quality: 3 });\n  \n  /**\n   * Draws the light halo effect with realistic diffusion\n   */\n  const drawHalo = (g) => {\n    const radius = currentRadius();\n    const opacity = currentOpacity();\n    const color = getLightColor();\n\n    if (opacity <= 0 || radius <= 0) return;\n  \n    // Set blend mode to ADD for glowing light effect\n    g.blendMode = 'add';\n    \n    // Apply blur filter for soft light diffusion\n    g.filters = [blurFilter];\n    \n    // Draw main light source\n    // The blur filter will spread this out into a nice gradient\n    g.circle(0, 0, radius);\n    g.fill({ \n      color: color, \n      alpha: opacity \n    });\n    \n    // Draw a smaller, brighter core\n    g.circle(0, 0, radius * 0.4);\n    g.fill({ \n      color: 0xffffff, \n      alpha: opacity * 0.5 \n    });\n  };\n  \n  // ====================\n  // Animation loop\n  // ====================\n  tick(() => {\n    time.update(t => t + 1);\n  });\n  </script>"
  },
  {
    "path": "sample/src/loader-spritesheet.ce",
    "content": "<Canvas backgroundColor=\"#1a1a1a\">\n    <Container>\n        @for (sprite of sprites) {\n            <Child ...sprite />\n        }\n        \n        <!-- Spritesheet example -->\n        <Sprite \n            sheet={{\n                definition: spritesheetDef,\n                playing: \"default\"\n            }}\n            x={500}\n            y={100}\n        />\n        \n        <Text \n            text=\"All assets loaded! 🎉\"\n            x={250}\n            y={500}\n            color=\"#00ff00\"\n            size={32}\n        />\n    </Container>\n</Canvas>\n\n<script>\nimport { mount, signal, computed } from 'canvasengine'\nimport Child from './child.ce'\n\nconst isLoading = signal(true)\nconst loadingProgress = signal(0)\nconst totalCount = signal(0)\nconst completedCount = signal(0)\n\n// Sprites data - will be loaded via Child components\nconst spritesData = signal()\n\nconst sprites = computed(() => {\n    return spritesData() || []\n})\n\n// Spritesheet definition\nconst spritesheetDef = {\n    id: \"explosion\",\n    image: \"https://pixijs.com/assets/flowerTop.png\",\n    width: 256,\n    height: 256,\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n        default: {\n            animations: () => [\n                [ \n                    { time: 0, frameX: 0, frameY: 0 },\n                    { time: 10, frameX: 1, frameY: 0 },\n                    { time: 20, frameX: 2, frameY: 0 },\n                    { time: 30, frameX: 3, frameY: 0 }\n                ]\n            ]\n        }\n    }\n}\n\nsetTimeout(() => {\n    spritesData.set([\n    {\n        image: 'https://pixijs.com/assets/flowerTop.png',\n        x: 100,\n        y: 100,\n    },\n    {\n        image: 'https://pixijs.com/assets/bunny.png',\n        x: 300,\n        y: 100,\n    },\n    {\n        image: 'https://pixijs.com/assets/flowerTop.png',\n        x: 100,\n        y: 300,\n    },\n    {\n        image: 'https://pixijs.com/assets/bunny.png',\n        x: 300,\n        y: 300,\n    },\n    {\n        image: 'https://pixijs.com/assets/flowerTop.png',\n        x: 500,\n        y: 300,\n    }\n])\n}, 1000)\n\nmount((element) => {\n    const loader = element.props.context?.globalLoader\n\n    if (loader) {\n        // Track overall loading progress\n        loader.onProgress((progress) => {\n            loadingProgress.set(progress)\n            totalCount.set(loader.getAssetCount())\n            completedCount.set(loader.getCompletedCount())\n            console.log(`Loading progress: ${(progress * 100).toFixed(0)}% (${completedCount()} / ${totalCount()} assets)`)\n        })\n        \n        // Hide loader when all assets are loaded\n        loader.onComplete(() => {\n            console.log('All assets loaded!')\n            isLoading.set(false)\n        })\n    }\n})\n</script>\n\n"
  },
  {
    "path": "sample/src/main.ts",
    "content": "import { bootstrapCanvas } from 'canvasengine';\n//import App from './test.ce'\n// Uncomment to test shake directive examples:\n// import App from './shake.ce'\n// Uncomment to test global asset loader (simple):\n// import App from './loader.ce'\n// Uncomment to test global asset loader (with spritesheets):\n// import App from './fogofwar.ce'\n// import App from './sprite-shadows.ce'\n// import App from './spritesheet.ce'\nimport App from './fx.ce'\n\nbootstrapCanvas(document.getElementById(\"root\"), App).then(() => {\n    console.log(\"CanvasEngine initialized\");\n});\n"
  },
  {
    "path": "sample/src/preset.ce",
    "content": "<Canvas>\n\n\n    <Container>\n        <Rect color=\"#3498db\" width={60} height={60} borderRadius={8} controls x y />\n\n        <!-- Display gamepad status -->\n        <Text text={gamepadStatus} x={10} y={10} color=\"#ecf0f1\" size=\"16\" fontFamily=\"Arial\" />\n\n        <!-- Instructions -->\n        <Text text=\"Use arrow keys or a gamepad to move the rectangle\" x={10} y={40} color=\"#95a5a6\" size=\"12\"\n            fontFamily=\"Arial\" />\n    </Container>\n\n\n    <Container>\n        <Weather effect=\"fog\" density={1} />\n    </Container>\n\n</Canvas>\n\n<script>\n    import { Weather } from '@canvasengine/presets'\n    import { signal, computed, effect } from \"canvasengine\";\n\n    // Rectangle position\n    const x = signal(200);\n    const y = signal(200);\n\n    // Movement speed\n    const speed = signal(5);\n\n    // Gamepad connection status signal\n    const gamepadConnected = signal(false);\n\n    // Gamepad status text (reactive, updated when gamepadConnected changes)\n    const gamepadStatus = computed(() =>\n        gamepadConnected() ? \"Gamepad: Connected ✅\" : \"Gamepad: Not connected\"\n    );\n\n    effect(() => {\n        console.log(gamepadConnected());\n    });\n\n    // Controls configuration\n    const controls = signal({\n        up: {\n            repeat: true,\n            bind: \"up\",\n            keyDown() {\n                y.update((y) => Math.max(0, y - speed()));\n            },\n        },\n        down: {\n            repeat: true,\n            bind: \"down\",\n            keyDown() {\n                y.update((y) => y + speed());\n            },\n        },\n        left: {\n            repeat: true,\n            bind: \"left\",\n            keyDown() {\n                x.update((x) => Math.max(0, x - speed()));\n            },\n        },\n        right: {\n            repeat: true,\n            bind: \"right\",\n            keyDown() {\n                x.update((x) => x + speed());\n            },\n        },\n        // Gamepad configuration with callbacks and signal\n        gamepad: {\n            enabled: true,\n            // Default mappings will be used if joypad.js is available\n            // button_0 -> action, button_1 -> back\n            // Left stick axes will be mapped to up/down/left/right directions\n\n            // Signal to track connection status (automatically updated)\n            gamepadConnected: gamepadConnected,\n\n            // Optional callbacks\n            onConnect() {\n                console.log(\"Gamepad connected!\");\n            },\n            onDisconnect() {\n                console.log(\"Gamepad disconnected!\");\n            }\n        }\n    });\n</script>"
  },
  {
    "path": "sample/src/shake.ce",
    "content": "<Canvas>\n    <Container>\n        <!-- Instructions -->\n        <Text text=\"Click the rectangles to shake them!\" x={10} y={10} color=\"#ecf0f1\" size=\"18\" fontFamily=\"Arial\" />\n        <Text text=\"Different shake configurations are demonstrated below\" x={10} y={35} color=\"#95a5a6\" size=\"14\" fontFamily=\"Arial\" />\n    </Container>\n\n    <!-- Basic shake example -->\n    <Container x={100} y={100} controls>\n        <Text text=\"Basic Shake\" x={0} y={-30} color=\"#ecf0f1\" size=\"14\" fontFamily=\"Arial\" />\n        <Sprite \n            image=\"exp.png\"\n            width={200}\n            height={200}\n            borderRadius={8} \n            shake={shakeConfig}\n            click={() => shakeTrigger.start()}\n        />\n    </Container>\n</Canvas>\n\n<script>\n    import { trigger, signal, on } from 'canvasengine';\n\n    const shakeTrigger = trigger();\n\n    const shakeConfig = {\n  trigger: shakeTrigger\n};\n\nconst controls = signal({\n    up: {\n        bind: \"up\",\n        keyDown() {\n            shakeTrigger.start();\n        }\n    }\n});\n</script>\n\n"
  },
  {
    "path": "sample/src/sprite-shadows.ce",
    "content": "<Canvas backgroundColor=\"#0f1220\">\n  <Viewport\n    worldWidth={worldWidth}\n    worldHeight={worldHeight}\n    sortableChildren={true}\n    clamp={viewportClamp}\n  >\n    <Sprite image=\"./back.png\" width={worldWidth} height={worldHeight} />\n<!-- \n    <NightAmbiant\n      lightSpots={nightLights}\n      darkness={0.6}\n      darkColor=\"#080a12\"\n      fogColor=\"#12182a\"\n      fogRadius={0.44}\n      fogSoftness={0.3}\n    /> -->\n\n    <SpriteShadows\n      lights={shadowLights}\n      mode=\"strongest\"\n      updateHz={60}\n      shadowColor=\"#05070d\"\n    />\n\n    <Sprite\n      x={heroX}\n      y={heroY}\n      width={96}\n      height={96}\n      zIndex={20}\n      controls={heroControls}\n      sheet={heroSheet}\n      shadowCaster={heroShadowCaster}\n    />\n\n    <Sprite\n      x={enemyX}\n      y={enemyY}\n      width={84}\n      height={84}\n      alpha={0.92}\n      zIndex={18}\n      sheet={enemySheet}\n      shadowCaster={enemyShadowCaster}\n    />\n\n    <Graphics x={torchX} y={torchY} zIndex={30} draw={drawTorch} />\n\n    <Text\n      x={26}\n      y={24}\n      zIndex={100}\n      text=\"SpriteShadows demo: move with arrows. Shadows are projected opposite to fixed map lights.\"\n      style={labelStyle}\n    />\n  </Viewport>\n</Canvas>\n\n<script>\n  import { computed, signal, tick } from \"canvasengine\";\n  import { NightAmbiant, SpriteShadows } from \"@canvasengine/presets\";\n\n  const worldWidth = 2048;\n  const worldHeight = 2048;\n  const viewportClamp = { direction: \"all\" };\n  const labelStyle = {\n    fill: \"#f3f4ff\",\n    fontSize: 18,\n    fontFamily: \"Courier New\",\n  };\n  const heroShadowCaster = {\n    height: 96,\n    alpha: 0.62,\n    blur: 3.2,\n    gradientPower: 2.4,\n    hardness: 1,\n    footOffset: { x: 0, y: 4 },\n    maxLength: 260,\n  };\n  const enemyShadowCaster = {\n    height: 84,\n    alpha: 0.48,\n    blur: 3.2,\n    gradientPower: 2.4,\n    hardness: 0.55,\n    footOffset: { x: 0, y: 3 },\n  };\n  const spritesheetDefinition = {\n    id: \"exp-shadow-demo\",\n    image: \"./exp.png\",\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n      loop: {\n        animations: () => [\n          [\n            { time: 0, frameX: 0, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 8, frameX: 1, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 16, frameX: 2, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 24, frameX: 3, frameY: 0, anchor: [0.5, 0.86] },\n            { time: 32, frameX: 0, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 40, frameX: 1, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 48, frameX: 2, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 56, frameX: 3, frameY: 1, anchor: [0.5, 0.86] },\n            { time: 64, frameX: 0, frameY: 2, anchor: [0.5, 0.86] },\n            { time: 72, frameX: 1, frameY: 2, anchor: [0.5, 0.86] },\n            { time: 80, frameX: 2, frameY: 2, anchor: [0.5, 0.86] },\n            { time: 88, frameX: 3, frameY: 2, anchor: [0.5, 0.86] },\n            { time: 96, frameX: 0, frameY: 3, anchor: [0.5, 0.86] },\n            { time: 104, frameX: 1, frameY: 3, anchor: [0.5, 0.86] },\n            { time: 112, frameX: 2, frameY: 3, anchor: [0.5, 0.86] },\n            { time: 120, frameX: 3, frameY: 3, anchor: [0.5, 0.86] },\n          ],\n        ],\n      },\n    },\n  };\n  const heroSheet = {\n    definition: spritesheetDefinition,\n    playing: \"loop\",\n  };\n  const enemySheet = {\n    definition: spritesheetDefinition,\n    playing: \"loop\",\n  };\n  const heroX = signal(620);\n  const heroY = signal(540);\n  const enemyX = signal(1000);\n  const enemyY = signal(700);\n  const torchX = signal(760);\n  const torchY = signal(430);\n  const time = signal(0);\n\n  const moveSpeed = 12;\n  const heroControls = signal({\n    right: {\n      repeat: true,\n      bind: \"right\",\n      keyDown() {\n        heroX.update((x) => Math.min(x + moveSpeed, worldWidth - 40));\n      },\n    },\n    left: {\n      repeat: true,\n      bind: \"left\",\n      keyDown() {\n        heroX.update((x) => Math.max(x - moveSpeed, 40));\n      },\n    },\n    up: {\n      repeat: true,\n      bind: \"up\",\n      keyDown() {\n        heroY.update((y) => Math.max(y - moveSpeed, 40));\n      },\n    },\n    down: {\n      repeat: true,\n      bind: \"down\",\n      keyDown() {\n        heroY.update((y) => Math.min(y + moveSpeed, worldHeight - 40));\n      },\n    },\n  });\n\n  tick(({ deltaTime }) => {\n    time.update((t) => t + deltaTime / 1000);\n    const t = time();\n    enemyX.set(980 + Math.cos(t * 0.8) * 240);\n    enemyY.set(680 + Math.sin(t * 0.65) * 170);\n    torchX.set(760 + Math.sin(t * 0.35) * 120);\n    torchY.set(430 + Math.cos(t * 0.42) * 60);\n  });\n\n  const shadowLights = computed(() => [\n    {\n      x: torchX(),\n      y: torchY(),\n      z: 170,\n      radius: 420,\n      intensity: 1.3,\n      shadowWeight: 1.5,\n    },\n  ]);\n\n  const nightLights = computed(() =>\n    shadowLights().map((light, index) => ({\n      x: light.x,\n      y: light.y,\n      radius: light.radius * 0.72,\n      intensity: index === 0 ? 1 : 0.92,\n      flicker: index === 1,\n      flickerSpeed: 14,\n    }))\n  );\n\n  const drawTorch = (graphics) => {\n    graphics.clear();\n    graphics.circle(0, 0, 8);\n    graphics.fill({ color: 0xffcc66, alpha: 1 });\n    graphics.circle(0, 0, 20);\n    graphics.fill({ color: 0xffcc66, alpha: 0.28 });\n  };\n</script>\n"
  },
  {
    "path": "sample/src/spritesheet.ce",
    "content": "\n<Canvas>\n    <Container>\n        @for (item of items) {\n            <Sprite \n                sheet={{\n                    definition: item.definition,\n                    playing: \"default\"\n                }}\n            />\n        }\n    </Container>\n</Canvas>\n\n<script>\nimport { signal } from 'canvasengine';\n\nconst definition =  async () => {\n    await new Promise(resolve => setTimeout(resolve, 1000));\n    return {\n    id: \"explosion\",\n    image: \"./exp.png\",\n    framesWidth: 4,\n    framesHeight: 4,\n    textures: {\n        default: {\n             animations: () => [\n                [ \n                    { time: 0, frameX: 0, frameY: 0 },\n                    { time: 10, frameX: 1, frameY: 0 },\n                    { time: 20, frameX: 2, frameY: 0 },\n                    { time: 30, frameX: 3, frameY: 0 },\n                    { time: 40, frameX: 0, frameY: 1 },\n                    { time: 50, frameX: 1, frameY: 1 },\n                    { time: 60, frameX: 2, frameY: 1 },     \n                    { time: 70, frameX: 3, frameY: 1 },\n                    { time: 80, frameX: 0, frameY: 2 },\n                    { time: 90, frameX: 1, frameY: 2 },\n                    { time: 100, frameX: 2, frameY: 2 },\n                    { time: 110, frameX: 3, frameY: 2 },\n                    { time: 120, frameX: 0, frameY: 3 },\n                    { time: 130, frameX: 1, frameY: 3 },\n                    { time: 140, frameX: 2, frameY: 3 },\n                    { time: 150, frameX: 3, frameY: 3 },\n                ]\n                ]\n            }\n        }\n    }\n}\n\nconst items =  signal([\n    \n])\n\nsetTimeout(() => {\n    items.set([\n        {\n            definition: definition()\n        }\n    ])\n}, 2000)\n</script>\n\n        "
  },
  {
    "path": "sample/src/spritesheet2.ce",
    "content": "\n<Canvas>\n    <Container>\n        <Sprite \n            sheet={{\n                definition: definition(),\n                playing: \"default\"\n            }}\n        />\n    </Container>\n    <DOMContainer y={400}>\n        <DOMSprite \n            sheet={{\n                definition: definition(),\n                playing: \"default\"\n            }}\n            objectFit=\"contain\"\n            width={100}\n            height={100}\n        />\n    </DOMContainer>\n</Canvas>\n\n<style scoped>\n\n</style>\n\n<script>\nimport { signal } from 'canvasengine';\n\nconst definition =  async () => {\n    await new Promise(resolve => setTimeout(resolve, 1000));\n    return {\n        id: \"faceset\",\n        image: \"./faceset.png\",\n        framesWidth: 3,\n        framesHeight: 4,\n        textures: {\n            default: {\n                animations: () => [\n                    [ \n                        { time: 0, frameX: 0, frameY: 0 }\n                    ]\n                ]\n            }\n        }\n    }\n}\n</script>\n\n        "
  },
  {
    "path": "sample/src/test.ce",
    "content": "\n<Canvas>\n    <DOMContainer>  \n      <img src=\"https://pixijs.com/assets/flowerTop.png\" />\n    </DOMContainer>\n</Canvas>\n\n<style scoped>\n  p {\n    font-size: 24px;\n    font-weight: bold;\n    color: red;\n    margin: 10px;\n  }\n</style>\n\n<script>\nimport { signal } from \"canvasengine\";\n\nconst text = {\n  gold: signal(0),\n}\n\nsetInterval(() => {\n  text.gold.set(text.gold() + 1);\n}, 1000);\n</script>"
  },
  {
    "path": "sample/src/tiled.ce",
    "content": "<Canvas>\n    <TiledMap \n        map={map} \n        createLayersPerTilesZ={true} \n        basePath=\"/tiled\" \n            objectLayer={(layer) => <Container x y  controls>\n                <Sprite \n                    sheet={{\n                        definition: definition(),\n                        playing: \"default\"\n                    }}\n                   \n                    hitbox\n                />\n                <Rect width={hitbox.w} height={hitbox.h} color=\"red\" />\n            </Container> } \n    />\n</Canvas>\n\n<script>\n    import { TiledMap } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n    \n    let map = signal(null)\n    const x = signal(0)\n    const y = signal(0)\n    const speed = signal(4)\n    const hitbox = { w: 32, h: 32 }\n    const controls = signal({\n        up: {\n            repeat: true,\n            bind: 'up',\n            keyDown() {\n                y.update((y) => y - speed())\n            }\n        },\n        down: {\n            repeat: true,\n            bind: 'down',\n            keyDown() {\n                y.update((y) => y + speed())\n            }\n        },\n        left: {\n            repeat: true,\n            bind: 'left',\n            keyDown() {\n                x.update((x) => x - speed())\n            }\n        },\n        right: {\n            repeat: true,\n            bind: 'right',\n            keyDown() {\n                x.update((x) => x + speed())\n            }\n        }\n    })\n\n    const definition =   () => {\n        return {\n        id: \"explosion\",\n        image: \"./exp.png\",\n        framesWidth: 4,\n        framesHeight: 4,\n        textures: {\n            default: {\n                animations: () => [\n                    [ \n                        { time: 0, frameX: 0, frameY: 0 },\n                        { time: 10, frameX: 1, frameY: 0 },\n                        { time: 20, frameX: 2, frameY: 0 },\n                        { time: 30, frameX: 3, frameY: 0 },\n                        { time: 40, frameX: 0, frameY: 1 },\n                        { time: 50, frameX: 1, frameY: 1 },\n                        { time: 60, frameX: 2, frameY: 1 },     \n                        { time: 70, frameX: 3, frameY: 1 },\n                        { time: 80, frameX: 0, frameY: 2 },\n                        { time: 90, frameX: 1, frameY: 2 },\n                        { time: 100, frameX: 2, frameY: 2 },\n                        { time: 110, frameX: 3, frameY: 2 },\n                        { time: 120, frameX: 0, frameY: 3 },\n                        { time: 130, frameX: 1, frameY: 3 },\n                        { time: 140, frameX: 2, frameY: 3 },\n                        { time: 150, frameX: 3, frameY: 3 },\n                    ]\n                    ]\n                }\n            }\n        }\n    }\n\n    \n    fetch('/tiled/simplemap.tmx')\n        .then((res) => res.text())\n        .then((text) => {\n            map.set(text)\n        })\n</script>\n"
  },
  {
    "path": "sample/src/viewport.ce",
    "content": "<Canvas>\n  <Viewport worldWidth={2048} worldHeight={2048} clamp={clamp}>\n    <Sprite image=\"back.png\" />\n    @for (sprite of sprites) {\n      <Container  x={@sprite.x} y={@sprite.@y} viewportFollow={true}>\n        <Text text={@sprite.x} />\n        <Sprite image={@sprite.@image} controls={@sprite.controls}   />\n      </Container>\n    }\n</Viewport>\n<Container>\n  <MenuComponent />\n</Container>\n</Canvas>\n\n  <script>\n    import { signal, animatedSignal, mount, effect, animatedSequence } from \"canvasengine\";\n    import MenuComponent from './focus-navigation-dom.ce'\n\n    const speed = signal(10);\n    const acceleration = signal(0.1);\n    const radius = signal(100);\n\n    const drag = {\n      direction: 'all',\n      keyToPress: ['space'],\n      pressDrag: false\n    }\n\n   const viewportFollow = signal({\n    speed,\n    //acceleration,\n    //radius,\n   });\n   const clamp = {direction: 'all'};\n   const x = signal(0);\n   const y = signal(0);\n   const controls = signal({\n      right: {\n        repeat: true,\n        bind: \"right\",\n        keyDown() {\n          x.update(x => x + 20)\n        },\n      },\n      left: {\n        repeat: true,\n        bind: \"left\",\n        keyDown() {\n          x.update(x => x - 20)\n        },\n      },\n      up: {\n        repeat: true,\n        bind: \"up\",\n        keyDown() {\n          y.update(y => y - 20)\n        },\n      },\n      down: {\n        repeat: true,\n        bind: \"down\",\n        keyDown() {\n          y.update(y => y + 20)\n        },\n      },\n    });\n\n    const snap = signal(50);\n    \n\n    const click = () => {\n      viewportFollow.set({\n        speed: 0.1,\n        acceleration: 0.1,\n        radius: 100\n      })\n      console.log('viewport follow', viewportFollow())\n    }\n  \n\n    const dragStart = () => {\n      console.log(\"drag start\")\n    }\n\n    const sprites = signal([\n      // {\n      //   image: \"https://pixijs.com/assets/flowerTop.png\",\n      //   x: signal(0),\n      //   y: 400,\n      //   controls: signal(false),\n      //   viewportFollow: false,  \n      // },\n      // {\n      //   image: \"https://pixijs.com/assets/flowerTop.png\",\n      //   x: signal(0),\n      //   y: 500,\n      //   controls: signal(false),\n      //   viewportFollow: false,  \n      // },\n      {\n        image: \"https://pixijs.com/assets/flowerTop.png\",\n        x,\n        y,\n        controls,\n        viewportFollow,  \n        drag,\n      },\n    ]);\n  </script>"
  },
  {
    "path": "sample/src/weather.ce",
    "content": "<Canvas backgroundColor=\"#000\">\n   \n    <Viewport worldWidth={2048} worldHeight={2048} clamp={clamp} sortableChildren={true}>\n        <!-- <NightAmbiant lightSpots={lightSpots} darkness={intensity}  darkColor=\"#0a1020\"\n        fogColor=\"#0a1020\" /> -->\n\n        \n\n          <Sprite image=\"back.png\" />  \n        \n        <Graphics\n            x={playerX}\n            y={playerY}\n            zIndex={1}\n            draw={(g) => {\n                g.clear();\n                g.beginFill(0xffcc00);\n                g.drawCircle(0, 0, 20);\n                g.endFill();\n            }}\n            controls\n            viewportFollow={true}\n        />\n\n        <Weather\n            effect={cloudPreset.effect}\n            speed={cloudPreset.speed}\n            density={cloudPreset.density}\n            height={cloudPreset.height}\n            scale={cloudPreset.scale}\n            sunIntensity={cloudPreset.sunIntensity}\n            sunAngle={cloudPreset.sunAngle}\n            raySpread={cloudPreset.raySpread}\n            rayTwinkle={cloudPreset.rayTwinkle}\n            rayTwinkleSpeed={cloudPreset.rayTwinkleSpeed}\n            zIndex={1000}\n        />\n        \n        \n        \n        </Viewport>\n\n       \n</Canvas>\n\n<script>\n    import { NightAmbiant, Weather, CLOUD_PRESETS } from '@canvasengine/presets'\n    import { signal } from 'canvasengine'\n\n    const clamp = {direction: 'all'};\n\n    const intensity = signal(0.5)\n    const cloudPreset = CLOUD_PRESETS.dramaticCrepuscularRays\n\n    // setInterval(() => {\n    //     intensity.update(n => n + 0.1)\n    // }, 1000)\n\n    const playerX = signal(400);\n    const playerY = signal(300);\n    const staticLights = [\n        { x: 280, y: 260, radius: 180, intensity: 0.95, flicker: true, flickerSpeed: 13 },\n        { x: 720, y: 540, radius: 130, intensity: 0.8, pulse: true, pulseSpeed: 1.5, phase: 1.4 },\n        { x: 1450, y: 360, radius: 160, intensity: 1.0, flicker: true, flickerSpeed: 9, phase: 0.6 },\n        { x: 1650, y: 1020, radius: 220, intensity: 0.7, pulse: true, pulseSpeed: 0.9, phase: 2.1 },\n    ];\n    const lightSpots = () => [\n        {\n            x: playerX,\n            y: playerY,\n            radius: 170,\n            intensity: 1.0,\n            flicker: true,\n            flickerSpeed: 15,\n        },\n        ...staticLights,\n    ];\n\n    const controls = signal({\n        right: {\n            repeat: true,\n            bind: \"right\",\n            keyDown() {\n                playerX.update((x) => Math.min(x + 10, 2028));\n            },\n        },\n        left: {\n            repeat: true,\n            bind: \"left\",\n            keyDown() {\n                playerX.update((x) => Math.max(x - 10, 20));\n            },\n        },\n        up: {\n            repeat: true,\n            bind: \"up\",\n            keyDown() {\n                playerY.update((y) => Math.max(y - 10, 20));\n            },\n        },\n        down: {\n            repeat: true,\n            bind: \"down\",\n            keyDown() {\n                playerY.update((y) => Math.min(y + 10, 2028));\n            },\n        },\n    })\n</script>\n"
  },
  {
    "path": "sample/tests/README.md",
    "content": "# Testing Examples\n\nThis directory contains example tests demonstrating how to use the `@canvasengine/testing` package.\n\n## Running Tests\n\nTo run the tests, use:\n\n```bash\nnpm test\n```\n\nOr to run once:\n\n```bash\nnpm run test:run\n```\n\n## Example Test File\n\nThe `example.spec.ts` file demonstrates:\n\n- Creating mock elements with `createMockElement`\n- Using PixiJS mocks directly (`MockContainer`, `MockSprite`, etc.)\n- Spying on element methods and properties with `spyOnElement`\n- Testing real-world scenarios like parent-child relationships\n- Testing event handling\n- Testing element properties and state\n\n## Key Concepts\n\n### Creating Mock Elements\n\n```typescript\nimport { createMockElement } from '@canvasengine/testing';\n\nconst element = createMockElement('Container', { x: 100, y: 50 });\n```\n\n### Using PixiJS Mocks\n\n```typescript\nimport { MockContainer, MockSprite } from '@canvasengine/testing';\n\nconst container = new MockContainer();\nconst sprite = new MockSprite();\ncontainer.addChild(sprite);\n```\n\n### Spying on Elements\n\n```typescript\nimport { createMockElement, spyOnElement } from '@canvasengine/testing';\n\nconst element = createMockElement('Container');\nconst spy = spyOnElement(element, 'addChild');\nelement.componentInstance.addChild(new MockSprite());\nexpect(spy).toHaveBeenCalled();\n```\n\n## More Information\n\nFor complete documentation, see the [Testing Package Documentation](/api/testing).\n"
  },
  {
    "path": "sample/tests/example.spec.ts",
    "content": "import { describe, test, expect, vi, beforeEach } from 'vitest';\nimport {\n  createMockElement,\n  createMockComponentInstance,\n  spyOnElement,\n  spyOnElementMultiple,\n  MockContainer,\n  MockSprite,\n  MockText,\n} from '@canvasengine/testing';\n\n/**\n * Example test file demonstrating how to use @canvasengine/testing\n * \n * This file shows various ways to use the testing package to test\n * CanvasEngine components without requiring a full PixiJS environment.\n */\n\ndescribe('Testing Package Examples', () => {\n  beforeEach(() => {\n    vi.clearAllMocks();\n  });\n\n  describe('Creating Mock Elements', () => {\n    test('should create a basic mock element', () => {\n      const element = createMockElement('Container', {\n        x: 100,\n        y: 50,\n        width: 200,\n        height: 150,\n      });\n\n      expect(element.tag).toBe('Container');\n      expect(element.props.x).toBe(100);\n      expect(element.props.y).toBe(50);\n      expect(element.componentInstance.x).toBe(100);\n      expect(element.componentInstance.y).toBe(50);\n    });\n\n    test('should create element with custom componentInstance', () => {\n      const customSprite = new MockSprite();\n      customSprite.x = 200;\n      customSprite.y = 300;\n\n      const element = createMockElement('Sprite', { image: 'hero.png' }, customSprite);\n\n      expect(element.componentInstance).toBe(customSprite);\n      expect(element.componentInstance.x).toBe(200);\n      expect(element.componentInstance.y).toBe(300);\n    });\n\n    test('should create element with all required properties', () => {\n      const element = createMockElement('Container');\n\n      expect(element).toHaveProperty('tag');\n      expect(element).toHaveProperty('props');\n      expect(element).toHaveProperty('componentInstance');\n      expect(element).toHaveProperty('propSubscriptions');\n      expect(element).toHaveProperty('effectSubscriptions');\n      expect(element).toHaveProperty('directives');\n      expect(element).toHaveProperty('destroy');\n      expect(element).toHaveProperty('allElements');\n      expect(element).toHaveProperty('isFrozen');\n    });\n  });\n\n  describe('Using PixiJS Mocks', () => {\n    test('should create and manipulate MockContainer', () => {\n      const container = new MockContainer();\n      container.x = 100;\n      container.y = 50;\n      container.width = 200;\n      container.height = 150;\n\n      expect(container.x).toBe(100);\n      expect(container.y).toBe(50);\n      expect(container.width).toBe(200);\n      expect(container.height).toBe(150);\n    });\n\n    test('should add and remove children from MockContainer', () => {\n      const parent = new MockContainer();\n      const child1 = new MockSprite();\n      const child2 = new MockText();\n\n      parent.addChild(child1);\n      parent.addChild(child2);\n\n      expect(parent.children).toHaveLength(2);\n      expect(parent.children[0]).toBe(child1);\n      expect(parent.children[1]).toBe(child2);\n      expect(child1.parent).toBe(parent);\n      expect(child2.parent).toBe(parent);\n\n      parent.removeChild(child1);\n      expect(parent.children).toHaveLength(1);\n      expect(parent.children[0]).toBe(child2);\n      expect(child1.parent).toBeNull();\n    });\n\n    test('should handle events on MockContainer', () => {\n      const container = new MockContainer();\n      const clickHandler = vi.fn();\n\n      container.on('click', clickHandler);\n      container.emit('click', { x: 100, y: 100 });\n\n      expect(clickHandler).toHaveBeenCalledWith({ x: 100, y: 100 });\n    });\n  });\n\n  describe('Spying on Elements', () => {\n    test('should spy on componentInstance methods', () => {\n      const element = createMockElement('Container');\n      const addChildSpy = spyOnElement(element, 'addChild');\n\n      const child = new MockSprite();\n      element.componentInstance.addChild(child);\n\n      expect(addChildSpy).toHaveBeenCalledWith(child);\n      expect(addChildSpy).toHaveBeenCalledTimes(1);\n    });\n\n    test('should spy on multiple methods at once', () => {\n      const element = createMockElement('Container');\n      const spies = spyOnElementMultiple(element, ['addChild', 'removeChild', 'destroy']);\n\n      const child = new MockSprite();\n      element.componentInstance.addChild(child);\n      element.componentInstance.removeChild(child);\n      element.componentInstance.destroy();\n\n      expect(spies.addChild).toHaveBeenCalled();\n      expect(spies.removeChild).toHaveBeenCalled();\n      expect(spies.destroy).toHaveBeenCalled();\n    });\n\n    test('should verify method calls with spies', () => {\n      const element = createMockElement('Container');\n      const addChildSpy = spyOnElement(element, 'addChild');\n\n      const child1 = new MockSprite();\n      const child2 = new MockText();\n\n      element.componentInstance.addChild(child1);\n      element.componentInstance.addChild(child2);\n\n      expect(addChildSpy).toHaveBeenCalledTimes(2);\n      expect(addChildSpy).toHaveBeenNthCalledWith(1, child1);\n      expect(addChildSpy).toHaveBeenNthCalledWith(2, child2);\n    });\n  });\n\n  describe('Creating Mock Component Instances', () => {\n    test('should create mock instance for Container', () => {\n      const instance = createMockComponentInstance('Container');\n      expect(instance).toBeInstanceOf(MockContainer);\n    });\n\n    test('should create mock instance for Sprite', () => {\n      const instance = createMockComponentInstance('Sprite');\n      expect(instance).toBeInstanceOf(MockSprite);\n    });\n\n    test('should create mock instance for Text', () => {\n      const instance = createMockComponentInstance('Text');\n      expect(instance).toBeInstanceOf(MockText);\n    });\n\n    test('should default to Container for unknown types', () => {\n      const instance = createMockComponentInstance('UnknownType');\n      expect(instance).toBeInstanceOf(MockContainer);\n    });\n  });\n\n  describe('Real-world Testing Scenarios', () => {\n    test('should test component position updates', () => {\n      const element = createMockElement('Sprite', { x: 0, y: 0 });\n\n      // Simulate position update\n      element.componentInstance.x = 100;\n      element.componentInstance.y = 50;\n\n      expect(element.componentInstance.x).toBe(100);\n      expect(element.componentInstance.y).toBe(50);\n    });\n\n    test('should test parent-child relationships', () => {\n      const parent = createMockElement('Container');\n      const child = createMockElement('Sprite');\n\n      const addChildSpy = spyOnElement(parent, 'addChild');\n      parent.componentInstance.addChild(child.componentInstance);\n\n      expect(addChildSpy).toHaveBeenCalledWith(child.componentInstance);\n      expect(parent.componentInstance.children).toContain(child.componentInstance);\n      expect(child.componentInstance.parent).toBe(parent.componentInstance);\n    });\n\n    test('should test event handling', () => {\n      const element = createMockElement('Sprite');\n      const clickHandler = vi.fn();\n      const mouseOverHandler = vi.fn();\n\n      element.componentInstance.on('click', clickHandler);\n      element.componentInstance.on('mouseover', mouseOverHandler);\n\n      element.componentInstance.emit('click', { x: 100, y: 100 });\n      element.componentInstance.emit('mouseover', { x: 50, y: 50 });\n\n      expect(clickHandler).toHaveBeenCalledWith({ x: 100, y: 100 });\n      expect(mouseOverHandler).toHaveBeenCalledWith({ x: 50, y: 50 });\n    });\n\n    test('should test element destruction', () => {\n      const element = createMockElement('Container');\n      const child1 = createMockElement('Sprite');\n      const child2 = createMockElement('Text');\n\n      element.componentInstance.addChild(child1.componentInstance);\n      element.componentInstance.addChild(child2.componentInstance);\n\n      const destroySpy = spyOnElement(element, 'destroy');\n      element.componentInstance.destroy();\n\n      expect(destroySpy).toHaveBeenCalled();\n      expect(element.componentInstance.destroyed).toBe(true);\n      expect(element.componentInstance.children).toHaveLength(0);\n    });\n\n    test('should test multiple elements interaction', () => {\n      const container = createMockElement('Container');\n      const sprite1 = createMockElement('Sprite', { x: 10, y: 10 });\n      const sprite2 = createMockElement('Sprite', { x: 20, y: 20 });\n\n      container.componentInstance.addChild(sprite1.componentInstance);\n      container.componentInstance.addChild(sprite2.componentInstance);\n\n      expect(container.componentInstance.children).toHaveLength(2);\n      expect(container.componentInstance.getChildAt(0)).toBe(sprite1.componentInstance);\n      expect(container.componentInstance.getChildAt(1)).toBe(sprite2.componentInstance);\n    });\n  });\n\n  describe('Element Properties and State', () => {\n    test('should access and modify element properties', () => {\n      const element = createMockElement('Container', {\n        x: 100,\n        y: 50,\n        alpha: 0.5,\n        visible: true,\n      });\n\n      expect(element.props.x).toBe(100);\n      expect(element.props.y).toBe(50);\n      expect(element.componentInstance.alpha).toBe(0.5);\n      expect(element.componentInstance.visible).toBe(true);\n\n      // Modify properties\n      element.componentInstance.alpha = 0.8;\n      element.componentInstance.visible = false;\n\n      expect(element.componentInstance.alpha).toBe(0.8);\n      expect(element.componentInstance.visible).toBe(false);\n    });\n\n    test('should test element freezing state', () => {\n      const element = createMockElement('Container');\n      \n      expect(element.isFrozen).toBe(false);\n      \n      element.isFrozen = true;\n      expect(element.isFrozen).toBe(true);\n    });\n  });\n});\n"
  },
  {
    "path": "sample/tsconfig.json",
    "content": "{\n  \"extends\": \"../tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"ES2020\",\n    \"target\": \"ES2020\",\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\n    \"src/**/*\",\n    \"vite.config.ts\"\n  ]\n} "
  },
  {
    "path": "sample/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport canvasengine, { shaderLoader } from '../packages/compiler'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = path.dirname(__filename)\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [canvasengine(), shaderLoader()],\n  resolve: {\n    alias: {\n      canvasengine: path.resolve(__dirname, '../packages/core/src/index.ts'),\n      '@canvasengine/presets': path.resolve(__dirname, '../packages/presets/src/index.ts'),\n      path: 'path-browserify',\n      '@canvasengine/testing': path.resolve(__dirname, '../packages/testing/src/index.ts'),\n    }\n  }\n});\n"
  },
  {
    "path": "sample/vitest.config.ts",
    "content": "/// <reference types=\"vitest\" />\nimport { defineConfig } from 'vite';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport default defineConfig({\n  resolve: {\n    alias: {\n      'canvasengine': path.resolve(__dirname, '../packages/core/src'),\n      '@canvasengine/testing': path.resolve(__dirname, '../packages/testing/src'),\n      '@canvasengine/presets': path.resolve(__dirname, '../packages/presets/src'),\n    },\n  },\n  test: {\n    environment: 'jsdom',\n    globals: true,\n    include: ['tests/**/*.spec.ts'],\n  },\n});\n"
  },
  {
    "path": "skills-lock.json",
    "content": "{\n  \"version\": 1,\n  \"skills\": {\n    \"pixijs\": {\n      \"source\": \"pixijs/pixijs-skills\",\n      \"sourceType\": \"github\",\n      \"skillPath\": \"skills/pixijs/SKILL.md\",\n      \"computedHash\": \"880175c74d347ba7e40e8434544f4ae8c1d006ed68296cec6ba355da0d532508\"\n    }\n  }\n}\n"
  },
  {
    "path": "starter/.gitignore",
    "content": "node_modules\ndist"
  },
  {
    "path": "starter/components/app.ce",
    "content": "<Canvas \n    backgroundColor=\"#fff\" \n    width=\"100%\" \n    height=\"100%\"\n    >\n    <Container\n        width=\"100%\" \n        height=\"100%\" \n        justifyContent=\"center\"\n        alignItems=\"center\">\n        <HelloWorld text=\"CanvasEngine\" color=\"black\" />\n    </Container>\n</Canvas>\n\n<script>\n    import HelloWorld from \"./hello.ce\";\n</script>"
  },
  {
    "path": "starter/components/hello.ce",
    "content": "<Container flexDirection=\"row\" width={500}>\n    <Sprite \n        image={imgUrl} \n        anchor={0.5}\n        rotation\n        scale\n        @pointerenter={onEnter} \n        @pointerleave={onLeave}\n    />\n    <Text text size={70} fontFamily=\"Helvetica\" x={50} y={40} />\n</Container>\n\n<script>\nimport imgUrl from '../assets/logo.png'\nimport { signal, tick, animatedSignal, Easing } from \"canvasengine\";\n\nconst { text } = defineProps();\nconst rotation = signal(0);\nconst scale = animatedSignal(1, {\n    duration: 300,\n    ease: Easing.easeInOut,\n});\n\ntick(() => {\n    rotation.update(rotation => rotation + 0.01);\n});\n\nconst onEnter = () => {\n    scale.set(1.5);\n};\n\nconst onLeave = () => {\n    scale.set(1);\n};\n</script>"
  },
  {
    "path": "starter/index.html",
    "content": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"UTF-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Canvas Engine</title>\n    <style>\n      body, html, #root {\n        margin: 0;\n        padding: 0;\n        height: 100vh;\n        width: 100vw;\n        overflow: hidden;\n      }\n    </style>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "starter/main.ts",
    "content": "import App from './components/app.ce'\nimport { bootstrapCanvas } from 'canvasengine';\n\nbootstrapCanvas(document.getElementById(\"root\"), App).then(() => {\n    console.log(\"CanvasEngine initialized\");\n});\n"
  },
  {
    "path": "starter/package.json",
    "content": "{\n  \"name\": \"canvasengine-starter\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\"\n  },\n  \"keywords\": [],\n  \"author\": \"\",\n  \"license\": \"MIT\",\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"canvasengine\": \"2.0.0-beta.58\",\n    \"pixi.js\": \"^8.18.1\"\n  },\n  \"devDependencies\": {\n    \"vite\": \"^8.0.10\",\n    \"@canvasengine/compiler\": \"2.0.0-beta.58\"\n  }\n}\n"
  },
  {
    "path": "starter/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"esnext\",\n    \"outDir\": \"dist\",\n    \"strict\": true,\n    \"sourceMap\": true,\n    \"strictNullChecks\": true,\n    \"strictPropertyInitialization\": false,\n    \"moduleResolution\": \"node\",\n    \"esModuleInterop\": true,\n    \"removeComments\": false,\n    \"noUnusedParameters\": false,\n    \"noUnusedLocals\": false,\n    \"noImplicitThis\": false,\n    \"noImplicitAny\": false,\n    \"noImplicitReturns\": false,\n    \"declaration\": false,\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true,\n    \"resolveJsonModule\": true\n  },\n  \"include\": [\n    \".\",\n    \"index.d.ts\",\n    \"node_modules/canvasengine/index.d.ts\"\n  ]\n}"
  },
  {
    "path": "starter/vite.config.ts",
    "content": "import { defineConfig } from 'vite'\nimport canvasengine from '@canvasengine/compiler'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  plugins: [canvasengine()]\n});\n"
  },
  {
    "path": "tests/components/canvas.spec.ts",
    "content": "import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport { bootstrapCanvas, Canvas, ComponentInstance, Element } from 'canvasengine';\n\ndescribe('Canvas', () => {\n  let rootElement: HTMLElement;\n  let canvasElement: Element<ComponentInstance>\n\n  beforeEach(async () => {\n    const { canvasElement: value } = await bootstrapCanvas(document.getElementById('root'), Canvas)\n    rootElement = document.getElementById('root')\n    canvasElement = value\n  });\n\n  afterEach(() => {\n    rootElement.innerHTML = ''\n    vi.clearAllMocks();\n  });\n\n  it('should create a canvas element and append it to the root element', async () => {\n    expect(rootElement.querySelector('canvas')).not.toBeNull();\n  });\n\n  it('should return correct canvas size when calling canvasSize', async () => {\n    const context = canvasElement.props.context;\n    const { width, height } = context.canvasSize();\n\n    expect(typeof width).toBe('number');\n    expect(typeof height).toBe('number');\n    expect(width).toBeGreaterThan(0);\n    expect(height).toBeGreaterThan(0);\n  });\n});\n"
  },
  {
    "path": "tests/components/component.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { bootstrapCanvas, Canvas, createComponent, h, registerComponent, signal } from 'canvasengine'\n\ndescribe('Component', () => {\n    test('bootstrap application', async () => {\n        function MyComponent() {    \n            return h(Canvas, {\n                tickStart: false\n            })\n        }\n        const value = await bootstrapCanvas(document.getElementById('root'), MyComponent)\n        expect(value).toBeDefined()\n    })\n})\n\ndescribe('createComponent', () => {\n    class TestComponent {\n        onInit(props) {}\n        onUpdate(props) {}\n        onMount(element, index) {}\n    }\n    let element;\n    let dynamicProp;\n    let testComponent;\n\n    beforeEach(() => {\n        testComponent = new TestComponent()\n        vi.spyOn(TestComponent.prototype, 'onInit')\n        vi.spyOn(TestComponent.prototype, 'onUpdate')\n        vi.spyOn(TestComponent.prototype, 'onMount')\n        registerComponent('TestComponent', TestComponent)\n        dynamicProp = signal('initial value')\n        element = createComponent('TestComponent', {\n            staticProp: 'static value',\n            dynamicProp: dynamicProp\n        })\n    })\n\n    test('returns an element with correct base properties', () => {\n        expect(element).toHaveProperty('tag', 'TestComponent')\n        expect(element).toHaveProperty('props')\n        expect(element).toHaveProperty('componentInstance')\n        expect(element.componentInstance).toBeInstanceOf(TestComponent)\n    })\n\n    test('handles static properties correctly', () => {\n        expect(element.props).toHaveProperty('staticProp', 'static value')\n    })\n\n    test('handles dynamic properties correctly', () => {\n        expect(element.props).toHaveProperty('dynamicProp', 'initial value')\n        expect(element.propSubscriptions).toHaveLength(1)\n    })\n\n    test('updates dynamic properties', () => {\n        dynamicProp.set('new value')\n        expect(element.props.dynamicProp).toBe('new value')\n    })\n\n    test('initializes other properties correctly', () => {\n        expect(element).toHaveProperty('effectSubscriptions')\n        expect(element).toHaveProperty('effectMounts')\n        expect(element).toHaveProperty('effectUnmounts')\n        expect(element).toHaveProperty('parent', null)\n        expect(element).toHaveProperty('directives')\n    })\n\n    test('calls onInit with correct props', () => {\n        expect(TestComponent.prototype.onInit).toHaveBeenCalledWith({\n            staticProp: 'static value',\n            dynamicProp: 'initial value'\n        })\n    })\n\n    test('calls onUpdate when dynamic prop changes', () => {\n        dynamicProp.set('new value')\n        expect(TestComponent.prototype.onUpdate).toHaveBeenCalledWith({\n            dynamicProp: 'new value'\n        })\n    })\n\n    test('calls onMount with correct parameters', () => {\n        const parentElement = createComponent('TestComponent', {})\n        element.parent = parentElement\n        element.componentInstance.onMount(element, 0)\n        expect(TestComponent.prototype.onMount).toHaveBeenCalledWith(element, 0)\n        expect(TestComponent.prototype.onUpdate).toHaveBeenCalled()\n    })\n})"
  },
  {
    "path": "tests/components/container.spec.ts",
    "content": "import { describe, it, expect, test } from 'vitest';\nimport { cond, Container, h, signal } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\nimport { CanvasContainer } from '../../packages/core/src/components/Container';\n\ndescribe('Container', () => {\n    const props = {\n        x: 10,\n        y: 15,\n        rotation: 180,\n        alpha: 0.1,\n        visible: true,\n        zIndex: 1,\n        roundPixels: true,\n        angle: 180,\n    }\n\n    for (const [prop, testValue] of Object.entries(props)) {\n        describe(`${prop} property`, () => {\n            test(`should set ${prop} property`, async () => {\n                const value = signal(testValue)\n                const container = await TestBed.createComponent(Container, { [prop]: value })\n                expect(container.componentInstance[prop]).toBe(value())\n            });\n\n            test(`${prop} property updated`, async () => {\n                const value = signal(testValue)\n                const container = await TestBed.createComponent(Container, { [prop]: value })\n\n                if (typeof testValue === 'number') {\n                    value.set(testValue + 1)\n                } else if (typeof testValue === 'boolean') {\n                    value.set(!testValue)\n                }\n\n                expect(container.componentInstance[prop]).toBe(value())\n            });\n        });\n    }\n\n    describe('attach', () => {\n\n        const testChild = async (Comp: any) => {\n            const container = await TestBed.createComponent(Container, { attach: Comp })\n            const children = container.componentInstance.children\n            expect(children.length).toBe(1)\n            expect(children[0]).instanceOf(CanvasContainer)\n        }\n\n        test('should attach child', async () => {\n            await testChild(h(Container))\n        })\n\n        test('should attach child width signal', async () => {\n            await testChild(signal(h(Container)))\n        })\n        \n        test('Change child', async () => {\n            const attach = signal(h(Container, { x: 100 }))\n            const Comp2 = h(Container, { x: 200 })\n            const container = await TestBed.createComponent(Container, { attach })\n            expect((container.componentInstance.children[0] as any).x).toBe(100)\n            attach.set(Comp2)\n            expect((container.componentInstance.children[0] as any).x).toBe(200)\n        })\n    })\n})"
  },
  {
    "path": "tests/components/displayobject.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { DisplayObject } from '../../packages/core/src/components/DisplayObject'\n\n// Mock PixiJS Container for testing\nclass MockContainer {\n    x = 0;\n    y = 0;\n    width = 0;\n    height = 0;\n    alpha = 1;\n    visible = true;\n    rotation = 0;\n    scale = { x: 1, y: 1 };\n    anchor = { x: 0, y: 0 };\n    pivot = { x: 0, y: 0 };\n    skew = { x: 0, y: 0 };\n    tint = 0xffffff;\n    blendMode = 0;\n    filters = [];\n    mask = null;\n    parent = null;\n    children = [];\n    eventMode = 'auto';\n    destroyed = false;\n    #eventListeners: Map<string, Function[]> = new Map();\n    \n    addChild() {}\n    addChildAt() {}\n    destroy() {\n        this.destroyed = true;\n        this.#eventListeners.clear();\n    }\n    \n    on(event: string, handler: Function) {\n        if (!this.#eventListeners.has(event)) {\n            this.#eventListeners.set(event, []);\n        }\n        this.#eventListeners.get(event)!.push(handler);\n    }\n    \n    off(event: string, handler?: Function) {\n        if (!this.#eventListeners.has(event)) return;\n        if (handler) {\n            const handlers = this.#eventListeners.get(event)!;\n            const index = handlers.indexOf(handler);\n            if (index > -1) {\n                handlers.splice(index, 1);\n            }\n        } else {\n            this.#eventListeners.delete(event);\n        }\n    }\n    \n    emit(event: string, data?: any) {\n        if (this.#eventListeners.has(event)) {\n            this.#eventListeners.get(event)!.forEach(handler => handler(data));\n        }\n    }\n}\n\ndescribe('DisplayObject Component', () => {\n    let TestDisplayObject;\n    let mockContext;\n    let mockTick;\n\n    beforeEach(() => {\n        mockTick = signal({ deltaRatio: 1 })\n        mockContext = {\n            tick: mockTick,\n            app: () => ({ renderer: {} }),\n            scheduler: {\n                tick: { value: { deltaRatio: 1 } }\n            }\n        }\n        \n        // Create a test class that extends DisplayObject\n        TestDisplayObject = DisplayObject(MockContainer)\n    })\n\n    test('creates display object with basic properties', () => {\n        const instance = new TestDisplayObject()\n        \n        expect(instance).toBeDefined()\n        expect(instance.isFlex).toBe(false)\n        expect(instance.isMounted).toBe(false)\n        expect(instance.disableLayout).toBe(false)\n    })\n\n    test('handles initialization with props', () => {\n        const instance = new TestDisplayObject()\n        const props = {\n            id: 'test-object',\n            x: 100,\n            y: 50,\n            width: 200,\n            height: 150\n        }\n        \n        instance.onInit(props)\n        \n        expect(instance._id).toBe('test-object')\n    })\n\n    test('handles flex layout properties', () => {\n        const instance = new TestDisplayObject()\n        const props = {\n            display: 'flex',\n            justifyContent: 'center',\n            alignItems: 'center'\n        }\n        \n        instance.onInit(props)\n        \n        expect(instance.isFlex).toBe(true)\n        expect(instance.layout).toBeDefined()\n    })\n\n    test('handles percentage width and height', () => {\n        const instance = new TestDisplayObject()\n        const props = {\n            width: '50%',\n            height: '75%'\n        }\n        \n        instance.onInit(props)\n        \n        expect(instance.isFlex).toBe(true)\n    })\n\n    test('handles event listeners', () => {\n        const instance = new TestDisplayObject()\n        const onClick = vi.fn()\n        const onMouseOver = vi.fn()\n        \n        const props = {\n            x: 100,\n            y: 50\n        }\n        \n        instance.onInit(props)\n        \n        // Basic properties should be handled\n        expect(instance).toBeDefined()\n        expect(onClick).toBeDefined()\n        expect(onMouseOver).toBeDefined()\n    })\n\n    test('handles lifecycle hooks', () => {\n        const instance = new TestDisplayObject()\n        const onBeforeDestroy = vi.fn()\n        const onAfterMount = vi.fn()\n        \n        const props = {\n            onBeforeDestroy: onBeforeDestroy,\n            onAfterMount: onAfterMount\n        }\n        \n        instance.onInit(props)\n        \n        expect(instance.onBeforeDestroy).toBe(onBeforeDestroy)\n        expect(instance.onAfterMount).toBe(onAfterMount)\n    })\n\n    test('handles position updates', () => {\n        const instance = new TestDisplayObject()\n        instance.displayWidth = signal(100)\n        instance.displayHeight = signal(50)\n        \n        instance.setX(200)\n        instance.setY(150)\n        \n        expect(instance.x).toBe(200)\n        expect(instance.y).toBe(150)\n    })\n\n    test('handles dimension updates', () => {\n        const instance = new TestDisplayObject()\n        \n        instance.setWidth(300)\n        instance.setHeight(200)\n        \n        expect(instance.displayWidth()).toBe(300)\n        expect(instance.displayHeight()).toBe(200)\n    })\n\n    test('handles flex properties', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setFlexGrow(2)\n        instance.setFlexShrink(1)\n        instance.setFlexBasis('auto')\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setFlexGrow).toBe('function')\n        expect(typeof instance.setFlexShrink).toBe('function')\n        expect(typeof instance.setFlexBasis).toBe('function')\n    })\n\n    test('handles margin and padding', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setMargin([10, 20])\n        instance.setPadding([5, 15])\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setMargin).toBe('function')\n        expect(typeof instance.setPadding).toBe('function')\n    })\n\n    test('handles margin and padding with 4 values', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setMargin([10, 20, 30, 40])\n        instance.setPadding([5, 15, 25, 35])\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setMargin).toBe('function')\n        expect(typeof instance.setPadding).toBe('function')\n    })\n\n    test('handles constraints', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setMinWidth(100)\n        instance.setMaxWidth(500)\n        instance.setMinHeight(50)\n        instance.setMaxHeight(300)\n        instance.setAspectRatio(16/9)\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setMinWidth).toBe('function')\n        expect(typeof instance.setMaxWidth).toBe('function')\n        expect(typeof instance.setMinHeight).toBe('function')\n        expect(typeof instance.setMaxHeight).toBe('function')\n        expect(typeof instance.setAspectRatio).toBe('function')\n    })\n\n    test('handles position insets', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setTop(10)\n        instance.setLeft(20)\n        instance.setRight(30)\n        instance.setBottom(40)\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setTop).toBe('function')\n        expect(typeof instance.setLeft).toBe('function')\n        expect(typeof instance.setRight).toBe('function')\n        expect(typeof instance.setBottom).toBe('function')\n    })\n\n    test('handles object fit and position', () => {\n        const instance = new TestDisplayObject()\n        instance.layout = {}\n        \n        instance.setObjectFit('cover')\n        instance.setObjectPosition('center')\n        instance.setTransformOrigin('50% 50%')\n        \n        expect(instance.layout).toBeDefined()\n        expect(typeof instance.setObjectFit).toBe('function')\n        expect(typeof instance.setObjectPosition).toBe('function')\n        expect(typeof instance.setTransformOrigin).toBe('function')\n    })\n\n    test('handles delta ratio access', () => {\n        const instance = new TestDisplayObject()\n        // Set up the canvas context properly by calling onMount\n        instance.onMount({ \n            parent: null, \n            props: { context: mockContext } \n        })\n        \n        const deltaRatio = instance.deltaRatio\n        expect(deltaRatio).toBeDefined()\n    })\n\n    test('handles parent flex detection', () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = true\n        \n        instance.parent = { isFlex: true }\n        \n        expect(instance.parentIsFlex).toBe(true)\n    })\n\n    test('getWidth returns static width when not using percentages', () => {\n        const instance = new TestDisplayObject()\n        const props = { width: 250, height: 150, context: mockContext }\n        instance.onInit(props)\n        instance.width = 250\n        instance.setWidth(250)\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getWidth()).toBe(250)\n    })\n\n    test('getHeight returns static height when not using percentages', () => {\n        const instance = new TestDisplayObject()\n        const props = { width: 250, height: 150, context: mockContext }\n        instance.onInit(props)\n        instance.height = 150\n        instance.setHeight(150)\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getHeight()).toBe(150)\n    })\n\n    test('getWidth returns displayWidth when native width is 0', () => {\n        const instance = new TestDisplayObject()\n        const props = { width: 300, context: mockContext }\n        instance.onInit(props)\n        instance.width = 0\n        instance.setWidth(300)\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getWidth()).toBe(300)\n    })\n\n    test('getHeight returns displayHeight when native height is 0', () => {\n        const instance = new TestDisplayObject()\n        const props = { height: 200, context: mockContext }\n        instance.onInit(props)\n        instance.height = 0\n        instance.setHeight(200)\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getHeight()).toBe(200)\n    })\n\n    test('getWidth returns 0 when no width is set', () => {\n        const instance = new TestDisplayObject()\n        const props = { context: mockContext }\n        instance.onInit(props)\n        instance.width = 0\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getWidth()).toBe(0)\n    })\n\n    test('getHeight returns 0 when no height is set', () => {\n        const instance = new TestDisplayObject()\n        const props = { context: mockContext }\n        instance.onInit(props)\n        instance.height = 0\n        \n        // Update fullProps via onUpdate\n        instance.onUpdate(props)\n        \n        expect(instance.getHeight()).toBe(0)\n    })\n\n    test('getWidth returns computed layout width for percentages', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '100%', height: '100%', context: mockContext }\n        instance.onInit(props)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Emit layout event with computed dimensions\n        instance.emit('layout', {\n            computedLayout: {\n                width: 800,\n                height: 600\n            }\n        })\n        \n        expect(instance.getWidth()).toBe(800)\n    })\n\n    test('getHeight returns computed layout height for percentages', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '100%', height: '100%', context: mockContext }\n        instance.onInit(props)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Emit layout event with computed dimensions\n        instance.emit('layout', {\n            computedLayout: {\n                width: 800,\n                height: 600\n            }\n        })\n        \n        expect(instance.getHeight()).toBe(600)\n    })\n\n    test('getWidth falls back to native width when layout not computed for percentages', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '100%', context: mockContext }\n        instance.onInit(props)\n        instance.width = 500\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Before layout event, should fallback to native width\n        expect(instance.getWidth()).toBe(500)\n    })\n\n    test('getHeight falls back to native height when layout not computed for percentages', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { height: '100%', context: mockContext }\n        instance.onInit(props)\n        instance.height = 400\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Before layout event, should fallback to native height\n        expect(instance.getHeight()).toBe(400)\n    })\n\n    test('layout event updates computed layout box', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '50%', height: '75%', context: mockContext }\n        instance.onInit(props)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Emit layout event\n        instance.emit('layout', {\n            computedLayout: {\n                width: 400,\n                height: 450\n            }\n        })\n        \n        // getWidth and getHeight should now return computed values\n        expect(instance.getWidth()).toBe(400)\n        expect(instance.getHeight()).toBe(450)\n    })\n\n    test('layout event listener is registered during onMount', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '100%', context: mockContext }\n        instance.onInit(props)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Verify layout event listener is registered by emitting an event\n        // and checking that getWidth returns the computed value\n        instance.emit('layout', {\n            computedLayout: { width: 800, height: 600 }\n        })\n        \n        // Verify the layout box was updated\n        expect(instance.getWidth()).toBe(800)\n    })\n\n    test('getWidth handles mixed percentage and static values', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: '100%', height: 200, context: mockContext }\n        instance.onInit(props)\n        instance.height = 200\n        instance.setHeight(200)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Emit layout event\n        instance.emit('layout', {\n            computedLayout: {\n                width: 800,\n                height: 600\n            }\n        })\n        \n        // Width should use computed layout, height should use static value\n        expect(instance.getWidth()).toBe(800)\n        expect(instance.getHeight()).toBe(200)\n    })\n\n    test('getHeight handles mixed percentage and static values', async () => {\n        const instance = new TestDisplayObject()\n        const parentInstance = new TestDisplayObject()\n        parentInstance.isFlex = false\n        \n        const props = { width: 300, height: '100%', context: mockContext }\n        instance.onInit(props)\n        instance.width = 300\n        instance.setWidth(300)\n        \n        await instance.onMount({\n            parent: {\n                componentInstance: parentInstance\n            },\n            props\n        })\n        \n        // Emit layout event\n        instance.emit('layout', {\n            computedLayout: {\n                width: 800,\n                height: 600\n            }\n        })\n        \n        // Width should use static value, height should use computed layout\n        expect(instance.getWidth()).toBe(300)\n        expect(instance.getHeight()).toBe(600)\n    })\n}) "
  },
  {
    "path": "tests/components/domcontainer.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { DOMContainer } from '../../packages/core/src/components/DOMContainer'\nimport { DOMElement } from '../../packages/core/src/components/DOMElement'\nimport { FocusContainer } from '../../packages/core/src/components/FocusContainer'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('DOMContainer and DOMElement Components', () => {\n    beforeEach(() => {\n        // Reset DOM before each test but keep the root element\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n\n\n    describe('DOMContainer Component', () => {\n        test('creates DOM container with basic properties', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {\n                x: 100,\n                y: 50\n            })\n\n            expect(containerElement).toBeDefined()\n            expect(typeof containerElement).toBe('object')\n            expect((containerElement.componentInstance as any).x).toBe(100)\n            expect((containerElement.componentInstance as any).y).toBe(50)\n        })\n\n        test('creates DOM container with DOMElement child', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {\n                x: 100,\n                y: 50\n            }, [\n                DOMElement({\n                    element: 'div',\n                    textContent: 'Hello World'\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            expect(wrapperDiv.tagName.toLowerCase()).toBe('div')\n            \n            // Check the child element\n            const childElement = wrapperDiv.children[0]\n            expect(childElement.tagName.toLowerCase()).toBe('div')\n            expect(childElement.textContent).toBe('Hello World')\n        })\n\n        test('creates DOM container with input element', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'input',\n                    attrs: {\n                        type: 'text',\n                        placeholder: 'Enter text...'\n                    }\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const inputElement = wrapperDiv.children[0]\n            expect(inputElement.tagName.toLowerCase()).toBe('input')\n            expect(inputElement.type).toBe('text')\n            expect(inputElement.placeholder).toBe('Enter text...')\n        })\n\n        test('handles DOM container with multiple display properties', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {\n                x: 50,\n                y: 25,\n                alpha: 0.8,\n                visible: true\n            }, [\n                DOMElement({\n                    element: 'div',\n                    textContent: 'Container content'\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            expect((containerElement.componentInstance as any).x).toBe(50)\n            expect((containerElement.componentInstance as any).y).toBe(25)\n            expect((containerElement.componentInstance as any).alpha).toBe(0.8)\n            expect((containerElement.componentInstance as any).visible).toBe(true)\n        })\n\n        test('supports nested DOMContainer inside DOMElement', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: { class: 'outer' },\n                    children: [\n                        DOMContainer({\n                            children: [\n                                DOMElement({\n                                    element: 'button',\n                                    textContent: 'test'\n                                })\n                            ]\n                        })\n                    ]\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const outerDiv = wrapperDiv.querySelector('.outer')\n            expect(outerDiv).toBeDefined()\n            expect(outerDiv.children.length).toBe(1)\n            expect(outerDiv.children[0].tagName.toLowerCase()).toBe('div')\n            expect(outerDiv.children[0].querySelector('button')?.textContent).toBe('test')\n        })\n    })\n\n    describe('DOMElement Component', () => {\n        test('creates DOM element with string element type', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    textContent: 'Test content'\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.tagName.toLowerCase()).toBe('div')\n            expect(domElement.textContent).toBe('Test content')\n        })\n\n        test('renders numeric textContent including zero', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'p',\n                    textContent: 0\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.tagName.toLowerCase()).toBe('p')\n            expect(domElement.textContent).toBe('0')\n        })\n\n        test('creates DOM element with HTML element object', async () => {\n            const htmlElement = document.createElement('span')\n            htmlElement.textContent = 'Span content'\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: { value: htmlElement }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.tagName.toLowerCase()).toBe('span')\n            expect(domElement.textContent).toBe('Span content')\n        })\n\n        test('handles DOM element with class attributes - string format', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: 'container primary-theme'\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.className).toBe('container primary-theme')\n        })\n\n        test('handles DOM element with class attributes - array format', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: ['container', 'primary-theme', 'active']\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.classList.contains('container')).toBe(true)\n            expect(domElement.classList.contains('primary-theme')).toBe(true)\n            expect(domElement.classList.contains('active')).toBe(true)\n        })\n\n        test('handles DOM element with class attributes - object format', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: {\n                            'container': true,\n                            'primary-theme': true,\n                            'disabled': false\n                        }\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.classList.contains('container')).toBe(true)\n            expect(domElement.classList.contains('primary-theme')).toBe(true)\n            expect(domElement.classList.contains('disabled')).toBe(false)\n        })\n\n        test('handles DOM element with style attributes - string format', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        style: 'background-color: red; padding: 10px;'\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.getAttribute('style')).toBe('background-color: red; padding: 10px;')\n        })\n\n        test('handles DOM element with style attributes - object format', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        style: {\n                            backgroundColor: 'blue',\n                            padding: '20px',\n                            fontSize: '16px'\n                        }\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const domElement = wrapperDiv.children[0]\n            expect(domElement.style.backgroundColor).toBe('blue')\n            expect(domElement.style.padding).toBe('20px')\n            // fontSize number is converted to string with 'px' suffix\n            expect(domElement.style.fontSize).toBe('16px')\n        })\n\n        test('handles DOM element with multiple attributes', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'input',\n                    attrs: {\n                        type: 'text',\n                        placeholder: 'Enter username...',\n                        id: 'username-input',\n                        name: 'username',\n                        required: true\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const inputElement = wrapperDiv.children[0]\n            expect(inputElement.type).toBe('text')\n            expect(inputElement.placeholder).toBe('Enter username...')\n            expect(inputElement.id).toBe('username-input')\n            expect(inputElement.name).toBe('username')\n            expect(inputElement.required).toBe(true)\n        })\n\n        test('handles DOM element with event handlers', async () => {\n            const onClick = vi.fn()\n            const onFocus = vi.fn()\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'button',\n                    textContent: 'Click me',\n                    attrs: {\n                        click: onClick,\n                        focus: onFocus\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const buttonElement = wrapperDiv.children[0]\n            \n            // Simulate click event\n            buttonElement.click()\n            expect(onClick).toHaveBeenCalled()\n\n            // Simulate focus event\n            buttonElement.focus()\n            expect(onFocus).toHaveBeenCalled()\n        })\n\n        test('handles form element with reactive signal value', async () => {\n            const inputValue = signal('initial value')\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'input',\n                    attrs: {\n                        type: 'text',\n                        value: inputValue\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const inputElement = wrapperDiv.children[0]\n            expect(inputElement.value).toBe('initial value')\n\n            // Update signal value\n            inputValue.set('updated value')\n            expect(inputElement.value).toBe('updated value')\n        })\n\n        test('handles form submission with data collection', async () => {\n            const onSubmit = vi.fn()\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'form',\n                    attrs: {\n                        submit: onSubmit\n                    },\n                    children: [\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'username',\n                                type: 'text',\n                                value: 'john'\n                            }\n                        }),\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'password',\n                                type: 'password',\n                                value: 'secret'\n                            }\n                        }),\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'remember',\n                                type: 'checkbox',\n                                value: 'on',\n                                checked: true\n                            }\n                        }),\n                        DOMElement({\n                            element: 'button',\n                            attrs: {\n                                type: 'submit'\n                            },\n                            textContent: 'Submit'\n                        })\n                    ]\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const formElement = wrapperDiv.children[0]\n            \n            // Create and dispatch submit event\n            const submitEvent = new Event('submit', { bubbles: true, cancelable: true })\n            formElement.dispatchEvent(submitEvent)\n\n            expect(onSubmit).toHaveBeenCalled()\n            const [event, formData] = onSubmit.mock.calls[0]\n            \n            // Check that preventDefault was called\n            expect(event.defaultPrevented).toBe(true)\n            \n            // Check form data collection\n            expect(formData).toBeDefined()\n            expect(typeof formData).toBe('object')\n        })\n\n        test('handles textarea element with signal binding', async () => {\n            const textValue = signal('Initial textarea content')\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'textarea',\n                    attrs: {\n                        value: textValue,\n                        placeholder: 'Enter your message...'\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const textareaElement = wrapperDiv.children[0]\n            expect(textareaElement.value).toBe('Initial textarea content')\n            expect(textareaElement.placeholder).toBe('Enter your message...')\n\n            // Update signal\n            textValue.set('Updated content')\n            expect(textareaElement.value).toBe('Updated content')\n        })\n\n        test('handles select element with options', async () => {\n            const selectedValue = signal('option2')\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'select',\n                    attrs: {\n                        name: 'choices',\n                        value: selectedValue\n                    },\n                    children: [\n                        DOMElement({\n                            element: 'option',\n                            attrs: { value: 'option1' },\n                            textContent: 'Option 1'\n                        }),\n                        DOMElement({\n                            element: 'option',\n                            attrs: { value: 'option2' },\n                            textContent: 'Option 2'\n                        }),\n                        DOMElement({\n                            element: 'option',\n                            attrs: { value: 'option3' },\n                            textContent: 'Option 3'\n                        })\n                    ]\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const selectElement = wrapperDiv.children[0]\n            expect(selectElement.value).toBe('option2')\n            expect(selectElement.name).toBe('choices')\n        })\n\n        test('handles nested DOM elements', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: 'outer-container'\n                    },\n                    children: [\n                        DOMElement({\n                            element: 'div',\n                            attrs: {\n                                class: 'inner-container'\n                            },\n                            textContent: 'Nested content'\n                        })\n                    ]\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const outerElement = wrapperDiv.children[0]\n            expect(outerElement.classList.contains('outer-container')).toBe(true)\n            \n            const innerElement = outerElement.querySelector('.inner-container')\n            expect(innerElement).toBeDefined()\n            expect(innerElement.textContent).toBe('Nested content')\n        })\n\n        test('handles dynamic class updates with signals', async () => {\n            const isActive = signal(false)\n            const theme = signal('light')\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: {\n                            'container': true,\n                            'active': isActive(),\n                            'theme-light': theme() === 'light',\n                            'theme-dark': theme() === 'dark'\n                        }\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const divElement = wrapperDiv.children[0]\n            expect(divElement.classList.contains('container')).toBe(true)\n            expect(divElement.classList.contains('active')).toBe(false)\n            expect(divElement.classList.contains('theme-light')).toBe(true)\n            expect(divElement.classList.contains('theme-dark')).toBe(false)\n        })\n\n        test('updates class list when signal inside class array changes', async () => {\n            const isActive = signal(false)\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: {\n                        class: ['base', { active: isActive }]\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const divElement = wrapperDiv.children[0]\n            expect(divElement.classList.contains('base')).toBe(true)\n            expect(divElement.classList.contains('active')).toBe(false)\n\n            isActive.set(true)\n            await Promise.resolve()\n            expect(divElement.classList.contains('active')).toBe(true)\n\n            isActive.set(false)\n            await Promise.resolve()\n            expect(divElement.classList.contains('active')).toBe(false)\n        })\n\n        test('renders FocusContainer children inside DOMElement', async () => {\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    attrs: { class: 'outer' },\n                    children: [\n                        FocusContainer({\n                            children: [\n                                DOMElement({\n                                    element: 'button',\n                                    textContent: 'Focus Item'\n                                })\n                            ]\n                        })\n                    ]\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const outerDiv = wrapperDiv.querySelector('.outer')\n            const button = outerDiv?.querySelector('button')\n            expect(button?.textContent).toBe('Focus Item')\n        })\n\n        test('handles onBeforeDestroy hook', async () => {\n            const onBeforeDestroy = vi.fn()\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'div',\n                    textContent: 'Will be destroyed',\n                    onBeforeDestroy: onBeforeDestroy\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            \n            // The onBeforeDestroy hook should be defined and ready to be called\n            // In a real scenario, it would be called when the DOM element is removed\n            expect(onBeforeDestroy).toBeDefined()\n            expect(typeof onBeforeDestroy).toBe('function')\n            \n            // Manually test the hook functionality\n            await onBeforeDestroy()\n            expect(onBeforeDestroy).toHaveBeenCalled()\n        })\n    })\n\n    describe('Integration Tests', () => {\n        test('creates complete form with reactive inputs', async () => {\n            const username = signal('')\n            const password = signal('')\n            const rememberMe = signal(false)\n            const onSubmit = vi.fn()\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {\n                x: 100,\n                y: 100\n            }, [\n                DOMElement({\n                    element: 'form',\n                    attrs: {\n                        class: 'login-form',\n                        submit: onSubmit\n                    },\n                    children: [\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'username',\n                                type: 'text',\n                                placeholder: 'Username',\n                                value: username\n                            }\n                        }),\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'password',\n                                type: 'password',\n                                placeholder: 'Password',\n                                value: password\n                            }\n                        }),\n                        DOMElement({\n                            element: 'input',\n                            attrs: {\n                                name: 'remember',\n                                type: 'checkbox',\n                                checked: rememberMe()\n                            }\n                        }),\n                        DOMElement({\n                            element: 'button',\n                            attrs: {\n                                type: 'submit'\n                            },\n                            textContent: 'Login'\n                        })\n                    ]\n                })\n            ])\n\n            expect(containerElement).toBeDefined()\n            expect((containerElement.componentInstance as any).x).toBe(100)\n            expect((containerElement.componentInstance as any).y).toBe(100)\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const formElement = wrapperDiv.children[0]\n            expect(formElement.classList.contains('login-form')).toBe(true)\n\n            // Test reactive updates\n            username.set('testuser')\n            password.set('testpass')\n            \n            const usernameInput = formElement.querySelector('input[name=\"username\"]')\n            const passwordInput = formElement.querySelector('input[name=\"password\"]')\n            \n            expect(usernameInput.value).toBe('testuser')\n            expect(passwordInput.value).toBe('testpass')\n        })\n\n        test('handles complex styling and interactions', async () => {\n            const isHovered = signal(false)\n            const onClick = vi.fn()\n            const onMouseEnter = vi.fn(() => isHovered.set(true))\n            const onMouseLeave = vi.fn(() => isHovered.set(false))\n\n            const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n                DOMElement({\n                    element: 'button',\n                    textContent: 'Interactive Button',\n                    attrs: {\n                        class: {\n                            'btn': true,\n                            'btn-primary': true,\n                            'btn-hovered': isHovered()\n                        },\n                        style: {\n                            padding: '10px 20px',\n                            borderRadius: '4px',\n                            backgroundColor: isHovered() ? '#0056b3' : '#007bff',\n                            color: 'white',\n                            border: 'none',\n                            cursor: 'pointer'\n                        },\n                        click: onClick,\n                        mouseenter: onMouseEnter,\n                        mouseleave: onMouseLeave\n                    }\n                })\n            ])\n\n            const wrapperDiv = (containerElement.componentInstance as any).element\n            const buttonElement = wrapperDiv.children[0]\n            expect(buttonElement.classList.contains('btn')).toBe(true)\n            expect(buttonElement.classList.contains('btn-primary')).toBe(true)\n            expect(buttonElement.style.padding).toBe('10px 20px')\n            expect(buttonElement.style.backgroundColor).toBe('rgb(0, 123, 255)') // #007bff\n        })\n    })\n}) \n"
  },
  {
    "path": "tests/components/domsprite.spec.ts",
    "content": "import { beforeEach, describe, expect, test } from 'vitest'\nimport { DOMContainer, DOMSprite, signal } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\nconst normalizePosition = (value: string) => value.replace(/-0px/g, '0px')\n\ndescribe('DOMSprite Component', () => {\n    beforeEach(() => {\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n    test('renders DOMSprite as img element with frame positioning', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                element: 'img',\n                image: 'sprite.png',\n                rectangle: {\n                    x: 2,\n                    y: 3,\n                    width: 20,\n                    height: 30\n                }\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLImageElement\n\n        expect(spriteElement.tagName.toLowerCase()).toBe('img')\n        expect(spriteElement.style.width).toBe('20px')\n        expect(spriteElement.style.height).toBe('30px')\n        expect(spriteElement.style.objectFit).toBe('none')\n        expect(spriteElement.style.objectPosition).toBe('-2px -3px')\n    })\n\n    \n    test('contains frame within explicit size using objectFit', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                objectFit: 'contain',\n                width: 100,\n                height: 50,\n                rectangle: {\n                    x: 0,\n                    y: 0,\n                    width: 20,\n                    height: 20\n                }\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteWrapper = wrapperDiv.children[0] as HTMLElement\n        const spriteInner = spriteWrapper.children[0] as HTMLElement\n\n        expect(spriteWrapper.style.width).toBe('100px')\n        expect(spriteWrapper.style.height).toBe('50px')\n        expect(spriteInner.style.transform).toContain('scale(2.5)')\n    })\n\n    test('applies transform and anchor props to DOMSprite', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                x: 10.4,\n                y: 20.6,\n                roundPixels: true,\n                scale: [2, 3],\n                angle: 90,\n                skew: { x: Math.PI / 4, y: 0 },\n                anchor: { x: 0.5, y: 0.5 }\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.transform).toContain('translate3d(10px, 21px, 0)')\n        expect(spriteElement.style.transform).toContain('rotate(90deg)')\n        expect(spriteElement.style.transform).toContain('skew(45deg, 0deg)')\n        expect(spriteElement.style.transform).toContain('scale(2, 3)')\n        expect(spriteElement.style.transformOrigin).toBe('50% 50%')\n    })\n\n    test('angle overrides rotation when both are provided', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                angle: 45,\n                rotation: Math.PI\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.transform).toContain('rotate(45deg)')\n    })\n\n    test('pivot overrides anchor for transform origin', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                pivot: { x: 10, y: 20 },\n                anchor: { x: 0.5, y: 0.5 }\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.transformOrigin).toBe('10px 20px')\n    })\n\n    test('clamps frameIndex when loop is false', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                loop: false,\n                frameIndex: -1,\n                frames: [\n                    { x: 0, y: 0, width: 10, height: 10 },\n                    { x: 10, y: 0, width: 10, height: 10 }\n                ]\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(normalizePosition(spriteElement.style.backgroundPosition)).toBe('0px 0px')\n    })\n\n    test('wraps frameIndex when loop is true', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                loop: true,\n                frameIndex: -1,\n                frames: [\n                    { x: 0, y: 0, width: 10, height: 10 },\n                    { x: 10, y: 0, width: 10, height: 10 }\n                ]\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(normalizePosition(spriteElement.style.backgroundPosition)).toBe('-10px 0px')\n    })\n\n    test('respects explicit width and height over frame size', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                width: 100,\n                height: 200,\n                rectangle: {\n                    x: 0,\n                    y: 0,\n                    width: 10,\n                    height: 20\n                }\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.width).toBe('100px')\n        expect(spriteElement.style.height).toBe('200px')\n    })\n\n    test('advances frames when advance is called', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                fps: 1,\n                playing: true,\n                loop: true,\n                frames: [\n                    { x: 0, y: 0, width: 10, height: 10 },\n                    { x: 10, y: 0, width: 10, height: 10 }\n                ]\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n        const spriteNode = containerElement.props.children?.[0]\n        const spriteInstance = spriteNode?.componentInstance as any\n\n        expect(normalizePosition(spriteElement.style.backgroundPosition)).toBe('0px 0px')\n\n        spriteInstance.advance(1000)\n        expect(normalizePosition(spriteElement.style.backgroundPosition)).toBe('-10px 0px')\n    })\n\n    test('applies visibility, alpha, cursor, zIndex, and tint props', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                visible: false,\n                alpha: 0.5,\n                cursor: 'pointer',\n                zIndex: 5,\n                tint: 0xff0000\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.display).toBe('none')\n        expect(spriteElement.style.opacity).toBe('0.5')\n        expect(spriteElement.style.cursor).toBe('pointer')\n        expect(spriteElement.style.zIndex).toBe('5')\n        expect(spriteElement.style.filter).toContain('ff0000')\n    })\n\n    test('updates visibility and tint when signals change', async () => {\n        const visible = signal(true)\n        const tint = signal(0x00ff00)\n\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            DOMSprite({\n                visible,\n                tint\n            })\n        ], { enableLayout: false })\n\n        const wrapperDiv = (containerElement.componentInstance as any).element as HTMLElement\n        const spriteElement = wrapperDiv.children[0] as HTMLElement\n\n        expect(spriteElement.style.display).toBe('')\n        expect(spriteElement.style.filter).toContain('00ff00')\n\n        visible.set(false)\n        tint.set(0xff00ff)\n        await Promise.resolve()\n\n        expect(spriteElement.style.display).toBe('none')\n        expect(spriteElement.style.filter).toContain('ff00ff')\n    })\n})\n"
  },
  {
    "path": "tests/components/flex.spec.ts",
    "content": "import { describe, it, expect } from 'vitest';\nimport { ComponentInstance, Element, Container, h  } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\n\ndescribe('Flex Positioning', () => {\n    it('should position children correctly in flex row', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            width: 300, \n            height: 100 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(0)\n        expect(child1.componentInstance.layout.realY).toBe(0)\n        expect(child2.componentInstance.layout.realX).toBe(50)\n        expect(child2.componentInstance.layout.realY).toBe(0)\n    })\n\n    it('should position children correctly in flex column', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'column', \n            width: 100, \n            height: 300 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(0)\n        expect(child1.componentInstance.layout.realY).toBe(0)\n        expect(child2.componentInstance.layout.realX).toBe(0)\n        expect(child2.componentInstance.layout.realY).toBe(50)\n    })\n\n    it('should respect x and y properties for non-flex elements', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            width: 200, \n            height: 200 \n        }, [\n            h(Container, { \n                x: 30, \n                y: 40, \n                width: 50, \n                height: 50 \n            })\n        ])\n\n        const child = parent.props.children?.[0] as Element<ComponentInstance>\n\n        expect(child.componentInstance.layout).toBeNull()\n    })\n\n    it('should align items correctly with justifyContent', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            justifyContent: 'space-between', \n            width: 300, \n            height: 100 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(0)\n        expect(child2.componentInstance.layout.realX).toBe(250)\n    })\n\n    it('should align items correctly with alignItems', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            alignItems: 'flex-end', \n            width: 300, \n            height: 100 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 75 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realY).toBe(50)\n        expect(child2.componentInstance.layout.realY).toBe(25)\n    })\n    \n    it('should apply gap correctly', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            gap: 10, \n            width: 300, \n            height: 100 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(0)\n        expect(child2.componentInstance.layout.realX).toBe(60)\n    })\n\n    it('should apply margin correctly', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            width: 300, \n            height: 100 \n        }, [\n            h(Container, { width: 50, height: 50, margin: 10 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(10)\n        expect(child2.componentInstance.layout.realX).toBe(70)\n    })\n\n    it('should apply padding correctly', async () => {\n        const parent = await TestBed.createComponent(Container, { \n            flexDirection: 'row', \n            width: 300, \n            height: 100, \n            padding: 20 \n        }, [\n            h(Container, { width: 50, height: 50 }),\n            h(Container, { width: 50, height: 50 })\n        ])\n\n        const child1 = parent.props.children?.[0] as Element<ComponentInstance>\n        const child2 = parent.props.children?.[1] as Element<ComponentInstance>\n\n        expect(child1.componentInstance.layout.realX).toBe(20)\n        expect(child1.componentInstance.layout.realY).toBe(20)\n        expect(child2.componentInstance.layout.realX).toBe(70)\n        expect(child2.componentInstance.layout.realY).toBe(20)\n    })\n})"
  },
  {
    "path": "tests/components/focus-container-tabindex.spec.ts",
    "content": "import { describe, test, expect, vi, beforeEach } from \"vitest\";\nimport { FocusContainer, Button, signal } from \"canvasengine\";\nimport { TestBed } from \"../../packages/core/testing\";\nimport { focusManager } from \"../../packages/core/src/engine/FocusManager\";\n\ndescribe(\"FocusContainer tabindex synchronization\", () => {\n    test(\"should set initial focus based on tabindex prop\", async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' });\n        const button2 = Button({ tabindex: 1, text: 'Button 2' });\n\n        const containerElement = await TestBed.createComponent(FocusContainer, {\n            tabindex: 1\n        }, [button1, button2], { enableLayout: false });\n\n        // Wait for children registration and initial focus application\n        await new Promise(resolve => setTimeout(resolve, 50));\n\n        const currentIndex = containerElement.componentInstance.getCurrentIndexSignal()();\n        expect(currentIndex).toBe(1);\n    });\n\n    test(\"should update focus when tabindex signal changes\", async () => {\n        const tabindex = signal(0);\n        const button1 = Button({ tabindex: 0, text: 'Button 1' });\n        const button2 = Button({ tabindex: 1, text: 'Button 2' });\n\n        const containerElement = await TestBed.createComponent(FocusContainer, {\n            tabindex\n        }, [button1, button2], { enableLayout: false });\n\n        await new Promise(resolve => setTimeout(resolve, 50));\n        expect(containerElement.componentInstance.getCurrentIndexSignal()()).toBe(0);\n\n        // Update external signal\n        tabindex.set(1);\n\n        // Wait for effect\n        await new Promise(resolve => setTimeout(resolve, 50));\n        expect(containerElement.componentInstance.getCurrentIndexSignal()()).toBe(1);\n    });\n\n    test(\"should update tabindex signal when focus changes internally\", async () => {\n        const tabindex = signal(0);\n        const button1 = Button({ tabindex: 0, text: 'Button 1' });\n        const button2 = Button({ tabindex: 1, text: 'Button 2' });\n\n        const containerElement = await TestBed.createComponent(FocusContainer, {\n            tabindex\n        }, [button1, button2], { enableLayout: false });\n\n        await new Promise(resolve => setTimeout(resolve, 50));\n        const containerId = containerElement.componentInstance.getContainerId();\n\n        // Navigate internally\n        focusManager.navigate(containerId, 'next');\n\n        // Wait for effect\n        await new Promise(resolve => setTimeout(resolve, 50));\n        expect(tabindex()).toBe(1);\n    });\n});\n"
  },
  {
    "path": "tests/components/focus-container.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { Navigation, Button, Container, signal } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\nimport { focusManager } from '../../packages/core/src/engine/FocusManager'\nimport { useFocusIndex, useFocusedElement, useFocusChange } from '../../packages/core/src/hooks/useFocus'\n\ndescribe('Navigation Component', () => {\n    beforeEach(() => {\n        // Clean up any existing containers\n        const containers = (focusManager as any).containers;\n        if (containers) {\n            containers.clear();\n        }\n    })\n\n    test('creates Navigation with basic properties', async () => {\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [], { enableLayout: false })\n\n        expect(containerElement).toBeDefined()\n        expect(typeof containerElement).toBe('object')\n        const instance = containerElement.componentInstance as any\n        expect(instance.getContainerId).toBeDefined()\n    })\n\n    test('registers focusable children with tabindex', async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [button1, button2], { enableLayout: false })\n\n        expect(containerElement).toBeDefined()\n\n        // Wait a bit for children to be registered\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        // Check that elements are registered\n        const element0 = focusManager.getElement(containerId, 0)\n        const element1 = focusManager.getElement(containerId, 1)\n\n        expect(element0).toBeDefined()\n        expect(element1).toBeDefined()\n    })\n\n    test('does not register focusables from nested Navigation', async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const nestedButton = Button({ tabindex: 1, text: 'Nested Button' })\n\n        const nestedContainer = Navigation({\n            tabindex: 0,\n            children: [nestedButton]\n        })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [button1, nestedContainer], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const parentId = containerElement.componentInstance.getContainerId()\n        const parentElement0 = focusManager.getElement(parentId, 0)\n        const parentElement1 = focusManager.getElement(parentId, 1)\n\n        expect(parentElement0).toBeDefined()\n        expect(parentElement1).toBeNull()\n    })\n\n    test('updates focus when tabindex signal changes', async () => {\n        const tabindex = signal(0)\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n        const button3 = Button({ tabindex: 2, text: 'Button 3' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex\n        }, [button1, button2, button3], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        // Move focus via external signal updates\n        tabindex.set(0)\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(0)\n\n        tabindex.set(1)\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(1)\n\n        tabindex.set(2)\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(2)\n\n        tabindex.set(1)\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(1)\n    })\n\n    test('supports external wrap-around logic via tabindex signal', async () => {\n        const tabindex = signal(0)\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex\n        }, [button1, button2], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        // Set to last element\n        tabindex.set(1)\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        // External wrap to first\n        tabindex.set((tabindex() + 1) % 2)\n        await new Promise(resolve => setTimeout(resolve, 10))\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(0)\n\n        // External wrap to last\n        tabindex.set((tabindex() - 1 + 2) % 2)\n        await new Promise(resolve => setTimeout(resolve, 10))\n        expect(focusManager.getCurrentIndexSignal(containerId)?.()).toBe(1)\n    })\n\n    test('calls onFocusChange callback when focus changes', async () => {\n        const onFocusChange = vi.fn()\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0,\n            onFocusChange,\n        }, [button1, button2], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        // Change focus\n        focusManager.setIndex(containerId, 0)\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        expect(onFocusChange).toHaveBeenCalled()\n        expect(onFocusChange).toHaveBeenCalledWith(0, expect.anything())\n    })\n\n    test('useFocusIndex hook returns current index signal', async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [button1, button2], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        const indexSignal = useFocusIndex(containerId)\n        expect(indexSignal).toBeDefined()\n\n        focusManager.setIndex(containerId, 1)\n        expect(indexSignal?.()).toBe(1)\n    })\n\n    test('useFocusedElement hook returns focused element signal', async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [button1, button2], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        const elementSignal = useFocusedElement(containerId)\n        expect(elementSignal).toBeDefined()\n\n        focusManager.setIndex(containerId, 1)\n        const focusedElement = elementSignal?.()\n        expect(focusedElement).toBeDefined()\n    })\n\n    test('useFocusChange hook triggers callback on focus change', async () => {\n        const button1 = Button({ tabindex: 0, text: 'Button 1' })\n        const button2 = Button({ tabindex: 1, text: 'Button 2' })\n\n        const containerElement = await TestBed.createComponent(Navigation, {\n            tabindex: 0\n        }, [button1, button2], { enableLayout: false })\n\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        const instance = containerElement.componentInstance as any\n        const containerId = instance.getContainerId()\n\n        const callback = vi.fn()\n        useFocusChange(containerId, callback)\n\n        focusManager.setIndex(containerId, 0)\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        expect(callback).toHaveBeenCalled()\n    })\n})\n"
  },
  {
    "path": "tests/components/graphics.spec.ts",
    "content": "import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';\nimport { Canvas, ComponentInstance, bootstrapCanvas, Container, Element, h, signal, Rect, mount, computed } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\n\nconst mockRect = vi.fn()\n\nfunction findPrototypeWithMethod(instance: object, method: string) {\n    let proto = Object.getPrototypeOf(instance);\n    while (proto && !Object.prototype.hasOwnProperty.call(proto, method)) {\n        proto = Object.getPrototypeOf(proto);\n    }\n    return proto;\n}\n\nbeforeEach(async () => {\n    const rect = await TestBed.createComponent(Rect, { width: 1, height: 1, color: '#fff' })\n    const graphicsPrototype = findPrototypeWithMethod(rect.componentInstance, 'rect')\n    vi.spyOn(graphicsPrototype, 'rect').mockImplementation(mockRect)\n    mockRect.mockClear()\n})\n\nafterEach(() => {\n    vi.clearAllMocks()\n})\n\ndescribe('Graphics', () => {\n    let rect: Element<ComponentInstance>\n\n    describe('Rect', () => {\n        it('should create a rect', async () => {\n            await TestBed.createComponent(Rect, { width: 100, height: 100, color: '#fff' })\n            expect(mockRect).toHaveBeenCalled()\n            expect(mockRect).toHaveBeenCalledWith(-0, -0, 100, 100)\n        })\n\n        it('should create a rect, change width', async () => {\n            const width = signal(100)\n            await TestBed.createComponent(Rect, { width, height: 100, color: '#fff' })\n            \n            // First call should be with initial width\n            expect(mockRect).toHaveBeenCalledWith(-0, -0, 100, 100)\n            \n            width.set(200)\n            // Wait for the effect to run\n            await new Promise(resolve => setTimeout(resolve, 0))\n            \n            // Should be called twice now\n            expect(mockRect).toHaveBeenCalledTimes(2)\n            // Second call should be with updated width\n            expect(mockRect).toHaveBeenLastCalledWith(-0, -0, 200, 100)\n        })\n    })\n})\n"
  },
  {
    "path": "tests/components/mesh.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { Mesh } from '../../packages/core/src/components/Mesh'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Mesh Component', () => {\n    let mockGeometry;\n    let mockShader;\n\n    beforeEach(() => {\n        // Mock basic geometry and shader objects with proper EventEmitter methods\n        mockGeometry = {\n            vertices: new Float32Array([0, 0, 1, 0, 0, 1]),\n            indices: new Uint16Array([0, 1, 2]),\n            bounds: { minX: 0, minY: 0, maxX: 1, maxY: 1 },\n            attributes: {\n                aPosition: {\n                    buffer: new Float32Array([0, 0, 1, 0, 0, 1]),\n                    size: 2,\n                    stride: 0,\n                    offset: 0,\n                    normalized: false,\n                    type: 'float32',\n                    divisor: 0\n                }\n            },\n            buffers: [],\n            indexBuffer: {\n                data: new Uint16Array([0, 1, 2]),\n                type: 'uint16'\n            },\n            instanceCount: 1,\n            glVertexArrayObjects: {},\n            on: vi.fn(),\n            off: vi.fn(),\n            emit: vi.fn(),\n            once: vi.fn(),\n            removeListener: vi.fn(),\n            removeAllListeners: vi.fn(),\n            listeners: vi.fn(() => []),\n            listenerCount: vi.fn(() => 0),\n            eventNames: vi.fn(() => []),\n            destroy: vi.fn(),\n            addAttribute: vi.fn(),\n            getAttribute: vi.fn(),\n            hasAttribute: vi.fn(() => true),\n            getBuffer: vi.fn(),\n            interleave: vi.fn(),\n            getSize: vi.fn(() => 3)\n        }\n        \n        mockShader = {\n            vertex: 'vertex shader code',\n            fragment: 'fragment shader code'\n        }\n    })\n\n    test('creates mesh component with basic properties', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            x: 100,\n            y: 50\n        })\n\n        expect(meshElement).toBeDefined()\n        expect(typeof meshElement).toBe('object')\n        expect((meshElement.componentInstance as any).x).toBe(100)\n        expect((meshElement.componentInstance as any).y).toBe(50)\n    })\n\n    test('creates mesh component with geometry', async () => {\n        // Test that the component can be created and geometry property is handled\n        // without triggering complex PixiJS rendering that's hard to mock\n        const meshElement = await TestBed.createComponent(Mesh, {\n            x: 100,\n            y: 50\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).x).toBe(100)\n        expect((meshElement.componentInstance as any).y).toBe(50)\n        \n        // Test that the component has the geometry property available\n        expect('geometry' in meshElement.componentInstance).toBe(true)\n    })\n\n    test('creates mesh component with shader', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            shader: mockShader,\n            x: 100,\n            y: 50\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).shader).toStrictEqual(mockShader)\n    })\n\n    test('creates mesh component with texture property', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            x: 100,\n            y: 50,\n            tint: 0xffffff\n        })\n\n        expect(meshElement).toBeDefined()\n    })\n\n    test('creates mesh component with basic properties', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            x: 100,\n            y: 50,\n            width: 64,\n            height: 64\n        })\n\n        expect(meshElement).toBeDefined()\n    })\n\n    test('handles tint property', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            tint: 0xff0000\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).tint).toBe(0xff0000)\n    })\n\n    test('handles dynamic tint with signal', async () => {\n        const dynamicTint = signal(0xff0000)\n        \n        const meshElement = await TestBed.createComponent(Mesh, {\n            tint: dynamicTint\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).tint).toBe(0xff0000)\n        \n        dynamicTint.set(0x00ff00)\n        expect((meshElement.componentInstance as any).tint).toBe(0x00ff00)\n    })\n\n    test('handles roundPixels property', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            roundPixels: true\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).roundPixels).toBe(true)\n    })\n\n    test('handles dynamic roundPixels with signal', async () => {\n        const dynamicRoundPixels = signal(false)\n        \n        const meshElement = await TestBed.createComponent(Mesh, {\n            roundPixels: dynamicRoundPixels\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).roundPixels).toBe(false)\n        \n        dynamicRoundPixels.set(true)\n        expect((meshElement.componentInstance as any).roundPixels).toBe(true)\n    })\n\n    test('creates mesh with multiple properties', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {\n            geometry: mockGeometry,\n            shader: mockShader,\n            tint: 0xff0000,\n            roundPixels: true,\n            x: 100,\n            y: 50,\n            width: 200,\n            height: 150\n        })\n\n        expect(meshElement).toBeDefined()\n        // Just check that geometry was set, not the exact object due to PixiJS internal modifications\n        expect((meshElement.componentInstance as any).geometry).toBeDefined()\n        expect((meshElement.componentInstance as any).shader).toStrictEqual(mockShader)\n        expect((meshElement.componentInstance as any).tint).toBe(0xff0000)\n        expect((meshElement.componentInstance as any).roundPixels).toBe(true)\n    })\n\n    test('handles empty mesh creation', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {})\n        expect(meshElement).toBeDefined()\n    })\n\n    test('handles dynamic geometry updates', async () => {\n        const dynamicGeometry = signal(mockGeometry)\n        \n        const meshElement = await TestBed.createComponent(Mesh, {\n            geometry: dynamicGeometry\n        })\n\n        expect(meshElement).toBeDefined()\n        expect((meshElement.componentInstance as any).geometry).toBeDefined()\n        \n        const newGeometry = {\n            vertices: new Float32Array([0, 0, 2, 0, 0, 2]),\n            indices: new Uint16Array([0, 1, 2]),\n            bounds: { minX: 0, minY: 0, maxX: 2, maxY: 2 },\n            attributes: {\n                aPosition: {\n                    buffer: new Float32Array([0, 0, 2, 0, 0, 2]),\n                    size: 2,\n                    stride: 0,\n                    offset: 0,\n                    normalized: false,\n                    type: 'float32',\n                    divisor: 0\n                }\n            },\n            buffers: [],\n            indexBuffer: {\n                data: new Uint16Array([0, 1, 2]),\n                type: 'uint16'\n            },\n            instanceCount: 1,\n            glVertexArrayObjects: {},\n            on: vi.fn(),\n            off: vi.fn(),\n            emit: vi.fn(),\n            once: vi.fn(),\n            removeListener: vi.fn(),\n            removeAllListeners: vi.fn(),\n            listeners: vi.fn(() => []),\n            listenerCount: vi.fn(() => 0),\n            eventNames: vi.fn(() => []),\n            destroy: vi.fn(),\n            addAttribute: vi.fn(),\n            getAttribute: vi.fn(),\n            hasAttribute: vi.fn(() => true),\n            getBuffer: vi.fn(),\n            interleave: vi.fn(),\n            getSize: vi.fn(() => 3)\n        }\n        \n        dynamicGeometry.set(newGeometry)\n        // Just check that geometry was updated, not the exact object\n        expect((meshElement.componentInstance as any).geometry).toBeDefined()\n    })\n\n    test('component instance has correct methods', async () => {\n        const meshElement = await TestBed.createComponent(Mesh, {})\n\n        const instance = meshElement.componentInstance\n        expect(instance).toBeDefined()\n        expect(typeof instance.onMount).toBe('function')\n        expect(typeof instance.onUpdate).toBe('function')\n        expect(typeof instance.onDestroy).toBe('function')\n        expect(typeof instance.onInit).toBe('function')\n    })\n}) "
  },
  {
    "path": "tests/components/nineslicesprite.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { NineSliceSprite } from '../../packages/core/src/components/NineSliceSprite'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('NineSliceSprite Component', () => {\n    test('creates nine slice sprite component with basic properties', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 200,\n            height: 50,\n            x: 100,\n            y: 50\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect(typeof nineSliceElement).toBe('object')\n        expect((nineSliceElement.componentInstance as any).x).toBe(100)\n        expect((nineSliceElement.componentInstance as any).y).toBe(50)\n    })\n\n    test('creates nine slice sprite with slice dimensions', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 300,\n            height: 200,\n            leftWidth: 10,\n            rightWidth: 10,\n            topHeight: 10,\n            bottomHeight: 10\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect((nineSliceElement.componentInstance as any).leftWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).rightWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).topHeight).toBe(10)\n        expect((nineSliceElement.componentInstance as any).bottomHeight).toBe(10)\n    })\n\n    test('handles roundPixels property', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 150,\n            height: 75,\n            roundPixels: true\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect((nineSliceElement.componentInstance as any).roundPixels).toBe(true)\n    })\n\n    test('handles dynamic dimensions with signals', async () => {\n        const dynamicWidth = signal(100)\n        const dynamicHeight = signal(50)\n\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: dynamicWidth,\n            height: dynamicHeight\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect((nineSliceElement.componentInstance as any).width).toBe(100)\n        expect((nineSliceElement.componentInstance as any).height).toBe(50)\n\n        dynamicWidth.set(200)\n        dynamicHeight.set(100)\n\n        expect((nineSliceElement.componentInstance as any).width).toBe(200)\n        expect((nineSliceElement.componentInstance as any).height).toBe(100)\n    })\n\n    test('creates nine slice sprite with all slice properties', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 400,\n            height: 300,\n            leftWidth: 10,\n            rightWidth: 10,\n            topHeight: 10,\n            bottomHeight: 10,\n            roundPixels: false,\n            x: 50,\n            y: 75\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect((nineSliceElement.componentInstance as any).leftWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).rightWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).topHeight).toBe(10)\n        expect((nineSliceElement.componentInstance as any).bottomHeight).toBe(10)\n        expect((nineSliceElement.componentInstance as any).roundPixels).toBe(false)\n    })\n\n    test('handles empty nine slice sprite creation', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {})\n        expect(nineSliceElement).toBeDefined()\n    })\n\n    test('handles nine slice sprite without image', async () => {\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 100,\n            height: 50,\n            leftWidth: 10,\n            rightWidth: 10\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        // When no texture is provided, PixiJS may return NaN for dimensions\n        // Just check that the component was created successfully\n        expect((nineSliceElement.componentInstance as any).leftWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).rightWidth).toBe(10)\n    })\n\n    test('handles dynamic slice dimensions', async () => {\n        const dynamicLeftWidth = signal(10)\n        const dynamicRightWidth = signal(10)\n\n        const nineSliceElement = await TestBed.createComponent(NineSliceSprite, {\n            width: 200,\n            height: 100,\n            leftWidth: dynamicLeftWidth,\n            rightWidth: dynamicRightWidth\n        })\n\n        expect(nineSliceElement).toBeDefined()\n        expect((nineSliceElement.componentInstance as any).leftWidth).toBe(10)\n        expect((nineSliceElement.componentInstance as any).rightWidth).toBe(10)\n\n        dynamicLeftWidth.set(20)\n        dynamicRightWidth.set(25)\n\n        expect((nineSliceElement.componentInstance as any).leftWidth).toBe(20)\n        expect((nineSliceElement.componentInstance as any).rightWidth).toBe(25)\n    })\n}) "
  },
  {
    "path": "tests/components/particleemitter.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { ParticlesEmitter } from '../../packages/core/src/components/ParticleEmitter'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('ParticleEmitter Component', () => {\n    let mockConfig;\n\n    beforeEach(() => {\n        mockConfig = {\n            alpha: {\n                start: 1,\n                end: 0\n            },\n            scale: {\n                start: 0.5,\n                end: 1\n            },\n            color: {\n                start: \"#ffffff\",\n                end: \"#000000\"\n            },\n            speed: {\n                start: 100,\n                end: 50\n            },\n            lifetime: {\n                min: 0.5,\n                max: 2.0\n            },\n            frequency: 0.1,\n            emitterLifetime: -1,\n            maxParticles: 100,\n            pos: {\n                x: 0,\n                y: 0\n            },\n            addAtBack: false,\n            spawnType: \"circle\",\n            spawnCircle: {\n                x: 0,\n                y: 0,\n                r: 10\n            },\n            behaviors: []\n        }\n    })\n\n    test('creates particle emitter component with basic config', async () => {\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: mockConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n        expect(typeof emitterElement).toBe('object')\n    })\n\n    test('creates particle emitter with simple config', async () => {\n        const simpleConfig = {\n            alpha: { start: 1, end: 0 },\n            lifetime: { min: 1, max: 2 },\n            frequency: 0.2,\n            behaviors: []\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: simpleConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('creates particle emitter with position properties', async () => {\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: mockConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n        expect((emitterElement.componentInstance as any).x).toBeDefined()\n        expect((emitterElement.componentInstance as any).y).toBeDefined()\n    })\n\n    test('handles particle emitter with color animation', async () => {\n        const colorConfig = {\n            ...mockConfig,\n            color: {\n                start: \"#ff0000\",\n                end: \"#0000ff\"\n            }\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: colorConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles particle emitter with scale animation', async () => {\n        const scaleConfig = {\n            ...mockConfig,\n            scale: {\n                start: 0.1,\n                end: 2.0\n            }\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: scaleConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles particle emitter with speed configuration', async () => {\n        const speedConfig = {\n            ...mockConfig,\n            speed: {\n                start: 200,\n                end: 0\n            },\n            acceleration: {\n                x: 0,\n                y: 100\n            }\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: speedConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles particle emitter with spawn shapes', async () => {\n        const rectSpawnConfig = {\n            ...mockConfig,\n            spawnType: \"rect\",\n            spawnRect: {\n                x: -50,\n                y: -25,\n                w: 100,\n                h: 50\n            }\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: rectSpawnConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles particle emitter with lifetime settings', async () => {\n        const lifetimeConfig = {\n            ...mockConfig,\n            lifetime: {\n                min: 0.5,\n                max: 3.0\n            },\n            emitterLifetime: 10\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: lifetimeConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles particle emitter with max particles limit', async () => {\n        const limitedConfig = {\n            ...mockConfig,\n            maxParticles: 50,\n            frequency: 0.05\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: limitedConfig\n        })\n\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('handles dynamic config updates', async () => {\n        const dynamicFrequency = signal(0.1)\n        \n        const configWithSignal = {\n            ...mockConfig,\n            frequency: dynamicFrequency()\n        }\n\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: configWithSignal\n        })\n\n        expect(emitterElement).toBeDefined()\n\n        dynamicFrequency.set(0.2)\n        expect(dynamicFrequency()).toBe(0.2)\n    })\n\n    test('handles empty particle emitter creation', async () => {\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {})\n        expect(emitterElement).toBeDefined()\n    })\n\n    test('component instance has correct methods', async () => {\n        const emitterElement = await TestBed.createComponent(ParticlesEmitter, {\n            config: mockConfig\n        })\n\n        const instance = emitterElement.componentInstance\n        expect(instance).toBeDefined()\n        expect(typeof instance.onMount).toBe('function')\n        expect(typeof instance.onUpdate).toBe('function')\n        expect(typeof instance.onDestroy).toBe('function')\n    })\n}) "
  },
  {
    "path": "tests/components/scene.spec.ts",
    "content": "import { describe, expect, test } from 'vitest'\nimport { Scene } from '../../packages/core/src/components/Scene'\n\ndescribe('Scene Component', () => {\n    test('creates scene component', () => {\n        const sceneElement = Scene({})\n\n        expect(sceneElement).toBeDefined()\n        expect(typeof sceneElement).toBe('object')\n    })\n\n    test('creates scene component with properties', () => {\n        const sceneElement = Scene({\n            x: 100,\n            y: 50,\n            width: 800,\n            height: 600\n        })\n\n        expect(sceneElement).toBeDefined()\n    })\n\n    test('creates scene component with children', () => {\n        const sceneElement = Scene({\n            children: []\n        })\n\n        expect(sceneElement).toBeDefined()\n    })\n\n    test('creates scene component with all properties', () => {\n        const sceneElement = Scene({\n            x: 0,\n            y: 0,\n            width: 1024,\n            height: 768,\n            alpha: 1,\n            visible: true,\n            children: []\n        })\n\n        expect(sceneElement).toBeDefined()\n    })\n\n    test('scene component is essentially a container', () => {\n        const sceneElement = Scene({})\n        \n        // Scene is just a wrapper around Container\n        expect(sceneElement).toBeDefined()\n        expect(typeof sceneElement).toBe('object')\n    })\n}) "
  },
  {
    "path": "tests/components/sprite.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { Sprite, signal, Canvas, mount } from 'canvasengine'\nimport { Texture } from 'pixi.js'\nimport { TestBed } from '../../packages/core/testing'\nimport { CanvasSprite } from '../../packages/core/src/components/Sprite'\nimport { GlobalAssetLoader } from '../../packages/core/src/utils/GlobalAssetLoader'\n\nfunction createAnimatedHitboxSprite(hitbox: { w: number; h: number; anchorMode?: 'top-left' | 'center' | 'foot' }) {\n    const sprite = new CanvasSprite()\n    sprite.hitbox = hitbox\n\n    ;(sprite as any).spritesheet = {}\n    ;(sprite as any).currentAnimationContainer = { children: [{}] }\n    ;(sprite as any).currentAnimation = {\n        frames: [[Texture.EMPTY]],\n        sprites: [{ time: 0, frameX: 0, frameY: 0 }],\n        name: 'stand',\n        animations: [],\n        params: [],\n        data: {\n            spriteWidth: 64,\n            spriteHeight: 128,\n            image: 'hero.png',\n            spriteRealSize: { width: 32, height: 96 }\n        }\n    }\n\n    return sprite\n}\n\ndescribe('Sprite Component', () => {\n    test('creates sprite component with basic properties', async () => {\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            x: 100,\n            y: 50,\n            width: 64,\n            height: 64\n        })\n\n        expect(spriteElement).toBeDefined()\n        expect(typeof spriteElement).toBe('object')\n        expect((spriteElement.componentInstance as any).x).toBe(100)\n        expect((spriteElement.componentInstance as any).y).toBe(50)\n    })\n\n    test('creates sprite component with rectangle', async () => {\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            rectangle: {\n                x: 0,\n                y: 0,\n                width: 32,\n                height: 32\n            }\n        })\n\n        expect(spriteElement).toBeDefined()\n    })\n\n    test('creates sprite component with basic sheet', async () => {\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            sheet: {\n                definition: {\n                    width: 256,\n                    height: 256,\n                    spriteWidth: 64,\n                    spriteHeight: 64,\n                    textures: {}\n                }\n            }\n        })\n\n        expect(spriteElement).toBeDefined()\n    })\n\n    test('handles scale mode property', async () => {\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            scaleMode: 0,\n            width: 32,\n            height: 32\n        })\n\n        expect(spriteElement).toBeDefined()\n    })\n\n    test('handles dynamic properties with signals', async () => {\n        const dynamicX = signal(0)\n        const dynamicY = signal(0)\n\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            x: dynamicX,\n            y: dynamicY,\n            width: 64,\n            height: 64\n        })\n\n        expect(spriteElement).toBeDefined()\n        expect((spriteElement.componentInstance as any).x).toBe(0)\n        expect((spriteElement.componentInstance as any).y).toBe(0)\n\n        dynamicX.set(100)\n        dynamicY.set(200)\n\n        expect((spriteElement.componentInstance as any).x).toBe(100)\n        expect((spriteElement.componentInstance as any).y).toBe(200)\n    })\n\n    test('handles sprite without context', () => {\n        expect(() => {\n            TestBed.createComponent(Sprite, {\n                width: 32,\n                height: 32\n            })\n        }).not.toThrow()\n    })\n\n    test('handles loader callbacks', async () => {\n        const onProgress = vi.fn()\n        const onComplete = vi.fn()\n\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            width: 64,\n            height: 64,\n            loader: {\n                onProgress: onProgress,\n                onComplete: onComplete\n            }\n        })\n\n        expect(spriteElement).toBeDefined()\n        expect(onProgress).toBeDefined()\n        expect(onComplete).toBeDefined()\n    })\n\n    test('handles basic spritesheet parameters', async () => {\n        const onFinish = vi.fn()\n\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            sheet: {\n                definition: {\n                    width: 128,\n                    height: 128,\n                    spriteWidth: 32,\n                    spriteHeight: 32,\n                    textures: {}\n                },\n                onFinish: onFinish\n            }\n        })\n\n        expect(spriteElement).toBeDefined()\n        expect(onFinish).toBeDefined()\n    })\n\n    test('component instance has correct methods', async () => {\n        const spriteElement = await TestBed.createComponent(Sprite, {\n            width: 32,\n            height: 32\n        })\n\n        const instance = spriteElement.componentInstance as any\n        expect(instance).toBeDefined()\n        expect(typeof instance.onMount).toBe('function')\n        expect(typeof instance.onUpdate).toBe('function')\n        expect(typeof instance.onDestroy).toBe('function')\n        expect(typeof instance.play).toBe('function')\n        expect(typeof instance.stop).toBe('function')\n        expect(typeof instance.has).toBe('function')\n        expect(typeof instance.get).toBe('function')\n        expect(typeof instance.isPlaying).toBe('function')\n    })\n\n    test('uses top-left hitbox alignment by default', () => {\n        const sprite = createAnimatedHitboxSprite({ w: 32, h: 48 })\n\n        sprite.update({ deltaRatio: 1 })\n\n        expect(sprite.anchor.x).toBeCloseTo(0.25)\n        expect(sprite.anchor.y).toBeCloseTo(0.5)\n    })\n\n    test('can align to the hitbox center', () => {\n        const sprite = createAnimatedHitboxSprite({\n            w: 32,\n            h: 48,\n            anchorMode: 'center'\n        })\n\n        sprite.update({ deltaRatio: 1 })\n\n        expect(sprite.anchor.x).toBeCloseTo(0.5)\n        expect(sprite.anchor.y).toBeCloseTo(0.6875)\n    })\n\n    test('can align to the character foot point', () => {\n        const sprite = createAnimatedHitboxSprite({\n            w: 32,\n            h: 48,\n            anchorMode: 'foot'\n        })\n\n        sprite.update({ deltaRatio: 1 })\n\n        expect(sprite.anchor.x).toBeCloseTo(0.5)\n        expect(sprite.anchor.y).toBeCloseTo(0.875)\n    })\n\n    test('keeps sprite and hitbox bottoms aligned when spriteRealSize is not provided', () => {\n        const sprite = new CanvasSprite()\n        sprite.hitbox = { w: 32, h: 48 }\n\n        ;(sprite as any).applyHitboxAnchor(64, 128)\n\n        expect(sprite.anchor.x).toBeCloseTo(0.25)\n        expect(sprite.anchor.y).toBeCloseTo(0.625)\n    })\n\n    test('does not offset a sprite when the hitbox matches the frame size', () => {\n        const sprite = new CanvasSprite()\n        sprite.hitbox = { w: 32, h: 32 }\n\n        ;(sprite as any).applyHitboxAnchor(32, 32)\n\n        expect(sprite.anchor.x).toBeCloseTo(0)\n        expect(sprite.anchor.y).toBeCloseTo(0)\n    })\n\n    describe('Global Asset Loader Integration', () => {\n        test('globalLoader is available in context', async () => {\n            const canvasElement = await TestBed.createComponent(Sprite, {\n                width: 32,\n                height: 32\n            })\n\n            // Access the canvas element's context\n            const canvasParent = canvasElement.parent\n            expect(canvasParent).toBeDefined()\n            \n            const globalLoader = canvasParent?.props?.context?.globalLoader\n            expect(globalLoader).toBeDefined()\n            expect(globalLoader).toBeInstanceOf(GlobalAssetLoader)\n        })\n\n        test('sprite can access globalLoader from context', async () => {\n            const spriteElement = await TestBed.createComponent(Sprite, {\n                width: 32,\n                height: 32\n            })\n\n            const instance = spriteElement.componentInstance as any\n            expect(instance).toBeDefined()\n            \n            // The globalLoader should be accessible from the sprite's context\n            const canvasParent = spriteElement.parent\n            const globalLoader = canvasParent?.props?.context?.globalLoader\n            expect(globalLoader).toBeDefined()\n        })\n    })\n}) \n"
  },
  {
    "path": "tests/components/text.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { Text, signal } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Text Component', () => {\n    test('creates text component with basic properties', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Hello World',\n            x: 100,\n            y: 50\n        })\n\n        expect(textElement).toBeDefined()\n        expect((textElement.componentInstance as any).text).toBe('Hello World')\n        expect((textElement.componentInstance as any).x).toBe(100)\n        expect((textElement.componentInstance as any).y).toBe(50)\n    })\n\n    test('handles text style properties', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Styled Text',\n            color: '#ff0000',\n            size: 24,\n            fontFamily: 'Arial',\n            style: {\n                fontSize: 20,\n                fill: 0x00ff00\n            }\n        })\n\n        expect((textElement.componentInstance as any).text).toBe('Styled Text')\n        expect((textElement.componentInstance as any).style.fill).toBe('#ff0000')\n        expect((textElement.componentInstance as any).style.fontSize).toBe(24)\n        expect((textElement.componentInstance as any).style.fontFamily).toBe('Arial')\n    })\n\n    test('handles typewriter effect configuration', async () => {\n        const onComplete = vi.fn()\n        const onStart = vi.fn()\n        const onSkip = vi.fn()\n\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Typewriter text',\n            typewriter: {\n                speed: 2,\n                start: onStart,\n                onComplete: onComplete,\n                skip: onSkip\n            }\n        })\n\n        // The typewriter effect may have already started, so we check that it's either empty or has started\n        const currentText = (textElement.componentInstance as any).text\n        expect(currentText.length).toBeLessThanOrEqual('Typewriter text'.length)\n        expect((textElement.componentInstance as any).fullText).toBe('Typewriter text')\n        expect(onComplete).toBeDefined()\n        expect(onStart).toBeDefined()\n        expect(onSkip).toBeDefined()\n    })\n\n    test('handles dynamic text updates', async () => {\n        const dynamicText = signal('Initial text')\n        \n        const textElement = await TestBed.createComponent(Text, {\n            text: dynamicText\n        })\n\n        expect((textElement.componentInstance as any).text).toBe('Initial text')\n\n        dynamicText.set('Updated text')\n        expect((textElement.componentInstance as any).text).toBe('Updated text')\n    })\n\n    test('component instance has correct methods', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Test'\n        })\n\n        const instance = textElement.componentInstance\n        expect(instance).toBeDefined()\n        expect(typeof instance.onMount).toBe('function')\n        expect(typeof instance.onUpdate).toBe('function')\n        expect(typeof instance.onDestroy).toBe('function')\n    })\n\n    test('handles word wrap width', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Long text that should wrap',\n            style: {\n                wordWrapWidth: 200,\n                wordWrap: true\n            }\n        })\n\n        expect((textElement.componentInstance as any).style.wordWrapWidth).toBe(200)\n        expect((textElement.componentInstance as any).style.wordWrap).toBe(true)\n    })\n\n    test('typewriter effect with different speeds', async () => {\n        const slowTypewriter = await TestBed.createComponent(Text, {\n            text: 'Slow typing',\n            typewriter: { speed: 0.5 }\n        })\n\n        const fastTypewriter = await TestBed.createComponent(Text, {\n            text: 'Fast typing',\n            typewriter: { speed: 3 }\n        })\n\n        expect((slowTypewriter.componentInstance as any).typewriterOptions.speed).toBe(0.5)\n        expect((fastTypewriter.componentInstance as any).typewriterOptions.speed).toBe(3)\n    })\n\n    test('handles empty text', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: ''\n        })\n\n        expect((textElement.componentInstance as any).text).toBe('')\n    })\n\n    test('handles string text conversion', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: '42'\n        })\n\n        expect((textElement.componentInstance as any).text).toBe('42')\n    })\n\n    test('handles color property updates', async () => {\n        const colorSignal = signal('#ff0000')\n        \n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Colored text',\n            color: colorSignal\n        })\n\n        expect((textElement.componentInstance as any).style.fill).toBe('#ff0000')\n\n        colorSignal.set('#00ff00')\n        expect((textElement.componentInstance as any).style.fill).toBe('#00ff00')\n    })\n\n    test('handles font size updates', async () => {\n        const sizeSignal = signal(16)\n        \n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Sized text',\n            size: sizeSignal\n        })\n\n        expect((textElement.componentInstance as any).style.fontSize).toBe(16)\n\n        sizeSignal.set(24)\n        expect((textElement.componentInstance as any).style.fontSize).toBe(24)\n    })\n\n    test('handles typewriter sound configuration', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Text with sound',\n            typewriter: {\n                speed: 1,\n                sound: {\n                    src: '/assets/typewriter.mp3',\n                    volume: 0.5,\n                    rate: 1.0\n                }\n            }\n        })\n\n        const instance = textElement.componentInstance as any\n        expect(instance.typewriterOptions.sound).toBeDefined()\n        expect(instance.typewriterOptions.sound.src).toBe('/assets/typewriter.mp3')\n        expect(instance.typewriterOptions.sound.volume).toBe(0.5)\n        expect(instance.typewriterOptions.sound.rate).toBe(1.0)\n        expect(instance.typewriterSound).toBeDefined()\n        expect(instance.soundDuration).toBe(0) // Initially 0 until sound loads\n    })\n\n    test('handles typewriter without sound configuration', async () => {\n        const textElement = await TestBed.createComponent(Text, {\n            text: 'Text without sound',\n            typewriter: {\n                speed: 1\n            }\n        })\n\n        const instance = textElement.componentInstance as any\n        expect(instance.typewriterOptions.sound).toBeUndefined()\n        expect(instance.typewriterSound).toBeUndefined()\n    })\n}) "
  },
  {
    "path": "tests/components/tilingsprite.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { TilingSprite } from '../../packages/core/src/components/TilingSprite'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('TilingSprite Component', () => {\n    test('creates tiling sprite component with basic properties', async () => {\n        const tilingSpriteElement = await TestBed.createComponent(TilingSprite, {\n            image: 'pattern.png',\n            width: 400,\n            height: 300,\n            x: 100,\n            y: 50\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n        expect(typeof tilingSpriteElement).toBe('object')\n        expect((tilingSpriteElement.componentInstance as any).width).toBe(400)\n        expect((tilingSpriteElement.componentInstance as any).height).toBe(300)\n    })\n\n    test('creates tiling sprite with tile scale', async () => {\n        const tilingSpriteElement = await TestBed.createComponent(TilingSprite, {\n            image: 'texture.png',\n            width: 200,\n            height: 200,\n            tileScale: { x: 2, y: 2 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('creates tiling sprite with tile position', () => {\n        const tilingSpriteElement = TilingSprite({\n            image: 'background.png',\n            width: 500,\n            height: 400,\n            tilePosition: { x: 50, y: 25 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('creates tiling sprite with both tile scale and position', () => {\n        const tilingSpriteElement = TilingSprite({\n            image: 'seamless-pattern.png',\n            width: 300,\n            height: 250,\n            tileScale: { x: 1.5, y: 1.5 },\n            tilePosition: { x: 10, y: 20 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('handles dynamic tile scale with signals', () => {\n        const dynamicScaleX = signal(1)\n        const dynamicScaleY = signal(1)\n\n        const tilingSpriteElement = TilingSprite({\n            image: 'animated-pattern.png',\n            width: 200,\n            height: 200,\n            tileScale: { x: dynamicScaleX(), y: dynamicScaleY() }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n\n        dynamicScaleX.set(2)\n        dynamicScaleY.set(3)\n\n        expect(dynamicScaleX()).toBe(2)\n        expect(dynamicScaleY()).toBe(3)\n    })\n\n    test('handles dynamic tile position with signals', () => {\n        const dynamicPosX = signal(0)\n        const dynamicPosY = signal(0)\n\n        const tilingSpriteElement = TilingSprite({\n            image: 'scrolling-bg.png',\n            width: 400,\n            height: 300,\n            tilePosition: { x: dynamicPosX(), y: dynamicPosY() }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n\n        dynamicPosX.set(100)\n        dynamicPosY.set(50)\n\n        expect(dynamicPosX()).toBe(100)\n        expect(dynamicPosY()).toBe(50)\n    })\n\n    test('handles dynamic dimensions with signals', () => {\n        const dynamicWidth = signal(200)\n        const dynamicHeight = signal(150)\n\n        const tilingSpriteElement = TilingSprite({\n            image: 'resizable-pattern.png',\n            width: dynamicWidth(),\n            height: dynamicHeight()\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n\n        dynamicWidth.set(400)\n        dynamicHeight.set(300)\n\n        expect(dynamicWidth()).toBe(400)\n        expect(dynamicHeight()).toBe(300)\n    })\n\n    test('creates tiling sprite with all properties', () => {\n        const tilingSpriteElement = TilingSprite({\n            image: 'complex-pattern.png',\n            width: 600,\n            height: 400,\n            tileScale: { x: 0.8, y: 1.2 },\n            tilePosition: { x: 30, y: 40 },\n            x: 50,\n            y: 75,\n            alpha: 0.8,\n            rotation: 0.1\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('handles empty tiling sprite creation', () => {\n        const tilingSpriteElement = TilingSprite({})\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('handles tiling sprite without image', () => {\n        const tilingSpriteElement = TilingSprite({\n            width: 100,\n            height: 100,\n            tileScale: { x: 1, y: 1 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('handles fractional tile scales', () => {\n        const tilingSpriteElement = TilingSprite({\n            image: 'micro-pattern.png',\n            width: 200,\n            height: 200,\n            tileScale: { x: 0.25, y: 0.5 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n\n    test('handles negative tile positions', () => {\n        const tilingSpriteElement = TilingSprite({\n            image: 'offset-pattern.png',\n            width: 300,\n            height: 200,\n            tilePosition: { x: -50, y: -25 }\n        })\n\n        expect(tilingSpriteElement).toBeDefined()\n    })\n}) "
  },
  {
    "path": "tests/components/video.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { Video } from '../../packages/core/src/components/Video'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Video Component', () => {\n    test('creates video component with basic properties', async () => {\n        const videoElement = await TestBed.createComponent(Video, {\n            paused: true,\n            loop: false,\n            muted: true\n        })\n\n        expect(videoElement).toBeDefined()\n        expect(typeof videoElement).toBe('object')\n    })\n\n    test('creates video component with playback controls', async () => {\n        const videoElement = await TestBed.createComponent(Video, {\n            paused: false,\n            loop: true,\n            muted: false\n        })\n\n        expect(videoElement).toBeDefined()\n    })\n\n    test('handles video with loader callbacks', async () => {\n        const onProgress = vi.fn()\n        const onComplete = vi.fn()\n\n        const videoElement = await TestBed.createComponent(Video, {\n            loader: {\n                onProgress: onProgress,\n                onComplete: onComplete\n            }\n        })\n\n        expect(videoElement).toBeDefined()\n        expect(onProgress).toBeDefined()\n        expect(onComplete).toBeDefined()\n    })\n\n    test('handles dynamic playback state with signals', async () => {\n        const dynamicPaused = signal(true)\n        const dynamicLoop = signal(false)\n        const dynamicMuted = signal(true)\n\n        const videoElement = await TestBed.createComponent(Video, {\n            paused: dynamicPaused,\n            loop: dynamicLoop,\n            muted: dynamicMuted\n        })\n\n        expect(videoElement).toBeDefined()\n\n        dynamicPaused.set(false)\n        dynamicLoop.set(true)\n        dynamicMuted.set(false)\n\n        expect(dynamicPaused()).toBe(false)\n        expect(dynamicLoop()).toBe(true)\n        expect(dynamicMuted()).toBe(false)\n    })\n\n    test('handles video with different properties', async () => {\n        const video1 = await TestBed.createComponent(Video, {\n            paused: true\n        })\n\n        const video2 = await TestBed.createComponent(Video, {\n            loop: true\n        })\n\n        const video3 = await TestBed.createComponent(Video, {\n            muted: false\n        })\n\n        expect(video1).toBeDefined()\n        expect(video2).toBeDefined()\n        expect(video3).toBeDefined()\n    })\n\n    test('handles video with all basic properties', async () => {\n        const onComplete = vi.fn()\n\n        const videoElement = await TestBed.createComponent(Video, {\n            paused: false,\n            loop: true,\n            muted: false,\n            loader: {\n                onComplete: onComplete\n            }\n        })\n\n        expect(videoElement).toBeDefined()\n        expect(onComplete).toBeDefined()\n    })\n\n    test('handles video with loader progress tracking', async () => {\n        const onProgress = vi.fn()\n\n        const videoElement = await TestBed.createComponent(Video, {\n            loader: {\n                onProgress: onProgress\n            }\n        })\n\n        expect(videoElement).toBeDefined()\n        expect(onProgress).toBeDefined()\n    })\n\n    test('handles video with both loader callbacks', async () => {\n        const onProgress = vi.fn()\n        const onComplete = vi.fn()\n\n        const videoElement = await TestBed.createComponent(Video, {\n            paused: true,\n            loader: {\n                onProgress: onProgress,\n                onComplete: onComplete\n            }\n        })\n\n        expect(videoElement).toBeDefined()\n        expect(onProgress).toBeDefined()\n        expect(onComplete).toBeDefined()\n    })\n\n    test('handles video playback states', async () => {\n        const pausedVideo = await TestBed.createComponent(Video, {\n            paused: true\n        })\n\n        const playingVideo = await TestBed.createComponent(Video, {\n            paused: false\n        })\n\n        expect(pausedVideo).toBeDefined()\n        expect(playingVideo).toBeDefined()\n    })\n\n    test('handles video loop settings', async () => {\n        const loopingVideo = await TestBed.createComponent(Video, {\n            loop: true\n        })\n\n        const nonLoopingVideo = await TestBed.createComponent(Video, {\n            loop: false\n        })\n\n        expect(loopingVideo).toBeDefined()\n        expect(nonLoopingVideo).toBeDefined()\n    })\n\n    test('handles video mute settings', async () => {\n        const mutedVideo = await TestBed.createComponent(Video, {\n            muted: true\n        })\n\n        const audibleVideo = await TestBed.createComponent(Video, {\n            muted: false\n        })\n\n        expect(mutedVideo).toBeDefined()\n        expect(audibleVideo).toBeDefined()\n    })\n}) "
  },
  {
    "path": "tests/components/viewport.spec.ts",
    "content": "import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';\nimport { Viewport, Canvas, h, signal, computed } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\n\nvi.mock('pixi-viewport');\n\ndescribe('Viewport', () => {\n    // Mock function variables are not strictly needed here anymore,\n    // as we will access mocks via the instance.\n\n    beforeEach(() => {\n        // Reset mocks before each test\n        vi.resetAllMocks();\n    });\n\n    // afterEach is not needed if beforeEach resets mocks\n\n    test('should create a viewport with default settings', async () => {\n        const viewportElement = await TestBed.createComponent(Viewport);\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance).toBeDefined();\n        // Optionally check if the super constructor was called implicitly\n        // or if default options were set on the mock if necessary.\n    });\n\n    test('should set drag options', async () => {\n        const dragOptions = { pressDrag: true };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            drag: dragOptions\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.drag).toHaveBeenCalledWith(dragOptions);\n    });\n\n    test('should set wheel options when boolean', async () => {\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            wheel: true\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.wheel).toHaveBeenCalled();\n    });\n\n    test('should set wheel options with config', async () => {\n        const wheelOptions = { smooth: 10 };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            wheel: wheelOptions\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.wheel).toHaveBeenCalledWith(wheelOptions);\n    });\n\n    test('should set clamp options when boolean', async () => {\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            clamp: true\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        // Check if the correct argument is passed based on CanvasViewport logic\n        expect(viewportInstance.viewport.clamp).toHaveBeenCalledWith(true); // Assuming boolean true maps to clamp(true)\n    });\n\n    test('should set clamp options with config', async () => {\n        const clampOptions = { left: 0, right: 100, top: 0, bottom: 100 };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            clamp: clampOptions\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.clamp).toHaveBeenCalledWith(clampOptions);\n    });\n\n    test('should set decelerate options when boolean', async () => {\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            decelerate: true\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.decelerate).toHaveBeenCalled();\n    });\n\n    test('should set decelerate options with config', async () => {\n        const decelerateOptions = { friction: 0.95 };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            decelerate: decelerateOptions\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.decelerate).toHaveBeenCalledWith(decelerateOptions);\n    });\n\n    test('should set pinch options when boolean', async () => {\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            pinch: true\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.pinch).toHaveBeenCalled();\n    });\n\n    test('should set pinch options with config', async () => {\n        const pinchOptions = { percent: 1 };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            pinch: pinchOptions\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.pinch).toHaveBeenCalledWith(pinchOptions);\n    });\n\n    test('should register event listeners', async () => {\n        const onDragStart = vi.fn();\n        const onDragEnd = vi.fn();\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            'drag-start': onDragStart,\n            'drag-end': onDragEnd\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.on).toHaveBeenCalledWith('drag-start', onDragStart);\n        expect(viewportInstance.viewport.on).toHaveBeenCalledWith('drag-end', onDragEnd);\n    });\n\n    test('should update screen size based on context', async () => {\n        const width = signal(800);\n        const height = signal(600);\n\n        // Mock the context parts needed by CanvasViewport\n        const mockTick = { observable: { subscribe: vi.fn(() => ({ unsubscribe: vi.fn() })) } };\n        const mockRenderer = { events: { domElement: { addEventListener: vi.fn(), removeEventListener: vi.fn() } } };\n        const canvasSize = () => ({ width: width(), height: height() });\n        const context = { canvasSize, tick: mockTick, renderer: mockRenderer };\n\n        // Create component with mocked context\n        const viewportElement = await TestBed.createComponent(Viewport, { context });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        // Check initial screen size set during mount\n        expect(viewportInstance.viewport.screenWidth).toBe(800);\n        expect(viewportInstance.viewport.screenHeight).toBe(600);\n\n        // Update signal and trigger effect (difficult to test effect directly)\n        width.set(1024);\n        height.set(768);\n\n        // Re-render or manually trigger update if possible/needed to test effect\n        // In this setup, testing the effect directly is complex.\n        // We mostly verified that the initial values from context are used.\n    });\n\n    test('should update viewport settings when props change', async () => {\n        const worldWidth = signal(1000);\n        const worldHeight = signal(800);\n        const clampOptions = signal({ left: 0, right: 1000 });\n\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            worldWidth,\n            worldHeight,\n            clamp: clampOptions // Use signal for clamp options\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        // Check initial settings\n        expect(viewportInstance.viewport.worldWidth).toBe(1000);\n        expect(viewportInstance.viewport.worldHeight).toBe(800);\n        expect(viewportInstance.viewport.clamp).toHaveBeenCalledWith({ left: 0, right: 1000 });\n\n        // Update signals to trigger onUpdate\n        worldWidth.set(1200);\n        worldHeight.set(900);\n        clampOptions.set({ left: 10, right: 1190 });\n\n        expect(viewportInstance.viewport.worldWidth).toBe(1200);\n        expect(viewportInstance.viewport.worldHeight).toBe(900);\n        expect(viewportInstance.viewport.clamp).toHaveBeenCalledWith({ left: 10, right: 1190 });\n\n        // Re-check if mocks were called again during update (this part is hard without explicit update trigger)\n        // expect(viewportInstance.clamp).toHaveBeenCalledWith({ left: 10, right: 1190 });\n    });\n\n    test('should handle clamp prop with value property', async () => {\n        const clampConfig = { value: { left: 10, right: 90 } };\n        const viewportElement = await TestBed.createComponent(Viewport, {\n            clamp: clampConfig\n        });\n        const viewportInstance = viewportElement.componentInstance as any;\n\n        expect(viewportInstance.viewport.clamp).toHaveBeenCalledWith({ left: 10, right: 90 });\n    });\n});\n"
  },
  {
    "path": "tests/directives/drag.spec.ts",
    "content": "import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';\nimport { Container, h, signal, cond } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\nimport { Point, FederatedPointerEvent } from 'pixi.js';\n\nfunction findPrototypeWithMethod(instance: object, method: string) {\n    let proto = Object.getPrototypeOf(instance);\n    while (proto && !Object.prototype.hasOwnProperty.call(proto, method)) {\n        proto = Object.getPrototypeOf(proto);\n    }\n    return proto;\n}\n\ndescribe('Drag', () => {\n    let mockOn: ReturnType<typeof vi.fn>;\n    let mockOff: ReturnType<typeof vi.fn>;\n    let mockToLocal: ReturnType<typeof vi.fn>;\n    \n    // Mock window event listeners\n    beforeEach(async () => {\n        mockOn = vi.fn();\n        mockOff = vi.fn();\n        mockToLocal = vi.fn().mockReturnValue(new Point(10, 10));\n\n        const container = await TestBed.createComponent(Container);\n        const onPrototype = findPrototypeWithMethod(container.componentInstance, 'on');\n        const toLocalPrototype = findPrototypeWithMethod(container.componentInstance, 'toLocal');\n        vi.spyOn(onPrototype, 'on').mockImplementation(mockOn);\n        vi.spyOn(onPrototype, 'off').mockImplementation(mockOff);\n        vi.spyOn(toLocalPrototype, 'toLocal').mockImplementation(mockToLocal);\n        \n        // Spy on window methods without implementation to avoid browser errors\n        vi.spyOn(window, 'addEventListener').mockImplementation(vi.fn());\n        vi.spyOn(window, 'removeEventListener').mockImplementation(vi.fn());\n    });\n    \n    afterEach(() => {\n        vi.restoreAllMocks();\n    });\n\n    describe('drag directive', () => {\n        test('should set drag directive with all direction', async () => {\n            const container = await TestBed.createComponent(Container, { \n                drag: {\n                    direction: 'all',\n                } \n            });\n            \n            expect(container.componentInstance.eventMode).toBe('static');\n            expect(mockOn).toHaveBeenCalledWith('pointerdown', expect.any(Function));\n        });\n        \n        test('should set drag directive with x direction only', async () => {\n            const container = await TestBed.createComponent(Container, { \n                drag: {\n                    direction: 'x',\n                } \n            });\n            \n            expect(container.componentInstance.eventMode).toBe('static');\n            expect(mockOn).toHaveBeenCalledWith('pointerdown', expect.any(Function));\n        });\n        \n        test('should set drag directive with y direction only', async () => {\n            const container = await TestBed.createComponent(Container, { \n                drag: {\n                    direction: 'y',\n                } \n            });\n            \n            expect(container.componentInstance.eventMode).toBe('static');\n            expect(mockOn).toHaveBeenCalledWith('pointerdown', expect.any(Function));\n        });\n        \n        test('should work with signal values for drag properties', async () => {\n            const direction = signal('all');\n            \n            const container = await TestBed.createComponent(Container, { \n                drag: {\n                    direction,\n                    snap: 10\n                } \n            });\n            \n            expect(container.componentInstance.eventMode).toBe('static');\n            direction.set('x');\n            expect(mockOn).toHaveBeenCalledWith('pointerdown', expect.any(Function));\n        });\n        \n        test('should clean up event listeners on destroy', async () => {\n            const display = signal(true);\n            await TestBed.createComponent(\n               () => {\n                 return cond(\n                    display,\n                    () => h(Container, {\n                        drag: {\n                            direction: 'all',\n                        }\n                    })\n                )\n               } \n            );\n\n            mockOff.mockClear();\n            expect(mockOff).not.toHaveBeenCalled();\n            display.set(false);\n            expect(mockOff).toHaveBeenCalled();\n        });\n        \n        test('should handle start, move and end callbacks', async () => {\n            const onStart = vi.fn();\n            const onMove = vi.fn();\n            const onEnd = vi.fn();\n            \n            await TestBed.createComponent(Container, { \n                drag: {\n                    direction: 'all',\n                    start: onStart,\n                    move: onMove,\n                    end: onEnd\n                } \n            });\n            \n            expect(mockOn).toHaveBeenCalledWith('pointerdown', expect.any(Function));\n        });\n        \n        test('should handle conditional drag', async () => {\n            const isActive = signal(true);\n            const container = await TestBed.createComponent(Container, { \n                drag: {\n                    direction: 'all',\n                } \n            });\n            expect(container.componentInstance.eventMode).toBe('static');\n        });\n    });\n\n    describe('drag directive with keyToPress', () => {\n        test('should add keyboard listeners when keyToPress is provided', async () => {\n            // This test verifies that addEventListener is called for the keyboard events\n            await TestBed.createComponent(Container, { \n                drag: {\n                    keyToPress: ['Space']\n                } \n            });\n            \n            // Check that window event listeners were added\n            expect(window.addEventListener).toHaveBeenCalledWith('keydown', expect.any(Function));\n            expect(window.addEventListener).toHaveBeenCalledWith('keyup', expect.any(Function));\n        });\n        \n        test('should remove keyboard listeners on destroy', async () => {\n            // This test verifies that removeEventListener is called on destroy\n            const display = signal(true);\n            \n            await TestBed.createComponent(() => {\n                return cond(\n                    display,\n                    () => h(Container, {\n                        drag: {\n                            keyToPress: ['Space']\n                        }\n                    })\n                );\n            });\n            \n            // Initially, addEventListener should be called but not removeEventListener\n            expect(window.addEventListener).toHaveBeenCalledWith('keydown', expect.any(Function));\n            expect(window.addEventListener).toHaveBeenCalledWith('keyup', expect.any(Function));\n            \n            // After setting display to false (triggering destroy), removeEventListener should be called\n            display.set(false);\n            \n            // Check removeEventListener was called with the same event types\n            expect(window.removeEventListener).toHaveBeenCalledWith('keydown', expect.any(Function));\n            expect(window.removeEventListener).toHaveBeenCalledWith('keyup', expect.any(Function));\n        });\n        \n        test('should support various key configurations', async () => {\n            // Just test that we can create components with different key configurations\n            await TestBed.createComponent(Container, { \n                drag: {\n                    keyToPress: ['Space']\n                } \n            });\n            \n            await TestBed.createComponent(Container, { \n                drag: {\n                    keyToPress: ['ShiftLeft', 'ShiftRight']\n                } \n            });\n            \n            await TestBed.createComponent(Container, { \n                drag: {\n                    keyToPress: ['ControlLeft']\n                } \n            });\n            \n            await TestBed.createComponent(Container, { \n                drag: {\n                    keyToPress: ['AltLeft']\n                } \n            });\n            \n            // All tests should pass, verifying the component accepts these configurations\n            expect(true).toBe(true);\n        });\n    });\n});\n       \n"
  },
  {
    "path": "tests/directives/flash.spec.ts",
    "content": "import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';\nimport { Container, trigger, signal, cond, h } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\n\ndescribe('Flash Directive', () => {\n    beforeEach(() => {\n        vi.useFakeTimers({ shouldAdvanceTime: true });\n    });\n\n    afterEach(() => {\n        vi.restoreAllMocks();\n        vi.useRealTimers();\n    });\n\n    describe('Basic functionality', () => {\n        test('should initialize flash directive with trigger', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                }\n            });\n\n            expect(container.componentInstance).toBeDefined();\n            const originalAlpha = container.componentInstance.alpha;\n\n            // Trigger flash\n            const flashPromise = flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Alpha should have changed during flash\n            const currentAlpha = container.componentInstance.alpha;\n            expect(typeof currentAlpha).toBe('number');\n\n            // Wait for animation to complete\n            await vi.advanceTimersByTimeAsync(300);\n            await flashPromise;\n\n            // Alpha should be back to original\n            expect(container.componentInstance.alpha).toBeCloseTo(originalAlpha, 2);\n        });\n\n        test('should not flash if no trigger is provided', async () => {\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    // No trigger\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            await vi.advanceTimersByTimeAsync(1000);\n\n            // Alpha should remain unchanged\n            expect(container.componentInstance.alpha).toBe(originalAlpha);\n        });\n    });\n\n    describe('Flash type options', () => {\n        test('should flash alpha by default', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    // type defaults to 'alpha'\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150); // Halfway through default 300ms duration\n\n            // Alpha should be flashing\n            const midAlpha = container.componentInstance.alpha;\n            expect(typeof midAlpha).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should flash tint when type is tint', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'tint',\n                    tint: 0xff0000, // Red\n                }\n            });\n\n            const originalTint = (container.componentInstance as any).tint ?? 0xffffff;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Tint should be changing\n            const currentTint = (container.componentInstance as any).tint;\n            expect(currentTint).toBeDefined();\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should flash both alpha and tint when type is both', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'both',\n                    alpha: 0.3,\n                    tint: 0xff0000,\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n            const originalTint = (container.componentInstance as any).tint ?? 0xffffff;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Both alpha and tint should be changing\n            const currentAlpha = container.componentInstance.alpha;\n            const currentTint = (container.componentInstance as any).tint;\n            \n            expect(typeof currentAlpha).toBe('number');\n            expect(currentTint).toBeDefined();\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n    });\n\n    describe('Flash options', () => {\n        test('should use default values when options are not provided', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150); // Halfway through default 300ms duration\n\n            // Should be flashing - alpha might be at original if timing is exact\n            const midAlpha = container.componentInstance.alpha;\n            expect(typeof midAlpha).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should respect custom duration', async () => {\n            const flashTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            // Advance time to verify animation is running\n            await vi.advanceTimersByTimeAsync(100);\n            const currentAlpha = container.componentInstance.alpha;\n            expect(typeof currentAlpha).toBe('number');\n        }, 10000);\n\n        test('should respect custom alpha value', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'alpha',\n                    alpha: 0.1, // Very low alpha\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Alpha should be lower during flash\n            const currentAlpha = container.componentInstance.alpha;\n            expect(typeof currentAlpha).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should respect custom tint value', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'tint',\n                    tint: 0x00ff00, // Green\n                }\n            });\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Tint should be changing\n            const currentTint = (container.componentInstance as any).tint;\n            expect(currentTint).toBeDefined();\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should respect custom cycles', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    cycles: 3, // Flash 3 times\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n            const alphaValues: number[] = [];\n\n            flashTrigger.start();\n            \n            // Sample alpha values during animation\n            for (let i = 0; i < 5; i++) {\n                await vi.advanceTimersByTimeAsync(30);\n                alphaValues.push(container.componentInstance.alpha);\n            }\n\n            // With 3 cycles, we should see multiple flash patterns\n            expect(alphaValues.length).toBe(5);\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n    });\n\n    describe('Callbacks', () => {\n        test('should call onStart callback when flash starts', async () => {\n            const flashTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    onStart,\n                }\n            });\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should call onComplete callback when flash completes', async () => {\n            const flashTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalledTimes(1);\n            \n            // Verify animation is set up\n            const currentAlpha = container.componentInstance.alpha;\n            expect(typeof currentAlpha).toBe('number');\n        }, 10000);\n    });\n\n    describe('Reactive signals', () => {\n        test('should work with signal values for flash properties', async () => {\n            const flashTrigger = trigger();\n            const alphaSignal = signal(0.3);\n            const durationSignal = signal(300);\n            \n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    alpha: alphaSignal,\n                    duration: durationSignal,\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(100);\n\n            // Change alpha during animation\n            alphaSignal.set(0.1);\n            await vi.advanceTimersByTimeAsync(100);\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n\n        test('should work with signal for type', async () => {\n            const flashTrigger = trigger();\n            const typeSignal = signal<'alpha' | 'tint' | 'both'>('alpha');\n            \n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: typeSignal,\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Should flash alpha\n            const currentAlpha = container.componentInstance.alpha;\n            expect(typeof currentAlpha).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n    });\n\n    describe('Original values', () => {\n        test('should store and restore original alpha', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    originalAlpha: 0.8,\n                    duration: 200,\n                }\n            });\n\n            // Set initial alpha\n            container.componentInstance.alpha = 0.5;\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            \n            // After animation completes, should restore to originalAlpha\n            await vi.advanceTimersByTimeAsync(300);\n            \n            // Should restore to originalAlpha (0.8) not the initial value (0.5)\n            // Note: This may not work perfectly with fake timers, but we verify the setup\n            expect(container.componentInstance).toBeDefined();\n        }, 10000);\n\n        test('should store and restore original tint', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'tint',\n                    originalTint: 0x0000ff, // Blue\n                    duration: 200,\n                }\n            });\n\n            // Set initial tint\n            (container.componentInstance as any).tint = 0x00ff00; // Green\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            \n            // After animation completes, should restore to originalTint\n            await vi.advanceTimersByTimeAsync(300);\n            \n            // Should restore to originalTint (0x0000ff) not the initial value (0x00ff00)\n            // Note: This may not work perfectly with fake timers, but we verify the setup\n            const restoredTint = (container.componentInstance as any).tint;\n            expect(restoredTint).toBeDefined();\n        }, 10000);\n    });\n\n    describe('Trigger data override', () => {\n        test('should override default options with trigger data', async () => {\n            const flashTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    duration: 1000,\n                    alpha: 0.3,\n                    onStart,\n                }\n            });\n\n            // Override with trigger data\n            flashTrigger.start({\n                duration: 200,\n                alpha: 0.1,\n            });\n\n            await vi.advanceTimersByTimeAsync(0);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalled();\n        }, 10000);\n\n        test('should override type with trigger data', async () => {\n            const flashTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    type: 'alpha',\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n            const originalTint = (container.componentInstance as any).tint ?? 0xffffff;\n\n            // Override type to 'both'\n            flashTrigger.start({\n                type: 'both',\n                tint: 0xff0000,\n            });\n\n            await vi.advanceTimersByTimeAsync(150);\n\n            // Both should be changing\n            const currentAlpha = container.componentInstance.alpha;\n            const currentTint = (container.componentInstance as any).tint;\n            expect(typeof currentAlpha).toBe('number');\n            expect(currentTint).toBeDefined();\n\n            await vi.advanceTimersByTimeAsync(300);\n        });\n    });\n\n    describe('Multiple flashes', () => {\n        test('should handle multiple consecutive flashes', async () => {\n            const flashTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                flash: {\n                    trigger: flashTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            const originalAlpha = container.componentInstance.alpha;\n\n            // First flash\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            // Second flash\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            expect(onStart).toHaveBeenCalledTimes(2);\n\n            // Alpha should be back to original after animations complete\n            await vi.advanceTimersByTimeAsync(400);\n            expect(container.componentInstance.alpha).toBeCloseTo(originalAlpha, 2);\n        }, 10000);\n    });\n\n    describe('Cleanup', () => {\n        test('should restore original values on destroy', async () => {\n            const flashTrigger = trigger();\n            const display = signal(true);\n            \n            await TestBed.createComponent(() => {\n                return cond(\n                    display,\n                    () => h(Container, {\n                        flash: {\n                            trigger: flashTrigger,\n                            originalAlpha: 0.8,\n                        }\n                    })\n                );\n            });\n\n            flashTrigger.start();\n            await vi.advanceTimersByTimeAsync(100);\n\n            // Destroy component\n            display.set(false);\n            await vi.advanceTimersByTimeAsync(0);\n\n            // No errors should occur\n            expect(true).toBe(true);\n        });\n    });\n});\n\n"
  },
  {
    "path": "tests/directives/shake.spec.ts",
    "content": "import { describe, expect, test, vi, beforeEach, afterEach } from 'vitest';\nimport { Container, trigger, signal, cond, h } from 'canvasengine';\nimport { TestBed } from '../../packages/core/testing';\nimport { Point } from 'pixi.js';\n\ndescribe('Shake Directive', () => {\n    beforeEach(() => {\n        vi.useFakeTimers({ shouldAdvanceTime: true });\n    });\n\n    afterEach(() => {\n        vi.restoreAllMocks();\n        vi.useRealTimers();\n    });\n\n    describe('Basic functionality', () => {\n        test('should initialize shake directive with trigger', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200,\n                }\n            });\n\n            expect(container.componentInstance).toBeDefined();\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            // Trigger shake\n            const shakePromise = shakeTrigger.start();\n            \n            // Advance time to allow animation to progress\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Position should have changed during shake\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n            \n            // Position might be different during animation\n            expect(typeof currentX).toBe('number');\n            expect(typeof currentY).toBe('number');\n\n            // Wait for animation to complete\n            await vi.advanceTimersByTimeAsync(200);\n            await shakePromise;\n\n            // Position should be back to original\n            expect(container.componentInstance.position.x).toBeCloseTo(originalX, 1);\n            expect(container.componentInstance.position.y).toBeCloseTo(originalY, 1);\n        });\n\n        test('should not shake if no trigger is provided', async () => {\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    // No trigger\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            await vi.advanceTimersByTimeAsync(1000);\n\n            // Position should remain unchanged\n            expect(container.componentInstance.position.x).toBe(originalX);\n            expect(container.componentInstance.position.y).toBe(originalY);\n        });\n    });\n\n    describe('Shake options', () => {\n        test('should use default values when options are not provided', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200, // Use shorter duration for test\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(100); // Halfway through 200ms duration\n\n            // Should be shaking - check that position has changed or animation is active\n            const midX = container.componentInstance.position.x;\n            const midY = container.componentInstance.position.y;\n            // At least verify the directive is working\n            expect(container.componentInstance).toBeDefined();\n            expect(typeof midX).toBe('number');\n            expect(typeof midY).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should respect custom intensity', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    intensity: 20,\n                    duration: 200,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // With higher intensity, position should change more\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n\n            // Should be shaking - verify directive is working\n            expect(container.componentInstance).toBeDefined();\n            expect(typeof currentX).toBe('number');\n            expect(typeof currentY).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should respect custom duration', async () => {\n            const shakeTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            // Advance time to verify animation is running\n            await vi.advanceTimersByTimeAsync(100);\n            const currentX = container.componentInstance.position.x;\n            expect(typeof currentX).toBe('number');\n        }, 10000);\n\n        test('should respect custom frequency', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    frequency: 20, // More oscillations\n                    duration: 200,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            shakeTrigger.start();\n            \n            // Track position changes to verify frequency\n            const positions: number[] = [];\n            for (let i = 0; i < 5; i++) {\n                await vi.advanceTimersByTimeAsync(20);\n                positions.push(container.componentInstance.position.x);\n            }\n\n            // With higher frequency, we should see more oscillations\n            expect(positions.length).toBe(5);\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should shake only in x direction', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    direction: 'x',\n                    duration: 200,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // X should change, Y should remain the same\n            // Note: position might be at original if animation hasn't started or has completed\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n            expect(currentY).toBe(originalY); // Y should always remain unchanged\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should shake only in y direction', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    direction: 'y',\n                    duration: 200,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Y should change, X should remain the same\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n            expect(currentX).toBe(originalX); // X should always remain unchanged\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should shake in both directions by default', async () => {\n            const shakeTrigger = trigger();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200,\n                    // direction defaults to 'both'\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Both X and Y can change (or be at original if animation timing)\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n            expect(typeof currentX).toBe('number');\n            expect(typeof currentY).toBe('number');\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n    });\n\n    describe('Callbacks', () => {\n        test('should call onStart callback when shake starts', async () => {\n            const shakeTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    onStart,\n                    duration: 200,\n                }\n            });\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n\n        test('should call onComplete callback when shake completes', async () => {\n            const shakeTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(0);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalledTimes(1);\n            \n            // Verify animation is set up\n            const currentX = container.componentInstance.position.x;\n            expect(typeof currentX).toBe('number');\n        }, 10000);\n    });\n\n    describe('Reactive signals', () => {\n        test('should work with signal values for shake properties', async () => {\n            const shakeTrigger = trigger();\n            const intensitySignal = signal(10);\n            const durationSignal = signal(500);\n            \n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    intensity: intensitySignal,\n                    duration: durationSignal,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(100);\n\n            // Change intensity during animation\n            intensitySignal.set(20);\n            await vi.advanceTimersByTimeAsync(100);\n\n            await vi.advanceTimersByTimeAsync(500);\n        });\n\n        test('should work with signal for direction', async () => {\n            const shakeTrigger = trigger();\n            const directionSignal = signal<'x' | 'y' | 'both'>('x');\n            \n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    direction: directionSignal,\n                    duration: 200,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Should shake only in X - Y should remain unchanged\n            const currentX = container.componentInstance.position.x;\n            const currentY = container.componentInstance.position.y;\n            expect(currentY).toBe(originalY); // Y should always remain unchanged\n\n            await vi.advanceTimersByTimeAsync(200);\n        });\n    });\n\n    describe('Trigger data override', () => {\n        test('should override default options with trigger data', async () => {\n            const shakeTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 1000,\n                    intensity: 10,\n                    onStart,\n                }\n            });\n\n            // Override with trigger data\n            shakeTrigger.start({\n                duration: 200,\n                intensity: 30,\n            });\n\n            await vi.advanceTimersByTimeAsync(50);\n\n            // onStart should be called immediately\n            expect(onStart).toHaveBeenCalled();\n        }, 10000);\n    });\n\n    describe('Multiple shakes', () => {\n        test('should handle multiple consecutive shakes', async () => {\n            const shakeTrigger = trigger();\n            const onStart = vi.fn();\n            const container = await TestBed.createComponent(Container, {\n                shake: {\n                    trigger: shakeTrigger,\n                    duration: 200,\n                    onStart,\n                }\n            });\n\n            const originalX = container.componentInstance.position.x;\n            const originalY = container.componentInstance.position.y;\n\n            // First shake\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            expect(onStart).toHaveBeenCalledTimes(1);\n\n            // Second shake\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n            expect(onStart).toHaveBeenCalledTimes(2);\n\n            // Position should be back to original after animations complete\n            await vi.advanceTimersByTimeAsync(400);\n            expect(container.componentInstance.position.x).toBeCloseTo(originalX, 1);\n            expect(container.componentInstance.position.y).toBeCloseTo(originalY, 1);\n        }, 10000);\n    });\n\n    describe('Cleanup', () => {\n        test('should reset position on destroy', async () => {\n            const shakeTrigger = trigger();\n            const display = signal(true);\n            \n            await TestBed.createComponent(() => {\n                return cond(\n                    display,\n                    () => h(Container, {\n                        shake: {\n                            trigger: shakeTrigger,\n                        }\n                    })\n                );\n            });\n\n            shakeTrigger.start();\n            await vi.advanceTimersByTimeAsync(50);\n\n            // Destroy component\n            display.set(false);\n            await vi.advanceTimersByTimeAsync(0);\n\n            // No errors should occur\n            expect(true).toBe(true);\n        });\n    });\n});\n\n"
  },
  {
    "path": "tests/engine/animation.spec.ts",
    "content": "import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'\nimport { animatedSignal, isAnimatedSignal, animatedSequence, signal, AnimateOptions, effect } from 'canvasengine'\n\ndescribe('animation', () => {\n  describe('animatedSignal', () => {\n    beforeEach(() => {\n      vi.useFakeTimers({ shouldAdvanceTime: true })\n    })\n\n    afterEach(() => {\n      vi.useRealTimers()\n    })\n\n    it('should create an animated signal with initial value', () => {\n      const signal = animatedSignal(10)\n      expect(signal()).toBe(10)\n    })\n\n    it('should update value with set', async () => {\n      const signal = animatedSignal(0, { duration: 100 })\n      const promise = signal.set(10)\n      \n      // Check initial state\n      expect(signal()).toBe(0)\n      \n      // Advance halfway through animation\n      await vi.advanceTimersByTimeAsync(50)\n      const midValue = signal()\n      expect(midValue).toBeGreaterThan(0)\n      expect(midValue).toBeLessThan(10)\n      \n      await promise\n      expect(signal()).toBe(10)\n    })\n\n    it('should update value with update function', async () => {\n      const signal = animatedSignal(5)\n      signal.update(v => v * 2)\n      await vi.advanceTimersByTimeAsync(100)\n      expect(signal()).toBe(10)\n    })\n\n    it('should call onUpdate during animation', async () => {\n      const onUpdate = vi.fn()\n      const signal = animatedSignal(0, { onUpdate })\n      await signal.set(10)\n      await vi.advanceTimersByTimeAsync(100)\n      expect(onUpdate).toHaveBeenCalled()\n    })\n\n    it('should track animation state', async () => {\n      const signal = animatedSignal(0)\n      const promise = signal.set(10)\n      await vi.advanceTimersByTimeAsync(100)\n      expect(signal.animatedState().start).toBe(0)\n      expect(signal.animatedState().end).toBe(10)\n      await promise\n      expect(signal.animatedState().current).toBe(10)\n    })\n\n    it('should use custom duration from options', async () => {\n      const signal = animatedSignal(0, { duration: 200 })\n      const promise = signal.set(10)\n      \n      await vi.advanceTimersByTimeAsync(100)\n      const midValue = signal()\n      expect(midValue).toBeGreaterThan(0)\n      expect(midValue).toBeLessThan(10)\n      \n      await vi.advanceTimersByTimeAsync(100)\n      await promise\n      expect(signal()).toBe(10)\n    })\n\n    it('should override duration in set method', async () => {\n      const signal = animatedSignal(0, { duration: 500 })\n      const promise = signal.set(10, { duration: 100 })\n      \n      await vi.advanceTimersByTimeAsync(50)\n      const midValue = signal()\n      expect(midValue).toBeGreaterThan(0)\n      expect(midValue).toBeLessThan(10)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      await promise\n      expect(signal()).toBe(10)\n    })\n\n    it('should call onComplete callback when animation finishes', async () => {\n      const onComplete = vi.fn()\n      const signal = animatedSignal(0, { duration: 100 })\n      const promise = signal.set(10, { onComplete })\n      \n      expect(onComplete).not.toHaveBeenCalled()\n      await vi.runAllTimersAsync()\n      await promise\n      // onComplete should be called when animation completes\n      expect(onComplete).toHaveBeenCalledTimes(1)\n      expect(signal()).toBe(10)\n    })\n\n    it('should call onComplete from options when no onComplete in animationConfig', async () => {\n      const onComplete = vi.fn()\n      const signal = animatedSignal(0, { duration: 100, onComplete })\n      const promise = signal.set(10)\n      \n      expect(onComplete).not.toHaveBeenCalled()\n      await vi.runAllTimersAsync()\n      await promise\n      // onComplete from options should be called when animation completes\n      expect(onComplete).toHaveBeenCalledTimes(1)\n      expect(signal()).toBe(10)\n    })\n\n    it('should prioritize animationConfig.onComplete over options.onComplete', async () => {\n      const optionsOnComplete = vi.fn()\n      const configOnComplete = vi.fn()\n      const signal = animatedSignal(0, { duration: 100, onComplete: optionsOnComplete })\n      const promise = signal.set(10, { onComplete: configOnComplete })\n      \n      expect(optionsOnComplete).not.toHaveBeenCalled()\n      expect(configOnComplete).not.toHaveBeenCalled()\n      await vi.runAllTimersAsync()\n      await promise\n      // Only configOnComplete should be called\n      expect(configOnComplete).toHaveBeenCalledTimes(1)\n      expect(optionsOnComplete).not.toHaveBeenCalled()\n      expect(signal()).toBe(10)\n    })\n\n    it('should use custom ease function', async () => {\n      const linearEase = (t: number) => t\n      const signal = animatedSignal(0, { duration: 100, ease: linearEase })\n      const promise = signal.set(10)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      const midValue = signal()\n      // With linear ease, halfway through duration should be roughly halfway through value\n      expect(midValue).toBeGreaterThan(0)\n      expect(midValue).toBeLessThan(10)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      await promise\n      expect(signal()).toBe(10)\n    })\n\n    it('should interrupt previous animation when new one starts', async () => {\n      const signal = animatedSignal(0, { duration: 200 })\n      signal.set(10)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      const midValue = signal()\n      // Animation should have progressed\n      expect(midValue).toBeGreaterThanOrEqual(0)\n      \n      // Start new animation before first completes\n      const secondPromise = signal.set(20)\n      expect(signal.animatedState().end).toBe(20)\n      \n      await vi.advanceTimersByTimeAsync(200)\n      await secondPromise\n      expect(signal()).toBe(20)\n    })\n\n    it('should be reactive with effect', async () => {\n      const signal = animatedSignal(0, { duration: 100 })\n      const values: number[] = []\n      \n      effect(() => {\n        values.push(signal())\n      })\n      \n      expect(values.length).toBeGreaterThan(0)\n      expect(values[values.length - 1]).toBe(0)\n      \n      const promise = signal.set(10)\n      await vi.advanceTimersByTimeAsync(50)\n      // Effect should have been called during animation\n      expect(values.length).toBeGreaterThan(1)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      await promise\n      expect(values[values.length - 1]).toBe(10)\n    })\n\n    it('should have reactive animatedState', async () => {\n      const signal = animatedSignal(0, { duration: 100 })\n      const states: Array<{ start: number; end: number; current: number }> = []\n      \n      effect(() => {\n        const state = signal.animatedState()\n        states.push({ ...state })\n      })\n      \n      expect(states.length).toBeGreaterThan(0)\n      expect(states[0].current).toBe(0)\n      \n      const promise = signal.set(10)\n      await vi.advanceTimersByTimeAsync(100)\n      await promise\n      \n      const lastState = states[states.length - 1]\n      expect(lastState.end).toBe(10)\n      expect(lastState.current).toBe(10)\n    })\n\n    it('should work with different value types', async () => {\n      const stringSignal = animatedSignal('start', { duration: 100 })\n      const promise = stringSignal.set('end')\n      await vi.advanceTimersByTimeAsync(100)\n      await promise\n      expect(stringSignal()).toBe('end')\n    })\n\n    it('should call onUpdate with correct values during animation', async () => {\n      const updateValues: number[] = []\n      const onUpdate = vi.fn((value: number) => {\n        updateValues.push(value)\n      })\n      const signal = animatedSignal(0, { duration: 100, onUpdate })\n      \n      const promise = signal.set(10)\n      await vi.advanceTimersByTimeAsync(50)\n      // onUpdate should have been called during animation\n      expect(onUpdate).toHaveBeenCalled()\n      expect(updateValues.length).toBeGreaterThan(0)\n      expect(updateValues[0]).toBeGreaterThanOrEqual(0)\n      \n      await vi.advanceTimersByTimeAsync(50)\n      await promise\n      expect(updateValues[updateValues.length - 1]).toBeCloseTo(10, 1)\n    })\n\n    it('should handle multiple sequential set calls', async () => {\n      const signal = animatedSignal(0, { duration: 50 })\n      \n      const promise1 = signal.set(10)\n      await vi.advanceTimersByTimeAsync(50)\n      await promise1\n      expect(signal()).toBe(10)\n      \n      const promise2 = signal.set(20)\n      await vi.advanceTimersByTimeAsync(50)\n      await promise2\n      expect(signal()).toBe(20)\n      \n      const promise3 = signal.set(30)\n      await vi.advanceTimersByTimeAsync(50)\n      await promise3\n      expect(signal()).toBe(30)\n    })\n\n    it('should handle update with custom options', async () => {\n      const signal = animatedSignal(5, { duration: 100 })\n      signal.update(v => v * 2)\n      // Update uses default duration (20ms) from animation implementation\n      await vi.runAllTimersAsync()\n      expect(signal()).toBe(10)\n    })\n  })\n\n  describe('isAnimatedSignal', () => {\n    it('should return true for animated signals', () => {\n      const animSignal = animatedSignal(0)\n      expect(isAnimatedSignal(animSignal)).toBe(true)\n    })\n\n    it('should return false for non-animated signals', () => {\n      const regularSignal = signal(0)\n      expect(isAnimatedSignal(regularSignal)).toBe(false)\n    })\n  })\n\n  describe('animatedSequence', () => {\n    beforeEach(() => {\n      vi.useFakeTimers({ shouldAdvanceTime: true })\n    })\n\n    afterEach(() => {\n      vi.useRealTimers()\n    })\n\n    it('should execute animations in sequence', async () => {\n      const values: number[] = []\n      const sequence = [\n        async () => { values.push(1) },\n        async () => { values.push(2) },\n        async () => { values.push(3) }\n      ]\n      await animatedSequence(sequence)\n      expect(values).toEqual([1, 2, 3])\n    })\n\n    it('should execute parallel animations', async () => {\n      const values = new Set<number>()\n      const addWithDelay = (n: number, delay: number) => \n        async () => {\n          await new Promise(resolve => setTimeout(resolve, delay))\n          values.add(n)\n        }\n\n      await animatedSequence([\n        [\n          addWithDelay(1, 20),\n          addWithDelay(2, 10)\n        ]\n      ])\n      \n      expect(values.has(1)).toBe(true)\n      expect(values.has(2)).toBe(true)\n    })\n\n    it('should handle mixed sequential and parallel animations', async () => {\n      const values: number[] = []\n      await animatedSequence([\n        async () => { values.push(1) },\n        [\n          async () => { values.push(2) },\n          async () => { values.push(3) }\n        ],\n        async () => { values.push(4) }\n      ])\n      \n      expect(values[0]).toBe(1)\n      expect(values.includes(2)).toBe(true)\n      expect(values.includes(3)).toBe(true)\n      expect(values[values.length - 1]).toBe(4)\n    })\n\n    it('should execute animatedSignal animations in sequence', async () => {\n      const signal1 = animatedSignal(0, { duration: 50 })\n      const signal2 = animatedSignal(0, { duration: 50 })\n      \n      const promise = animatedSequence([\n        () => signal1.set(10),\n        () => signal2.set(20)\n      ])\n      \n      // Run all timers to allow both animations to complete\n      await vi.runAllTimersAsync()\n      await promise\n      expect(signal1()).toBe(10)\n      expect(signal2()).toBe(20)\n    })\n\n    it('should execute animatedSignal animations in parallel', async () => {\n      const signal1 = animatedSignal(0, { duration: 100 })\n      const signal2 = animatedSignal(0, { duration: 100 })\n      \n      const promise = animatedSequence([\n        [\n          () => signal1.set(10),\n          () => signal2.set(20)\n        ]\n      ])\n      \n      // Run all timers to allow both animations to complete\n      await vi.runAllTimersAsync()\n      await promise\n      expect(signal1()).toBe(10)\n      expect(signal2()).toBe(20)\n    })\n\n    it('should handle empty sequence', async () => {\n      await expect(animatedSequence([])).resolves.toBeUndefined()\n    })\n\n    it('should return a promise that resolves when sequence completes', async () => {\n      const signal1 = animatedSignal(0, { duration: 50 })\n      const signal2 = animatedSignal(0, { duration: 50 })\n      \n      let sequenceCompleted = false\n      const sequencePromise = animatedSequence([\n        () => signal1.set(10),\n        () => signal2.set(20)\n      ]).then(() => {\n        sequenceCompleted = true\n      })\n      \n      expect(sequenceCompleted).toBe(false)\n      // Run all timers to allow both sequential animations to complete\n      await vi.runAllTimersAsync()\n      await sequencePromise\n      expect(sequenceCompleted).toBe(true)\n    })\n\n    it('should handle complex mixed sequence with animatedSignals', async () => {\n      const rect1X = animatedSignal(10, { duration: 50 })\n      const rect2Y = animatedSignal(10, { duration: 50 })\n      const rect3Scale = animatedSignal(1, { duration: 50 })\n      \n      const promise = animatedSequence([\n        () => rect1X.set(100),\n        [\n          () => rect2Y.set(50),\n          () => rect3Scale.set(1.5)\n        ],\n        () => rect1X.set(10),\n        [\n          () => rect1X.set(30),\n          () => rect2Y.set(20),\n          () => rect3Scale.set(0.8)\n        ]\n      ])\n      \n      // Run all timers to allow the entire sequence to complete\n      await vi.runAllTimersAsync()\n      await promise\n      expect(rect1X()).toBe(30)\n      expect(rect2Y()).toBe(20)\n      expect(rect3Scale()).toBeCloseTo(0.8, 1)\n    })\n      \n  })\n})\n"
  },
  {
    "path": "tests/engine/cond-loop.spec.ts",
    "content": "import { describe, expect, test, beforeEach, vi } from 'vitest'\nimport { loop, Container, h, signal, computed, cond } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Cond cleanup in Loop', () => {\n    beforeEach(() => {\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n    test('should destroy conditional element when loop updates', async () => {\n        const data = signal({\n            elements: [\n                { id: 1, x: 0, y: 0 }\n            ]\n        })\n\n        const elements = computed(() => data().elements)\n\n        // Child component simulating the user's structure:\n        // <Sprite />\n        // @if (true) { <Rect /> }\n        const Child = (props) => {\n            return [\n                h(Container, { ...props, name: 'sprite' }),\n                cond(true, () => h(Container, { ...props, name: 'rect' }))\n            ]\n        }\n\n        const loopValue = loop(elements, (item) => {\n            return h(Child, item)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state\n        // Container children should contain the elements from the loop.\n        // Since Child returns an array [Sprite, Rect], and loop flattens?\n        // Let's check how loop handles component returning array.\n        // If Child is a component, `h(Child)` creates an Element with componentInstance.\n        // But Child here is a functional component returning an array.\n        // In CanvasEngine, functional components are just functions returning Elements.\n        // So `h(Child)` might not be the right way if Child is just a function.\n        // The user uses `<Child ...obj />` which implies Child is a component.\n        // If Child is a .ce file, it's a class component or similar.\n\n        // Let's simulate Child as a class component that renders the array in its render/template.\n        // But for simplicity, let's assume `createElementFn` in `loop` returns the result of `Child(item)`.\n\n        // If I use `h(Child, item)`, `Child` must be a class with `render` or similar, OR `h` handles functional components.\n        // Looking at `reactive.ts`, `h` is likely `createComponent` or similar.\n        // `createComponent` expects a tag (string) and looks up in `components`.\n        // But `h` in tests usually maps to `createElement` or helper.\n        // In `loop-spread-props.spec.ts`, it uses `h(Container, obj)`. `Container` is a class.\n\n        // Let's try to define Child as a class component.\n        class ChildComponent {\n            props: any\n            children: any[] = []\n\n            onInit(props) {\n                this.props = props\n            }\n\n            // In the real engine, the template compiler generates code that calls `createElement` or returns structure.\n            // If `Child.ce` has `<Sprite>... <Rect>...`, it effectively puts them in the parent container?\n            // Or does Child create a container itself?\n            // Usually `<Child>` creates a component instance.\n            // If the template has multiple root nodes, it might be a fragment.\n\n            // Let's look at `reactive.ts` `createElement` again.\n            // It handles `Observable` which emits `elements`.\n\n            // If I want to simulate the user's issue exactly, I should probably use `loop` directly returning the structure.\n            // loop(elements, (item) => [ h(Sprite, item), cond(true, () => h(Rect, item)) ])\n        }\n\n        // Let's try to simulate what the compiler does for `Child.ce`.\n        // It probably compiles to a function that sets up the view.\n        // But here we are testing `loop` + `cond`.\n\n        // Let's try to reproduce with `loop` returning an array containing `cond`.\n        const loopValue2 = loop(elements, (item) => {\n            return [\n                h(Container, { name: 'sprite', ...item }),\n                cond(true, () => h(Container, { name: 'rect', ...item }))\n            ] as any\n        })\n\n        const root = await TestBed.createComponent(Container, {}, loopValue2)\n\n        // Check children of root.\n        // loop returns a FlowObservable.\n        // TestBed.createComponent mounts the loopValue.\n        // If loop returns array of elements, they should be appended to root.\n\n        // Initial check\n        // We expect 1 item in loop.\n        // That item returns [Sprite, Rect].\n        // So root should have 2 children.\n        expect(root.componentInstance.children.length).toBe(2)\n        expect(root.componentInstance.children[1].x).toBe(0)\n\n        // Update data\n        data.set({\n            elements: [\n                { id: 1, x: 100, y: 100 } // Same ID, but new object reference, loop might treat as update or replace\n            ]\n        })\n\n        // In `reactive.ts`, `loop` handles updates.\n        // If it's a replace (new object), it might destroy old and create new.\n\n        await vi.waitFor(() => {\n            // Should still have 2 children (new ones)\n            // The issue is that the old Rect might remain, so we might have 3 children or more?\n            // Or the new Rect is there but the old one wasn't destroyed?\n\n            // If the bug exists, we might see extra children.\n            expect(root.componentInstance.children.length).toBe(2)\n            expect(root.componentInstance.children[1].x).toBe(100)\n        })\n    })\n})\n"
  },
  {
    "path": "tests/engine/cond.spec.ts",
    "content": "import { cond, Container, h, signal, Text } from \"canvasengine\";\nimport { expect, test } from \"vitest\";\nimport { TestBed } from \"../../packages/core/testing\";\n\ntest(`Test cond`, async () => {\n    const value = cond(\n        signal(true),\n        () => h(Container)\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n});\n\ntest(`Test cond == false`, async () => {\n    const value = cond(\n        signal(false),\n        () => h(Container)\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(0)\n});\n\ntest(`Use not signal`, async () => {\n    const value = cond(\n        true,\n        () => h(Container)\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n});\n\ntest(`Test cond with else - condition true`, async () => {\n    const value = cond(\n        signal(true),\n        () => h(Text, { text: 'If case' }),\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('If case')\n});\n\ntest(`Test cond with else - condition false`, async () => {\n    const value = cond(\n        signal(false),\n        () => h(Text, { text: 'If case' }),\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Else case')\n});\n\ntest(`Test cond with else - static boolean true`, async () => {\n    const value = cond(\n        true,\n        () => h(Text, { text: 'If case' }),\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('If case')\n});\n\ntest(`Test cond with else - static boolean false`, async () => {\n    const value = cond(\n        false,\n        () => h(Text, { text: 'If case' }),\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Else case')\n});\n\ntest(`Test cond with else if - first condition true`, async () => {\n    const value = cond(\n        signal(true),\n        () => h(Text, { text: 'If case' }),\n        [signal(false), () => h(Text, { text: 'Else if case' })],\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('If case')\n});\n\ntest(`Test cond with else if - second condition true`, async () => {\n    const value = cond(\n        signal(false),\n        () => h(Text, { text: 'If case' }),\n        [signal(true), () => h(Text, { text: 'Else if case' })],\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Else if case')\n});\n\ntest(`Test cond with else if - no condition true, use else`, async () => {\n    const value = cond(\n        signal(false),\n        () => h(Text, { text: 'If case' }),\n        [signal(false), () => h(Text, { text: 'Else if case' })],\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Else case')\n});\n\ntest(`Test cond with multiple else if conditions`, async () => {\n    const score = signal(85)\n    const value = cond(\n        () => score() >= 90,\n        () => h(Text, { text: 'A+' }),\n        [() => score() >= 80, () => h(Text, { text: 'A' })],\n        [() => score() >= 70, () => h(Text, { text: 'B' })],\n        [() => score() >= 60, () => h(Text, { text: 'C' })],\n        () => h(Text, { text: 'F' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('A')\n});\n\ntest(`Test cond with multiple else if - no match, use else`, async () => {\n    const score = signal(45)\n    const value = cond(\n        () => score() >= 90,\n        () => h(Text, { text: 'A+' }),\n        [() => score() >= 80, () => h(Text, { text: 'A' })],\n        [() => score() >= 70, () => h(Text, { text: 'B' })],\n        [() => score() >= 60, () => h(Text, { text: 'C' })],\n        () => h(Text, { text: 'F' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('F')\n});\n\ntest(`Test cond reactivity - condition changes`, async () => {\n    const isVisible = signal(true)\n    const value = cond(\n        isVisible,\n        () => h(Text, { text: 'Visible' }),\n        () => h(Text, { text: 'Hidden' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    \n    // Initially visible\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Visible')\n    \n    // Change to hidden\n    isVisible.set(false)\n    await new Promise(resolve => setTimeout(resolve, 10)) // Wait for reactivity\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Hidden')\n    \n    // Change back to visible\n    isVisible.set(true)\n    await new Promise(resolve => setTimeout(resolve, 10)) // Wait for reactivity\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Visible')\n});\n\ntest(`Test cond reactivity with else if - conditions change`, async () => {\n    const status = signal('loading')\n    const value = cond(\n        () => status() === 'loading',\n        () => h(Text, { text: 'Loading...' }),\n        [() => status() === 'error', () => h(Text, { text: 'Error!' })],\n        [() => status() === 'success', () => h(Text, { text: 'Success!' })],\n        () => h(Text, { text: 'Unknown' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    \n    // Initially loading\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Loading...')\n    \n    // Change to error\n    status.set('error')\n    await new Promise(resolve => setTimeout(resolve, 10)) // Wait for reactivity\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Error!')\n    \n    // Change to success\n    status.set('success')\n    await new Promise(resolve => setTimeout(resolve, 10)) // Wait for reactivity\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Success!')\n    \n    // Change to unknown status\n    status.set('unknown')\n    await new Promise(resolve => setTimeout(resolve, 10)) // Wait for reactivity\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Unknown')\n});\n\ntest(`Test cond with static boolean conditions`, async () => {\n    const value = cond(\n        false,\n        () => h(Text, { text: 'If case' }),\n        [false, () => h(Text, { text: 'Else if 1' })],\n        [true, () => h(Text, { text: 'Else if 2' })],\n        [false, () => h(Text, { text: 'Else if 3' })],\n        () => h(Text, { text: 'Else case' })\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(1)\n    expect((container.componentInstance.children[0] as any).text).toBe('Else if 2')\n});\n\ntest(`Test cond without else - no condition matches`, async () => {\n    const value = cond(\n        signal(false),\n        () => h(Text, { text: 'If case' }),\n        [signal(false), () => h(Text, { text: 'Else if case' })]\n    )\n    const container = await TestBed.createComponent(Container, {}, value)\n    expect(container.componentInstance.children.length).toBe(0)\n});\n"
  },
  {
    "path": "tests/engine/define-props.spec.ts",
    "content": "import { describe, it, expect } from 'vitest'\nimport { useDefineProps, signal, isSignal } from 'canvasengine'\n\ndescribe('useDefineProps', () => {\n\n    it('Just Get the props', () => {\n        const defineProps = useDefineProps({ speed: 1 })\n        const props = defineProps()\n\n        expect(props.speed()).toBe(1)\n    })\n\n    it('should handle basic props with default values', () => {\n        const defineProps = useDefineProps({ speed: 1 })\n        const props = defineProps({\n            speed: {\n                default: 0.05\n            }\n        })\n\n        expect(isSignal(props.speed)).toBe(true)\n        expect(props.speed()).toBe(1)\n    })\n\n    it('should use default value when prop is undefined', () => {\n        const defineProps = useDefineProps({})\n        const props = defineProps({\n            speed: {\n                default: 0.05\n            }\n        })\n\n        expect(isSignal(props.speed)).toBe(true)\n        expect(props.speed()).toBe(0.05)\n    })\n\n    it('should handle type validation', () => {\n        const defineProps = useDefineProps({ speed: 1, name: 'test' })\n        const props = defineProps({\n            speed: { type: Number },\n            name: { type: String }\n        })\n\n        expect(props.speed()).toBe(1)\n        expect(props.name()).toBe('test')\n    })\n\n    it('should throw error for invalid type', () => {\n        const defineProps = useDefineProps({ speed: 'invalid' })\n        \n        expect(() => {\n            defineProps({\n                speed: { type: Number }\n            })\n        }).toThrow('Invalid prop: type check failed for prop \"speed\"')\n    })\n\n    it('should handle required props', () => {\n        const defineProps = useDefineProps({ speed: 1 })\n        const props = defineProps({\n            speed: { required: true }\n        })\n\n        expect(props.speed()).toBe(1)\n    })\n\n    it('should throw error for missing required prop', () => {\n        const defineProps = useDefineProps({})\n        \n        expect(() => {\n            defineProps({\n                speed: { required: true }\n            })\n        }).toThrow('Missing required prop: speed')\n    })\n\n    it('should handle custom validator', () => {\n        const defineProps = useDefineProps({ speed: 5 })\n        const props = defineProps({\n            speed: {\n                validator: (value) => value >= 0 && value <= 10\n            }\n        })\n\n        expect(props.speed()).toBe(5)\n    })\n\n    it('should throw error for invalid custom validation', () => {\n        const defineProps = useDefineProps({ speed: 20 })\n        \n        expect(() => {\n            defineProps({\n                speed: {\n                    validator: (value) => value >= 0 && value <= 10\n                }\n            })\n        }).toThrow('Invalid prop: custom validation failed for prop \"speed\"')\n    })\n\n    it('should handle multiple types', () => {\n        const defineProps = useDefineProps({ value: 1 })\n        const props = defineProps({\n            value: { type: [Number, String] }\n        })\n\n        expect(props.value()).toBe(1)\n    })\n\n    it('should preserve signals passed as props', () => {\n        const speedSignal = signal(1)\n        const defineProps = useDefineProps({ speed: speedSignal })\n        const props = defineProps({\n            speed: { type: Number }\n        })\n\n        expect(props.speed).toBe(speedSignal)\n    })\n})"
  },
  {
    "path": "tests/engine/dependencies.spec.ts",
    "content": "import { Container, h, mount, signal } from \"canvasengine\";\nimport { describe, expect, test, vi } from \"vitest\";\nimport { TestBed } from \"../../packages/core/testing\";\n\ndescribe('Dependencies Prop', () => {\n    test('component mounts immediately with defined signal dependency', async () => {\n        const mockMount = vi.fn();\n        const mockCreate = vi.fn();\n        const dep = signal('defined value');\n\n        function MyComponent() {\n            mockCreate();\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [dep] });\n\n        expect(mockMount).toHaveBeenCalledTimes(1);\n        expect(mockCreate).toHaveBeenCalledTimes(1);\n    });\n\n    test('component does not mount with undefined signal dependency', async () => {\n        const mockMount = vi.fn();\n        const mockCreate = vi.fn();\n        const dep = signal<string | undefined>(undefined);\n\n        function MyComponent() {\n            mockCreate();\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [dep] });\n\n        // Should not have mounted because dependency is undefined\n        expect(mockMount).toHaveBeenCalledTimes(0);\n        expect(mockCreate).toHaveBeenCalledTimes(0);\n    });\n\n    test('component mounts when signal dependency becomes defined', async () => {\n        const mockMount = vi.fn();\n        const dep = signal<string | undefined>(undefined);\n\n        function MyComponent() {\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [dep] });\n\n        // Should not have mounted yet\n        expect(mockMount).toHaveBeenCalledTimes(0);\n\n        // Set the dependency to a defined value\n        dep.set('now defined');\n        await new Promise(resolve => setTimeout(resolve, 10));\n\n        // Should now be mounted\n        expect(mockMount).toHaveBeenCalledTimes(1);\n    });\n\n    test('component mounts with resolved promise dependency', async () => {\n        const mockMount = vi.fn();\n        const dep = Promise.resolve('resolved value');\n\n        function MyComponent() {\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [dep] });\n\n        // Wait for async checkDependencies to complete\n        await new Promise(resolve => setTimeout(resolve, 10));\n\n        expect(mockMount).toHaveBeenCalledTimes(1);\n    });\n\n    test('component does not mount when promise resolves to undefined', async () => {\n        const mockMount = vi.fn();\n        const dep = Promise.resolve(undefined);\n\n        function MyComponent() {\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [dep] });\n\n        expect(mockMount).toHaveBeenCalledTimes(0);\n    });\n\n    test('component mounts when all mixed dependencies are ready', async () => {\n        const mockMount = vi.fn();\n        const signalDep = signal('signal value');\n        const promiseDep = Promise.resolve('promise value');\n\n        function MyComponent() {\n\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [signalDep, promiseDep] });\n\n        // Wait for async checkDependencies to complete\n        await new Promise(resolve => setTimeout(resolve, 10));\n\n        expect(mockMount).toHaveBeenCalledTimes(1);\n    });\n\n    test('component does not mount when one of many dependencies is undefined', async () => {\n        const mockMount = vi.fn();\n        const definedSignal = signal('defined');\n        const undefinedSignal = signal<string | undefined>(undefined);\n\n        function MyComponent() {\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, { dependencies: [definedSignal, undefinedSignal] });\n\n        // Should not have mounted because one dependency is undefined\n        expect(mockMount).toHaveBeenCalledTimes(0);\n\n        // Set the undefined signal to a value\n        undefinedSignal.set('now defined');\n        await new Promise(resolve => setTimeout(resolve, 10));\n\n        // Should now be mounted\n        expect(mockMount).toHaveBeenCalledTimes(1);\n    });\n\n    test('component without dependencies prop mounts normally', async () => {\n        const mockMount = vi.fn();\n\n        function MyComponent() {\n            mount((element) => {\n                mockMount(element);\n            });\n            return h(Container);\n        }\n\n        await TestBed.createComponent(MyComponent, {});\n\n        expect(mockMount).toHaveBeenCalledTimes(1);\n    });\n});\n"
  },
  {
    "path": "tests/engine/focus-loop-sharing.spec.ts",
    "content": "import { loop, FocusContainer, Button, signal } from \"canvasengine\";\nimport { TestBed } from \"../../packages/core/testing\";\nimport { describe, expect, test, vi } from \"vitest\";\nimport { focusManager } from \"../../packages/core/src/engine/FocusManager\";\n\ndescribe(\"focus navigation with loop\", () => {\n    test(\"should call onFocusChange when items are in a loop\", async () => {\n        const items = signal([{ id: 0 }, { id: 1 }]);\n        const onFocusChange = vi.fn();\n\n        const containerElement = await TestBed.createComponent(FocusContainer, {\n            tabindex: 0,\n            onFocusChange\n        }, [\n            loop(items, (item) => Button({ tabindex: item.id, text: `Button ${item.id}` }))\n        ], { enableLayout: false });\n\n        // Wait for children to be registered\n        await new Promise(resolve => setTimeout(resolve, 50));\n\n        const instance = containerElement.componentInstance as any;\n        const containerId = instance.getContainerId();\n\n        // Check if elements are registered\n        const element0 = focusManager.getElement(containerId, 0);\n        expect(element0).toBeDefined();\n\n        // Change focus\n        focusManager.setIndex(containerId, 0);\n\n        expect(onFocusChange).toHaveBeenCalled();\n        expect(onFocusChange).toHaveBeenCalledWith(0, expect.anything());\n    });\n});\n"
  },
  {
    "path": "tests/engine/freeze.spec.ts",
    "content": "import { beforeEach, describe, expect, test, vi } from 'vitest'\nimport { signal } from 'canvasengine'\nimport { createComponent, registerComponent, isElementFrozen } from '../../packages/core/src/engine/reactive'\nimport { Container, CanvasContainer } from '../../packages/core/src/components/Container'\nimport { Sprite, CanvasSprite } from '../../packages/core/src/components/Sprite'\nimport { beforeAll } from 'vitest'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Freeze System', () => {\n    beforeAll(() => {\n        // Ensure core components are registered for tests\n        registerComponent('Sprite', CanvasSprite)\n        registerComponent('Container', CanvasContainer)\n    })\n    class TestComponent {\n        updateCount = 0\n        onInit(props) {}\n        onUpdate(props) {\n            this.updateCount++\n        }\n        onMount(element, index) {}\n    }\n\n    beforeEach(() => {\n        registerComponent('TestComponent', TestComponent)\n        registerComponent('Container', Container)\n        registerComponent('Sprite', Sprite)\n    })\n\n    describe('isElementFrozen', () => {\n        test('returns false when freeze prop is not set', () => {\n            const element = createComponent('TestComponent', {})\n            expect(isElementFrozen(element)).toBe(false)\n        })\n\n        test('returns true when freeze prop is true (boolean)', () => {\n            const element = createComponent('TestComponent', { freeze: true })\n            expect(isElementFrozen(element)).toBe(true)\n        })\n\n        test('returns false when freeze prop is false (boolean)', () => {\n            const element = createComponent('TestComponent', { freeze: false })\n            expect(isElementFrozen(element)).toBe(false)\n        })\n\n        test('returns true when freeze signal is true', () => {\n            const freezeSignal = signal(true)\n            const element = createComponent('TestComponent', { freeze: freezeSignal })\n            expect(isElementFrozen(element)).toBe(true)\n        })\n\n        test('returns false when freeze signal is false', () => {\n            const freezeSignal = signal(false)\n            const element = createComponent('TestComponent', { freeze: freezeSignal })\n            expect(isElementFrozen(element)).toBe(false)\n        })\n\n        test('reacts to freeze signal changes', () => {\n            const freezeSignal = signal(false)\n            const element = createComponent('TestComponent', { freeze: freezeSignal })\n            \n            expect(isElementFrozen(element)).toBe(false)\n            \n            freezeSignal.set(true)\n            expect(isElementFrozen(element)).toBe(true)\n            \n            freezeSignal.set(false)\n            expect(isElementFrozen(element)).toBe(false)\n        })\n    })\n\n    describe('Blocking reactive updates', () => {\n        test('blocks onUpdate when element is frozen (boolean)', () => {\n            class TestComponentWithUpdate {\n                updateCount = 0\n                onInit(props) {}\n                onUpdate(props) {\n                    this.updateCount++\n                }\n            }\n            registerComponent('TestComponentWithUpdate', TestComponentWithUpdate)\n            \n            const xSignal = signal(0)\n            const element = createComponent('TestComponentWithUpdate', {\n                freeze: true,\n                x: xSignal\n            })\n            \n            const instance = element.componentInstance\n            // onMount should be blocked by freeze\n            expect(instance.updateCount).toBe(0)\n            \n            xSignal.set(10)\n            expect(instance.updateCount).toBe(0) // Should not update when frozen\n        })\n\n        test('allows onUpdate when element is not frozen', () => {\n            class TestComponentWithUpdate {\n                updateCount = 0\n                onInit(props) {}\n                onUpdate(props) {\n                    this.updateCount++\n                }\n            }\n            registerComponent('TestComponentWithUpdate2', TestComponentWithUpdate)\n            \n            const xSignal = signal(0)\n            const element = createComponent('TestComponentWithUpdate2', {\n                freeze: false,\n                x: xSignal\n            })\n            \n            const instance = element.componentInstance\n            // onMount triggers an initial onUpdate call when not frozen\n            expect(instance.updateCount).toBe(1)\n            \n            xSignal.set(10)\n            expect(instance.updateCount).toBeGreaterThan(0) // Should update when not frozen\n        })\n\n        test('blocks onUpdate when freeze signal is true', () => {\n            class TestComponentWithUpdate {\n                updateCount = 0\n                onInit(props) {}\n                onUpdate(props) {\n                    this.updateCount++\n                }\n            }\n            registerComponent('TestComponentWithUpdate3', TestComponentWithUpdate)\n            \n            const freezeSignal = signal(false)\n            const xSignal = signal(0)\n            const element = createComponent('TestComponentWithUpdate3', {\n                freeze: freezeSignal,\n                x: xSignal\n            })\n            \n            const instance = element.componentInstance\n            \n            // Initially not frozen, should update\n            xSignal.set(10)\n            const initialCount = instance.updateCount\n            \n            // Freeze the element\n            freezeSignal.set(true)\n            \n            // Try to update - should be blocked\n            xSignal.set(20)\n            expect(instance.updateCount).toBe(initialCount) // Should not increase\n        })\n\n        test('allows onUpdate when freeze signal changes to false', () => {\n            class TestComponentWithUpdate {\n                updateCount = 0\n                onInit(props) {}\n                onUpdate(props) {\n                    this.updateCount++\n                }\n            }\n            registerComponent('TestComponentWithUpdate4', TestComponentWithUpdate)\n            \n            const freezeSignal = signal(true)\n            const xSignal = signal(0)\n            const element = createComponent('TestComponentWithUpdate4', {\n                freeze: freezeSignal,\n                x: xSignal\n            })\n            \n            const instance = element.componentInstance\n            \n            // Initially frozen, should not update\n            xSignal.set(10)\n            const initialCount = instance.updateCount\n            \n            // Unfreeze the element\n            freezeSignal.set(false)\n            \n            // Try to update - should work now\n            xSignal.set(20)\n            expect(instance.updateCount).toBeGreaterThan(initialCount)\n        })\n    })\n\n    describe('Blocking controls', () => {\n        test('stops controls when element is frozen', async () => {\n            const freezeSignal = signal(false)\n            const controlsConfig = {\n                up: {\n                    bind: 'ArrowUp',\n                    keyDown: vi.fn()\n                }\n            }\n            \n            const element = await TestBed.createComponent(Sprite, {\n                freeze: freezeSignal,\n                controls: controlsConfig\n            })\n            \n            // Wait for controls to initialize\n            await new Promise(resolve => setTimeout(resolve, 50))\n            \n            const controlsDirective = element.directives.controls\n            expect(controlsDirective).toBeDefined()\n            \n            // Initially not frozen, controls should be active\n            expect(controlsDirective.keyboard?.stop).toBe(false)\n            \n            // Freeze the element\n            freezeSignal.set(true)\n            await new Promise(resolve => setTimeout(resolve, 50))\n            \n            // Controls should be stopped\n            expect(controlsDirective.keyboard?.stop).toBe(true)\n            \n            // Unfreeze\n            freezeSignal.set(false)\n            await new Promise(resolve => setTimeout(resolve, 50))\n            \n            // Controls should be active again\n            expect(controlsDirective.keyboard?.stop).toBe(false)\n        })\n\n        test('stops controls on init when freeze is true', async () => {\n            const controlsConfig = {\n                up: {\n                    bind: 'ArrowUp',\n                    keyDown: vi.fn()\n                }\n            }\n            \n            const element = await TestBed.createComponent(Sprite, {\n                freeze: true,\n                controls: controlsConfig\n            })\n            \n            // Wait for controls to initialize\n            await new Promise(resolve => setTimeout(resolve, 50))\n            \n            const controlsDirective = element.directives.controls\n            expect(controlsDirective).toBeDefined()\n            \n            // Controls should be stopped from the start\n            expect(controlsDirective.keyboard?.stop).toBe(true)\n        })\n    })\n\n    describe('Blocking events', () => {\n        test('blocks click event when element is frozen', async () => {\n            const clickHandler = vi.fn()\n            const freezeSignal = signal(false)\n            \n            const element = await TestBed.createComponent(Container, {\n                freeze: freezeSignal,\n                click: clickHandler\n            })\n            \n            const instance = element.componentInstance\n            \n            // Mount the element so events can be registered\n            await instance.onMount(element)\n            \n            // Initially not frozen, event should work\n            instance.emit('pointertap', {})\n            expect(clickHandler).toHaveBeenCalledTimes(1)\n            \n            // Freeze the element\n            freezeSignal.set(true)\n            \n            // Event should be blocked\n            instance.emit('pointertap', {})\n            expect(clickHandler).toHaveBeenCalledTimes(1) // Should not increase\n            \n            // Unfreeze\n            freezeSignal.set(false)\n            \n            // Event should work again\n            instance.emit('pointertap', {})\n            expect(clickHandler).toHaveBeenCalledTimes(2)\n        })\n\n        test('blocks events on init when freeze is true', async () => {\n            const clickHandler = vi.fn()\n            \n            const element = await TestBed.createComponent(Container, {\n                freeze: true,\n                click: clickHandler\n            })\n            \n            const instance = element.componentInstance\n            \n            // Mount the element so events can be registered\n            await instance.onMount(element)\n            \n            // Event should be blocked from the start\n            instance.emit('pointertap', {})\n            expect(clickHandler).not.toHaveBeenCalled()\n        })\n\n        test('blocks multiple event types when frozen', async () => {\n            const clickHandler = vi.fn()\n            const mouseDownHandler = vi.fn()\n            const freezeSignal = signal(true)\n            \n            const element = await TestBed.createComponent(Container, {\n                freeze: freezeSignal,\n                click: clickHandler,\n                mousedown: mouseDownHandler\n            })\n            \n            const instance = element.componentInstance\n            \n            // Mount the element so events can be registered\n            await instance.onMount(element)\n            \n            // Both events should be blocked\n            instance.emit('pointertap', {})\n            instance.emit('mousedown', {})\n            \n            expect(clickHandler).not.toHaveBeenCalled()\n            expect(mouseDownHandler).not.toHaveBeenCalled()\n            \n            // Unfreeze\n            freezeSignal.set(false)\n            \n            // Events should work now\n            instance.emit('pointertap', {})\n            instance.emit('mousedown', {})\n            \n            expect(clickHandler).toHaveBeenCalledTimes(1)\n            expect(mouseDownHandler).toHaveBeenCalledTimes(1)\n        })\n    })\n\n    describe('Freeze state management', () => {\n        test('initializes isFrozen property correctly', () => {\n            const element1 = createComponent('TestComponent', { freeze: true })\n            expect(element1.isFrozen).toBe(true)\n            \n            const element2 = createComponent('TestComponent', { freeze: false })\n            expect(element2.isFrozen).toBe(false)\n            \n            const element3 = createComponent('TestComponent', {})\n            expect(element3.isFrozen).toBe(false)\n        })\n\n        test('updates isFrozen when freeze signal changes', () => {\n            const freezeSignal = signal(false)\n            const element = createComponent('TestComponent', { freeze: freezeSignal })\n            \n            expect(element.isFrozen).toBe(false)\n            \n            freezeSignal.set(true)\n            expect(element.isFrozen).toBe(true)\n            \n            freezeSignal.set(false)\n            expect(element.isFrozen).toBe(false)\n        })\n\n        test('cleans up freeze subscription on destroy', () => {\n            const freezeSignal = signal(false)\n            const element = createComponent('TestComponent', { freeze: freezeSignal })\n            \n            const initialSubscriptionCount = element.propSubscriptions.length\n            \n            // Change freeze state to create subscription\n            freezeSignal.set(true)\n            \n            // Destroy element\n            element.destroy()\n            \n            // Change freeze signal - should not affect destroyed element\n            freezeSignal.set(false)\n            expect(element.isFrozen).toBe(true) // Should remain frozen (no longer reactive)\n        })\n    })\n})\n"
  },
  {
    "path": "tests/engine/lifecycle.spec.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'\nimport { bootstrapCanvas, Canvas, Container, createComponent, h, mount, registerComponent, signal, tick, cond } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Lifecycle', () => {\n\n    test('mount function is called after component creation', async () => {\n        const mockMount = vi.fn()\n        \n        function MyComponent() { \n            mount((element) => {\n                mockMount(element)\n            })\n            \n            return h(Canvas, {\n                tickStart: false\n            })\n        }\n\n        await bootstrapCanvas(document.getElementById('root'), MyComponent)\n\n        expect(mockMount).toHaveBeenCalledTimes(1)\n        expect(mockMount).toHaveBeenCalledWith(expect.objectContaining({\n            props: expect.objectContaining({ isRoot: true })\n        }))\n    })\n\n    test('multiple mount functions are all called', async () => {\n        const mockMount1 = vi.fn()\n        const mockMount2 = vi.fn()\n        \n        function MyComponent() {\n            mount((element) => {\n                mockMount1(element)\n            })\n            \n            mount((element) => {\n                mockMount2(element)\n            })\n            \n            return h(Canvas, {\n                tickStart: false\n            })\n        }\n\n        await bootstrapCanvas(document.getElementById('root'), MyComponent)\n        expect(mockMount1).toHaveBeenCalledTimes(1)\n        expect(mockMount2).toHaveBeenCalledTimes(1)\n    })\n\n    test('mount function with async function is called and awaited', async () => {\n        const mockMount = vi.fn()\n        const asyncOperation = vi.fn().mockResolvedValue('async result')\n        \n        function MyComponent() { \n            mount(async (element) => {\n                const result = await asyncOperation()\n                mockMount(element, result)\n            })\n            \n            return h(Canvas, {\n                tickStart: false\n            })\n        }\n\n        await bootstrapCanvas(document.getElementById('root'), MyComponent)\n\n        expect(asyncOperation).toHaveBeenCalledTimes(1)\n        expect(mockMount).toHaveBeenCalledTimes(1)\n        expect(mockMount).toHaveBeenCalledWith(\n            expect.objectContaining({\n                props: expect.objectContaining({ isRoot: true })\n            }),\n            'async result'\n        )\n    })\n\n    test('unmount function is returned from mount and called when component is destroyed', async () => {\n        const mockMount = vi.fn()\n        const mockUnmount = vi.fn()\n\n        const visible = signal(true)\n        \n        function MyComponent() {\n            mount((element) => {\n                mockMount(element)\n                return () => {\n                    mockUnmount(element)\n                }\n            })\n            return h(Container)\n        }\n\n        await TestBed.createComponent(cond(visible, () => h(MyComponent)))\n\n        expect(mockMount).toHaveBeenCalledTimes(1)\n        expect(mockUnmount).toHaveBeenCalledTimes(0)\n\n        visible.set(false)\n\n        expect(mockUnmount).toHaveBeenCalledTimes(1)\n    })\n\n    test('async unmount function is returned from mount and called when component is destroyed', async () => {\n        const mockMount = vi.fn()\n        const mockUnmount = vi.fn()\n\n        const visible = signal(true)\n        \n        function MyComponent() {\n            mount(async (element) => {\n                mockMount(element)\n                return () => {\n                    mockUnmount(element)\n                }\n            })\n            return h(Container)\n        }\n\n        await TestBed.createComponent(cond(visible, () => h(MyComponent)))\n\n        expect(mockMount).toHaveBeenCalledTimes(1)\n        expect(mockUnmount).toHaveBeenCalledTimes(0)\n\n        visible.set(false)\n\n        await new Promise(resolve => setTimeout(resolve, 0))\n\n        expect(mockUnmount).toHaveBeenCalledTimes(1)\n    })\n\n\n    test('tick function is called on each frame', async () => {\n        const mockTick = vi.fn()\n        \n        function MyComponent() {\n            tick((tickValue, element) => {\n                mockTick(tickValue, element)\n            })\n            \n            return h(Canvas, {\n                tickStart: true\n            })\n        }\n\n        await bootstrapCanvas(document.getElementById('root'), MyComponent)\n        \n        // Wait for tick to be called\n        await new Promise(resolve => setTimeout(resolve, 50))\n        \n        expect(mockTick).toHaveBeenCalled()\n        const lastCall = mockTick.mock.calls[mockTick.mock.calls.length - 1]\n        const tickValue = lastCall[0]\n        const element = lastCall[1]\n        \n        expect(tickValue).toHaveProperty('timestamp')\n        expect(tickValue).toHaveProperty('deltaTime')\n        expect(tickValue).toHaveProperty('frame')\n        expect(tickValue).toHaveProperty('deltaRatio')\n        expect(typeof tickValue.timestamp).toBe('number')\n        expect(typeof tickValue.deltaTime).toBe('number')\n        expect(typeof tickValue.frame).toBe('number')\n        expect(typeof tickValue.deltaRatio).toBe('number')\n        expect(element).toHaveProperty('props')\n        expect(element.props).toHaveProperty('isRoot', true)\n    })\n\n    test('tick function is called and can be cleaned up', async () => {\n        const mockTick = vi.fn()\n        \n        function MyComponent() {\n            tick((tickValue, element) => {\n                mockTick(tickValue, element)\n            })\n            \n            return h(Canvas, {\n                tickStart: true\n            })\n        }\n\n        await bootstrapCanvas(document.getElementById('root'), MyComponent)\n        \n        // Wait for tick to be called (need to wait for component to mount and tick to start)\n        await new Promise(resolve => setTimeout(resolve, 200))\n        \n        expect(mockTick).toHaveBeenCalled()\n        const callCount = mockTick.mock.calls.length\n        expect(callCount).toBeGreaterThan(0)\n        \n        // Verify tick values have correct structure\n        const lastCall = mockTick.mock.calls[mockTick.mock.calls.length - 1]\n        const tickValue = lastCall[0]\n        const element = lastCall[1]\n        \n        expect(tickValue).toHaveProperty('timestamp')\n        expect(tickValue).toHaveProperty('deltaTime')\n        expect(tickValue).toHaveProperty('frame')\n        expect(tickValue).toHaveProperty('deltaRatio')\n        expect(element).toHaveProperty('props')\n    })\n})\n"
  },
  {
    "path": "tests/engine/loop-sharing.spec.ts",
    "content": "import { loop, Container, h, signal } from \"canvasengine\";\nimport { TestBed } from \"../../packages/core/testing\";\nimport { describe, expect, test, vi } from \"vitest\";\n\ndescribe(\"loop sharing\", () => {\n    test(\"should call createElementFn only once per item with multiple subscribers\", async () => {\n        const items = signal([1]);\n        let callCount = 0;\n        const flow = loop(items, (item) => {\n            callCount++;\n            return h(Container, { x: item });\n        });\n\n        // First subscription\n        const sub1 = flow.subscribe();\n        // Second subscription\n        const sub2 = flow.subscribe();\n\n        // If not shared, callCount will be 2 (one for each subscription)\n        // If shared, callCount will be 1\n        expect(callCount).toBe(1);\n\n        sub1.unsubscribe();\n        sub2.unsubscribe();\n    });\n});\n"
  },
  {
    "path": "tests/engine/loop-spread-props.spec.ts",
    "content": "import { describe, expect, test, beforeEach, vi } from 'vitest'\nimport { loop, Container, h, signal, computed } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\n/**\n * Test suite for loop with spread props and computed signals\n * \n * This test suite simulates the situation in test.ce and child.ce:\n * - A parent component with a @for loop iterating over a computed signal\n * - Props passed to child components using spread operator (...obj)\n * - Child component receiving props (x, y) via spread operator\n * - Signal updates after a delay (setTimeout)\n * \n * Note: We use Container instead of Sprite to avoid image loading issues in tests\n */\ndescribe('Loop with spread props and computed signals', () => {\n    beforeEach(() => {\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n    test('should create child components with spread props from computed signal', async () => {\n        // Simulate the data signal from test.ce\n        // In test.ce, data is a signal containing an object with elementsLow array\n        const data = signal({\n            elementsLow: [\n                {\n                    x: 0,\n                    y: 0,\n                }\n            ]\n        })\n\n        // Simulate the computed signal from test.ce\n        // elementsLow is computed from data().elementsLow\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        // Create loop with spread props (simulating @for (obj of elementsLow) { <Container ...obj /> })\n        // The spread operator passes all properties of obj as props to Container\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state - children should be created\n        expect(container.componentInstance.children.length).toBe(1)\n        const childElement = container.componentInstance.children[0]\n        expect(childElement.x).toBe(0)\n        expect(childElement.y).toBe(0)\n    })\n\n    test('should update child components when signal changes after delay', async () => {\n        // Simulate the data signal from test.ce\n        const data = signal({\n            elementsLow: [\n                {\n                    x: 0,\n                    y: 0,\n                }\n            ]\n        })\n\n        // Simulate the computed signal from test.ce\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        // Create loop with spread props\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state\n        expect(container.componentInstance.children.length).toBe(1)\n        let childElement = container.componentInstance.children[0]\n        expect(childElement.x).toBe(0)\n        expect(childElement.y).toBe(0)\n\n        // Update the signal (simulating what setTimeout would do)\n        data.set({\n            elementsLow: [\n                {\n                    x: 100,\n                    y: 100,\n                }\n            ]\n        })\n\n        // Wait for reactivity to propagate\n        await vi.waitFor(() => {\n            expect(container.componentInstance.children.length).toBe(1)\n            expect(container.componentInstance.children[0].x).toBe(100)\n            expect(container.componentInstance.children[0].y).toBe(100)\n        })\n    })\n\n    test('should handle multiple child components with spread props', async () => {\n        const data = signal({\n            elementsLow: [\n                {\n                    x: 0,\n                    y: 0,\n                },\n                {\n                    x: 50,\n                    y: 50,\n                }\n            ]\n        })\n\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state with multiple children\n        expect(container.componentInstance.children.length).toBe(2)\n        expect(container.componentInstance.children[0].x).toBe(0)\n        expect(container.componentInstance.children[0].y).toBe(0)\n        expect(container.componentInstance.children[1].x).toBe(50)\n        expect(container.componentInstance.children[1].y).toBe(50)\n    })\n\n    test('should update multiple child components when signal changes', async () => {\n        const data = signal({\n            elementsLow: [\n                {\n                    x: 0,\n                    y: 0,\n                },\n                {\n                    x: 50,\n                    y: 50,\n                }\n            ]\n        })\n\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state\n        expect(container.componentInstance.children.length).toBe(2)\n\n        // Update signal directly\n        data.set({\n            elementsLow: [\n                {\n                    x: 100,\n                    y: 100,\n                },\n                {\n                    x: 200,\n                    y: 200,\n                }\n            ]\n        })\n\n        // Wait for reactivity to propagate\n        await vi.waitFor(() => {\n            expect(container.componentInstance.children.length).toBe(2)\n            expect(container.componentInstance.children[0].x).toBe(100)\n            expect(container.componentInstance.children[0].y).toBe(100)\n            expect(container.componentInstance.children[1].x).toBe(200)\n            expect(container.componentInstance.children[1].y).toBe(200)\n        })\n    })\n\n    test('should handle empty array in computed signal', async () => {\n        const data = signal({\n            elementsLow: []\n        })\n\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify empty state\n        expect(container.componentInstance.children.length).toBe(0)\n    })\n\n    test('should handle adding items to array', async () => {\n        const data = signal({\n            elementsLow: [\n                {\n                    x: 0,\n                    y: 0,\n                }\n            ]\n        })\n\n        const elementsLow = computed(() => {\n            return data().elementsLow || []\n        })\n\n        const loopValue = loop(elementsLow, (obj) => {\n            return h(Container, obj)\n        })\n\n        const container = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Verify initial state\n        expect(container.componentInstance.children.length).toBe(1)\n\n        // Add new item - need to create a new array to trigger reactivity\n        const newElements = [...data().elementsLow, {\n            x: 100,\n            y: 100,\n        }]\n        data.set({\n            elementsLow: newElements\n        })\n\n        // Wait a bit for reactivity to propagate\n        await new Promise(resolve => setTimeout(resolve, 10))\n\n        // Verify new item was added\n        expect(container.componentInstance.children.length).toBe(2)\n        expect(container.componentInstance.children[1].x).toBe(100)\n        expect(container.componentInstance.children[1].y).toBe(100)\n    })\n})\n\n"
  },
  {
    "path": "tests/engine/loop.spec.ts",
    "content": "import { loop, Container, h, signal, Text, computed, mount } from \"canvasengine\";\nimport { describe, expect, test, vi } from \"vitest\";\nimport { TestBed } from \"../../packages/core/testing\";\n\ndescribe(\"loop with array\", () => {\n\n  test(`Test loop with static items`, async () => {\n    const items = [1, 2, 3];\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n  });\n\n  test(`Test loop with initial items`, async () => {\n    const items = signal([1, 2, 3]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n  });\n\n  test(`Test loop with computed initial items`, async () => {\n    const items = computed(() => [1, 2, 3]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n  });\n\n  test(`Test loop with computed`, async () => {\n    const reactive = signal([1, 2, 3])\n    const items = computed(() => reactive());\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n  });\n\n  test(`Test loop with adding items`, async () => {\n    const items = signal([1, 2]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(2);\n\n    items().push(3);\n    expect(container.componentInstance.children.length).toBe(3);\n    expect(container.componentInstance.children[2].x).toBe(3);\n  });\n\n  test(`Test loop does not remount existing items when adding`, async () => {\n    const items = signal([1, 2]);\n    const mounted = vi.fn();\n\n    function Item(props: { value: number }) {\n      mount(() => {\n        mounted(props.value);\n      });\n      return h(Container, { x: props.value });\n    }\n\n    const value = loop(items, (item) => h(Item, { value: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(mounted).toHaveBeenCalledTimes(2);\n    expect(mounted.mock.calls.map(([value]) => value)).toEqual([1, 2]);\n\n    items().push(3);\n\n    await vi.waitFor(() => {\n      expect(container.componentInstance.children.length).toBe(3);\n      expect(mounted).toHaveBeenCalledTimes(3);\n    });\n\n    expect(mounted.mock.calls.map(([value]) => value)).toEqual([1, 2, 3]);\n  });\n\n  test(`Test loop with removing items`, async () => {\n    const items = signal([1, 2, 3]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    items().splice(1, 1);\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].x).toBe(1);\n    expect(container.componentInstance.children[1].x).toBe(3);\n  });\n\n  /* TODO\n  test(`Test loop with multiple removing items`, async () => {\n    const items = signal([1, 2, 3]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    items().splice(1, 2);\n    expect(container.componentInstance.children.length).toBe(1);\n    expect(container.componentInstance.children[0].x).toBe(1);\n  });\n  */\n\n  test(`Test loop with reset items`, async () => {\n    const items = signal([1, 2, 3]);\n    const value = loop(items, (item) => h(Container, { x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    items.set([4, 5]);\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].x).toBe(4);\n    expect(container.componentInstance.children[1].x).toBe(5);\n  });\n});\n\ndescribe(\"loop with object\", () => {\n  test(`Test loop with object`, async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n    expect(container.componentInstance.children[0].text).toBe(\"a\");\n  });\n\n\n  test(`Test loop with adding object properties`, async () => {\n    const items = signal({ a: 1, b: 2 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(2);\n\n    items().c = 3;\n\n    expect(container.componentInstance.children.length).toBe(3);\n    expect(container.componentInstance.children[2].text).toBe(\"c\");\n    expect(container.componentInstance.children[2].x).toBe(3);\n  });\n\n  test(`Test loop with removing object properties`, async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    delete items().b;\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe(\"a\");\n    expect(container.componentInstance.children[1].text).toBe(\"c\");\n  });\n\n  test(`Test loop with removing object properties and add`, async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    delete items().b;\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe(\"a\");\n    expect(container.componentInstance.children[1].text).toBe(\"c\");\n  });\n\n  test(`Test loop with reset object`, async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(3);\n\n    items.set({ d: 4, e: 5 });\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe(\"d\");\n    expect(container.componentInstance.children[0].x).toBe(4);\n    expect(container.componentInstance.children[1].text).toBe(\"e\");\n    expect(container.componentInstance.children[1].x).toBe(5);\n  });\n\n  test('Test loop with object with nested object', async () => {\n    const obj = signal({\n      '7dzfez': {\n        position: {\n          x: signal(100),\n          y: signal(100)\n        },\n        direction: signal('down'),\n        graphics: signal('male')\n      }\n    })\n    const value = loop(obj, (item, key) => {\n      return h(Text, { text: computed(() => item.position.x()) })\n    });\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(1);\n    expect(container.componentInstance.children[0].text).toBe('100');\n  });\n\n\n  test('Test loop with object with added nested object', async () => {\n    const obj = signal({})\n\n    obj()['7dzfez'] = {\n      position: {\n        x: signal(100),\n        y: signal(100)\n      },\n    }\n\n    const value = loop(obj, (item, key) => {\n      return h(Text, { text: item.position.x })\n    });\n\n    const container = await TestBed.createComponent(Container, {}, value);\n    expect(container.componentInstance.children.length).toBe(1);\n    expect(container.componentInstance.children[0].text).toBe('100');\n  });\n\n  test('Test loop with object with added nested object', async () => {\n    const obj = signal({})\n\n    obj()['7dzfez'] = {\n      array: signal([{ id: 1 }])\n    }\n\n    const value = loop(obj, (item, key) => {\n      return h(Text, { text: item.array()[0].id })\n    });\n    const container = await TestBed.createComponent(Container, {}, value);\n\n    obj()['eee'] = {\n      array: signal([{ id: 2 }])\n    }\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe('1');\n    expect(container.componentInstance.children[1].text).toBe('2');\n  });\n\n  test('Test loop with object with multiple items', async () => {\n    const obj = signal({})\n\n    obj()['7dzfez'] = {\n      name: 'aaa'\n    }\n\n\n    obj()['eee'] = {\n     name: 'bbb'\n    }\n\n    const value = loop(obj, (item, key) => {\n      return h(Text, { text: item.name })\n    });\n    const container = await TestBed.createComponent(Container, {}, value);\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe('aaa');\n    expect(container.componentInstance.children[1].text).toBe('bbb');\n  });\n\n  test('Test loop with object with multiple items', async () => {\n    const obj = signal([])\n\n    obj().push('aaa')\n\n\n    obj().push('bbb')\n\n    const value = loop(obj, (name) => {\n      return h(Text, { text: name })\n    });\n    const container = await TestBed.createComponent(Container, {}, value);\n\n    expect(container.componentInstance.children.length).toBe(2);\n    expect(container.componentInstance.children[0].text).toBe('aaa');\n    expect(container.componentInstance.children[1].text).toBe('bbb');\n  });\n\n  test('Test loop with array direct index assignment', async () => {\n    const items = signal(['aaaa'])\n    \n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(1);\n    expect(children[0].text).toBe('aaaa');\n    \n    items()[2] = 'cccc';\n\n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('aaaa');\n    expect(children[1].text).toBe('cccc');\n  });\n});\n\n// Tests supplémentaires pour les fonctionnalités non testées de loop\ndescribe(\"loop additional tests\", () => {\n  test('Test loop with empty initial array', async () => {\n    const items = signal([]);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(0);\n    \n    items().push('item1');\n    expect(children.length).toBe(1);\n    expect(children[0].text).toBe('item1');\n  });\n\n  test('Test loop with empty initial object', async () => {\n    const items = signal({});\n    const value = loop(items, (value, key) => h(Text, { text: key }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(0);\n    \n    items().key1 = 'value1';\n    expect(children.length).toBe(1);\n    expect(children[0].text).toBe('key1');\n  });\n\n \n\n  test('Test loop with multiple removing object properties', async () => {\n    const items = signal({ a: 1, b: 2, c: 3, d: 4 });\n    const value = loop(items, (item, key) => h(Text, { text: key, x: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(4);\n\n    delete items().b;\n    delete items().c;\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('a');\n    expect(children[1].text).toBe('d');\n  });\n\n  test('Test loop with updating array item', async () => {\n    const items = signal(['a', 'b', 'c']);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(3);\n    expect(children[1].text).toBe('b');\n    \n    items()[1] = 'updated';\n    \n    expect(children.length).toBe(3);\n    expect(children[1].text).toBe('updated');\n  });\n\n  test('Test loop with updating object property', async () => {\n    const items = signal({ a: 'value1', b: 'value2' });\n    const value = loop(items, (item, key) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    \n    items().b = 'updated';\n    \n    expect(children.length).toBe(2);\n    expect(children[1].text).toBe('updated');\n  });\n\n  test('Test loop with null initial value then array', async () => {\n    const items = signal([]);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(0);\n    \n    items.set(['item1', 'item2']);\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('item1');\n    expect(children[1].text).toBe('item2');\n  });\n\n  test('Test loop with null initial value then object', async () => {\n    const items = signal({});\n    const value = loop(items, (item, key) => h(Text, { text: key }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(0);\n    \n    items.set({ key1: 'value1', key2: 'value2' });\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('key1');\n    expect(children[1].text).toBe('key2');\n  });\n\n  test('Test loop with array index parameter', async () => {\n    const items = signal(['a', 'b', 'c']);\n    const indices = [];\n    \n    const value = loop(items, (item, index) => {\n      indices.push(index);\n      return h(Text, { text: item });\n    });\n    \n    const container = await TestBed.createComponent(Container, {}, value);\n    \n    expect(indices).toEqual([0, 1, 2]);\n    \n    items().push('d');\n    \n    expect(indices).toEqual([0, 1, 2, 3]);\n  });\n\n  test('Test loop with object key parameter', async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const keys = [];\n    \n    const value = loop(items, (item, key) => {\n      keys.push(key);\n      return h(Text, { text: key });\n    });\n    \n    const container = await TestBed.createComponent(Container, {}, value);\n    \n    expect(keys.sort()).toEqual(['a', 'b', 'c']);\n    \n    items().d = 4;\n    \n    expect(keys.sort()).toEqual(['a', 'b', 'c', 'd']);\n  });\n\n  test('Test loop with sparse array', async () => {\n    const sparseArray = [];\n    sparseArray[0] = 'a';\n    sparseArray[2] = 'c';\n    \n    const items = signal(sparseArray);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('a');\n    expect(children[1].text).toBe('c');\n    \n    items()[1] = 'b';\n    \n    expect(children.length).toBe(3);\n    expect(children[0].text).toBe('a');\n    expect(children[1].text).toBe('b');\n    expect(children[2].text).toBe('c');\n  });\n\n  test('Test loop with array methods like shift and unshift', async () => {\n    const items = signal(['b', 'c']);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    \n    items().unshift('a'); // Add to the beginning\n    expect(children.length).toBe(3);\n    expect(children[0].text).toBe('a');\n    \n    items().shift(); // Remove from the beginning\n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('b');\n  });\n\n  test('Test loop with undefined function return', async () => {\n    const items = signal([1, 2, 3]);\n    const value = loop(items, (item) => {\n      if (item === 2) {\n        return null; // Renvoie null pour l'élément 2\n      }\n      return h(Text, { text: String(item) });\n    });\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('1');\n    expect(children[1].text).toBe('3');\n  });\n\n  test('Test loop with array pop operation', async () => {\n    const items = signal(['a', 'b', 'c']);\n    const value = loop(items, (item) => h(Text, { text: item }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(3);\n    \n    items().pop(); // Retire le dernier élément\n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('a');\n    expect(children[1].text).toBe('b');\n  });\n\n  test('Test loop with computed signal dependency updates', async () => {\n    // Au lieu d'utiliser des computed signals qui dépendent d'autres signals,\n    // utilisons directement un signal et mettons-le à jour pour voir si les éléments sont mis à jour\n    const computedItems = signal([1, 2]);\n    \n    const value = loop(computedItems, (item) => h(Text, { text: String(item) }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('1');\n    expect(children[1].text).toBe('2');\n    \n    // Mise à jour complète du signal avec de nouvelles valeurs\n    computedItems.set([10, 20]);\n    \n    // La mise à jour devrait être immédiate car nous utilisons set() directement\n    expect(children.length).toBe(2);\n    expect(children[0].text).toBe('10');\n    expect(children[1].text).toBe('20');\n    \n    // Ajouter un nouvel élément au tableau\n    computedItems().push(30);\n    \n    // Vérifions que la mise à jour a bien été prise en compte\n    expect(children.length).toBe(3);\n    expect(children[2].text).toBe('30');\n  });\n\n  test('Test loop with object property deletion and immediate addition', async () => {\n    const items = signal({ a: 1, b: 2, c: 3 });\n    const value = loop(items, (item, key) => h(Text, { text: key }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(3);\n    \n    delete items().b;\n    items().d = 4;\n    \n    expect(children.length).toBe(3);\n    \n    const keys = Array.from(children).map(child => child.text);\n    expect(keys.includes('a')).toBe(true);\n    expect(keys.includes('b')).toBe(false);\n    expect(keys.includes('c')).toBe(true);\n    expect(keys.includes('d')).toBe(true);\n  });\n\n  test('Test loop with complex object structure', async () => {\n    const items = signal({\n      user1: { name: 'Alice', age: 30 },\n      user2: { name: 'Bob', age: 25 }\n    });\n    \n    const value = loop(items, (item, key) => {\n      return h(Text, { text: `${key}:${item.name}:${item.age}` });\n    });\n    \n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(2);\n    \n    items.set({\n      user1: { name: 'Alice', age: 31 },\n      user2: { name: 'Bobby', age: 25 },\n      user3: { name: 'Charlie', age: 35 }\n    });\n    \n    await new Promise(resolve => setTimeout(resolve, 10));\n    \n    expect(children.length).toBe(3);\n    \n    const texts = Array.from(children).map(child => child.text);\n    expect(texts).toContain('user1:Alice:31');\n    expect(texts).toContain('user2:Bobby:25');\n    expect(texts).toContain('user3:Charlie:35');\n  });\n\n  test('Test loop with primitive to complex object transition', async () => {\n    const items = signal({});\n    const value = loop(items, (item, key) => h(Text, { text: String(key) }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    \n    expect(children.length).toBe(0);\n    \n    items.set(['a', 'b', 'c']);\n    \n    expect(children.length).toBe(3);\n    expect(children[0].text).toBe('0');\n    expect(children[1].text).toBe('1');\n    expect(children[2].text).toBe('2');\n    \n    items.set({ x: 1, y: 2 });\n    \n    expect(children.length).toBe(2);\n    \n    const keys = Array.from(children).map(child => child.text);\n    expect(keys.includes('x')).toBe(true);\n    expect(keys.includes('y')).toBe(true);\n  });\n\n  test('Test loop with nested loops', async () => {\n    const matrix = signal([\n      [1, 2],\n      [3, 4],\n      [5, 6]\n    ]);\n    \n    const value = loop(matrix, (row, rowIdx) => {\n      const rowIndex = Number(rowIdx);\n      \n      // Create a computed signal that depends on the matrix and the row index\n      const rowSignal = computed(() => matrix()[rowIndex] || []);\n      \n      const rowValue = loop(rowSignal, (cell, colIdx) => {\n        const colIndex = Number(colIdx);\n        return h(Text, { text: `${rowIndex}-${colIndex}:${cell}` });\n      });\n      \n      return h(Container, { y: rowIndex * 10 }, rowValue);\n    });\n    \n    const container = await TestBed.createComponent(Container, {}, value);\n    const rowContainers = container.componentInstance.children;\n    \n    expect(rowContainers.length).toBe(3);\n    \n    expect(rowContainers[0].children.length).toBe(2);\n    expect(rowContainers[0].children[0].text).toBe('0-0:1');\n    expect(rowContainers[0].children[1].text).toBe('0-1:2');\n    \n    expect(rowContainers[1].children.length).toBe(2);\n    expect(rowContainers[1].children[0].text).toBe('1-0:3');\n    expect(rowContainers[1].children[1].text).toBe('1-1:4');\n    \n    expect(rowContainers[2].children.length).toBe(2);\n    expect(rowContainers[2].children[0].text).toBe('2-0:5');\n    expect(rowContainers[2].children[1].text).toBe('2-1:6');\n    \n    const newMatrix = [...matrix()];\n    newMatrix[1] = [9, 4];\n    matrix.set(newMatrix);\n    \n    expect(rowContainers[1].children[0].text).toBe('1-0:9');\n    \n    matrix().push([7, 8]);\n    \n    expect(rowContainers.length).toBe(4);\n    expect(rowContainers[3].children.length).toBe(2);\n    expect(rowContainers[3].children[0].text).toBe('3-0:7');\n    expect(rowContainers[3].children[1].text).toBe('3-1:8');\n  });\n\n  test('Test loop with large array performance', async () => {\n    // Create a large array with strings\n    const largeArray = Array.from({ length: 100 }, (_, i) => `item-${i}`);\n    const items = signal(largeArray);\n    \n    const start = performance.now();\n    const value = loop(items, (item) => h(Text, { text: String(item) }));\n    const container = await TestBed.createComponent(Container, {}, value);\n    const children = container.componentInstance.children;\n    const end = performance.now();\n    \n    expect(children.length).toBe(100);\n    expect(children[0].text).toBe('item-0');\n    expect(children[99].text).toBe('item-99');\n    \n    const updateStart = performance.now();\n    const updatedArray = Array.from({ length: 100 }, (_, i) => `updated-${i}`);\n    items.set(updatedArray);\n    const updateEnd = performance.now();\n    \n    expect(children[0].text).toBe('updated-0');\n  });\n});\n"
  },
  {
    "path": "tests/engine/nested-loop.spec.ts",
    "content": "import { describe, expect, test, beforeEach, vi } from 'vitest'\nimport { loop, Container, h, signal, computed } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('Nested Loop Cleanup', () => {\n    beforeEach(() => {\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n    test('should destroy inner loop elements when outer loop updates', async () => {\n        const data = signal({\n            outer: [\n                { id: 1, inner: [1, 2] }\n            ]\n        })\n\n        const outerElements = computed(() => data().outer)\n\n        const Child = (props) => {\n            const innerElements = computed(() => props.inner)\n            return loop(innerElements, (item) => {\n                return h(Container, { name: `inner-${item}`, x: item * 10 })\n            })\n        }\n\n        const loopValue = loop(outerElements, (item) => {\n            return h(Child, item)\n        })\n\n        const root = await TestBed.createComponent(Container, {}, loopValue)\n\n        // Initial check\n        // Outer loop has 1 item.\n        // Child has inner loop with 2 items.\n        // Root should have 2 children (from inner loop of the single outer item).\n        expect(root.componentInstance.children.length).toBe(2)\n        expect(root.componentInstance.children[0].x).toBe(10)\n        expect(root.componentInstance.children[1].x).toBe(20)\n\n        // Update outer loop - replace the item\n        data.set({\n            outer: [\n                { id: 2, inner: [3] } // New item, different inner content\n            ]\n        })\n\n        await vi.waitFor(() => {\n            // Should have 1 child (from new inner loop)\n            // If bug exists, old children might remain, so length would be > 1\n            expect(root.componentInstance.children.length).toBe(1)\n            expect(root.componentInstance.children[0].x).toBe(30)\n        })\n    })\n})\n"
  },
  {
    "path": "tests/engine/reactive-routing.spec.ts",
    "content": "import { beforeEach, describe, expect, test } from 'vitest'\nimport { DOMContainer, Sprite } from 'canvasengine'\nimport { TestBed } from '../../packages/core/testing'\n\ndescribe('reactive DOM routing', () => {\n    beforeEach(() => {\n        document.body.innerHTML = '<div id=\"root\"></div>'\n    })\n\n    test('routes Sprite to DOMSprite under DOMContainer', async () => {\n        const containerElement = await TestBed.createComponent(DOMContainer, {}, [\n            Sprite({ width: 10, height: 10 })\n        ])\n\n        expect(containerElement.props.children?.[0]?.tag).toBe('DOMSprite')\n    })\n})\n"
  },
  {
    "path": "tests/engine/trigger.spec.ts",
    "content": "import { describe, expect, test, vi } from 'vitest'\nimport { on, trigger } from 'canvasengine'\n\ndescribe('Trigger', () => {\n    test('trigger is called', async () => {\n        const mockTrigger = vi.fn()\n\n        const myTrigger = trigger()\n\n        on(myTrigger, mockTrigger)\n\n        myTrigger.start()\n\n        expect(mockTrigger).toHaveBeenCalledTimes(1)\n    })\n\n    test('trigger passes data to handler', () => {\n        const mockTrigger = vi.fn()\n        const myTrigger = trigger()\n        const testData = { message: 'Hello World' }\n        \n        on(myTrigger, mockTrigger)\n        myTrigger.start(testData)\n        \n        expect(mockTrigger).toHaveBeenCalledWith(testData)\n    })\n\n    test('trigger merges global data with start data', () => {\n        const mockTrigger = vi.fn()\n        const globalData = { myData: 'myData' }\n        const startData = { otherData: 'otherData' }\n        const myTrigger = trigger(globalData)\n        \n        on(myTrigger, mockTrigger)\n        myTrigger.start(startData)\n        \n        expect(mockTrigger).toHaveBeenCalledWith({\n            ...globalData,\n            ...startData\n        })\n    })\n\n    test('async trigger can be awaited', async () => {\n        const mockTrigger = vi.fn(async () => {\n            await new Promise(resolve => setTimeout(resolve, 10))\n            return 'done'\n        })\n        const myTrigger = trigger()\n        \n        on(myTrigger, mockTrigger)\n        const result = await myTrigger.start()\n        \n        expect(mockTrigger).toHaveBeenCalled()\n        expect(result).toBe('done')\n    })\n})"
  },
  {
    "path": "tests/presets/fx.spec.ts",
    "content": "import { describe, expect, test, vi } from \"vitest\";\nimport { Container, Texture } from \"pixi.js\";\nimport {\n  FX_PRESETS,\n  FxRuntime,\n  type FxPreset,\n} from \"../../packages/presets/src/fx\";\n\ndescribe(\"Fx preset runtime\", () => {\n  test(\"spawns burst particles from a preset\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n    const spawned = vi.fn();\n\n    runtime.spawn(container, FX_PRESETS.hitSpark, {\n      onParticleSpawn: spawned,\n    });\n    runtime.update(16);\n\n    expect(spawned).toHaveBeenCalledTimes(18);\n    expect(container.children.length).toBe(18);\n  });\n\n  test(\"uses visible procedural textures for shape presets\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n\n    runtime.spawn(container, FX_PRESETS.hitSpark);\n    runtime.update(16);\n\n    const particle = container.children[0] as any;\n    expect(particle.texture.width).toBeGreaterThan(1);\n    expect(particle.texture.height).toBeGreaterThan(1);\n    expect(particle.width).toBeGreaterThan(1);\n  });\n\n  test(\"all built-in presets can emit particles\", () => {\n    for (const [name, preset] of Object.entries(FX_PRESETS)) {\n      const container = new Container();\n      const runtime = new FxRuntime({ seed: 1 });\n\n      runtime.spawn(container, preset);\n      runtime.update(100);\n\n      expect(container.children.length, name).toBeGreaterThan(0);\n    }\n  });\n\n  test(\"removes particles after their lifetime\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n    const preset: FxPreset = {\n      duration: 20,\n      emitters: [\n        {\n          burst: 3,\n          particle: {\n            texture: Texture.WHITE,\n            lifetime: 40,\n            alpha: [1, 0],\n            scale: [1, 0],\n          },\n        },\n      ],\n    };\n\n    runtime.spawn(container, preset);\n    runtime.update(1);\n    expect(container.children.length).toBe(3);\n\n    runtime.update(80);\n    expect(container.children.length).toBe(0);\n    expect(runtime.activeInstances).toBe(0);\n  });\n\n  test(\"emits particles over time with rate\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n    const preset: FxPreset = {\n      duration: 1000,\n      emitters: [\n        {\n          rate: 10,\n          particle: {\n            texture: Texture.WHITE,\n            lifetime: 700,\n          },\n        },\n      ],\n    };\n\n    runtime.spawn(container, preset);\n    runtime.update(100);\n    expect(container.children.length).toBe(1);\n    runtime.update(400);\n    expect(container.children.length).toBe(5);\n  });\n\n  test(\"uses image fallback shape when texture is missing\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n    const preset: FxPreset = {\n      emitters: [\n        {\n          burst: 1,\n          particle: {\n            image: \"/not-preloaded.png\",\n            lifetime: 100,\n          },\n        },\n      ],\n    };\n\n    runtime.spawn(container, preset, { missingTexture: \"shape\" });\n    runtime.update(1);\n\n    expect(container.children.length).toBe(1);\n  });\n\n  test(\"can skip missing image textures\", () => {\n    const container = new Container();\n    const runtime = new FxRuntime({ seed: 1 });\n    const preset: FxPreset = {\n      emitters: [\n        {\n          burst: 1,\n          particle: {\n            image: \"/not-preloaded.png\",\n            lifetime: 100,\n          },\n        },\n      ],\n    };\n\n    runtime.spawn(container, preset, { missingTexture: \"skip\" });\n    runtime.update(1);\n\n    expect(container.children.length).toBe(0);\n  });\n});\n"
  },
  {
    "path": "tests/setup/canvas.ts",
    "content": "import 'vitest-webgl-canvas-mock'\n\nconst LOAD_FAILURE_SRC = 'LOAD_FAILURE_SRC';\n\n// mock image loading\nObject.defineProperty(global.Image.prototype, 'src', {\n    set(src) {\n        if (src === LOAD_FAILURE_SRC) {\n            setTimeout(() => this.onerror(new Error('mocked error')));\n        } else if (src.startsWith('data')) {\n            setTimeout(() => this.dispatchEvent(new Event(\"load\")));\n        }\n    },\n});\n\nObject.defineProperty(global.window.HTMLMediaElement.prototype, 'play', {\n    configurable: true,\n    get() {\n        setTimeout(() => (this.onloadeddata && this.onloadeddata()))\n        return () => { }\n    }\n})\n\nObject.defineProperty(global.window.HTMLMediaElement.prototype, 'load', {\n    configurable: true,\n    get() {\n        setTimeout(() => (this.onloadeddata && this.onloadeddata()))\n        return () => { }\n    }\n})\n\nwindow.document.body.innerHTML = `<div id=\"root\"></div>`\n\nconsole.error = () => {}\n"
  },
  {
    "path": "tests/utils/GlobalAssetLoader.spec.ts",
    "content": "import { describe, expect, test, vi, beforeEach } from 'vitest'\nimport { GlobalAssetLoader } from '../../packages/core/src/utils/GlobalAssetLoader'\n\ndescribe('GlobalAssetLoader', () => {\n  let loader: GlobalAssetLoader\n\n  beforeEach(() => {\n    loader = new GlobalAssetLoader()\n  })\n\n  describe('registerAsset', () => {\n    test('registers a new asset and returns a unique ID', () => {\n      const assetId = loader.registerAsset('path/to/image.png')\n      \n      expect(assetId).toBeDefined()\n      expect(typeof assetId).toBe('string')\n      expect(assetId).toContain('asset_')\n      expect(assetId).toContain('path/to/image.png')\n    })\n\n    test('registers multiple assets with unique IDs', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      expect(id1).not.toBe(id2)\n      expect(loader.getAssetCount()).toBe(2)\n    })\n\n    test('resets completion state when registering new asset', () => {\n      const id1 = loader.registerAsset('image1.png')\n      loader.completeAsset(id1)\n      \n      expect(loader.getGlobalProgress()).toBe(1)\n      \n      const id2 = loader.registerAsset('image2.png')\n      expect(loader.getGlobalProgress()).toBeLessThan(1)\n    })\n  })\n\n  describe('updateProgress', () => {\n    test('updates progress for a registered asset', () => {\n      const assetId = loader.registerAsset('image.png')\n      \n      loader.updateProgress(assetId, 0.5)\n      expect(loader.getGlobalProgress()).toBe(0.5)\n    })\n\n    test('clamps progress to 0-1 range', () => {\n      const assetId = loader.registerAsset('image.png')\n      \n      loader.updateProgress(assetId, -0.5)\n      expect(loader.getGlobalProgress()).toBe(0)\n      \n      loader.updateProgress(assetId, 1.5)\n      expect(loader.getGlobalProgress()).toBe(1)\n    })\n\n    test('warns when updating progress for non-existent asset', () => {\n      const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n      \n      loader.updateProgress('non-existent-id', 0.5)\n      \n      expect(consoleSpy).toHaveBeenCalledWith(\n        expect.stringContaining('Asset non-existent-id not found')\n      )\n      \n      consoleSpy.mockRestore()\n    })\n  })\n\n  describe('completeAsset', () => {\n    test('marks asset as completed', () => {\n      const assetId = loader.registerAsset('image.png')\n      \n      loader.completeAsset(assetId)\n      \n      expect(loader.getCompletedCount()).toBe(1)\n      expect(loader.getGlobalProgress()).toBe(1)\n    })\n\n    test('warns when completing non-existent asset', () => {\n      const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})\n      \n      loader.completeAsset('non-existent-id')\n      \n      expect(consoleSpy).toHaveBeenCalledWith(\n        expect.stringContaining('Asset non-existent-id not found')\n      )\n      \n      consoleSpy.mockRestore()\n    })\n  })\n\n  describe('removeAsset', () => {\n    test('removes asset from tracking', () => {\n      const assetId = loader.registerAsset('image.png')\n      \n      expect(loader.getAssetCount()).toBe(1)\n      \n      loader.removeAsset(assetId)\n      \n      expect(loader.getAssetCount()).toBe(0)\n    })\n\n    test('updates global progress after removal', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      loader.updateProgress(id1, 0.5)\n      loader.updateProgress(id2, 0.5)\n      \n      expect(loader.getGlobalProgress()).toBe(0.5)\n      \n      loader.removeAsset(id1)\n      \n      expect(loader.getGlobalProgress()).toBe(0.5) // Only id2 remains at 50%\n    })\n  })\n\n  describe('onProgress', () => {\n    test('registers progress callback', () => {\n      const callback = vi.fn()\n      \n      const unsubscribe = loader.onProgress(callback)\n      \n      expect(callback).toHaveBeenCalledWith(1) // Initial call with current progress (no assets = 100%)\n      expect(typeof unsubscribe).toBe('function')\n    })\n\n    test('calls callback when progress updates', () => {\n      const callback = vi.fn()\n      loader.onProgress(callback)\n      \n      callback.mockClear()\n      \n      const assetId = loader.registerAsset('image.png')\n      expect(callback).toHaveBeenCalledWith(0) // New asset starts at 0\n      \n      callback.mockClear()\n      \n      loader.updateProgress(assetId, 0.5)\n      expect(callback).toHaveBeenCalledWith(0.5)\n    })\n\n    test('unsubscribe removes callback', () => {\n      const callback = vi.fn()\n      const unsubscribe = loader.onProgress(callback)\n      \n      callback.mockClear()\n      unsubscribe()\n      \n      loader.registerAsset('image.png')\n      expect(callback).not.toHaveBeenCalled()\n    })\n\n    test('handles multiple progress callbacks', () => {\n      const callback1 = vi.fn()\n      const callback2 = vi.fn()\n      \n      loader.onProgress(callback1)\n      loader.onProgress(callback2)\n      \n      callback1.mockClear()\n      callback2.mockClear()\n      \n      const assetId = loader.registerAsset('image.png')\n      \n      expect(callback1).toHaveBeenCalled()\n      expect(callback2).toHaveBeenCalled()\n    })\n\n    test('handles errors in progress callbacks gracefully', () => {\n      const errorCallback = vi.fn(() => {\n        throw new Error('Callback error')\n      })\n      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})\n      const normalCallback = vi.fn()\n      \n      loader.onProgress(errorCallback)\n      loader.onProgress(normalCallback)\n      \n      const assetId = loader.registerAsset('image.png')\n      \n      expect(consoleSpy).toHaveBeenCalledWith(\n        'Error in onProgress callback:',\n        expect.any(Error)\n      )\n      // Normal callback should still be called\n      expect(normalCallback).toHaveBeenCalled()\n      \n      consoleSpy.mockRestore()\n    })\n  })\n\n  describe('onComplete', () => {\n    test('registers complete callback', () => {\n      const callback = vi.fn()\n      \n      const unsubscribe = loader.onComplete(callback)\n      \n      expect(typeof unsubscribe).toBe('function')\n    })\n\n    test('calls callback when all assets are complete', () => {\n      const callback = vi.fn()\n      loader.onComplete(callback)\n      \n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      expect(callback).not.toHaveBeenCalled()\n      \n      loader.completeAsset(id1)\n      expect(callback).not.toHaveBeenCalled() // Still one asset pending\n      \n      loader.completeAsset(id2)\n      expect(callback).toHaveBeenCalledTimes(1) // All assets complete\n    })\n\n    test('calls callback immediately if already complete', () => {\n      const callback = vi.fn()\n      \n      const id1 = loader.registerAsset('image1.png')\n      loader.completeAsset(id1)\n      \n      loader.onComplete(callback)\n      \n      expect(callback).toHaveBeenCalledTimes(1)\n    })\n\n    test('unsubscribe removes callback', () => {\n      const callback = vi.fn()\n      const unsubscribe = loader.onComplete(callback)\n      \n      unsubscribe()\n      \n      const assetId = loader.registerAsset('image.png')\n      loader.completeAsset(assetId)\n      \n      expect(callback).not.toHaveBeenCalled()\n    })\n\n    test('handles multiple complete callbacks', () => {\n      const callback1 = vi.fn()\n      const callback2 = vi.fn()\n      \n      loader.onComplete(callback1)\n      loader.onComplete(callback2)\n      \n      const assetId = loader.registerAsset('image.png')\n      loader.completeAsset(assetId)\n      \n      expect(callback1).toHaveBeenCalledTimes(1)\n      expect(callback2).toHaveBeenCalledTimes(1)\n    })\n\n    test('handles errors in complete callbacks gracefully', () => {\n      const errorCallback = vi.fn(() => {\n        throw new Error('Callback error')\n      })\n      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})\n      \n      loader.onComplete(errorCallback)\n      \n      const assetId = loader.registerAsset('image.png')\n      loader.completeAsset(assetId)\n      \n      expect(consoleSpy).toHaveBeenCalledWith(\n        'Error in onComplete callback:',\n        expect.any(Error)\n      )\n      \n      consoleSpy.mockRestore()\n    })\n  })\n\n  describe('getGlobalProgress', () => {\n    test('returns 1 when no assets are registered', () => {\n      expect(loader.getGlobalProgress()).toBe(1)\n    })\n\n    test('returns 0 when asset is registered but not started', () => {\n      loader.registerAsset('image.png')\n      expect(loader.getGlobalProgress()).toBe(0)\n    })\n\n    test('calculates average progress across all assets', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      loader.updateProgress(id1, 0.5)\n      loader.updateProgress(id2, 0.75)\n      \n      expect(loader.getGlobalProgress()).toBe(0.625) // (0.5 + 0.75) / 2\n    })\n\n    test('returns 1 when all assets are complete', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      loader.completeAsset(id1)\n      loader.completeAsset(id2)\n      \n      expect(loader.getGlobalProgress()).toBe(1)\n    })\n  })\n\n  describe('getAssetCount', () => {\n    test('returns 0 initially', () => {\n      expect(loader.getAssetCount()).toBe(0)\n    })\n\n    test('returns correct count after registering assets', () => {\n      loader.registerAsset('image1.png')\n      expect(loader.getAssetCount()).toBe(1)\n      \n      loader.registerAsset('image2.png')\n      expect(loader.getAssetCount()).toBe(2)\n    })\n\n    test('decreases count after removing assets', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      expect(loader.getAssetCount()).toBe(2)\n      \n      loader.removeAsset(id1)\n      expect(loader.getAssetCount()).toBe(1)\n    })\n  })\n\n  describe('getCompletedCount', () => {\n    test('returns 0 initially', () => {\n      expect(loader.getCompletedCount()).toBe(0)\n    })\n\n    test('returns correct count of completed assets', () => {\n      const id1 = loader.registerAsset('image1.png')\n      const id2 = loader.registerAsset('image2.png')\n      \n      expect(loader.getCompletedCount()).toBe(0)\n      \n      loader.completeAsset(id1)\n      expect(loader.getCompletedCount()).toBe(1)\n      \n      loader.completeAsset(id2)\n      expect(loader.getCompletedCount()).toBe(2)\n    })\n  })\n\n  describe('reset', () => {\n    test('clears all assets and callbacks', () => {\n      const progressCallback = vi.fn()\n      const completeCallback = vi.fn()\n      \n      loader.onProgress(progressCallback)\n      loader.onComplete(completeCallback)\n      \n      const id1 = loader.registerAsset('image1.png')\n      loader.updateProgress(id1, 0.5)\n      \n      expect(loader.getAssetCount()).toBe(1)\n      \n      // Clear previous calls\n      progressCallback.mockClear()\n      completeCallback.mockClear()\n      \n      loader.reset()\n      \n      expect(loader.getAssetCount()).toBe(0)\n      expect(loader.getGlobalProgress()).toBe(1)\n      \n      // Callbacks should be cleared - new asset registration shouldn't trigger them\n      const id2 = loader.registerAsset('image2.png')\n      // The initial call from onProgress registration happens, but after reset\n      // new registrations shouldn't trigger the old callbacks\n      expect(progressCallback).not.toHaveBeenCalled()\n    })\n  })\n})\n\n"
  },
  {
    "path": "tests/utils/tabindex.spec.ts",
    "content": "import { describe, expect, test } from \"vitest\";\nimport { signal } from \"canvasengine\";\nimport { createTabindexNavigator } from \"../../packages/core/src/utils/tabindex\";\n\ndescribe(\"createTabindexNavigator\", () => {\n  test(\"wraps values within bounds\", () => {\n    const tabindex = signal(0);\n    const nav = createTabindexNavigator(tabindex, { count: () => 3 }, \"wrap\");\n\n    nav.set(2);\n    expect(tabindex()).toBe(2);\n\n    nav.set(3);\n    expect(tabindex()).toBe(0);\n\n    nav.set(-1);\n    expect(tabindex()).toBe(2);\n  });\n\n  test(\"clamps values within bounds\", () => {\n    const tabindex = signal(0);\n    const nav = createTabindexNavigator(tabindex, { min: 0, max: 2 }, \"clamp\");\n\n    nav.set(10);\n    expect(tabindex()).toBe(2);\n\n    nav.set(-5);\n    expect(tabindex()).toBe(0);\n  });\n\n  test(\"ignores out-of-bounds values in none mode\", () => {\n    const tabindex = signal(1);\n    const nav = createTabindexNavigator(tabindex, { min: 0, max: 2 }, \"none\");\n\n    nav.set(5);\n    expect(tabindex()).toBe(1);\n\n    nav.set(2);\n    expect(tabindex()).toBe(2);\n  });\n\n  test(\"no-ops when count is not positive\", () => {\n    const tabindex = signal(1);\n    const nav = createTabindexNavigator(tabindex, { count: () => 0 }, \"wrap\");\n\n    nav.next(1);\n    expect(tabindex()).toBe(1);\n  });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": false,\n    \"lib\": [\"ES2020\", \"DOM\"],\n    \"moduleResolution\": \"Bundler\",\n    \"paths\": {\n      \"canvasengine\": [\"./packages/core/src/index.ts\"],\n      \"@canvasengine/presets\": [\"./packages/presets/src/index.ts\"]\n    },\n    \"declaration\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true\n  },\n  \"exclude\": [\"**/dist/**\", \"node_modules\", \"docs/**\"]\n}"
  },
  {
    "path": "tsconfig.node.json",
    "content": "{\n  \"compilerOptions\": {\n    \"composite\": true,\n    \"skipLibCheck\": true,\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"bundler\",\n    \"allowSyntheticDefaultImports\": true\n  },\n  \"include\": [\"vite.config.ts\"]\n}\n"
  },
  {
    "path": "tsup.config.ts",
    "content": "import { defineConfig } from 'tsup'\n\nexport default defineConfig({\n  format: ['esm', 'iife'],\n  target: 'es2020',\n  splitting: true,\n  clean: true,\n  shims: false,\n  minify: true,\n  dts: true,\n  sourcemap: true,\n  entry: ['src/index.ts'],\n  outDir: 'dist',\n  define: {\n    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')\n  },\n  globalName: 'CanvasEngine'\n})\n"
  },
  {
    "path": "vitest.config.ts",
    "content": "/// <reference types=\"vitest\" />\nimport { defineConfig } from 'vite'\nimport path from 'path'\nexport default defineConfig(async () => {\n    return {\n        resolve: {\n            alias: {\n                'canvasengine': path.resolve(__dirname, 'packages/core/src'),\n                'pixi-viewport': path.resolve(__dirname, 'packages/core/node_modules/pixi-viewport')\n            }\n        },\n        test: {\n            environment: 'jsdom',\n            pool: 'forks',\n            setupFiles: ['./tests/setup/canvas.ts'],\n            exclude: [\n                '**/sample/**',\n                '**/node_modules/**'\n            ],\n            coverage: {\n                include: [\n                    'packages/**'\n                ]\n            }\n        }\n    }\n})\n"
  }
]