ts-tiled-converter
Version:
Typescript library to convert tiled map to Studio map
45 lines (33 loc) • 2.29 kB
text/typescript
import { layerToTiles } from './layerToTiles';
import { SPECIAL_LAYER_TILESETS } from './splitSpecialAndRegularLayers';
import { TiledXMLGroup, TiledXMLLayer, TiledXMLMap, getXMLProperties } from '../tiledXML/objects';
import type { LayerWithMetaData, TileMetaData } from '../types';
import { throwIfError, toError } from '../util';
let cache: Map<number, TileMetaData | null>;
export const mapToTileLayersWithMetaData = ({ map }: TiledXMLMap): LayerWithMetaData[] | Error => {
try {
cache = new Map<number, TileMetaData | null>();
return filterAndFlatten(map, 0).map(mapLayerToTileLayers);
} catch (error) {
return toError(error);
}
};
type AnyMapOrGroupChild = (TiledXMLMap['map'] | TiledXMLGroup['group'])[number];
type LayerWithZIndex = { z: number; name: string; entity: TiledXMLLayer };
const isVisibleLayer = (entity: AnyMapOrGroupChild): entity is TiledXMLLayer =>
'layer' in entity && (getXMLProperties(entity).visible != 0 || getXMLProperties(entity).name in SPECIAL_LAYER_TILESETS);
const isVisibleGroup = (entity: AnyMapOrGroupChild): entity is TiledXMLGroup =>
'group' in entity && (getXMLProperties(entity).visible != 0 || getXMLProperties(entity).name.startsWith('system'));
const filterLayerOrGroup = (entity: AnyMapOrGroupChild): entity is TiledXMLLayer | TiledXMLGroup => isVisibleLayer(entity) || isVisibleGroup(entity);
const filterAndFlatten = (e: AnyMapOrGroupChild[], groupZIndex: number) => e.filter(filterLayerOrGroup).flatMap(mapGroupOrLayerToLayers(groupZIndex));
const flattenGroup = (group: TiledXMLGroup, groupZIndex: number): LayerWithZIndex[] => {
const { name } = getXMLProperties(group);
return filterAndFlatten(group.group, name.startsWith('z=') ? Number(name.split('=')[1]) - 1 : groupZIndex);
};
const mapGroupOrLayerToLayers = (groupZIndex: number) => (entity: TiledXMLLayer | TiledXMLGroup) => {
if ('group' in entity) return flattenGroup(entity, groupZIndex);
const { name } = getXMLProperties(entity);
const regMatch = name.match(/([1-6])$/);
return { z: regMatch ? Number(regMatch[0]) - 1 : groupZIndex, name, entity };
};
const mapLayerToTileLayers = ({ z, name, entity }: LayerWithZIndex) => ({ z, name, layer: throwIfError(layerToTiles(entity, cache)) });