kaplay-plugin-tiled
Version:
KAPLAY plugin for Tiled maps
1 lines • 19.5 kB
Source Map (JSON)
{"version":3,"file":"plugin.mjs","names":[],"sources":["../src/utils.ts","../src/plugin.ts"],"sourcesContent":["import type { CompList, GameObj, KAPLAYCtx, Quad } from 'kaplay';\n\nimport type {\n ParsedTiledLayer,\n ParsedTiledMap,\n ParsedTiledObjectLayer,\n ParsedTiledTile,\n ParsedTiledTileLayer,\n TiledLayer,\n TiledLayerComp,\n TiledMap,\n TiledMapData,\n TiledMapOpt,\n TiledObjectContext,\n TiledObjectLayer,\n TiledObjectMatch,\n TiledProperty,\n TiledPropertyValue,\n TiledTileContext,\n TiledTileLayer,\n TiledTileMatch,\n} from './types';\n\nconst FLIPPED_HORIZONTALLY_FLAG = 0x80000000;\nconst FLIPPED_VERTICALLY_FLAG = 0x40000000;\nconst FLIPPED_DIAGONALLY_FLAG = 0x20000000;\nconst FLIP_FLAGS =\n FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;\n\ninterface ParsedTileGid {\n gid: number;\n flip: {\n diagonal: boolean;\n horizontal: boolean;\n vertical: boolean;\n };\n}\n\nexport function resolveTiledMap(k: KAPLAYCtx, map: TiledMap): TiledMapData {\n if (typeof map !== 'string') {\n return map;\n }\n\n const asset = k.getAsset(map);\n\n if (!asset) {\n throw new Error(`Tiled map asset \"${map}\" is not loaded.`);\n }\n\n if (!asset.data) {\n throw new Error(`Tiled map asset \"${map}\" is not ready yet.`);\n }\n\n return asset.data as TiledMapData;\n}\n\nfunction getPropertyRecord(\n properties: TiledProperty[] | undefined,\n): Record<string, TiledPropertyValue> {\n const record: Record<string, TiledPropertyValue> = {};\n\n properties?.forEach((property) => {\n record[property.name] = property.value;\n });\n\n return record;\n}\n\nfunction isObjectLayer(layer: TiledLayer): layer is TiledObjectLayer {\n return layer.type === 'objectgroup';\n}\n\nfunction isTileLayer(layer: TiledLayer): layer is TiledTileLayer {\n return layer.type === 'tilelayer';\n}\n\nfunction normalizeTileLayer(layer: TiledTileLayer): ParsedTiledLayer {\n return {\n data: layer.data,\n height: layer.height,\n name: layer.name,\n opacity: layer.opacity ?? 1,\n type: 'tilelayer',\n visible: layer.visible ?? true,\n width: layer.width,\n x: layer.x ?? 0,\n y: layer.y ?? 0,\n zIndex: 0,\n };\n}\n\nfunction normalizeObjectLayer(layer: TiledObjectLayer): ParsedTiledObjectLayer {\n return {\n name: layer.name,\n objects: layer.objects,\n type: 'objectgroup',\n visible: layer.visible ?? true,\n zIndex: 0,\n };\n}\n\nexport function parseTileGid(rawGid: number): ParsedTileGid | null {\n if (rawGid === 0) {\n return null;\n }\n\n return {\n gid: (rawGid & ~FLIP_FLAGS) >>> 0,\n flip: {\n diagonal: (rawGid & FLIPPED_DIAGONALLY_FLAG) !== 0,\n horizontal: (rawGid & FLIPPED_HORIZONTALLY_FLAG) !== 0,\n vertical: (rawGid & FLIPPED_VERTICALLY_FLAG) !== 0,\n },\n };\n}\n\nfunction getTileDrawTransform(flip: ParsedTileGid['flip']): {\n angle: number;\n flipX: boolean;\n flipY: boolean;\n} {\n if (!flip.diagonal) {\n return {\n angle: 0,\n flipX: flip.horizontal,\n flipY: flip.vertical,\n };\n }\n\n if (flip.horizontal && flip.vertical) {\n return {\n angle: 270,\n flipX: true,\n flipY: false,\n };\n }\n\n if (flip.horizontal) {\n return {\n angle: 270,\n flipX: false,\n flipY: false,\n };\n }\n\n if (flip.vertical) {\n return {\n angle: 90,\n flipX: false,\n flipY: false,\n };\n }\n\n return {\n angle: 270,\n flipX: false,\n flipY: true,\n };\n}\n\nfunction getTileQuad(k: KAPLAYCtx, map: ParsedTiledMap, gid: number): Quad {\n const localTileId = gid - map.tileset.firstGid;\n const column = localTileId % map.tileset.columns;\n const row = Math.floor(localTileId / map.tileset.columns);\n const x =\n map.tileset.margin + column * (map.tileset.tileWidth + map.tileset.spacing);\n const y =\n map.tileset.margin + row * (map.tileset.tileHeight + map.tileset.spacing);\n\n return k.quad(\n x / map.tileset.imageWidth,\n y / map.tileset.imageHeight,\n map.tileset.tileWidth / map.tileset.imageWidth,\n map.tileset.tileHeight / map.tileset.imageHeight,\n );\n}\n\nexport function getLayerNames(options: TiledMapOpt): Set<string> | null {\n if (!options.layerNames?.length) {\n return null;\n }\n\n return new Set(options.layerNames);\n}\n\nfunction getParsedTile(\n map: ParsedTiledMap,\n gid: number,\n): ParsedTiledTile | undefined {\n return map.tileset.tiles[gid];\n}\n\nfunction matchesProperties(\n expected: Record<string, TiledPropertyValue> | undefined,\n actual: Record<string, TiledPropertyValue>,\n): boolean {\n if (!expected) {\n return true;\n }\n\n return Object.entries(expected).every(\n ([name, value]) => actual[name] === value,\n );\n}\n\nfunction matchesTileRule(\n match: TiledTileMatch,\n tile: TiledTileContext,\n): boolean {\n if (match.gid !== undefined && match.gid !== tile.gid) {\n return false;\n }\n\n if (match.tileId !== undefined && match.tileId !== tile.tileId) {\n return false;\n }\n\n if (match.layer !== undefined && match.layer !== tile.layer) {\n return false;\n }\n\n return matchesProperties(match.properties, tile.properties);\n}\n\nfunction matchesObjectRule(\n match: TiledObjectMatch,\n object: TiledObjectContext,\n): boolean {\n if (match.layer !== undefined && match.layer !== object.layer) {\n return false;\n }\n\n if (match.name !== undefined && match.name !== object.name) {\n return false;\n }\n\n if (match.type !== undefined && match.type !== object.type) {\n return false;\n }\n\n return matchesProperties(match.properties, object.properties);\n}\n\nexport function createLayerRenderer(\n k: KAPLAYCtx,\n layer: ParsedTiledTileLayer,\n map: ParsedTiledMap,\n sprite: string,\n): GameObj {\n return k.add([\n k.pos(0, 0),\n k.z(layer.zIndex),\n {\n draw: () => {\n layer.data.forEach((rawGid, index) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (!parsedGid) {\n return;\n }\n\n const column = index % layer.width;\n const row = Math.floor(index / layer.width);\n const drawTransform = getTileDrawTransform(parsedGid.flip);\n\n k.drawSprite({\n anchor: 'center',\n angle: drawTransform.angle,\n flipX: drawTransform.flipX,\n flipY: drawTransform.flipY,\n opacity: layer.opacity,\n pos: k.vec2(\n (column + layer.x) * map.tileWidth + map.tileset.tileWidth / 2,\n (row + layer.y) * map.tileHeight + map.tileset.tileHeight / 2,\n ),\n quad: getTileQuad(k, map, parsedGid.gid),\n sprite,\n });\n });\n },\n id: 'tiled-layer',\n },\n ] as CompList<TiledLayerComp>);\n}\n\nexport function createMatchedTileObjects(\n k: KAPLAYCtx,\n layer: ParsedTiledTileLayer,\n map: ParsedTiledMap,\n options: TiledMapOpt,\n): GameObj[] {\n const rules = options.tiles;\n\n if (!rules?.length) {\n return [];\n }\n\n const tiles: GameObj[] = [];\n\n layer.data.forEach((rawGid, index) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (!parsedGid) {\n return;\n }\n\n const parsedTile = getParsedTile(map, parsedGid.gid);\n const column = index % layer.width;\n const row = Math.floor(index / layer.width);\n const tile = {\n flip: parsedGid.flip,\n gid: parsedGid.gid,\n height: map.tileHeight,\n layer: layer.name,\n tileHeight: map.tileHeight,\n tileWidth: map.tileWidth,\n tileX: column + layer.x,\n tileY: row + layer.y,\n width: map.tileWidth,\n x: (column + layer.x) * map.tileWidth,\n y: (row + layer.y) * map.tileHeight,\n properties: parsedTile?.properties ?? {},\n tileId: parsedTile?.tileId ?? parsedGid.gid - map.tileset.firstGid,\n };\n\n rules.forEach((rule) => {\n if (!matchesTileRule(rule.match, tile)) {\n return;\n }\n\n tiles.push(\n k.add([\n k.pos(tile.x, tile.y),\n k.anchor('topleft'),\n k.z(layer.zIndex),\n ...rule.comps(tile),\n ] as CompList<unknown>),\n );\n });\n });\n\n return tiles;\n}\n\nexport function createMatchedObjectObjects(\n k: KAPLAYCtx,\n layer: ParsedTiledObjectLayer,\n options: TiledMapOpt,\n): GameObj[] {\n const rules = options.objects;\n\n if (!rules?.length) {\n return [];\n }\n\n const objects: GameObj[] = [];\n\n if (!layer.visible) {\n return objects;\n }\n\n layer.objects.forEach((object) => {\n if (!object.visible) {\n return;\n }\n\n const context: TiledObjectContext = {\n height: object.height,\n id: object.id,\n layer: layer.name,\n name: object.name,\n width: object.width,\n x: object.x,\n y: object.y,\n point: object.point ?? false,\n properties: getPropertyRecord(object.properties),\n rotation: object.rotation,\n type: object.type,\n };\n\n rules.forEach((rule) => {\n if (!matchesObjectRule(rule.match, context)) {\n return;\n }\n\n objects.push(\n k.add([\n k.pos(context.x, context.y),\n k.anchor('topleft'),\n k.z(layer.zIndex),\n ...rule.comps(context),\n ] as CompList<unknown>),\n );\n });\n });\n\n return objects;\n}\n\nexport function parseTiledMap(data: TiledMapData): ParsedTiledMap {\n if (data.orientation !== 'orthogonal') {\n throw new Error(\n `Unsupported Tiled orientation \"${data.orientation}\". Expected \"orthogonal\".`,\n );\n }\n\n if (data.infinite) {\n throw new Error('Infinite Tiled maps are not supported.');\n }\n\n if (data.tilesets.length !== 1) {\n throw new Error('Exactly one Tiled tileset is required.');\n }\n\n const [tileset] = data.tilesets;\n\n if (tileset.columns <= 0) {\n throw new Error('Tiled tileset columns must be greater than 0.');\n }\n\n const layers = data.layers.map((layer, zIndex) => {\n if (isTileLayer(layer)) {\n if (layer.data.length !== layer.width * layer.height) {\n throw new Error(\n `Layer \"${layer.name}\" data length does not match its dimensions.`,\n );\n }\n\n return {\n ...normalizeTileLayer(layer),\n zIndex,\n };\n }\n\n if (isObjectLayer(layer)) {\n return {\n ...normalizeObjectLayer(layer),\n zIndex,\n };\n }\n\n throw new Error('Unsupported Tiled layer type.');\n });\n\n return {\n height: data.height,\n layers,\n orientation: 'orthogonal',\n tileHeight: data.tileheight,\n tileWidth: data.tilewidth,\n tileset: {\n columns: tileset.columns,\n firstGid: tileset.firstgid,\n image: tileset.image,\n imageHeight: tileset.imageheight,\n imageWidth: tileset.imagewidth,\n lastGid: tileset.firstgid + tileset.tilecount - 1,\n margin: tileset.margin ?? 0,\n name: tileset.name,\n spacing: tileset.spacing ?? 0,\n tileCount: tileset.tilecount,\n tileHeight: tileset.tileheight,\n tiles: Object.fromEntries(\n (tileset.tiles ?? []).map((tile) => [\n tile.id + tileset.firstgid,\n {\n gid: tile.id + tileset.firstgid,\n properties: getPropertyRecord(tile.properties),\n tileId: tile.id,\n },\n ]),\n ),\n tileWidth: tileset.tilewidth,\n },\n width: data.width,\n };\n}\n","import type { KAPLAYCtx } from 'kaplay';\n\nimport type { AddTiledMap, TiledMap, TiledMapOpt } from './types';\nimport {\n createLayerRenderer,\n createMatchedObjectObjects,\n createMatchedTileObjects,\n getLayerNames,\n parseTiledMap,\n parseTileGid,\n resolveTiledMap,\n} from './utils';\n\nexport type { AddTiledMap, TiledMap, TiledMapOpt } from './types';\n\ndeclare module 'kaplay' {\n interface KAPLAYCtx {\n addTiledMap: (map: TiledMap, options: TiledMapOpt) => void;\n }\n}\n\n/**\n * Add a Tiled map to the current KAPLAY context.\n *\n * The `map` argument can either be:\n * - parsed map JSON, or\n * - the asset key of a map loaded with `loadJSON()`.\n *\n * @param k - The active KAPLAY context.\n * @param map - The Tiled map data.\n * @param opt - The Tiled map options.\n */\nfunction addTiledMap(k: KAPLAYCtx, map: TiledMap, opt: TiledMapOpt): void {\n const parsedMap = parseTiledMap(resolveTiledMap(k, map));\n const allowedLayerNames = getLayerNames(opt);\n\n parsedMap.layers.forEach((layer) => {\n if (!layer.visible) {\n return;\n }\n\n if (allowedLayerNames && !allowedLayerNames.has(layer.name)) {\n return;\n }\n\n if (layer.type === 'tilelayer') {\n layer.data.forEach((rawGid) => {\n const parsedGid = parseTileGid(rawGid);\n\n if (\n parsedGid &&\n (parsedGid.gid < parsedMap.tileset.firstGid ||\n parsedGid.gid > parsedMap.tileset.lastGid)\n ) {\n throw new Error(\n `Tile gid ${String(rawGid)} is outside the supported tileset range.`,\n );\n }\n });\n\n createLayerRenderer(k, layer, parsedMap, opt.sprite);\n createMatchedTileObjects(k, layer, parsedMap, opt);\n return;\n }\n\n createMatchedObjectObjects(k, layer, opt);\n });\n}\n\n/**\n * KAPLAY plugin that adds `addTiledMap()` to the context.\n *\n * @param k - The active KAPLAY context.\n * @returns - The plugin API.\n */\nexport function tiledPlugin(k: KAPLAYCtx) {\n const boundAddTiledMap: AddTiledMap = (map, options) => {\n addTiledMap(k, map, options);\n };\n\n return { addTiledMap: boundAddTiledMap };\n}\n"],"mappings":";AAuBA,IAAM,IAA4B,YAC5B,IAA0B,YAC1B,IAA0B,WAC1B,IACwB,IAAA;AAW9B,SAAgB,EAAgB,GAAc,GAA6B;AACzE,KAAI,OAAO,KAAQ,SACjB,QAAO;CAGT,IAAM,IAAQ,EAAE,SAAS,EAAI;AAE7B,KAAI,CAAC,EACH,OAAU,MAAM,oBAAoB,EAAI,kBAAkB;AAG5D,KAAI,CAAC,EAAM,KACT,OAAU,MAAM,oBAAoB,EAAI,qBAAqB;AAG/D,QAAO,EAAM;;AAGf,SAAS,EACP,GACoC;CACpC,IAAM,IAA6C,EAAE;AAMrD,QAJA,GAAY,SAAS,MAAa;AAChC,IAAO,EAAS,QAAQ,EAAS;GACjC,EAEK;;AAGT,SAAS,EAAc,GAA8C;AACnE,QAAO,EAAM,SAAS;;AAGxB,SAAS,EAAY,GAA4C;AAC/D,QAAO,EAAM,SAAS;;AAGxB,SAAS,EAAmB,GAAyC;AACnE,QAAO;EACL,MAAM,EAAM;EACZ,QAAQ,EAAM;EACd,MAAM,EAAM;EACZ,SAAS,EAAM,WAAW;EAC1B,MAAM;EACN,SAAS,EAAM,WAAW;EAC1B,OAAO,EAAM;EACb,GAAG,EAAM,KAAK;EACd,GAAG,EAAM,KAAK;EACd,QAAQ;EACT;;AAGH,SAAS,EAAqB,GAAiD;AAC7E,QAAO;EACL,MAAM,EAAM;EACZ,SAAS,EAAM;EACf,MAAM;EACN,SAAS,EAAM,WAAW;EAC1B,QAAQ;EACT;;AAGH,SAAgB,EAAa,GAAsC;AAKjE,QAJI,MAAW,IACN,OAGF;EACL,MAAM,IAAS,CAAC,OAAgB;EAChC,MAAM;GACJ,WAAW,IAAS,OAA6B;GACjD,aAAa,IAAS,OAA+B;GACrD,WAAW,IAAS,OAA6B;GAClD;EACF;;AAGH,SAAS,EAAqB,GAI5B;AAiCA,QAhCK,EAAK,WAQN,EAAK,cAAc,EAAK,WACnB;EACL,OAAO;EACP,OAAO;EACP,OAAO;EACR,GAGC,EAAK,aACA;EACL,OAAO;EACP,OAAO;EACP,OAAO;EACR,GAGC,EAAK,WACA;EACL,OAAO;EACP,OAAO;EACP,OAAO;EACR,GAGI;EACL,OAAO;EACP,OAAO;EACP,OAAO;EACR,GAnCQ;EACL,OAAO;EACP,OAAO,EAAK;EACZ,OAAO,EAAK;EACb;;AAkCL,SAAS,EAAY,GAAc,GAAqB,GAAmB;CACzE,IAAM,IAAc,IAAM,EAAI,QAAQ,UAChC,IAAS,IAAc,EAAI,QAAQ,SACnC,IAAM,KAAK,MAAM,IAAc,EAAI,QAAQ,QAAQ,EACnD,IACJ,EAAI,QAAQ,SAAS,KAAU,EAAI,QAAQ,YAAY,EAAI,QAAQ,UAC/D,IACJ,EAAI,QAAQ,SAAS,KAAO,EAAI,QAAQ,aAAa,EAAI,QAAQ;AAEnE,QAAO,EAAE,KACP,IAAI,EAAI,QAAQ,YAChB,IAAI,EAAI,QAAQ,aAChB,EAAI,QAAQ,YAAY,EAAI,QAAQ,YACpC,EAAI,QAAQ,aAAa,EAAI,QAAQ,YACtC;;AAGH,SAAgB,EAAc,GAA0C;AAKtE,QAJK,EAAQ,YAAY,SAIlB,IAAI,IAAI,EAAQ,WAAW,GAHzB;;AAMX,SAAS,EACP,GACA,GAC6B;AAC7B,QAAO,EAAI,QAAQ,MAAM;;AAG3B,SAAS,EACP,GACA,GACS;AAKT,QAJK,IAIE,OAAO,QAAQ,EAAS,CAAC,OAC7B,CAAC,GAAM,OAAW,EAAO,OAAU,EACrC,GALQ;;AAQX,SAAS,EACP,GACA,GACS;AAaT,QAZI,EAAM,QAAQ,KAAA,KAAa,EAAM,QAAQ,EAAK,OAI9C,EAAM,WAAW,KAAA,KAAa,EAAM,WAAW,EAAK,UAIpD,EAAM,UAAU,KAAA,KAAa,EAAM,UAAU,EAAK,QAC7C,KAGF,EAAkB,EAAM,YAAY,EAAK,WAAW;;AAG7D,SAAS,EACP,GACA,GACS;AAaT,QAZI,EAAM,UAAU,KAAA,KAAa,EAAM,UAAU,EAAO,SAIpD,EAAM,SAAS,KAAA,KAAa,EAAM,SAAS,EAAO,QAIlD,EAAM,SAAS,KAAA,KAAa,EAAM,SAAS,EAAO,OAC7C,KAGF,EAAkB,EAAM,YAAY,EAAO,WAAW;;AAG/D,SAAgB,EACd,GACA,GACA,GACA,GACS;AACT,QAAO,EAAE,IAAI;EACX,EAAE,IAAI,GAAG,EAAE;EACX,EAAE,EAAE,EAAM,OAAO;EACjB;GACE,YAAY;AACV,MAAM,KAAK,SAAS,GAAQ,MAAU;KACpC,IAAM,IAAY,EAAa,EAAO;AAEtC,SAAI,CAAC,EACH;KAGF,IAAM,IAAS,IAAQ,EAAM,OACvB,IAAM,KAAK,MAAM,IAAQ,EAAM,MAAM,EACrC,IAAgB,EAAqB,EAAU,KAAK;AAE1D,OAAE,WAAW;MACX,QAAQ;MACR,OAAO,EAAc;MACrB,OAAO,EAAc;MACrB,OAAO,EAAc;MACrB,SAAS,EAAM;MACf,KAAK,EAAE,MACJ,IAAS,EAAM,KAAK,EAAI,YAAY,EAAI,QAAQ,YAAY,IAC5D,IAAM,EAAM,KAAK,EAAI,aAAa,EAAI,QAAQ,aAAa,EAC7D;MACD,MAAM,EAAY,GAAG,GAAK,EAAU,IAAI;MACxC;MACD,CAAC;MACF;;GAEJ,IAAI;GACL;EACF,CAA6B;;AAGhC,SAAgB,EACd,GACA,GACA,GACA,GACW;CACX,IAAM,IAAQ,EAAQ;AAEtB,KAAI,CAAC,GAAO,OACV,QAAO,EAAE;CAGX,IAAM,IAAmB,EAAE;AA4C3B,QA1CA,EAAM,KAAK,SAAS,GAAQ,MAAU;EACpC,IAAM,IAAY,EAAa,EAAO;AAEtC,MAAI,CAAC,EACH;EAGF,IAAM,IAAa,EAAc,GAAK,EAAU,IAAI,EAC9C,IAAS,IAAQ,EAAM,OACvB,IAAM,KAAK,MAAM,IAAQ,EAAM,MAAM,EACrC,IAAO;GACX,MAAM,EAAU;GAChB,KAAK,EAAU;GACf,QAAQ,EAAI;GACZ,OAAO,EAAM;GACb,YAAY,EAAI;GAChB,WAAW,EAAI;GACf,OAAO,IAAS,EAAM;GACtB,OAAO,IAAM,EAAM;GACnB,OAAO,EAAI;GACX,IAAI,IAAS,EAAM,KAAK,EAAI;GAC5B,IAAI,IAAM,EAAM,KAAK,EAAI;GACzB,YAAY,GAAY,cAAc,EAAE;GACxC,QAAQ,GAAY,UAAU,EAAU,MAAM,EAAI,QAAQ;GAC3D;AAED,IAAM,SAAS,MAAS;AACjB,KAAgB,EAAK,OAAO,EAAK,IAItC,EAAM,KACJ,EAAE,IAAI;IACJ,EAAE,IAAI,EAAK,GAAG,EAAK,EAAE;IACrB,EAAE,OAAO,UAAU;IACnB,EAAE,EAAE,EAAM,OAAO;IACjB,GAAG,EAAK,MAAM,EAAK;IACpB,CAAsB,CACxB;IACD;GACF,EAEK;;AAGT,SAAgB,EACd,GACA,GACA,GACW;CACX,IAAM,IAAQ,EAAQ;AAEtB,KAAI,CAAC,GAAO,OACV,QAAO,EAAE;CAGX,IAAM,IAAqB,EAAE;AAyC7B,QAvCK,EAAM,WAIX,EAAM,QAAQ,SAAS,MAAW;AAChC,MAAI,CAAC,EAAO,QACV;EAGF,IAAM,IAA8B;GAClC,QAAQ,EAAO;GACf,IAAI,EAAO;GACX,OAAO,EAAM;GACb,MAAM,EAAO;GACb,OAAO,EAAO;GACd,GAAG,EAAO;GACV,GAAG,EAAO;GACV,OAAO,EAAO,SAAS;GACvB,YAAY,EAAkB,EAAO,WAAW;GAChD,UAAU,EAAO;GACjB,MAAM,EAAO;GACd;AAED,IAAM,SAAS,MAAS;AACjB,KAAkB,EAAK,OAAO,EAAQ,IAI3C,EAAQ,KACN,EAAE,IAAI;IACJ,EAAE,IAAI,EAAQ,GAAG,EAAQ,EAAE;IAC3B,EAAE,OAAO,UAAU;IACnB,EAAE,EAAE,EAAM,OAAO;IACjB,GAAG,EAAK,MAAM,EAAQ;IACvB,CAAsB,CACxB;IACD;GACF,EApCO;;AAyCX,SAAgB,EAAc,GAAoC;AAChE,KAAI,EAAK,gBAAgB,aACvB,OAAU,MACR,kCAAkC,EAAK,YAAY,2BACpD;AAGH,KAAI,EAAK,SACP,OAAU,MAAM,yCAAyC;AAG3D,KAAI,EAAK,SAAS,WAAW,EAC3B,OAAU,MAAM,yCAAyC;CAG3D,IAAM,CAAC,KAAW,EAAK;AAEvB,KAAI,EAAQ,WAAW,EACrB,OAAU,MAAM,gDAAgD;CAGlE,IAAM,IAAS,EAAK,OAAO,KAAK,GAAO,MAAW;AAChD,MAAI,EAAY,EAAM,EAAE;AACtB,OAAI,EAAM,KAAK,WAAW,EAAM,QAAQ,EAAM,OAC5C,OAAU,MACR,UAAU,EAAM,KAAK,8CACtB;AAGH,UAAO;IACL,GAAG,EAAmB,EAAM;IAC5B;IACD;;AAGH,MAAI,EAAc,EAAM,CACtB,QAAO;GACL,GAAG,EAAqB,EAAM;GAC9B;GACD;AAGH,QAAU,MAAM,gCAAgC;GAChD;AAEF,QAAO;EACL,QAAQ,EAAK;EACb;EACA,aAAa;EACb,YAAY,EAAK;EACjB,WAAW,EAAK;EAChB,SAAS;GACP,SAAS,EAAQ;GACjB,UAAU,EAAQ;GAClB,OAAO,EAAQ;GACf,aAAa,EAAQ;GACrB,YAAY,EAAQ;GACpB,SAAS,EAAQ,WAAW,EAAQ,YAAY;GAChD,QAAQ,EAAQ,UAAU;GAC1B,MAAM,EAAQ;GACd,SAAS,EAAQ,WAAW;GAC5B,WAAW,EAAQ;GACnB,YAAY,EAAQ;GACpB,OAAO,OAAO,aACX,EAAQ,SAAS,EAAE,EAAE,KAAK,MAAS,CAClC,EAAK,KAAK,EAAQ,UAClB;IACE,KAAK,EAAK,KAAK,EAAQ;IACvB,YAAY,EAAkB,EAAK,WAAW;IAC9C,QAAQ,EAAK;IACd,CACF,CAAC,CACH;GACD,WAAW,EAAQ;GACpB;EACD,OAAO,EAAK;EACb;;;;AC3bH,SAAS,EAAY,GAAc,GAAe,GAAwB;CACxE,IAAM,IAAY,EAAc,EAAgB,GAAG,EAAI,CAAC,EAClD,IAAoB,EAAc,EAAI;AAE5C,GAAU,OAAO,SAAS,MAAU;AAC7B,QAAM,WAIP,OAAqB,CAAC,EAAkB,IAAI,EAAM,KAAK,GAI3D;OAAI,EAAM,SAAS,aAAa;AAgB9B,IAfA,EAAM,KAAK,SAAS,MAAW;KAC7B,IAAM,IAAY,EAAa,EAAO;AAEtC,SACE,MACC,EAAU,MAAM,EAAU,QAAQ,YACjC,EAAU,MAAM,EAAU,QAAQ,SAEpC,OAAU,MACR,YAAY,OAAO,EAAO,CAAC,0CAC5B;MAEH,EAEF,EAAoB,GAAG,GAAO,GAAW,EAAI,OAAO,EACpD,EAAyB,GAAG,GAAO,GAAW,EAAI;AAClD;;AAGF,KAA2B,GAAG,GAAO,EAAI;;GACzC;;AASJ,SAAgB,EAAY,GAAc;AAKxC,QAAO,EAAE,cAJ8B,GAAK,MAAY;AACtD,IAAY,GAAG,GAAK,EAAQ;IAGU"}