Changes to API

Should make integration with game engines easier in general.

Puts the burden of color parsing on Pytiled. As well as formatting layer data into a two dimensional list from a straight one dimensional.
This commit is contained in:
Darren Eberly
2021-02-21 00:58:30 -05:00
parent ed825c5b71
commit 674b4b50c4
24 changed files with 700 additions and 738 deletions

View File

@@ -12,8 +12,8 @@ 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 .layer import Layer
from .layer import ImageLayer, Layer, LayerGroup, ObjectLayer, TileLayer
from .properties import Properties
from .tiled_map import TiledMap
from .tileset import Tileset
from .tiled_map import TiledMap, parse_map
from .tileset import Tile, Tileset
from .version import __version__

View File

@@ -6,7 +6,21 @@ from typing import NamedTuple
import attr
Color = str
class Color(NamedTuple):
"""Color NamedTuple.
Attributes:
red: Red, between 1 and 255.
green: Green, between 1 and 255.
blue: Blue, between 1 and 255.
alpha: Alpha, between 1 and 255.
"""
red: int
green: int
blue: int
alpha: int
@attr.s(auto_attribs=True)

View File

@@ -21,6 +21,7 @@ from typing_extensions import TypedDict
from . import properties as properties_
from . import tiled_object
from .common_types import Color, OrderedPair, Size
from .util import parse_color
@attr.s(auto_attribs=True, kw_only=True)
@@ -71,7 +72,7 @@ class Chunk:
coordinates: OrderedPair
size: Size
data: List[int]
data: List[List[int]]
# The tile data for one layer.
@@ -95,7 +96,7 @@ class TileLayer(Layer):
"""
chunks: Optional[List[Chunk]] = None
data: Optional[List[int]] = None
data: Optional[List[List[int]]] = None
@attr.s(auto_attribs=True, kw_only=True)
@@ -155,7 +156,7 @@ class LayerGroup(Layer):
class RawChunk(TypedDict):
""" The keys and their types that appear in a Chunk JSON Object.
"""The keys and their types that appear in a Chunk JSON Object.
See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#chunk
"""
@@ -168,7 +169,7 @@ class RawChunk(TypedDict):
class RawLayer(TypedDict):
""" The keys and their types that appear in a Layer JSON Object.
"""The keys and their types that appear in a Layer JSON Object.
See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer
"""
@@ -198,7 +199,33 @@ class RawLayer(TypedDict):
y: int
def _decode_tile_layer_data(data: str, compression: str) -> List[int]:
def _convert_raw_tile_layer_data(data: List[int], layer_width: int) -> List[List[int]]:
"""Convert raw layer data into a nested lit based on the layer width
Args:
data: The data to convert
layer_width: Width of the layer
Returns:
List[List[int]]: A nested list containing the converted data
"""
tile_grid: List[List[int]] = [[]]
column_count = 0
row_count = 0
for item in data:
column_count += 1
tile_grid[row_count].append(item)
if not column_count % layer_width and column_count < len(data):
row_count += 1
tile_grid.append([])
return tile_grid
def _decode_tile_layer_data(
data: str, compression: str, layer_width: int
) -> List[List[int]]:
"""Decode Base64 Encoded tile data. Optionally supports gzip and zlib compression.
Args:
@@ -206,7 +233,7 @@ def _decode_tile_layer_data(data: str, compression: str) -> List[int]:
compression: Either zlib, gzip, or empty. If empty no decompression is done.
Returns:
TileLayer: The TileLayer with the decoded data
List[List[int]]: A nested list containing the decoded data
Raises:
ValueError: For an unsupported compression type.
@@ -219,7 +246,7 @@ def _decode_tile_layer_data(data: str, compression: str) -> List[int]:
else:
unzipped_data = unencoded_data
tile_grid = []
tile_grid: List[int] = []
byte_count = 0
int_count = 0
@@ -233,13 +260,13 @@ def _decode_tile_layer_data(data: str, compression: str) -> List[int]:
tile_grid.append(int_value)
int_value = 0
return tile_grid
return _convert_raw_tile_layer_data(tile_grid, layer_width)
def _cast_chunk(
raw_chunk: RawChunk, encoding: Optional[str] = None, compression: str = None
) -> Chunk:
""" Cast the raw_chunk to a Chunk.
"""Cast the raw_chunk to a Chunk.
Args:
raw_chunk: RawChunk to be casted to a Chunk
@@ -249,11 +276,16 @@ def _cast_chunk(
Returns:
Chunk: The Chunk created from the raw_chunk
"""
data = type_cast(List[int], raw_chunk["data"])
if encoding == "base64":
assert isinstance(compression, str)
data = _decode_tile_layer_data(type_cast(str, raw_chunk["data"]), compression)
assert isinstance(raw_chunk["data"], str)
data = _decode_tile_layer_data(
raw_chunk["data"], compression, raw_chunk["width"]
)
else:
data = _convert_raw_tile_layer_data(
raw_chunk["data"], raw_chunk["width"] # type: ignore
)
chunk = Chunk(
coordinates=OrderedPair(raw_chunk["x"], raw_chunk["y"]),
@@ -265,7 +297,7 @@ def _cast_chunk(
def _get_common_attributes(raw_layer: RawLayer) -> Layer:
""" Create a Layer containing all the attributes common to all layers.
"""Create a Layer containing all the attributes common to all layers.
This is to create the stub Layer object that can then be used to create the actual
specific sub-classes of Layer.
@@ -307,7 +339,7 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer:
def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer:
""" Cast the raw_layer to a TileLayer.
"""Cast the raw_layer to a TileLayer.
Args:
raw_layer: RawLayer to be casted to a TileLayer
@@ -332,15 +364,18 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer:
tile_layer.data = _decode_tile_layer_data(
data=type_cast(str, raw_layer["data"]),
compression=raw_layer["compression"],
layer_width=raw_layer["width"],
)
else:
tile_layer.data = type_cast(List[int], raw_layer["data"])
tile_layer.data = _convert_raw_tile_layer_data(
raw_layer["data"], raw_layer["width"] # type: ignore
)
return tile_layer
def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer:
""" Cast the raw_layer to an ObjectLayer.
"""Cast the raw_layer to an ObjectLayer.
Args:
raw_layer: RawLayer to be casted to an ObjectLayer
@@ -360,7 +395,7 @@ def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer:
def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer:
""" Cast the raw_layer to a ImageLayer.
"""Cast the raw_layer to a ImageLayer.
Args:
raw_layer: RawLayer to be casted to a ImageLayer
@@ -373,13 +408,13 @@ def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer:
)
if raw_layer.get("transparentcolor") is not None:
image_layer.transparent_color = Color(raw_layer["transparentcolor"])
image_layer.transparent_color = parse_color(raw_layer["transparentcolor"])
return image_layer
def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup:
""" Cast the raw_layer to a LayerGroup.
"""Cast the raw_layer to a LayerGroup.
Args:
raw_layer: RawLayer to be casted to a LayerGroup
@@ -397,7 +432,7 @@ def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup:
def _get_caster(type_: str) -> Callable[[RawLayer], Layer]:
""" Get the caster function for the raw layer.
"""Get the caster function for the raw layer.
Args:
type_: the type of the layer
@@ -415,7 +450,7 @@ def _get_caster(type_: str) -> Callable[[RawLayer], Layer]:
def cast(raw_layer: RawLayer) -> Layer:
""" Cast a raw Tiled layer into a pytiled_parser type.
"""Cast a raw Tiled layer into a pytiled_parser type.
This function will determine the type of layer and cast accordingly.

View File

@@ -6,10 +6,12 @@ properly typed Properties.
from pathlib import Path
from typing import Dict, List, Union
from typing import cast as type_cast
from typing_extensions import TypedDict
from .common_types import Color
from .util import parse_color
Property = Union[float, Path, str, bool, Color]
@@ -29,7 +31,7 @@ class RawProperty(TypedDict):
def cast(raw_properties: List[RawProperty]) -> Properties:
""" Cast a list of `RawProperty`s into `Properties`
"""Cast a list of `RawProperty`s into `Properties`
Args:
raw_properties: The list of `RawProperty`s to cast.
@@ -43,11 +45,11 @@ def cast(raw_properties: List[RawProperty]) -> Properties:
for property_ in raw_properties:
if property_["type"] == "file":
value = Path(str(property_["value"]))
value = Path(type_cast(str, property_["value"]))
elif property_["type"] == "color":
value = Color(str(property_["value"]))
value = parse_color(type_cast(str, property_["value"]))
else:
value = property_["value"]
final[str(property_["name"])] = value
final[property_["name"]] = value
return final

View File

@@ -13,6 +13,7 @@ from .common_types import Color, Size
from .layer import Layer, RawLayer
from .properties import Properties, RawProperty
from .tileset import RawTileSet, Tileset
from .util import parse_color
TilesetDict = Dict[int, Tileset]
@@ -61,6 +62,7 @@ class TiledMap:
tilesets: TilesetDict
version: float
map_file: Optional[Path] = None
background_color: Optional[Color] = None
properties: Optional[Properties] = None
hex_side_length: Optional[int] = None
@@ -76,11 +78,11 @@ class _RawTilesetMapping(TypedDict):
class _RawTiledMap(TypedDict):
""" The keys and their types that appear in a Tiled JSON Map.
"""The keys and their types that appear in a Tiled JSON Map.
Keys:
compressionlevel: not documented - https://github.com/bjorn/tiled/issues/2815
"""
"""
backgroundcolor: str
compressionlevel: int
@@ -104,8 +106,8 @@ class _RawTiledMap(TypedDict):
width: int
def cast(file: Path) -> TiledMap:
""" Cast the raw Tiled map into a pytiled_parser type
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
@@ -138,6 +140,7 @@ def cast(file: Path) -> TiledMap:
# `map` is a built-in function
map_ = TiledMap(
map_file=file,
infinite=raw_tiled_map["infinite"],
layers=[layer.cast(layer_) for layer_ in raw_tiled_map["layers"]],
map_size=Size(raw_tiled_map["width"], raw_tiled_map["height"]),
@@ -152,7 +155,7 @@ def cast(file: Path) -> TiledMap:
)
if raw_tiled_map.get("backgroundcolor") is not None:
map_.background_color = raw_tiled_map["backgroundcolor"]
map_.background_color = parse_color(raw_tiled_map["backgroundcolor"])
if raw_tiled_map.get("hexsidelength") is not None:
map_.hex_side_length = raw_tiled_map["hexsidelength"]

View File

@@ -7,6 +7,7 @@ from typing_extensions import TypedDict
from . import properties as properties_
from .common_types import Color, OrderedPair, Size
from .util import parse_color
@attr.s(auto_attribs=True, kw_only=True)
@@ -119,7 +120,7 @@ class Text(TiledObject):
"""
text: str
color: Color = "#000000"
color: Color = Color(255, 255, 255, 255)
font_family: str = "sans-serif"
font_size: float = 16
@@ -152,7 +153,7 @@ class RawTextDict(TypedDict):
""" The keys and their types that appear in a Text JSON Object."""
text: str
color: Color
color: str
fontfamily: str
pixelsize: float # this is `font_size` in Text
@@ -193,7 +194,7 @@ RawTiledObjects = List[RawTiledObject]
def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject:
""" Create a TiledObject containing all the attributes common to all tiled objects
"""Create a TiledObject containing all the attributes common to all tiled objects
Args:
raw_tiled_object: Raw Tiled object get common attributes from
@@ -219,7 +220,7 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject:
def _cast_ellipse(raw_tiled_object: RawTiledObject) -> Ellipse:
""" Cast the raw_tiled_object to an Ellipse object.
"""Cast the raw_tiled_object to an Ellipse object.
Args:
raw_tiled_object: Raw Tiled object to be casted to an Ellipse
@@ -231,7 +232,7 @@ def _cast_ellipse(raw_tiled_object: RawTiledObject) -> Ellipse:
def _cast_rectangle(raw_tiled_object: RawTiledObject) -> Rectangle:
""" Cast the raw_tiled_object to a Rectangle object.
"""Cast the raw_tiled_object to a Rectangle object.
Args:
raw_tiled_object: Raw Tiled object to be casted to a Rectangle
@@ -243,7 +244,7 @@ def _cast_rectangle(raw_tiled_object: RawTiledObject) -> Rectangle:
def _cast_point(raw_tiled_object: RawTiledObject) -> Point:
""" Cast the raw_tiled_object to a Point object.
"""Cast the raw_tiled_object to a Point object.
Args:
raw_tiled_object: Raw Tiled object to be casted to a Point
@@ -255,7 +256,7 @@ def _cast_point(raw_tiled_object: RawTiledObject) -> Point:
def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile:
""" Cast the raw_tiled_object to a Tile object.
"""Cast the raw_tiled_object to a Tile object.
Args:
raw_tiled_object: Raw Tiled object to be casted to a Tile
@@ -269,7 +270,7 @@ def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile:
def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon:
""" Cast the raw_tiled_object to a Polygon object.
"""Cast the raw_tiled_object to a Polygon object.
Args:
raw_tiled_object: Raw Tiled object to be casted to a Polygon
@@ -285,8 +286,8 @@ def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon:
def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline:
""" Cast the raw_tiled_object to a Polyline object.
"""Cast the raw_tiled_object to a Polyline object.
Args:
raw_tiled_object: Raw Tiled Object to be casted to a Polyline
@@ -303,7 +304,7 @@ def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline:
def _cast_text(raw_tiled_object: RawTiledObject) -> Text:
""" Cast the raw_tiled_object to a Text object.
"""Cast the raw_tiled_object to a Text object.
Args:
raw_tiled_object: Raw Tiled object to be casted to a Text object
@@ -320,7 +321,7 @@ def _cast_text(raw_tiled_object: RawTiledObject) -> Text:
# optional attributes
if raw_text_dict.get("color") is not None:
text_object.color = raw_text_dict["color"]
text_object.color = parse_color(raw_text_dict["color"])
if raw_text_dict.get("fontfamily") is not None:
text_object.font_family = raw_text_dict["fontfamily"]
@@ -358,7 +359,7 @@ def _cast_text(raw_tiled_object: RawTiledObject) -> Text:
def _get_caster(
raw_tiled_object: RawTiledObject,
) -> Callable[[RawTiledObject], TiledObject]:
""" Get the caster function for the raw tiled object.
"""Get the caster function for the raw tiled object.
Args:
raw_tiled_object: Raw Tiled object that is analysed to determine which caster
@@ -390,7 +391,7 @@ def _get_caster(
def cast(raw_tiled_object: RawTiledObject) -> TiledObject:
""" Cast the raw tiled object into a pytiled_parser type
"""Cast the raw tiled object into a pytiled_parser type
Args:
raw_tiled_object: Raw Tiled object that is to be cast.

View File

@@ -1,6 +1,6 @@
# pylint: disable=too-few-public-methods
from pathlib import Path
from typing import List, NamedTuple, Optional
from typing import Dict, List, NamedTuple, Optional
import attr
from typing_extensions import TypedDict
@@ -8,6 +8,7 @@ from typing_extensions import TypedDict
from . import layer
from . import properties as properties_
from .common_types import Color, OrderedPair
from .util import parse_color
class Grid(NamedTuple):
@@ -162,7 +163,7 @@ class Tileset:
grid: Optional[Grid] = None
properties: Optional[properties_.Properties] = None
terrain_types: Optional[List[Terrain]] = None
tiles: Optional[List[Tile]] = None
tiles: Optional[Dict[int, Tile]] = None
class RawFrame(TypedDict):
@@ -213,7 +214,7 @@ class RawGrid(TypedDict):
class RawTileSet(TypedDict):
""" The keys and their types that appear in a TileSet JSON Object."""
backgroundcolor: Color
backgroundcolor: str
columns: int
firstgid: int
grid: RawGrid
@@ -232,13 +233,13 @@ class RawTileSet(TypedDict):
tileoffset: RawTileOffset
tiles: List[RawTile]
tilewidth: int
transparentcolor: Color
transparentcolor: str
type: str
version: float
def _cast_frame(raw_frame: RawFrame) -> Frame:
""" Cast the raw_frame to a Frame.
"""Cast the raw_frame to a Frame.
Args:
raw_frame: RawFrame to be casted to a Frame
@@ -251,7 +252,7 @@ def _cast_frame(raw_frame: RawFrame) -> Frame:
def _cast_tile_offset(raw_tile_offset: RawTileOffset) -> OrderedPair:
""" Cast the raw_tile_offset to an OrderedPair.
"""Cast the raw_tile_offset to an OrderedPair.
Args:
raw_tile_offset: RawTileOffset to be casted to an OrderedPair
@@ -264,7 +265,7 @@ def _cast_tile_offset(raw_tile_offset: RawTileOffset) -> OrderedPair:
def _cast_terrain(raw_terrain: RawTerrain) -> Terrain:
""" Cast the raw_terrain to a Terrain object.
"""Cast the raw_terrain to a Terrain object.
Args:
raw_terrain: RawTerrain to be casted to a Terrain
@@ -280,11 +281,14 @@ def _cast_terrain(raw_terrain: RawTerrain) -> Terrain:
properties=properties_.cast(raw_terrain["properties"]),
)
else:
return Terrain(name=raw_terrain["name"], tile=raw_terrain["tile"],)
return Terrain(
name=raw_terrain["name"],
tile=raw_terrain["tile"],
)
def _cast_tile(raw_tile: RawTile) -> Tile:
""" Cast the raw_tile to a Tile object.
"""Cast the raw_tile to a Tile object.
Args:
raw_tile: RawTile to be casted to a Tile
@@ -333,7 +337,7 @@ def _cast_tile(raw_tile: RawTile) -> Tile:
def _cast_grid(raw_grid: RawGrid) -> Grid:
""" Cast the raw_grid to a Grid object.
"""Cast the raw_grid to a Grid object.
Args:
raw_grid: RawGrid to be casted to a Grid
@@ -350,7 +354,7 @@ def _cast_grid(raw_grid: RawGrid) -> Grid:
def cast(raw_tileset: RawTileSet) -> Tileset:
""" Cast the raw tileset into a pytiled_parser type
"""Cast the raw tileset into a pytiled_parser type
Args:
raw_tileset: Raw Tileset to be cast.
@@ -391,13 +395,13 @@ def cast(raw_tileset: RawTileSet) -> Tileset:
tileset.firstgid = raw_tileset["firstgid"]
if raw_tileset.get("backgroundcolor") is not None:
tileset.background_color = raw_tileset["backgroundcolor"]
tileset.background_color = parse_color(raw_tileset["backgroundcolor"])
if raw_tileset.get("tileoffset") is not None:
tileset.tile_offset = _cast_tile_offset(raw_tileset["tileoffset"])
if raw_tileset.get("transparentcolor") is not None:
tileset.transparent_color = raw_tileset["transparentcolor"]
tileset.transparent_color = parse_color(raw_tileset["transparentcolor"])
if raw_tileset.get("grid") is not None:
tileset.grid = _cast_grid(raw_tileset["grid"])
@@ -412,9 +416,9 @@ def cast(raw_tileset: RawTileSet) -> Tileset:
tileset.terrain_types = terrains
if raw_tileset.get("tiles") is not None:
tiles = []
tiles = {}
for raw_tile in raw_tileset["tiles"]:
tiles.append(_cast_tile(raw_tile))
tiles[raw_tile["id"]] = _cast_tile(raw_tile)
tileset.tiles = tiles
return tileset

29
pytiled_parser/util.py Normal file
View File

@@ -0,0 +1,29 @@
"""Utility Functions for PyTiled"""
from pytiled_parser.common_types import Color
def parse_color(color: str) -> Color:
"""Convert Tiled color format into PyTiled's.
Args:
color (str): Tiled formatted color string.
Returns:
:Color: Color object in the format that PyTiled understands.
"""
# the actual part we care about is always an even number
if len(color) % 2:
# strip initial '#' character
color = color[1:]
if len(color) == 6:
# full opacity if no alpha specified
return Color(int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), 255)
elif len(color) == 8:
return Color(
int(color[0:2], 16),
int(color[2:4], 16),
int(color[4:6], 16),
int(color[6:8], 16),
)
raise ValueError("Improperly formatted color passed to parse_color")

View File

@@ -10,56 +10,70 @@ EXPECTED = [
id=1,
size=common_types.Size(8, 6),
offset=common_types.OrderedPair(1, 3),
properties={"test": "test property",},
properties={
"test": "test property",
},
data=[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
[
1,
2,
3,
4,
5,
6,
7,
8,
],
[
9,
10,
11,
12,
13,
14,
15,
16,
],
[
17,
18,
19,
20,
21,
22,
23,
24,
],
[
25,
26,
27,
28,
29,
30,
31,
32,
],
[
33,
34,
35,
36,
37,
38,
39,
40,
],
[
41,
42,
43,
44,
45,
46,
47,
48,
],
],
),
layer.LayerGroup(
@@ -94,7 +108,7 @@ EXPECTED = [
visible=True,
id=3,
image=Path("../../images/tile_04.png"),
transparent_color=common_types.Color("#000000"),
transparent_color=common_types.Color(0, 0, 0, 255),
),
layer.ImageLayer(
name="Image Layer 2",

View File

@@ -10,54 +10,66 @@ EXPECTED = [
id=1,
size=common_types.Size(8, 6),
data=[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
[
1,
2,
3,
4,
5,
6,
7,
8,
],
[
9,
10,
11,
12,
13,
14,
15,
16,
],
[
17,
18,
19,
20,
21,
22,
23,
24,
],
[
25,
26,
27,
28,
29,
30,
31,
32,
],
[
33,
34,
35,
36,
37,
38,
39,
40,
],
[
41,
42,
43,
44,
45,
46,
47,
48,
],
],
),
layer.LayerGroup(
@@ -92,6 +104,6 @@ EXPECTED = [
visible=True,
id=3,
image=Path("../../images/tile_04.png"),
transparent_color=common_types.Color("#000000"),
transparent_color=common_types.Color(0, 0, 0, 255),
),
]

View File

@@ -10,54 +10,66 @@ EXPECTED = [
id=1,
size=common_types.Size(8, 6),
data=[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
[
1,
2,
3,
4,
5,
6,
7,
8,
],
[
9,
10,
11,
12,
13,
14,
15,
16,
],
[
17,
18,
19,
20,
21,
22,
23,
24,
],
[
25,
26,
27,
28,
29,
30,
31,
32,
],
[
33,
34,
35,
36,
37,
38,
39,
40,
],
[
41,
42,
43,
44,
45,
46,
47,
48,
],
],
),
layer.LayerGroup(
@@ -92,6 +104,6 @@ EXPECTED = [
visible=True,
id=3,
image=Path("../../images/tile_04.png"),
transparent_color=common_types.Color("#000000"),
transparent_color=common_types.Color(0, 0, 0, 255),
),
]

View File

@@ -10,54 +10,66 @@ EXPECTED = [
id=1,
size=common_types.Size(8, 6),
data=[
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
[
1,
2,
3,
4,
5,
6,
7,
8,
],
[
9,
10,
11,
12,
13,
14,
15,
16,
],
[
17,
18,
19,
20,
21,
22,
23,
24,
],
[
25,
26,
27,
28,
29,
30,
31,
32,
],
[
33,
34,
35,
36,
37,
38,
39,
40,
],
[
41,
42,
43,
44,
45,
46,
47,
48,
],
],
),
layer.LayerGroup(
@@ -92,6 +104,6 @@ EXPECTED = [
visible=True,
id=3,
image=Path("../../images/tile_04.png"),
transparent_color=common_types.Color("#000000"),
transparent_color=common_types.Color(0, 0, 0, 255),
),
]

View File

@@ -10,82 +10,116 @@ EXPECTED = [
id=1,
size=common_types.Size(16, 16),
offset=common_types.OrderedPair(163.089434111595, 116.462603878116),
properties={"test": "test property",},
properties={
"test": "test property",
},
chunks=[
layer.Chunk(
coordinates=common_types.OrderedPair(0, 0),
size=common_types.Size(4, 8),
data=[
1,
2,
3,
4,
9,
10,
11,
12,
17,
18,
19,
20,
25,
26,
27,
28,
33,
34,
35,
36,
41,
42,
43,
44,
0,
0,
0,
0,
0,
0,
0,
0,
[
1,
2,
3,
4,
],
[
9,
10,
11,
12,
],
[
17,
18,
19,
20,
],
[
25,
26,
27,
28,
],
[
33,
34,
35,
36,
],
[
41,
42,
43,
44,
],
[
0,
0,
0,
0,
],
[
0,
0,
0,
0,
],
],
),
layer.Chunk(
coordinates=common_types.OrderedPair(4, 0),
size=common_types.Size(4, 8),
data=[
5,
6,
7,
8,
13,
14,
15,
16,
21,
22,
23,
24,
29,
30,
31,
32,
37,
38,
39,
40,
45,
46,
47,
48,
0,
0,
0,
0,
0,
0,
0,
0,
[
5,
6,
7,
8,
],
[
13,
14,
15,
16,
],
[
21,
22,
23,
24,
],
[
29,
30,
31,
32,
],
[
37,
38,
39,
40,
],
[
45,
46,
47,
48,
],
[
0,
0,
0,
0,
],
[
0,
0,
0,
0,
],
],
),
],

View File

@@ -10,268 +10,30 @@ EXPECTED = [
id=1,
size=common_types.Size(16, 16),
offset=common_types.OrderedPair(1, 3),
properties={"test": "test property",},
properties={
"test": "test property",
},
chunks=[
layer.Chunk(
coordinates=common_types.OrderedPair(0, 0),
size=common_types.Size(16, 16),
data=[
1,
2,
3,
4,
5,
6,
7,
8,
0,
0,
0,
0,
0,
0,
0,
0,
9,
10,
11,
12,
13,
14,
15,
16,
0,
0,
0,
0,
0,
0,
0,
0,
17,
18,
19,
20,
21,
22,
23,
24,
0,
0,
0,
0,
0,
0,
0,
0,
25,
26,
27,
28,
29,
30,
31,
32,
0,
0,
0,
0,
0,
0,
0,
0,
33,
34,
35,
36,
37,
38,
39,
40,
0,
0,
0,
0,
0,
0,
0,
0,
41,
42,
43,
44,
45,
46,
47,
48,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
[1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0],
[9, 10, 11, 12, 13, 14, 15, 16, 0, 0, 0, 0, 0, 0, 0, 0],
[17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0],
[25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0],
[33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0],
[41, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
],
)
],

View File

@@ -15,106 +15,115 @@ EXPECTED = tiled_map.TiledMap(
size=common_types.Size(10, 10),
id=1,
data=[
3,
3,
3,
3,
9,
9,
9,
9,
17,
17,
3,
3,
3,
9,
9,
9,
9,
17,
17,
17,
3,
3,
3,
9,
9,
9,
9,
9,
17,
17,
3,
3,
1,
7,
9,
9,
9,
15,
17,
17,
1,
1,
12,
5,
7,
7,
7,
15,
15,
15,
12,
1,
5,
5,
7,
7,
7,
15,
15,
15,
2,
2,
5,
5,
5,
5,
4,
14,
14,
14,
2,
2,
5,
5,
5,
4,
14,
14,
14,
14,
2,
2,
2,
5,
5,
5,
4,
14,
14,
14,
2,
2,
2,
2,
5,
5,
4,
4,
14,
14,
[
3,
3,
3,
3,
9,
9,
9,
9,
17,
17,
],
[
3,
3,
3,
9,
9,
9,
9,
17,
17,
17,
],
[
3,
3,
3,
9,
9,
9,
9,
9,
17,
17,
],
[3, 3, 1, 7, 9, 9, 9, 15, 17, 17],
[
1,
1,
12,
5,
7,
7,
7,
15,
15,
15,
],
[
12,
1,
5,
5,
7,
7,
7,
15,
15,
15,
],
[
2,
2,
5,
5,
5,
5,
4,
14,
14,
14,
],
[
2,
2,
5,
5,
5,
4,
14,
14,
14,
14,
],
[
2,
2,
2,
5,
5,
5,
4,
14,
14,
14,
],
[
2,
2,
2,
2,
5,
5,
4,
4,
14,
14,
],
],
)
],

View File

@@ -13,7 +13,7 @@ EXPECTED = tiled_map.TiledMap(
tiled_version="1.4.1",
tile_size=common_types.Size(32, 32),
version=1.4,
background_color=common_types.Color("#ff0004"),
background_color=common_types.Color(255, 0, 4, 255),
tilesets={
1: tileset.Tileset(
columns=8,
@@ -33,7 +33,7 @@ EXPECTED = tiled_map.TiledMap(
},
properties={
"bool property - true": True,
"color property": common_types.Color("#ff49fcff"),
"color property": common_types.Color(255, 73, 252, 255),
"file property": Path("../../../../../../var/log/syslog"),
"float property": 1.23456789,
"int property": 13,

View File

@@ -0,0 +1,18 @@
import pytest
from pytiled_parser.util import parse_color
def test_parse_color_wrong_format():
with pytest.raises(ValueError):
color = parse_color("#ff0000ff0")
def test_parse_color_no_hash():
color = parse_color("ff0000")
assert color == (255, 0, 0, 255)
def test_parse_color_no_alpha():
color = parse_color("#ff0000")
assert color == (255, 0, 0, 255)

View File

@@ -16,6 +16,6 @@ EXPECTED = tileset.Tileset(
tile_height=32,
tile_width=32,
version=1.2,
background_color=Color("#5500ff"),
background_color=Color(85, 0, 255, 255),
type="tileset",
)

View File

@@ -18,7 +18,7 @@ EXPECTED = tileset.Tileset(
version=1.2,
properties={
"bool property": True,
"color property": Color("#ff0000ff"),
"color property": Color(255, 0, 0, 255),
"float property": 5.6,
"int property": 5,
"string property": "testing",

View File

@@ -16,6 +16,6 @@ EXPECTED = tileset.Tileset(
tile_height=32,
tile_width=32,
version=1.2,
transparent_color=Color("#ff00ff"),
transparent_color=Color(255, 0, 255, 255),
type="tileset",
)

View File

@@ -14,8 +14,8 @@ EXPECTED = tileset.Tileset(
version=1.2,
type="tileset",
grid=tileset.Grid(orientation="orthogonal", width=1, height=1),
tiles=[
tileset.Tile(
tiles={
0: tileset.Tile(
animation=[
tileset.Frame(duration=100, tile_id=0),
tileset.Frame(duration=100, tile_id=1),
@@ -29,7 +29,7 @@ EXPECTED = tileset.Tileset(
properties={"float property": 2.2},
type="tile",
),
tileset.Tile(
1: tileset.Tile(
id=1,
image=Path("../../images/tile_02.png"),
image_height=32,
@@ -67,7 +67,7 @@ EXPECTED = tileset.Tileset(
properties={"string property": "testing"},
type="tile",
),
tileset.Tile(
2: tileset.Tile(
id=2,
image=Path("../../images/tile_03.png"),
image_height=32,
@@ -75,12 +75,12 @@ EXPECTED = tileset.Tileset(
properties={"bool property": True},
type="tile",
),
tileset.Tile(
3: tileset.Tile(
id=3,
image=Path("../../images/tile_04.png"),
image_height=32,
image_width=32,
type="tile",
),
],
},
)

View File

@@ -26,246 +26,246 @@ EXPECTED = tileset.Tileset(
tileset.Terrain(name="Pavement", tile=29),
tileset.Terrain(name="Dirt", tile=29),
],
tiles=[
tileset.Tile(
tiles={
0: tileset.Tile(
id=0,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=0, bottom_right=1
),
),
tileset.Tile(
1: tileset.Tile(
id=1,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=1, bottom_right=1
),
),
tileset.Tile(
2: tileset.Tile(
id=2,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=1, bottom_right=0
),
),
tileset.Tile(
3: tileset.Tile(
id=3,
terrain=tileset.TileTerrain(
top_left=3, top_right=3, bottom_left=3, bottom_right=0
),
),
tileset.Tile(
4: tileset.Tile(
id=4,
terrain=tileset.TileTerrain(
top_left=3, top_right=3, bottom_left=0, bottom_right=3
),
),
tileset.Tile(
5: tileset.Tile(
id=5,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=0, bottom_right=3
),
),
tileset.Tile(
6: tileset.Tile(
id=6,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=3, bottom_right=3
),
),
tileset.Tile(
7: tileset.Tile(
id=7,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=3, bottom_right=0
),
),
tileset.Tile(
8: tileset.Tile(
id=8,
terrain=tileset.TileTerrain(
top_left=0, top_right=1, bottom_left=0, bottom_right=1
),
),
tileset.Tile(
9: tileset.Tile(
id=9,
terrain=tileset.TileTerrain(
top_left=1, top_right=1, bottom_left=1, bottom_right=1
),
),
tileset.Tile(
10: tileset.Tile(
id=10,
terrain=tileset.TileTerrain(
top_left=1, top_right=0, bottom_left=1, bottom_right=0
),
),
tileset.Tile(
11: tileset.Tile(
id=11,
terrain=tileset.TileTerrain(
top_left=3, top_right=0, bottom_left=3, bottom_right=3
),
),
tileset.Tile(
12: tileset.Tile(
id=12,
terrain=tileset.TileTerrain(
top_left=0, top_right=3, bottom_left=3, bottom_right=3
),
),
tileset.Tile(
13: tileset.Tile(
id=13,
terrain=tileset.TileTerrain(
top_left=0, top_right=3, bottom_left=0, bottom_right=3
),
),
tileset.Tile(
14: tileset.Tile(
id=14,
terrain=tileset.TileTerrain(
top_left=3, top_right=3, bottom_left=3, bottom_right=3
),
),
tileset.Tile(
15: tileset.Tile(
id=15,
terrain=tileset.TileTerrain(
top_left=3, top_right=0, bottom_left=3, bottom_right=0
),
),
tileset.Tile(
16: tileset.Tile(
id=16,
terrain=tileset.TileTerrain(
top_left=0, top_right=1, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
17: tileset.Tile(
id=17,
terrain=tileset.TileTerrain(
top_left=1, top_right=1, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
18: tileset.Tile(
id=18,
terrain=tileset.TileTerrain(
top_left=1, top_right=0, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
19: tileset.Tile(
id=19,
terrain=tileset.TileTerrain(
top_left=1, top_right=1, bottom_left=1, bottom_right=0
),
),
tileset.Tile(
20: tileset.Tile(
id=20,
terrain=tileset.TileTerrain(
top_left=1, top_right=1, bottom_left=0, bottom_right=1
),
),
tileset.Tile(
21: tileset.Tile(
id=21,
terrain=tileset.TileTerrain(
top_left=0, top_right=3, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
22: tileset.Tile(
id=22,
terrain=tileset.TileTerrain(
top_left=3, top_right=3, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
23: tileset.Tile(
id=23,
terrain=tileset.TileTerrain(
top_left=3, top_right=0, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
24: tileset.Tile(
id=24,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=0, bottom_right=2
),
),
tileset.Tile(
25: tileset.Tile(
id=25,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=2, bottom_right=2
),
),
tileset.Tile(
26: tileset.Tile(
id=26,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=2, bottom_right=0
),
),
tileset.Tile(
27: tileset.Tile(
id=27,
terrain=tileset.TileTerrain(
top_left=1, top_right=0, bottom_left=1, bottom_right=1
),
),
tileset.Tile(
28: tileset.Tile(
id=28,
terrain=tileset.TileTerrain(
top_left=0, top_right=1, bottom_left=1, bottom_right=1
),
),
tileset.Tile(
29: tileset.Tile(
id=29,
terrain=tileset.TileTerrain(
top_left=0, top_right=0, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
32: tileset.Tile(
id=32,
terrain=tileset.TileTerrain(
top_left=0, top_right=2, bottom_left=0, bottom_right=2
),
),
tileset.Tile(
33: tileset.Tile(
id=33,
terrain=tileset.TileTerrain(
top_left=2, top_right=2, bottom_left=2, bottom_right=2
),
),
tileset.Tile(
34: tileset.Tile(
id=34,
terrain=tileset.TileTerrain(
top_left=2, top_right=0, bottom_left=2, bottom_right=0
),
),
tileset.Tile(
35: tileset.Tile(
id=35,
terrain=tileset.TileTerrain(
top_left=2, top_right=2, bottom_left=2, bottom_right=0
),
),
tileset.Tile(
36: tileset.Tile(
id=36,
terrain=tileset.TileTerrain(
top_left=2, top_right=2, bottom_left=0, bottom_right=2
),
),
tileset.Tile(
40: tileset.Tile(
id=40,
terrain=tileset.TileTerrain(
top_left=0, top_right=2, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
41: tileset.Tile(
id=41,
terrain=tileset.TileTerrain(
top_left=2, top_right=2, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
42: tileset.Tile(
id=42,
terrain=tileset.TileTerrain(
top_left=2, top_right=0, bottom_left=0, bottom_right=0
),
),
tileset.Tile(
43: tileset.Tile(
id=43,
terrain=tileset.TileTerrain(
top_left=2, top_right=0, bottom_left=2, bottom_right=2
),
),
tileset.Tile(
44: tileset.Tile(
id=44,
terrain=tileset.TileTerrain(
top_left=0, top_right=2, bottom_left=2, bottom_right=2
),
),
],
},
)

View File

@@ -29,6 +29,7 @@ def test_map_integration(map_test):
raw_maps_path = map_test / "map.json"
casted_map = tiled_map.cast(raw_maps_path)
casted_map = tiled_map.parse_map(raw_maps_path)
expected.EXPECTED.map_file = casted_map.map_file
assert casted_map == expected.EXPECTED

View File

@@ -261,7 +261,7 @@ RECTANGLES = [
coordinates=common_types.OrderedPair(39.0678640445606, 131.826759122428),
properties={
"bool property": False,
"color property": common_types.Color("#ffaa0000"),
"color property": common_types.Color(255, 170, 0, 0),
"file property": Path("../../../../../../dev/null"),
"float property": 42.1,
"int property": 8675309,
@@ -1044,7 +1044,7 @@ TEXTS = [
rotation=0,
text="Hello World",
wrap=True,
color="#aa0000",
color=common_types.Color(170, 0, 0, 255),
type="text",
visible=True,
size=common_types.Size(92.375, 19),