Automatic detection of map/tileset format

This commit is contained in:
Darren Eberly
2021-12-19 16:13:20 -05:00
parent 2395dd32ca
commit 5ce8bbafcb
6 changed files with 79 additions and 28 deletions

View File

@@ -12,8 +12,9 @@ PyTiled Parser is not tied to any particular graphics library or game engine.
# pylint: disable=too-few-public-methods
from .common_types import OrderedPair, Size
from .exception import UnknownFormat
from .layer import ImageLayer, Layer, LayerGroup, ObjectLayer, TileLayer
from .parser import parse_map, parse_tmx
from .parser import parse_map
from .properties import Properties
from .tiled_map import TiledMap
from .tileset import Tile, Tileset

View File

@@ -0,0 +1,2 @@
class UnknownFormat(Exception):
pass

View File

@@ -1,22 +1,29 @@
from pathlib import Path
from pytiled_parser import UnknownFormat
from pytiled_parser.parsers.json.tiled_map import parse as json_map_parse
from pytiled_parser.parsers.tmx.tiled_map import parse as tmx_map_parse
from pytiled_parser.tiled_map import TiledMap
from pytiled_parser.util import check_format
def parse_map(file: Path) -> TiledMap:
"""Parse the raw Tiled map into a pytiled_parser type
Args:
file: Path to the map's JSON file
file: Path to the map file
Returns:
TileSet: a properly typed TileSet.
Tiledmap: a properly typed TiledMap
"""
# I have no idea why, but mypy thinks this function returns "Any"
return json_map_parse(file) # type: ignore
parser = check_format(file)
def parse_tmx(file: Path) -> TiledMap:
return tmx_map_parse(file) # type: ignore
# The type ignores are because mypy for some reaosn thinks those functions return Any
if parser == "tmx":
return tmx_map_parse(file) # type: ignore
elif parser == "json":
return json_map_parse(file) # type: ignore
else:
raise UnknownFormat(
"Unknown Map Format, please use either the TMX or JSON format."
)

View File

@@ -1,18 +1,21 @@
import json
import xml.etree.ElementTree as etree
from pathlib import Path
from typing import List, Union, cast
from typing_extensions import TypedDict
from pytiled_parser.common_types import Size
from pytiled_parser.exception import UnknownFormat
from pytiled_parser.parsers.json.layer import RawLayer
from pytiled_parser.parsers.json.layer import parse as parse_layer
from pytiled_parser.parsers.json.properties import RawProperty
from pytiled_parser.parsers.json.properties import parse as parse_properties
from pytiled_parser.parsers.json.tileset import RawTileSet
from pytiled_parser.parsers.json.tileset import parse as parse_tileset
from pytiled_parser.parsers.json.tileset import parse as parse_json_tileset
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 parse_color
from pytiled_parser.util import check_format, parse_color
class RawTilesetMapping(TypedDict):
@@ -70,16 +73,30 @@ def parse(file: Path) -> TiledMap:
if raw_tileset.get("source") is not None:
# Is an external Tileset
tileset_path = Path(parent_dir / raw_tileset["source"])
parser = check_format(tileset_path)
with open(tileset_path) as raw_tileset_file:
tilesets[raw_tileset["firstgid"]] = parse_tileset(
json.load(raw_tileset_file),
raw_tileset["firstgid"],
external_path=tileset_path.parent,
)
if parser == "json":
tilesets[raw_tileset["firstgid"]] = parse_json_tileset(
json.load(raw_tileset_file),
raw_tileset["firstgid"],
external_path=tileset_path.parent,
)
elif parser == "tmx":
raw_tileset_external = etree.parse(raw_tileset_file).getroot()
tilesets[raw_tileset["firstgid"]] = parse_tmx_tileset(
raw_tileset_external,
raw_tileset["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
raw_tileset = cast(RawTileSet, raw_tileset)
tilesets[raw_tileset["firstgid"]] = parse_tileset(
tilesets[raw_tileset["firstgid"]] = parse_json_tileset(
raw_tileset, raw_tileset["firstgid"]
)
@@ -120,7 +137,7 @@ def parse(file: Path) -> TiledMap:
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_tileset(
map_.tilesets[new_firstgid] = parse_json_tileset(
tiled_object.new_tileset,
new_firstgid,
tiled_object.new_tileset_path,

View File

@@ -1,12 +1,15 @@
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_tileset
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 parse_color
from pytiled_parser.util import check_format, parse_color
def parse(file: Path) -> TiledMap:
@@ -18,7 +21,6 @@ def parse(file: Path) -> TiledMap:
Returns:
TiledMap: A parsed TiledMap.
"""
print(file)
with open(file) as map_file:
raw_map = etree.parse(map_file).getroot()
@@ -31,17 +33,29 @@ def parse(file: Path) -> TiledMap:
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:
raw_tileset_external = etree.parse(tileset_file).getroot()
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."
)
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tileset(
raw_tileset_external,
int(raw_tileset.attrib["firstgid"]),
external_path=tileset_path.parent,
)
else:
# Is an embedded Tileset
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tileset(
tilesets[int(raw_tileset.attrib["firstgid"])] = parse_tmx_tileset(
raw_tileset, int(raw_tileset.attrib["firstgid"])
)
@@ -83,7 +97,7 @@ def parse(file: Path) -> TiledMap:
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_tileset(
map_.tilesets[new_firstgid] = parse_tmx_tileset(
tiled_object.new_tileset,
new_firstgid,
tiled_object.new_tileset_path,

View File

@@ -1,4 +1,5 @@
"""Utility Functions for PyTiled"""
from pathlib import Path
from pytiled_parser.common_types import Color
@@ -27,3 +28,12 @@ def parse_color(color: str) -> Color:
)
raise ValueError("Improperly formatted color passed to parse_color")
def check_format(file_path: Path) -> str:
with open(file_path) as file:
line = file.readline().rstrip().strip()
if line[0] == "<":
return "tmx"
else:
return "json"