Files
pytiled_parser/pytiled_parser/parsers/tmx/tiled_map.py
2021-12-19 16:13:20 -05:00

132 lines
5.2 KiB
Python

import json
import xml.etree.ElementTree as etree
from pathlib import Path
from pytiled_parser.common_types import OrderedPair, Size
from pytiled_parser.exception import UnknownFormat
from pytiled_parser.parsers.json.tileset import parse as parse_json_tileset
from pytiled_parser.parsers.tmx.layer import parse as parse_layer
from pytiled_parser.parsers.tmx.properties import parse as parse_properties
from pytiled_parser.parsers.tmx.tileset import parse as parse_tmx_tileset
from pytiled_parser.tiled_map import TiledMap, TilesetDict
from pytiled_parser.util import check_format, parse_color
def parse(file: Path) -> TiledMap:
"""Parse the raw Tiled map into a pytiled_parser type.
Args:
file: Path to the map file.
Returns:
TiledMap: A parsed TiledMap.
"""
with open(file) as map_file:
raw_map = etree.parse(map_file).getroot()
parent_dir = file.parent
raw_tilesets = raw_map.findall("./tileset")
tilesets: TilesetDict = {}
for raw_tileset in raw_tilesets:
if raw_tileset.attrib.get("source") is not None:
# Is an external Tileset
tileset_path = Path(parent_dir / raw_tileset.attrib["source"])
parser = check_format(tileset_path)
with open(tileset_path) as tileset_file:
if parser == "tmx":
raw_tileset_external = etree.parse(tileset_file).getroot()
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tmx_tileset(
raw_tileset_external,
int(raw_tileset.attrib["firstgid"]),
external_path=tileset_path.parent,
)
elif parser == "json":
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_json_tileset(
json.load(tileset_file),
int(raw_tileset.attrib["firstgid"]),
external_path=tileset_path.parent,
)
else:
raise UnknownFormat(
"Unkown Tileset format, please use either the TSX or JSON format."
)
else:
# Is an embedded Tileset
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tmx_tileset(
raw_tileset, int(raw_tileset.attrib["firstgid"])
)
layers = []
for element in raw_map.iter():
if element.tag in ["layer", "objectgroup", "imagelayer", "group"]:
layers.append(parse_layer(element, parent_dir))
map_ = TiledMap(
map_file=file,
infinite=bool(int(raw_map.attrib["infinite"])),
layers=layers,
map_size=Size(int(raw_map.attrib["width"]), int(raw_map.attrib["height"])),
next_layer_id=int(raw_map.attrib["nextlayerid"]),
next_object_id=int(raw_map.attrib["nextobjectid"]),
orientation=raw_map.attrib["orientation"],
render_order=raw_map.attrib["renderorder"],
tiled_version=raw_map.attrib["tiledversion"],
tile_size=Size(
int(raw_map.attrib["tilewidth"]), int(raw_map.attrib["tileheight"])
),
tilesets=tilesets,
version=raw_map.attrib["version"],
)
layers = [layer for layer in map_.layers if hasattr(layer, "tiled_objects")]
for my_layer in layers:
for tiled_object in my_layer.tiled_objects:
if hasattr(tiled_object, "new_tileset"):
if tiled_object.new_tileset is not None:
already_loaded = None
for val in map_.tilesets.values():
if val.name == tiled_object.new_tileset.attrib["name"]:
already_loaded = val
break
if not already_loaded:
highest_firstgid = max(map_.tilesets.keys())
last_tileset_count = map_.tilesets[highest_firstgid].tile_count
new_firstgid = highest_firstgid + last_tileset_count
map_.tilesets[new_firstgid] = parse_tmx_tileset(
tiled_object.new_tileset,
new_firstgid,
tiled_object.new_tileset_path,
)
tiled_object.gid = tiled_object.gid + (new_firstgid - 1)
else:
tiled_object.gid = tiled_object.gid + (
already_loaded.firstgid - 1
)
tiled_object.new_tileset = None
tiled_object.new_tileset_path = None
if raw_map.attrib.get("backgroundcolor") is not None:
map_.background_color = parse_color(raw_map.attrib["backgroundcolor"])
if raw_map.attrib.get("hexsidelength") is not None:
map_.hex_side_length = int(raw_map.attrib["hexsidelength"])
properties_element = raw_map.find("./properties")
if properties_element:
map_.properties = parse_properties(properties_element)
if raw_map.attrib.get("staggeraxis") is not None:
map_.stagger_axis = raw_map.attrib["staggeraxis"]
if raw_map.attrib.get("staggerindex") is not None:
map_.stagger_index = raw_map.attrib["staggerindex"]
return map_