From 14c381ab567e85eb48afd36b553271841903aea2 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 19:14:51 -0400 Subject: [PATCH 001/198] re-doing everything as a caster instead of as a parser --- mypy.ini | 21 - pytiled_parser/__init__.py | 8 + pytiled_parser/common_types.py | 38 ++ pytiled_parser/layer.py | 85 +++ pytiled_parser/map.py | 75 +++ pytiled_parser/properties.py | 12 + pytiled_parser/template.py | 8 + pytiled_parser/tiled_object.py | 231 ++++++++ pytiled_parser/tileset.py | 175 +++++++ setup.cfg | 4 +- tests/test_data/simple_objects.json | 552 ++++++++++++++++++++ tests/test_data/test_map_simple_offset.json | 80 +++ tests/test_tiled_object.py | 82 +++ 13 files changed, 1348 insertions(+), 23 deletions(-) delete mode 100644 mypy.ini create mode 100644 pytiled_parser/common_types.py create mode 100644 pytiled_parser/layer.py create mode 100644 pytiled_parser/map.py create mode 100644 pytiled_parser/properties.py create mode 100644 pytiled_parser/template.py create mode 100644 pytiled_parser/tiled_object.py create mode 100644 pytiled_parser/tileset.py create mode 100644 tests/test_data/simple_objects.json create mode 100644 tests/test_data/test_map_simple_offset.json create mode 100644 tests/test_tiled_object.py diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index af3f209..0000000 --- a/mypy.ini +++ /dev/null @@ -1,21 +0,0 @@ -# Global options: - -[mypy] -python_version = 3.6 -warn_unused_configs = False -disallow_any_unimported = True -disallow_any_expr = True -disallow_any_decorated = True -disallow_any_explicit = True -disallow_any_generics = True -disallow_subclassing_any = True -disallow_untyped_calls = True -disallow_untyped_defs = True -disallow_incomplete_defs = True -check_untyped_defs = True -disallow_untyped_decorators = True -warn_return_any = True - -# Per-module options: -[mypy-tests.*] -ignore_errors = True diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 7fd3538..3ed056d 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -1 +1,9 @@ """Parse Tiled Maps and Tilesets""" + +# pylint: disable=too-few-public-methods + +from .common_types import OrderedPair, Size +from .layer import Layer +from .map import Map +from .properties import Properties +from .tileset import TileSet diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py new file mode 100644 index 0000000..95c7196 --- /dev/null +++ b/pytiled_parser/common_types.py @@ -0,0 +1,38 @@ +"""Module containing types that are common to multiple other modules.""" + +# pylint: disable=too-few-public-methods + +from typing import NamedTuple, Union + +import attr + +Color = str + + +@attr.s(auto_attribs=True) +class Template: + """FIXME TODO""" + + +class Size(NamedTuple): + """Size NamedTuple. + + Attributes: + width: The width of the object. + size: The height of the object. + """ + + width: Union[int, float] + height: Union[int, float] + + +class OrderedPair(NamedTuple): + """OrderedPair NamedTuple. + + Attributes: + x: X coordinate. + y: Y coordinate. + """ + + x: Union[int, float] + y: Union[int, float] diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py new file mode 100644 index 0000000..76c3632 --- /dev/null +++ b/pytiled_parser/layer.py @@ -0,0 +1,85 @@ +# pylint: disable=too-few-public-methods + +from typing import List, Optional, Union + +import attr + +from .common_types import OrderedPair, Size +from .properties import Properties + + +@attr.s(auto_attribs=True, kw_only=True) +class Layer: + # FIXME:this docstring appears to be innacurate + """Class that all layers inherit from. + + Args: + id: Unique ID of the layer. Each layer that added to a map gets a unique id. + Even if a layer is deleted, no layer ever gets the same ID. + name: The name of the layer object. + tiled_objects: List of tiled_objects in the layer. + offset: Rendering offset of the layer object in pixels. + opacity: Decimal value between 0 and 1 to determine opacity. 1 is completely + opaque, 0 is completely transparent. + properties: Properties for the layer. + color: The color used to display the objects in this group. + draworder: Whether the objects are drawn according to the order of the object + elements in the object group element ('manual'), or sorted by their + y-coordinate ('topdown'). Defaults to 'topdown'. + See: + https://doc.mapeditor.org/en/stable/manual/objects/#changing-stacking-order + for more info. + """ + + id_: int + name: str + + offset: Optional[OrderedPair] + opacity: Optional[float] + properties: Optional[Properties] + + +TileLayerGrid = List[List[int]] + + +@attr.s(auto_attribs=True) +class Chunk: + """Chunk object for infinite maps. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#chunk + + Attributes: + location: Location of chunk in tiles. + width: The width of the chunk in tiles. + height: The height of the chunk in tiles. + layer_data: The global tile IDs in chunky according to row. + """ + + location: OrderedPair + width: int + height: int + chunk_data: TileLayerGrid + + +LayerData = Union[TileLayerGrid, List[Chunk]] +# The tile data for one layer. +# +# Either a 2 dimensional array of integers representing the global tile IDs +# for a TileLayerGrid, or a list of chunks for an infinite map layer. + + +@attr.s(auto_attribs=True, kw_only=True) +class TileLayer(Layer): + """Tile map layer containing tiles. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#layer + + Args: + size: The width of the layer in tiles. The same as the map width unless map is + infitite. + data: Either an 2 dimensional array of integers representing the global tile + IDs for the map layer, or a list of chunks for an infinite map. + """ + + size: Size + layer_data: LayerData diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py new file mode 100644 index 0000000..eaf0b99 --- /dev/null +++ b/pytiled_parser/map.py @@ -0,0 +1,75 @@ +# pylint: disable=too-few-public-methods + +from pathlib import Path +from typing import Dict, List, NamedTuple, Optional, Union + +import attr + +from .common_types import Color, Size +from .layer import Layer +from .properties import Properties +from .tileset import TileSet + +TileSetDict = Dict[int, TileSet] + + +@attr.s(auto_attribs=True) +class Map: + """Object for storing a TMX with all associated layers and properties. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#map + + Attributes: + parent_dir: The directory the TMX file is in. Used for finding relative paths + to TSX files and other assets. + version: The TMX format version. + tiled_version: The Tiled version used to save the file. May be a date (for + snapshot builds). + orientation: Map orientation. Tiled supports "orthogonal", "isometric", + "staggered" and "hexagonal" + render_order: The order in which tiles on tile layers are rendered. Valid values + are right-down, right-up, left-down and left-up. In all cases, the map is + drawn row-by-row. (only supported for orthogonal maps at the moment) + map_size: The map width in tiles. + tile_size: The width of a tile. + infinite: If the map is infinite or not. + hex_side_length: Only for hexagonal maps. Determines the width or height + (depending on the staggered axis) of the tile's edge, in pixels. + stagger_axis: For staggered and hexagonal maps, determines which axis ("x" or + "y") is staggered. + stagger_index: For staggered and hexagonal maps, determines whether the "even" + or "odd" indexes along the staggered axis are shifted. + background_color: The background color of the map. + next_layer_id: Stores the next available ID for new layers. + next_object_id: Stores the next available ID for new objects. + tile_sets: Dict of tile sets used in this map. Key is the first GID for the + tile set. The value is a TileSet object. + layers: List of layer objects by draw order. + """ + + parent_dir: Path + tmx_file: Union[str, Path] + + version: str + tiled_version: str + orientation: str + render_order: str + map_size: Size + tile_size: Size + infinite: bool + next_layer_id: Optional[int] + next_object_id: int + + tile_sets: TileSetDict + layers: List[Layer] + + hex_side_length: Optional[int] = None + stagger_axis: Optional[int] = None + stagger_index: Optional[int] = None + background_color: Optional[Color] = None + + properties: Optional[Properties] = None + + +def parse() -> Map: + pass diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py new file mode 100644 index 0000000..54728fd --- /dev/null +++ b/pytiled_parser/properties.py @@ -0,0 +1,12 @@ +from pathlib import Path +from typing import Dict, List, NamedTuple, Optional, Union + +from .common_types import Color + +RawProperties = List[Dict[str, Union[str, bool, int, float]]] + + +Property = Union[int, float, Path, str, bool, Color] + + +Properties = Dict[str, Property] diff --git a/pytiled_parser/template.py b/pytiled_parser/template.py new file mode 100644 index 0000000..c6d58d8 --- /dev/null +++ b/pytiled_parser/template.py @@ -0,0 +1,8 @@ +# pylint: disable=too-few-public-methods + +import attr + + +@attr.s(auto_attribs=True) +class Template: + """FIXME TODO""" diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py new file mode 100644 index 0000000..9bb0449 --- /dev/null +++ b/pytiled_parser/tiled_object.py @@ -0,0 +1,231 @@ +# pylint: disable=too-few-public-methods + +from typing import Callable, Dict, List, Optional, Union + +import attr + +from pytiled_parser import OrderedPair, Size +from pytiled_parser.properties import Properties +from pytiled_parser.template import Template + + +@attr.s(auto_attribs=True, kw_only=True) +class TiledObject: + """TiledObject object. + + See: + https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#object + + Attributes: + id_: Unique ID of the tiled object. Each tiled object that is placed on a map + gets a unique id. Even if an tiled object was deleted, no tiled object gets + the same ID. + gid: Global tiled object ID. + coordinates: The location of the tiled object in pixels. + size: The width of the tiled object in pixels (default: (0, 0)). + rotation: The rotation of the tiled object in degrees clockwise (default: 0). + opacity: The opacity of the tiled object. (default: 1) + name: The name of the tiled object. + type: The type of the tiled object. + properties: The properties of the TiledObject. + template: A reference to a Template tiled object FIXME + """ + + id_: int + gid: Optional[int] = None + + coordinates: OrderedPair + size: Size = Size(0, 0) + rotation: float = 0 + opacity: float = 1 + + name: Optional[str] = None + type: Optional[str] = None + + properties: Optional[Properties] = None + template: Optional[Template] = None + + +@attr.s() +class Ellipse(TiledObject): + """Elipse shape defined by a point, width, height, and rotation. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#ellipse + """ + + +@attr.s() +class Point(TiledObject): + """Point defined by a coordinate (x,y). + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#point + """ + + +@attr.s(auto_attribs=True, kw_only=True) +class Polygon(TiledObject): + """Polygon shape defined by a set of connections between points. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#polygon + + Attributes: + points: FIXME + """ + + points: List[OrderedPair] + + +@attr.s(auto_attribs=True, kw_only=True) +class Polyline(TiledObject): + """Polyline defined by a set of connections between points. + + See: + https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#polyline + + Attributes: + points: List of coordinates relative to the location of the object. + """ + + points: List[OrderedPair] + + +@attr.s() +class Rectangle(TiledObject): + """Rectangle shape defined by a point, width, and height. + + See: https://doc.mapeditor.org/en/stable/manual/objects/#insert-rectangle + (objects in tiled are rectangles by default, so there is no specific + documentation on the tmx-map-format page for it.) + """ + + +@attr.s(auto_attribs=True, kw_only=True) +class Text(TiledObject): + """Text object with associated settings. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#text + and https://doc.mapeditor.org/en/stable/manual/objects/#insert-text + + Attributes: + font_family: The font family used (default: "sans-serif") + font_size: The size of the font in pixels. (default: 16) + wrap: Whether word wrapping is enabled. (default: False) + color: Color of the text. (default: #000000) + bold: Whether the font is bold. (default: False) + italic: Whether the font is italic. (default: False) + underline: Whether the text is underlined. (default: False) + strike_out: Whether the text is striked-out. (default: False) + kerning: Whether kerning should be used while rendering the text. (default: + False) + horizontal_align: Horizontal alignment of the text (default: "left") + vertical_align: Vertical alignment of the text (defalt: "top") + """ + + text: str + font_family: str = "sans-serif" + font_size: int = 16 + wrap: bool = False + color: str = "#000000" + bold: bool = False + italic: bool = False + underline: bool = False + strike_out: bool = False + kerning: bool = False + horizontal_align: str = "left" + vertical_align: str = "top" + + +@attr.s(auto_attribs=True, kw_only=True) +class TileImage(TiledObject): + """Tile object + + See: https://doc.mapeditor.org/en/stable/manual/objects/#insert-tile + + Attributes: + gid: Reference to a global tile id. + """ + + gid: int + + +RawProperties = Dict[str, Union[str, int, float, bool]] + + +RawTiledObject = Dict[str, Union[str, int, float, bool, RawProperties]] + + +RawTiledObjects = List[RawTiledObject] + + +def _cast_ellipse(raw_tiled_object: RawTiledObject) -> Ellipse: + pass + + +def _cast_rectangle(raw_tiled_object: RawTiledObject) -> Rectangle: + pass + + +def _cast_point(raw_tiled_object: RawTiledObject) -> Point: + pass + + +def _cast_tile_image(raw_tiled_object: RawTiledObject) -> TileImage: + pass + + +def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: + pass + + +def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: + pass + + +def _cast_text(raw_tiled_object: RawTiledObject) -> Text: + pass + + +def _get_tiled_object_caster( + raw_tiled_object: RawTiledObject, +) -> Callable[[RawTiledObject], TiledObject]: + """ Get the caster function for the raw tiled object. + + Args: + raw_tiled_object: Raw Tiled object that is analysed to determine which caster + to return. + + Returns: + Callable[[RawTiledObject], TiledObject]: The caster function. + """ + + +def _cast_tiled_object(raw_tiled_object: RawTiledObject) -> TiledObject: + """ Cast the raw tiled object into a pytiled_parser type + + Args: + raw_tiled_object: Raw Tiled object that is to be cast. + + Returns: + TiledObject: a properly typed Tiled object. + """ + caster = _get_tiled_object_caster(raw_tiled_object) + + tiled_object = caster(raw_tiled_object) + return tiled_object + + +def cast_tiled_objects(raw_tiled_objects: RawTiledObjects) -> List[TiledObject]: + """Parses objects found in a 'objectgroup' element. + + Args: + object_elements: List of object elements to be parsed. + + Returns: + list: List of parsed tiled objects. + """ + tiled_objects: List[TiledObject] = [] + + for raw_tiled_object in raw_tiled_objects: + tiled_objects.append(_cast_tiled_object(raw_tiled_object)) + + return tiled_objects diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py new file mode 100644 index 0000000..15d4523 --- /dev/null +++ b/pytiled_parser/tileset.py @@ -0,0 +1,175 @@ +# pylint: disable=too-few-public-methods +from pathlib import Path +from typing import Dict, List, NamedTuple, Optional + +import attr + +from pytiled_parser import OrderedPair, Size +from pytiled_parser.properties import Properties, Property +from pytiled_parser.tiled_object import TiledObject + + +class Grid(NamedTuple): + """Contains info for isometric maps. + + This element is only used in case of isometric orientation, and determines how tile + overlays for terrain and collision information are rendered. + + Args: + orientation: Orientation of the grid for the tiles in this tileset (orthogonal + or isometric). + width: Width of a grid cell. + height: Height of a grid cell. + """ + + orientation: str + width: int + height: int + + +@attr.s(auto_attribs=True) +class Image: + """Image object. + + pytiled_parser does not support embedded data in image elements at this time, + even though the TMX format technically does. + + Attributes: + source: The reference to the tileset image file. Note that this is a relative + path compared to FIXME + trans: Defines a specific color that is treated as transparent. + width: The image width in pixels (optional, used for tile index correction when + the image changes). + height: The image height in pixels (optional). + """ + + source: str + size: Optional[Size] = None + trans: Optional[str] = None + width: Optional[int] = None + height: Optional[int] = None + + +class Terrain(NamedTuple): + """Terrain object. + + Args: + name: The name of the terrain type. + tile: The local tile-id of the tile that represents the terrain visually. + """ + + name: str + tile: int + + +@attr.s(auto_attribs=True) +class TileTerrain: + """Defines each corner of a tile by Terrain index in + 'TileSet.terrain_types'. + + Defaults to 'None'. 'None' means that corner has no terrain. + + Attributes: + top_left: Top left terrain type. + top_right: Top right terrain type. + bottom_left: Bottom left terrain type. + bottom_right: Bottom right terrain type. + """ + + top_left: Optional[int] = None + top_right: Optional[int] = None + bottom_left: Optional[int] = None + bottom_right: Optional[int] = None + + +class Frame(NamedTuple): + """Animation Frame object. + + This is only used as a part of an animation for Tile objects. + + Args: + tile_id: The local ID of a tile within the parent tile set object. + duration: How long in milliseconds this frame should be displayed before + advancing to the next frame. + """ + + tile_id: int + duration: int + + +@attr.s(auto_attribs=True, kw_only=True) +class Tile: + # FIXME: args + """Individual tile object. + + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tile + + Args: + id: The local tile ID within its tileset. + type: The type of the tile. Refers to an object type and is used by tile + objects. + terrain: Defines the terrain type of each corner of the tile. + animation: Each tile can have exactly one animation associated with it. + """ + + id_: int + type_: Optional[str] = None + terrain: Optional[TileTerrain] = None + animation: Optional[List[Frame]] = None + objectgroup: Optional[List[TiledObject]] = None + image: Optional[Image] = None + properties: Optional[List[Property]] = None + tileset: Optional["TileSet"] = None + flipped_horizontally: bool = False + flipped_diagonally: bool = False + flipped_vertically: bool = False + + +@attr.s(auto_attribs=True) +class TileSet: + """Object for storing a TSX with all associated collision data. + + Args: + name: The name of this tileset. + max_tile_size: The maximum size of a tile in this tile set in pixels. + spacing: The spacing in pixels between the tiles in this tileset (applies to + the tileset image). + margin: The margin around the tiles in this tileset (applies to the tileset + image). + tile_count: The number of tiles in this tileset. + columns: The number of tile columns in the tileset. For image collection + tilesets it is editable and is used when displaying the tileset. + grid: Only used in case of isometric orientation, and determines how tile + overlays for terrain and collision information are rendered. + tileoffset: Used to specify an offset in pixels when drawing a tile from the + tileset. When not present, no offset is applied. + image: Used for spritesheet tile sets. + terrain_types: List of of terrain types which can be referenced from the + terrain attribute of the tile object. Ordered according to the terrain + element's appearance in the TSX file. + tiles: Dict of Tile objects by Tile.id. + tsx_file: Path of the file containing the tileset, None if loaded internally + from a map + parent_dir: Path of the parent directory of the file containing the tileset, + None if loaded internally from a map + """ + + name: str + max_tile_size: Size + + spacing: Optional[int] = None + margin: Optional[int] = None + tile_count: Optional[int] = None + columns: Optional[int] = None + tile_offset: Optional[OrderedPair] = None + grid: Optional[Grid] = None + properties: Optional[Properties] = None + image: Optional[Image] = None + terrain_types: Optional[List[Terrain]] = None + tiles: Optional[Dict[int, Tile]] = None + tsx_file: Path = None + parent_dir: Path = None + + +def parse(): + pass diff --git a/setup.cfg b/setup.cfg index d115d33..dbf7dfa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,10 +59,10 @@ warn_redundant_casts = True # Per-module options: [mypy-pytiled_parser.*] -disallow_any_unimported = False +disallow_any_unimported = True disallow_any_decorated = True disallow_any_generics = True -disallow_subclassing_any = False +disallow_subclassing_any = True disallow_untyped_calls = True disallow_untyped_defs = True disallow_incomplete_defs = True diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json new file mode 100644 index 0000000..9e01620 --- /dev/null +++ b/tests/test_data/simple_objects.json @@ -0,0 +1,552 @@ +{ "compressionlevel":0, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":41.4686825053996, + "id":1, + "name":"name: rectangle", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":45.3972945322269, + "x":27.7185404115039, + "y":23.571672160964 + }, + { + "height":0, + "id":2, + "name":"name: point", + "point":true, + "rotation":0, + "type":"point", + "visible":true, + "width":0, + "x":159.981811981357, + "y":82.9373650107991 + }, + { + "height":0, + "id":3, + "name":"name: point invisible", + "point":true, + "rotation":0, + "type":"point", + "visible":false, + "width":0, + "x":109.346368080027, + "y":95.8144822098443 + }, + { + "height":32.7384335568944, + "id":4, + "name":"name: rectangle - invisible", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":30.9923837671934, + "x":163.910424008185, + "y":91.0128452881664 + }, + { + "height":22, + "id":5, + "name":"name: rectangle - rotated", + "rotation":10, + "type":"rectangle", + "visible":true, + "width":10, + "x":183.335227918609, + "y":23.3534159372513 + }, + { + "ellipse":true, + "height":18.5517790155735, + "id":6, + "name":"name: ellipse", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":57.4013868364215, + "x":37.5400704785722, + "y":81.1913152210981 + }, + { + "ellipse":true, + "height":31.4288962146186, + "id":7, + "name":"name: ellipse - invisible", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":6.32943048766625, + "x":22.6986472661134, + "y":53.9092872570194 + }, + { + "ellipse":true, + "height":24.2264408321018, + "id":8, + "name":"name: ellipse - rotated", + "rotation":111, + "type":"ellipse", + "visible":true, + "width":29.6828464249176, + "x":35.7940206888712, + "y":120.040923041946 + }, + { + "height":0, + "id":9, + "name":"name: polyline", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":19.424803910424, + "y":27.063771740366 + }, + { + "x":19.6430601341366, + "y":3.05558713197681 + }, + { + "x":-2.61907468455156, + "y":15.9327043310219 + }, + { + "x":25.317721950665, + "y":16.3692167784472 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":89.485051722178, + "y":38.6313515971354 + }, + { + "height":0, + "id":10, + "name":"name: polyline - invisible", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":7.63896782994203 + }, + { + "x":-14.8414232124588, + "y":-10.2580425144936 + }], + "rotation":0, + "type":"polyline", + "visible":false, + "width":0, + "x":133.791065135842, + "y":24.4446970558145 + }, + { + "height":0, + "id":11, + "name":"name: polyline - rotated", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":0 + }, + { + "x":-6.98419915880413, + "y":7.63896782994203 + }, + { + "x":-13.9683983176083, + "y":16.8057292258725 + }, + { + "x":3.71035580311468, + "y":15.277935659884 + }, + { + "x":-3.71035580311471, + "y":8.29373650107991 + }], + "rotation":123, + "type":"polyline", + "visible":true, + "width":0, + "x":152.779356598841, + "y":19.8613163578493 + }, + { + "height":0, + "id":12, + "name":"name: polyline - not closed", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-13.3136296464704, + "y":41.0321700579743 + }, + { + "x":21.3891099238377, + "y":16.8057292258725 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":124.187791292486, + "y":90.1398203933159 + }, + { + "gid":79, + "height":32, + "id":13, + "name":"name: tile", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":111.898147095601, + "y":48.3019211094691 + }, + { + "gid":80, + "height":32, + "id":14, + "name":"name: tile - invisible", + "rotation":0, + "type":"tile", + "visible":false, + "width":32, + "x":41.1831306127089, + "y":168.779356598841 + }, + { + "gid":2147483742, + "height":32, + "id":15, + "name":"name: tile - horizontal flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":197.236330567239, + "y":59.8695009662385 + }, + { + "gid":1073741918, + "height":32, + "id":16, + "name":"name: tile - vertical flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":32.4528816642037, + "y":60.742525861089 + }, + { + "gid":3221225558, + "height":32, + "id":17, + "name":"name: tile - both flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":167.553484142321, + "y":95.6635216551097 + }, + { + "gid":86, + "height":32, + "id":18, + "name":"name: tile - rotated", + "rotation":89, + "type":"tile", + "visible":true, + "width":32, + "x":85.65, + "y":142.62 + }, + { + "height":19, + "id":19, + "name":"name: text", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":81.7106470956008, + "y":93.2986813686484 + }, + { + "height":19, + "id":20, + "name":"name: text - invisible", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":false, + "width":92.375, + "x":8.37655592815732, + "y":112.068716607935 + }, + { + "height":19, + "id":21, + "name":"name: text - rotated", + "rotation":19, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":157.882069171308, + "y":78.4572581561896 + }, + { + "height":19, + "id":22, + "name":"name: text - different font", + "rotation":0, + "text": + { + "bold":true, + "fontfamily":"DejaVu Sans", + "pixelsize":19, + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":2.70189411162896, + "y":101.592417869728 + }, + { + "height":19, + "id":23, + "name":"name: text - no word wrap", + "rotation":0, + "text": + { + "text":"Hello World" + }, + "type":"text", + "visible":true, + "width":92.375, + "x":9.90434949414573, + "y":154.192167784472 + }, + { + "height":19, + "id":24, + "name":"name: text - right bottom align", + "rotation":0, + "text": + { + "halign":"right", + "text":"Hello World", + "valign":"bottom", + "wrap":true + }, + "type":"", + "visible":true, + "width":92.375, + "x":151.989151131067, + "y":1.19455496191883 + }, + { + "height":19, + "id":25, + "name":"text: center center align", + "rotation":0, + "text": + { + "halign":"center", + "text":"Hello World", + "valign":"center", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":4.22968767761736, + "y":3.81362964647039 + }, + { + "height":19, + "id":26, + "name":"name: text - justified", + "rotation":0, + "text": + { + "halign":"justify", + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":13.8329615209731, + "y":60.7785040354666 + }, + { + "height":19, + "id":27, + "name":"name: text - red", + "rotation":0, + "text": + { + "color":"#aa0000", + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":96.3338140843469, + "y":130.620495623508 + }, + { + "height":0, + "id":28, + "name":"name: rectangle - no width or height", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":0, + "x":131.17199045129, + "y":53.4727748095942 + }, + { + "ellipse":true, + "height":0, + "id":29, + "name":"name: ellipse - no width or height", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":0, + "x":72.4610662725929, + "y":127.679890871888 + }, + { + "height":13.7501420938956, + "id":30, + "name":"name: rectangle - properties", + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":false + }, + { + "name":"color property", + "type":"color", + "value":"#ffaa0000" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/dev\/null" + }, + { + "name":"float property", + "type":"float", + "value":42.1 + }, + { + "name":"int property", + "type":"int", + "value":8675309 + }, + { + "name":"string property", + "type":"string", + "value":"pytiled_parser rulez!1!!" + }], + "rotation":0, + "type":"rectangle", + "visible":true, + "width":21.170853700125, + "x":39.0678640445606, + "y":131.826759122428 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":31, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"..\/..\/old_tests\/test_data\/tile_set_image_objects.tsx" + }, + { + "firstgid":49, + "source":"..\/..\/old_tests\/test_data\/tile_set_image.tsx" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/test_map_simple_offset.json b/tests/test_data/test_map_simple_offset.json new file mode 100644 index 0000000..bc3f4f5 --- /dev/null +++ b/tests/test_data/test_map_simple_offset.json @@ -0,0 +1,80 @@ +{ "compressionlevel":0, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "offsetx":16, + "offsety":-16.42, + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"empty file", + "type":"file", + "value":"" + }, + { + "name":"empty string", + "type":"string", + "value":"" + }, + { + "name":"file_property", + "type":"file", + "value":"test_map_simple_offset.json" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"..\/..\/old_tests\/test_data\/tile_set_image.tsx" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} \ No newline at end of file diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py new file mode 100644 index 0000000..d0675d9 --- /dev/null +++ b/tests/test_tiled_object.py @@ -0,0 +1,82 @@ +"""Tests for objects""" +import xml.etree.ElementTree as etree +from contextlib import ExitStack as does_not_raise + +import pytest + +from pytiled_parser import tiled_object + +ELLIPSES = [] + +RECTANGLES = [ + ( + """ + {"height":41.4686825053996, + "id":1, + "name":"name: rectangle", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":45.3972945322269, + "x":27.7185404115039, + "y":23.571672160964} + """, + { + "height": 41.4686825053996, + "id": 1, + "name": "name: rectangle", + "rotation": 0, + "type": "rectangle", + "visible": True, + "width": 45.3972945322269, + "x": 27.7185404115039, + "y": 23.571672160964, + }, + ), +] + +POINTS = [ + ( + """ + {"height":0, + "id":2, + "name":"name: point", + "point":true, + "rotation":0, + "type":"point", + "visible":true, + "width":0, + "x":159.981811981357, + "y":82.9373650107991} + """, + { + "height": 0, + "id": 2, + "name": "name: point", + "point": True, + "rotation": 0, + "type": "point", + "visible": True, + "width": 0, + "x": 159.981811981357, + "y": 82.9373650107991, + }, + ), +] + +TILE_IMAGES = [] + +POLYGONS = [] + +POLYLINES = [] + +TEXTS = [] + +OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILE_IMAGES + POLYGONS + POLYLINES + TEXTS + + +@pytest.mark.parametrize("raw_object,expected", OBJECTS) +def test_parse_layer(raw_object, expected): + result = tiled_object._cast_tiled_object(raw_object) + + assert result == expected From becf4de4ea7167282893e15995d306acc22c2506 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 19:26:06 -0400 Subject: [PATCH 002/198] Added VS Code directory to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8a9b319..1200298 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,6 @@ venv.bak/ # mypy .mypy_cache/ .idea/ + +# VS Code Directory +.vscode \ No newline at end of file From ba80ecaf64857983f9500e690e15a640cab7896a Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:18:24 -0400 Subject: [PATCH 003/198] feat: visible attribute to tiled_object --- pytiled_parser/tiled_object.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 9bb0449..a93b943 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -38,6 +38,7 @@ class TiledObject: size: Size = Size(0, 0) rotation: float = 0 opacity: float = 1 + visible: bool name: Optional[str] = None type: Optional[str] = None From 0beea21560110b74596c2a2b68a17ba5b9dd32cc Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:18:38 -0400 Subject: [PATCH 004/198] fix(tiled_object): imports --- pytiled_parser/tiled_object.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index a93b943..c774794 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -4,9 +4,9 @@ from typing import Callable, Dict, List, Optional, Union import attr -from pytiled_parser import OrderedPair, Size -from pytiled_parser.properties import Properties -from pytiled_parser.template import Template +from .common_types import OrderedPair, Size +from .properties import Properties +from .template import Template @attr.s(auto_attribs=True, kw_only=True) From 59e8a77b266a74c63b3b659de9e83b7a11f89b44 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:18:57 -0400 Subject: [PATCH 005/198] tests: use casted type, not dict --- tests/test_tiled_object.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index d0675d9..22797f0 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -4,7 +4,7 @@ from contextlib import ExitStack as does_not_raise import pytest -from pytiled_parser import tiled_object +from pytiled_parser import common_types, tiled_object ELLIPSES = [] @@ -21,17 +21,15 @@ RECTANGLES = [ "x":27.7185404115039, "y":23.571672160964} """, - { - "height": 41.4686825053996, - "id": 1, - "name": "name: rectangle", - "rotation": 0, - "type": "rectangle", - "visible": True, - "width": 45.3972945322269, - "x": 27.7185404115039, - "y": 23.571672160964, - }, + tiled_object.Rectangle( + id_=1, + size=common_types.Size(41.4686825053996, 45.3972945322269), + name="name: rectangle", + rotation=0, + type="rectangle", + visible=True, + coordinates=common_types.OrderedPair(27.7185404115039, 23.571672160964), + ), ), ] From 13a031791114131b340bc3a48ce605b312731960 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:21:49 -0400 Subject: [PATCH 006/198] fix(common_types): correct attribute name in docstring --- pytiled_parser/common_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index 95c7196..9d88004 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -19,7 +19,7 @@ class Size(NamedTuple): Attributes: width: The width of the object. - size: The height of the object. + height: The height of the object. """ width: Union[int, float] From ce016a5f8eb888877f678107dd5355cebb2a6484 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:28:49 -0400 Subject: [PATCH 007/198] tests: fix visibility of invisible rectangle --- tests/test_data/simple_objects.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json index 9e01620..258958f 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/simple_objects.json @@ -67,7 +67,7 @@ "name":"name: rectangle - invisible", "rotation":0, "type":"rectangle", - "visible":true, + "visible":false, "width":30.9923837671934, "x":163.910424008185, "y":91.0128452881664 From e42b7e75328a384344b5da9916a34f389219869c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:31:24 -0400 Subject: [PATCH 008/198] tests: fix visibility of invisible ellipse --- tests/test_data/simple_objects.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json index 258958f..df9342e 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/simple_objects.json @@ -102,7 +102,7 @@ "name":"name: ellipse - invisible", "rotation":0, "type":"ellipse", - "visible":true, + "visible":false, "width":6.32943048766625, "x":22.6986472661134, "y":53.9092872570194 From 21281361c082455721c7aa8e63ccbcf4e807dbd7 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:33:31 -0400 Subject: [PATCH 009/198] tests: width and height were reversed --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 22797f0..72d7c99 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -23,7 +23,7 @@ RECTANGLES = [ """, tiled_object.Rectangle( id_=1, - size=common_types.Size(41.4686825053996, 45.3972945322269), + size=common_types.Size(45.3972945322269, 41.4686825053996), name="name: rectangle", rotation=0, type="rectangle", From 5b9ddff6ee7b289df44c114285fe691525280b7a Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 20:42:15 -0400 Subject: [PATCH 010/198] Implemented Ellipse Tests --- tests/test_tiled_object.py | 74 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 22797f0..5e26931 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -6,7 +6,77 @@ import pytest from pytiled_parser import common_types, tiled_object -ELLIPSES = [] +ELLIPSES = [ + ( + """ + {"ellipse":true, + "height":18.5517790155735, + "id":6, + "name":"name: ellipse", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":57.4013868364215, + "x":37.5400704785722, + "y":81.1913152210981} + """, + tiled_object.Ellipse( + id_=6, + size=common_types.Size(57.4013868364215, 18.5517790155735), + name="name: ellipse", + rotation=0, + type="ellipse", + visible=True, + coordinates=common_types.OrderedPair(37.5400704785722, 81.1913152210981), + ), + ), + ( + """ + {"ellipse":true, + "height":31.4288962146186, + "id":7, + "name":"name: ellipse - invisible", + "rotation":0, + "type":"ellipse", + "visible":false, + "width":6.32943048766625, + "x":22.6986472661134, + "y":53.9092872570194} + """, + tiled_object.Ellipse( + id_=7, + size=common_types.Size(6.32943048766625, 31.4288962146186), + name="name: ellipse - invisible", + rotation=0, + type="ellipse", + visible=True, + coordinates=common_types.OrderedPair(22.6986472661134, 53.9092872570194), + ), + ), + ( + """ + {"ellipse":true, + "height":24.2264408321018, + "id":8, + "name":"name: ellipse - rotated", + "rotation":111, + "type":"ellipse", + "visible":true, + "width":29.6828464249176, + "x":35.7940206888712, + "y":120.040923041946} + """, + tiled_object.Ellipse( + id_=8, + size=common_types.Size(29.6828464249176, 24.2264408321018), + name="name: ellipse - rotated", + rotation=111, + type="ellipse", + visible=True, + coordinates=common_types.OrderedPair(35.7940206888712, 120.040923041946), + ), + ), +] RECTANGLES = [ ( @@ -23,7 +93,7 @@ RECTANGLES = [ """, tiled_object.Rectangle( id_=1, - size=common_types.Size(41.4686825053996, 45.3972945322269), + size=common_types.Size(45.3972945322269, 41.4686825053996), name="name: rectangle", rotation=0, type="rectangle", From 93f603557adf996745663898d7901a9ea395a180 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 20:51:11 -0400 Subject: [PATCH 011/198] tests: Ben is fickle when it comes to json formatting --- tests/test_tiled_object.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 72d7c99..d1b4e7f 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -11,7 +11,8 @@ ELLIPSES = [] RECTANGLES = [ ( """ - {"height":41.4686825053996, + { + "height":41.4686825053996, "id":1, "name":"name: rectangle", "rotation":0, @@ -19,7 +20,8 @@ RECTANGLES = [ "visible":true, "width":45.3972945322269, "x":27.7185404115039, - "y":23.571672160964} + "y":23.571672160964 + } """, tiled_object.Rectangle( id_=1, @@ -36,7 +38,8 @@ RECTANGLES = [ POINTS = [ ( """ - {"height":0, + { + "height":0, "id":2, "name":"name: point", "point":true, @@ -45,7 +48,8 @@ POINTS = [ "visible":true, "width":0, "x":159.981811981357, - "y":82.9373650107991} + "y":82.9373650107991 + } """, { "height": 0, From d11274693c39bbc27b70147c0b86f530c1b2cc1d Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 21:15:06 -0400 Subject: [PATCH 012/198] Implemented Polyline Tests --- tests/test_tiled_object.py | 222 +++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 11 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 5e26931..b0b1de8 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -9,7 +9,8 @@ from pytiled_parser import common_types, tiled_object ELLIPSES = [ ( """ - {"ellipse":true, + { + "ellipse":true, "height":18.5517790155735, "id":6, "name":"name: ellipse", @@ -18,7 +19,8 @@ ELLIPSES = [ "visible":true, "width":57.4013868364215, "x":37.5400704785722, - "y":81.1913152210981} + "y":81.1913152210981 + } """, tiled_object.Ellipse( id_=6, @@ -32,7 +34,8 @@ ELLIPSES = [ ), ( """ - {"ellipse":true, + { + "ellipse":true, "height":31.4288962146186, "id":7, "name":"name: ellipse - invisible", @@ -41,7 +44,8 @@ ELLIPSES = [ "visible":false, "width":6.32943048766625, "x":22.6986472661134, - "y":53.9092872570194} + "y":53.9092872570194 + } """, tiled_object.Ellipse( id_=7, @@ -55,7 +59,8 @@ ELLIPSES = [ ), ( """ - {"ellipse":true, + { + "ellipse":true, "height":24.2264408321018, "id":8, "name":"name: ellipse - rotated", @@ -64,7 +69,8 @@ ELLIPSES = [ "visible":true, "width":29.6828464249176, "x":35.7940206888712, - "y":120.040923041946} + "y":120.040923041946 + } """, tiled_object.Ellipse( id_=8, @@ -81,7 +87,8 @@ ELLIPSES = [ RECTANGLES = [ ( """ - {"height":41.4686825053996, + { + "height":41.4686825053996, "id":1, "name":"name: rectangle", "rotation":0, @@ -89,7 +96,8 @@ RECTANGLES = [ "visible":true, "width":45.3972945322269, "x":27.7185404115039, - "y":23.571672160964} + "y":23.571672160964 + } """, tiled_object.Rectangle( id_=1, @@ -106,7 +114,8 @@ RECTANGLES = [ POINTS = [ ( """ - {"height":0, + { + "height":0, "id":2, "name":"name: point", "point":true, @@ -115,7 +124,8 @@ POINTS = [ "visible":true, "width":0, "x":159.981811981357, - "y":82.9373650107991} + "y":82.9373650107991 + } """, { "height": 0, @@ -136,7 +146,197 @@ TILE_IMAGES = [] POLYGONS = [] -POLYLINES = [] +POLYLINES = [ + ( + """ + { + "height":0, + "id":9, + "name":"name: polyline", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":19.424803910424, + "y":27.063771740366 + }, + { + "x":19.6430601341366, + "y":3.05558713197681 + }, + { + "x":-2.61907468455156, + "y":15.9327043310219 + }, + { + "x":25.317721950665, + "y":16.3692167784472 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":89.485051722178, + "y":38.6313515971354 + } + """, + tiled_object.Polyline( + id_=9, + name="name: polyline", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(19.424803910424, 27.063771740366), + common_types.OrderedPair(19.6430601341366, 3.05558713197681), + common_types.OrderedPair(-2.61907468455156, 15.9327043310219), + common_types.OrderedPair(25.317721950665, 16.3692167784472), + ], + rotation=0, + type="polyline", + visible=True, + coordinates=common_types.OrderedPair(89.485051722178, 38.6313515971354), + ), + ), + ( + """ + { + "height":0, + "id":10, + "name":"name: polyline - invisible", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":7.63896782994203 + }, + { + "x":-14.8414232124588, + "y":-10.2580425144936 + }], + "rotation":0, + "type":"polyline", + "visible":false, + "width":0, + "x":133.791065135842, + "y":24.4446970558145 + } + """, + tiled_object.Polyline( + id_=10, + name="name: polyline - invisible", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(-12.8771171990451, 7.63896782994203), + common_types.OrderedPair(-14.8414232124588, -10.2580425144936), + ], + rotation=0, + type="polyline", + visible=False, + coordinates=common_types.OrderedPair(133.791065135842, 24.4446970558145), + ), + ), + ( + """ + { + "height":0, + "id":11, + "name":"name: polyline - rotated", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":0 + }, + { + "x":-6.98419915880413, + "y":7.63896782994203 + }, + { + "x":-13.9683983176083, + "y":16.8057292258725 + }, + { + "x":3.71035580311468, + "y":15.277935659884 + }, + { + "x":-3.71035580311471, + "y":8.29373650107991 + }], + "rotation":123, + "type":"polyline", + "visible":true, + "width":0, + "x":152.779356598841, + "y":19.8613163578493 + } + """, + tiled_object.Polyline( + id_=11, + name="name: polyline - rotated", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(-12.8771171990451, 0), + common_types.OrderedPair(-6.98419915880413, 7.63896782994203), + common_types.OrderedPair(-13.9683983176083, 16.8057292258725), + common_types.OrderedPair(3.71035580311468, 15.277935659884), + common_types.OrderedPair(-3.71035580311471, 8.29373650107991), + ], + rotation=123, + type="polyline", + visible=True, + coordinates=common_types.OrderedPair(152.779356598841, 19.8613163578493), + ), + ), + ( + """ + { + "height":0, + "id":12, + "name":"name: polyline - not closed", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-13.3136296464704, + "y":41.0321700579743 + }, + { + "x":21.3891099238377, + "y":16.8057292258725 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":124.187791292486, + "y":90.1398203933159 + } + """, + tiled_object.Polyline( + id_=12, + name="name: polyline - not closed", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(-13.3136296464704, 41.0321700579743), + common_types.OrderedPair(21.3891099238377, 16.8057292258725), + ], + rotation=0, + type="polyline", + visible=True, + coordinates=common_types.OrderedPair(124.187791292486, 90.1398203933159), + ), + ), +] TEXTS = [] From ac6a4ff379e2f22cbbc76bb1ecbc6f675029f99a Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 21:32:11 -0400 Subject: [PATCH 013/198] Added full set of Polygons and Polylines to map --- tests/test_data/simple_objects.json | 66 +++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json index df9342e..1da91c1 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/simple_objects.json @@ -122,7 +122,7 @@ { "height":0, "id":9, - "name":"name: polyline", + "name":"name: polygon", "polygon":[ { "x":0, @@ -145,7 +145,7 @@ "y":16.3692167784472 }], "rotation":0, - "type":"polyline", + "type":"polygon", "visible":true, "width":0, "x":89.485051722178, @@ -154,7 +154,7 @@ { "height":0, "id":10, - "name":"name: polyline - invisible", + "name":"name: polygon - invisible", "polygon":[ { "x":0, @@ -169,7 +169,7 @@ "y":-10.2580425144936 }], "rotation":0, - "type":"polyline", + "type":"polygon", "visible":false, "width":0, "x":133.791065135842, @@ -178,7 +178,7 @@ { "height":0, "id":11, - "name":"name: polyline - rotated", + "name":"name: polygon - rotated", "polygon":[ { "x":0, @@ -205,7 +205,7 @@ "y":8.29373650107991 }], "rotation":123, - "type":"polyline", + "type":"polygon", "visible":true, "width":0, "x":152.779356598841, @@ -214,7 +214,7 @@ { "height":0, "id":12, - "name":"name: polyline - not closed", + "name":"name: polyline", "polyline":[ { "x":0, @@ -235,6 +235,54 @@ "x":124.187791292486, "y":90.1398203933159 }, + { + "height":0, + "id":31, + "name":"name: polyline - invisible", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-9, + "y":20.3333333333333 + }, + { + "x":5, + "y":23.6666666666667 + }], + "rotation":0, + "type":"polyline", + "visible":false, + "width":0, + "x":140, + "y":163.333333333333 + }, + { + "height":0, + "id":32, + "name":"name: polyline - rotated", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":10.3333333333333, + "y":13 + }, + { + "x":-5.33333333333331, + "y":19.6666666666667 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":192.333333333333, + "y":128.666666666667 + }, { "gid":79, "height":32, @@ -531,10 +579,10 @@ "y":0 }], "nextlayerid":3, - "nextobjectid":31, + "nextobjectid":33, "orientation":"orthogonal", "renderorder":"right-down", - "tiledversion":"1.3.1", + "tiledversion":"1.3.5", "tileheight":32, "tilesets":[ { From ef2002833849e2fa7a9262fe525079113283a673 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 21:36:20 -0400 Subject: [PATCH 014/198] tests: add rectangles to list --- tests/test_tiled_object.py | 138 ++++++++++++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index d1b4e7f..2ca7806 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1,10 +1,11 @@ """Tests for objects""" import xml.etree.ElementTree as etree from contextlib import ExitStack as does_not_raise +from pathlib import Path import pytest -from pytiled_parser import common_types, tiled_object +from pytiled_parser import common_types, properties, tiled_object ELLIPSES = [] @@ -33,6 +34,141 @@ RECTANGLES = [ coordinates=common_types.OrderedPair(27.7185404115039, 23.571672160964), ), ), + ( + """ + { + "height":32.7384335568944, + "id":4, + "name":"name: rectangle - invisible", + "rotation":0, + "type":"rectangle", + "visible":false, + "width":30.9923837671934, + "x":163.910424008185, + "y":91.0128452881664 + } + """, + tiled_object.Rectangle( + id_=4, + size=common_types.Size(30.9923837671934, 32.7384335568944), + name="name: rectangle - invisible", + rotation=0, + type="rectangle", + visible=False, + coordinates=common_types.OrderedPair(163.910424008185, 91.0128452881664), + ), + ), + ( + """ + { + "height":22, + "id":5, + "name":"name: rectangle - rotated", + "rotation":10, + "type":"rectangle", + "visible":true, + "width":10, + "x":183.335227918609, + "y":23.3534159372513 + }, + """, + tiled_object.Rectangle( + id_=5, + size=common_types.Size(10, 22), + name="name: rectangle - rotated", + rotation=10, + type="rectangle", + visible=True, + coordinates=common_types.OrderedPair(183.335227918609, 23.3534159372513), + ), + ), + ( + """ + { + "height":0, + "id":28, + "name":"name: rectangle - no width or height", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":0, + "x":131.17199045129, + "y":53.4727748095942 + } + """, + tiled_object.Rectangle( + id_=28, + size=common_types.Size(0, 0), + name="name: rectangle - no width or height", + rotation=0, + type="rectangle", + visible=True, + coordinates=common_types.OrderedPair(131.17199045129, 53.4727748095942), + ), + ), + ( + r""" + { + "height":13.7501420938956, + "id":30, + "name":"name: rectangle - properties", + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":false + }, + { + "name":"color property", + "type":"color", + "value":"#ffaa0000" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/dev\/null" + }, + { + "name":"float property", + "type":"float", + "value":42.1 + }, + { + "name":"int property", + "type":"int", + "value":8675309 + }, + { + "name":"string property", + "type":"string", + "value":"pytiled_parser rulez!1!!" + }], + "rotation":0, + "type":"rectangle", + "visible":true, + "width":21.170853700125, + "x":39.0678640445606, + "y":131.826759122428 + } + """, + tiled_object.Rectangle( + id_=30, + size=common_types.Size(21.170853700125, 13.7501420938956), + name="name: rectangle - properties", + rotation=0, + type="rectangle", + visible=True, + coordinates=common_types.OrderedPair(39.0678640445606, 131.826759122428), + properties={ + "bool property": False, + "color property": "#ffaa0000", + "file property": Path("../../../../../../dev/null"), + "float property": 42.1, + "int property": 8675309, + "string property": "pytiled_parser rulez!1!!", + }, + ), + ), ] POINTS = [ From 2424e7304efdde47ec6cfd800c3260099796c5e8 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 21:40:04 -0400 Subject: [PATCH 015/198] tests: remove unused imports --- tests/test_tiled_object.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index ea8a989..f55a792 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1,11 +1,10 @@ """Tests for objects""" -import xml.etree.ElementTree as etree from contextlib import ExitStack as does_not_raise from pathlib import Path import pytest -from pytiled_parser import common_types, properties, tiled_object +from pytiled_parser import common_types, tiled_object ELLIPSES = [ ( From 9e5453896de0b9bfd2dc3400634fc39146b61306 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 21:47:43 -0400 Subject: [PATCH 016/198] tests: remove whitespace --- tests/test_tiled_object.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index f55a792..64abf24 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -292,19 +292,19 @@ POLYLINES = [ { "x":0, "y":0 - }, + }, { "x":19.424803910424, "y":27.063771740366 - }, + }, { "x":19.6430601341366, "y":3.05558713197681 - }, + }, { "x":-2.61907468455156, "y":15.9327043310219 - }, + }, { "x":25.317721950665, "y":16.3692167784472 @@ -384,23 +384,23 @@ POLYLINES = [ { "x":0, "y":0 - }, + }, { "x":-12.8771171990451, "y":0 - }, + }, { "x":-6.98419915880413, "y":7.63896782994203 - }, + }, { "x":-13.9683983176083, "y":16.8057292258725 - }, + }, { "x":3.71035580311468, "y":15.277935659884 - }, + }, { "x":-3.71035580311471, "y":8.29373650107991 @@ -410,7 +410,7 @@ POLYLINES = [ "visible":true, "width":0, "x":152.779356598841, - "y":19.8613163578493 + "y":19.8613163578493 } """, tiled_object.Polyline( @@ -440,11 +440,11 @@ POLYLINES = [ { "x":0, "y":0 - }, + }, { "x":-13.3136296464704, "y":41.0321700579743 - }, + }, { "x":21.3891099238377, "y":16.8057292258725 From 0b36a2e0cc8675729f98bbaad0e4d319580b61e0 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 21:52:17 -0400 Subject: [PATCH 017/198] rf(tiled_object): rename TileImage to Tile to match what the UI calls it --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index c774794..ca68cfa 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -137,7 +137,7 @@ class Text(TiledObject): @attr.s(auto_attribs=True, kw_only=True) -class TileImage(TiledObject): +class Tile(TiledObject): """Tile object See: https://doc.mapeditor.org/en/stable/manual/objects/#insert-tile From ae7182d5fb48306fb6f977ca952572cfa852c7eb Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 21:58:07 -0400 Subject: [PATCH 018/198] tests: fixed Polyline tests, implemented Polygon tests --- tests/test_tiled_object.py | 263 ++++++++++++++++++++++++++----------- 1 file changed, 183 insertions(+), 80 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index b0b1de8..416c56e 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -115,76 +115,94 @@ POINTS = [ ( """ { - "height":0, - "id":2, - "name":"name: point", - "point":true, - "rotation":0, - "type":"point", - "visible":true, - "width":0, - "x":159.981811981357, - "y":82.9373650107991 + "height":0, + "id":2, + "name":"name: point", + "point":true, + "rotation":0, + "type":"point", + "visible":true, + "width":0, + "x":159.981811981357, + "y":82.9373650107991 } """, + tiled_object.Point( + id_=2, + name="name: point", + rotation=0, + type="point", + visible=True, + coordinates=common_types.OrderedPair(159.981811981357, 82.9373650107991), + ), + ), + ( + """ { - "height": 0, - "id": 2, - "name": "name: point", - "point": True, - "rotation": 0, - "type": "point", - "visible": True, - "width": 0, - "x": 159.981811981357, - "y": 82.9373650107991, - }, + "height":0, + "id":3, + "name":"name: point invisible", + "point":true, + "rotation":0, + "type":"point", + "visible":false, + "width":0, + "x":109.346368080027, + "y":95.8144822098443 + } + """, + tiled_object.Point( + id_=3, + name="name:name: point invisible", + rotation=0, + type="point", + visible=True, + coordinates=common_types.OrderedPair(109.346368080027, 95.8144822098443), + ), ), ] TILE_IMAGES = [] -POLYGONS = [] - -POLYLINES = [ +POLYGONS = [ ( """ { - "height":0, - "id":9, - "name":"name: polyline", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":19.424803910424, - "y":27.063771740366 - }, - { - "x":19.6430601341366, - "y":3.05558713197681 - }, - { - "x":-2.61907468455156, - "y":15.9327043310219 - }, - { - "x":25.317721950665, - "y":16.3692167784472 - }], - "rotation":0, - "type":"polyline", - "visible":true, - "width":0, - "x":89.485051722178, - "y":38.6313515971354 + "height":0, + "id":9, + "name":"name: polygon", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":19.424803910424, + "y":27.063771740366 + }, + { + "x":19.6430601341366, + "y":3.05558713197681 + }, + { + "x":-2.61907468455156, + "y":15.9327043310219 + }, + { + "x":25.317721950665, + "y":16.3692167784472 + }], + "rotation":0, + "type":"polygon", + "visible":true, + "width":0, + "x":89.485051722178, + "y":38.6313515971354 } """, - tiled_object.Polyline( + tiled_object.Polygon( id_=9, - name="name: polyline", + name="name: polygon", points=[ common_types.OrderedPair(0, 0), common_types.OrderedPair(19.424803910424, 27.063771740366), @@ -193,7 +211,7 @@ POLYLINES = [ common_types.OrderedPair(25.317721950665, 16.3692167784472), ], rotation=0, - type="polyline", + type="polygon", visible=True, coordinates=common_types.OrderedPair(89.485051722178, 38.6313515971354), ), @@ -203,7 +221,7 @@ POLYLINES = [ { "height":0, "id":10, - "name":"name: polyline - invisible", + "name":"name: polygon - invisible", "polygon":[ { "x":0, @@ -218,23 +236,23 @@ POLYLINES = [ "y":-10.2580425144936 }], "rotation":0, - "type":"polyline", + "type":"polygon", "visible":false, "width":0, "x":133.791065135842, "y":24.4446970558145 } """, - tiled_object.Polyline( - id_=10, - name="name: polyline - invisible", + tiled_object.Polygon( + id_=9, + name="name: polygon - invisible", points=[ common_types.OrderedPair(0, 0), common_types.OrderedPair(-12.8771171990451, 7.63896782994203), common_types.OrderedPair(-14.8414232124588, -10.2580425144936), ], rotation=0, - type="polyline", + type="polygon", visible=False, coordinates=common_types.OrderedPair(133.791065135842, 24.4446970558145), ), @@ -244,43 +262,43 @@ POLYLINES = [ { "height":0, "id":11, - "name":"name: polyline - rotated", + "name":"name: polygon - rotated", "polygon":[ { "x":0, "y":0 - }, + }, { "x":-12.8771171990451, "y":0 - }, + }, { "x":-6.98419915880413, "y":7.63896782994203 - }, + }, { "x":-13.9683983176083, "y":16.8057292258725 - }, + }, { "x":3.71035580311468, "y":15.277935659884 - }, + }, { "x":-3.71035580311471, "y":8.29373650107991 }], "rotation":123, - "type":"polyline", + "type":"polygon", "visible":true, "width":0, "x":152.779356598841, - "y":19.8613163578493 + "y":19.8613163578493 } """, - tiled_object.Polyline( - id_=11, - name="name: polyline - rotated", + tiled_object.Polygon( + id_=9, + name="name: polygon - rotated", points=[ common_types.OrderedPair(0, 0), common_types.OrderedPair(-12.8771171990451, 0), @@ -290,26 +308,29 @@ POLYLINES = [ common_types.OrderedPair(-3.71035580311471, 8.29373650107991), ], rotation=123, - type="polyline", + type="polygon", visible=True, coordinates=common_types.OrderedPair(152.779356598841, 19.8613163578493), ), ), +] + +POLYLINES = [ ( """ { "height":0, "id":12, - "name":"name: polyline - not closed", + "name":"name: polyline", "polyline":[ { "x":0, "y":0 - }, + }, { "x":-13.3136296464704, "y":41.0321700579743 - }, + }, { "x":21.3891099238377, "y":16.8057292258725 @@ -323,8 +344,8 @@ POLYLINES = [ } """, tiled_object.Polyline( - id_=12, - name="name: polyline - not closed", + id_=9, + name="name: polyline", points=[ common_types.OrderedPair(0, 0), common_types.OrderedPair(-13.3136296464704, 41.0321700579743), @@ -336,6 +357,88 @@ POLYLINES = [ coordinates=common_types.OrderedPair(124.187791292486, 90.1398203933159), ), ), + ( + """ + { + "height":0, + "id":31, + "name":"name: polyline - invisible", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-9, + "y":20.3333333333333 + }, + { + "x":5, + "y":23.6666666666667 + }], + "rotation":0, + "type":"polyline", + "visible":false, + "width":0, + "x":140, + "y":163.333333333333 + } + """, + tiled_object.Polyline( + id_=10, + name="name: polyline - invisible", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(-9, 20.3333333333333), + common_types.OrderedPair(5, 23.6666666666667), + ], + rotation=0, + type="polyline", + visible=False, + coordinates=common_types.OrderedPair(140, 163.333333333333), + ), + ), + ( + """ + { + "height":0, + "id":32, + "name":"name: polyline - rotated", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":10.3333333333333, + "y":13 + }, + { + "x":-5.33333333333331, + "y":19.6666666666667 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":192.333333333333, + "y":128.666666666667 + } + """, + tiled_object.Polyline( + id_=11, + name="name: polyline - rotated", + points=[ + common_types.OrderedPair(0, 0), + common_types.OrderedPair(10.3333333333333, 13), + common_types.OrderedPair(-5.33333333333331, 19.6666666666667), + ], + rotation=0, + type="polyline", + visible=True, + coordinates=common_types.OrderedPair(192.333333333333, 128.666666666667), + ), + ), ] TEXTS = [] From 161da5ef03ddd21b403b4ad29aad3118cd0773c6 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 22:12:47 -0400 Subject: [PATCH 019/198] tests: add Tiles to list --- tests/test_tiled_object.py | 159 ++++++++++++++++++++++++++++++++++++- 1 file changed, 158 insertions(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 64abf24..dcce283 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -277,7 +277,164 @@ POINTS = [ ), ] -TILE_IMAGES = [] +TILE_IMAGES = [ + ( + """ + { + "gid":79, + "height":32, + "id":13, + "name":"name: tile", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":111.898147095601, + "y":48.3019211094691 + } + """, + tiled_object.Tile( + id_=13, + size=common_types.Size(32, 32), + name="name: tile", + rotation=0, + type="tile", + visible=True, + coordinates=common_types.OrderedPair(111.898147095601, 48.3019211094691), + gid=79, + ), + ), + ( + """ + { + "gid":80, + "height":32, + "id":14, + "name":"name: tile - invisible", + "rotation":0, + "type":"tile", + "visible":false, + "width":32, + "x":41.1831306127089, + "y":168.779356598841 + } + """, + tiled_object.Tile( + id_=14, + size=common_types.Size(32, 32), + name="name: tile - invisible", + rotation=0, + type="tile", + visible=False, + coordinates=common_types.OrderedPair(41.1831306127089, 168.779356598841), + gid=80, + ), + ), + ( + """ + { + "gid":2147483742, + "height":32, + "id":15, + "name":"name: tile - horizontal flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":197.236330567239, + "y":59.8695009662385 + } + """, + tiled_object.Tile( + id_=15, + size=common_types.Size(32, 32), + name="name: tile - horizontal flipped", + rotation=0, + type="tile", + visible=True, + coordinates=common_types.OrderedPair(197.236330567239, 59.8695009662385), + gid=2147483742, + ), + ), + ( + """ + { + "gid":1073741918, + "height":32, + "id":16, + "name":"name: tile - vertical flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":32.4528816642037, + "y":60.742525861089 + } + """, + tiled_object.Tile( + id_=16, + size=common_types.Size(32, 32), + name="name: tile - vertical flipped", + rotation=0, + type="tile", + visible=True, + coordinates=common_types.OrderedPair(32.4528816642037, 60.742525861089), + gid=1073741918, + ), + ), + ( + """ + { + "gid":3221225558, + "height":32, + "id":17, + "name":"name: tile - both flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":167.553484142321, + "y":95.6635216551097 + } + """, + tiled_object.Tile( + id_=17, + size=common_types.Size(32, 32), + name="name: tile - both flipped", + rotation=0, + type="tile", + visible=True, + coordinates=common_types.OrderedPair(167.553484142321, 95.6635216551097), + gid=3221225558, + ), + ), + ( + """ + { + "gid":86, + "height":32, + "id":18, + "name":"name: tile - rotated", + "rotation":89, + "type":"tile", + "visible":true, + "width":32, + "x":85.65, + "y":142.62 + } + """, + tiled_object.Tile( + id_=18, + size=common_types.Size(32, 32), + name="name: tile - rotated", + rotation=89, + type="tile", + visible=True, + coordinates=common_types.OrderedPair(85.65, 142.62), + gid=86, + ), + ), +] POLYGONS = [] From ce226923262f486e5fedded864fbfb9aeea00455 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 22:22:14 -0400 Subject: [PATCH 020/198] fix(tiled_object): TileImage is now just Tile --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index ca68cfa..0aff80b 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -170,7 +170,7 @@ def _cast_point(raw_tiled_object: RawTiledObject) -> Point: pass -def _cast_tile_image(raw_tiled_object: RawTiledObject) -> TileImage: +def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile: pass From b73f5bd311415109921423e8900c6d4b0254e41f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 22:36:11 -0400 Subject: [PATCH 021/198] tests: fix: added type to bottom right align text in tiled map --- tests/test_data/simple_objects.json | 1237 ++++++++++++++------------- 1 file changed, 643 insertions(+), 594 deletions(-) diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json index 1da91c1..dbf407c 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/simple_objects.json @@ -1,600 +1,649 @@ -{ "compressionlevel":0, - "editorsettings": +{ + "compressionlevel": 0, + "editorsettings": { + "export": { + "target": "." + } + }, + "height": 6, + "infinite": false, + "layers": [ { - "export": - { - "target":"." - } + "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 + ], + "height": 6, + "id": 1, + "name": "Tile Layer 1", + "opacity": 1, + "type": "tilelayer", + "visible": true, + "width": 8, + "x": 0, + "y": 0 }, - "height":6, - "infinite":false, - "layers":[ + { + "draworder": "topdown", + "id": 2, + "name": "Object Layer 1", + "objects": [ { - "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], - "height":6, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":8, - "x":0, - "y":0 - }, + "height": 41.4686825053996, + "id": 1, + "name": "name: rectangle", + "rotation": 0, + "type": "rectangle", + "visible": true, + "width": 45.3972945322269, + "x": 27.7185404115039, + "y": 23.571672160964 + }, { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[ - { - "height":41.4686825053996, - "id":1, - "name":"name: rectangle", - "rotation":0, - "type":"rectangle", - "visible":true, - "width":45.3972945322269, - "x":27.7185404115039, - "y":23.571672160964 - }, - { - "height":0, - "id":2, - "name":"name: point", - "point":true, - "rotation":0, - "type":"point", - "visible":true, - "width":0, - "x":159.981811981357, - "y":82.9373650107991 - }, - { - "height":0, - "id":3, - "name":"name: point invisible", - "point":true, - "rotation":0, - "type":"point", - "visible":false, - "width":0, - "x":109.346368080027, - "y":95.8144822098443 - }, - { - "height":32.7384335568944, - "id":4, - "name":"name: rectangle - invisible", - "rotation":0, - "type":"rectangle", - "visible":false, - "width":30.9923837671934, - "x":163.910424008185, - "y":91.0128452881664 - }, - { - "height":22, - "id":5, - "name":"name: rectangle - rotated", - "rotation":10, - "type":"rectangle", - "visible":true, - "width":10, - "x":183.335227918609, - "y":23.3534159372513 - }, - { - "ellipse":true, - "height":18.5517790155735, - "id":6, - "name":"name: ellipse", - "rotation":0, - "type":"ellipse", - "visible":true, - "width":57.4013868364215, - "x":37.5400704785722, - "y":81.1913152210981 - }, - { - "ellipse":true, - "height":31.4288962146186, - "id":7, - "name":"name: ellipse - invisible", - "rotation":0, - "type":"ellipse", - "visible":false, - "width":6.32943048766625, - "x":22.6986472661134, - "y":53.9092872570194 - }, - { - "ellipse":true, - "height":24.2264408321018, - "id":8, - "name":"name: ellipse - rotated", - "rotation":111, - "type":"ellipse", - "visible":true, - "width":29.6828464249176, - "x":35.7940206888712, - "y":120.040923041946 - }, - { - "height":0, - "id":9, - "name":"name: polygon", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":19.424803910424, - "y":27.063771740366 - }, - { - "x":19.6430601341366, - "y":3.05558713197681 - }, - { - "x":-2.61907468455156, - "y":15.9327043310219 - }, - { - "x":25.317721950665, - "y":16.3692167784472 - }], - "rotation":0, - "type":"polygon", - "visible":true, - "width":0, - "x":89.485051722178, - "y":38.6313515971354 - }, - { - "height":0, - "id":10, - "name":"name: polygon - invisible", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":-12.8771171990451, - "y":7.63896782994203 - }, - { - "x":-14.8414232124588, - "y":-10.2580425144936 - }], - "rotation":0, - "type":"polygon", - "visible":false, - "width":0, - "x":133.791065135842, - "y":24.4446970558145 - }, - { - "height":0, - "id":11, - "name":"name: polygon - rotated", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":-12.8771171990451, - "y":0 - }, - { - "x":-6.98419915880413, - "y":7.63896782994203 - }, - { - "x":-13.9683983176083, - "y":16.8057292258725 - }, - { - "x":3.71035580311468, - "y":15.277935659884 - }, - { - "x":-3.71035580311471, - "y":8.29373650107991 - }], - "rotation":123, - "type":"polygon", - "visible":true, - "width":0, - "x":152.779356598841, - "y":19.8613163578493 - }, - { - "height":0, - "id":12, - "name":"name: polyline", - "polyline":[ - { - "x":0, - "y":0 - }, - { - "x":-13.3136296464704, - "y":41.0321700579743 - }, - { - "x":21.3891099238377, - "y":16.8057292258725 - }], - "rotation":0, - "type":"polyline", - "visible":true, - "width":0, - "x":124.187791292486, - "y":90.1398203933159 - }, - { - "height":0, - "id":31, - "name":"name: polyline - invisible", - "polyline":[ - { - "x":0, - "y":0 - }, - { - "x":-9, - "y":20.3333333333333 - }, - { - "x":5, - "y":23.6666666666667 - }], - "rotation":0, - "type":"polyline", - "visible":false, - "width":0, - "x":140, - "y":163.333333333333 - }, - { - "height":0, - "id":32, - "name":"name: polyline - rotated", - "polyline":[ - { - "x":0, - "y":0 - }, - { - "x":10.3333333333333, - "y":13 - }, - { - "x":-5.33333333333331, - "y":19.6666666666667 - }], - "rotation":0, - "type":"polyline", - "visible":true, - "width":0, - "x":192.333333333333, - "y":128.666666666667 - }, - { - "gid":79, - "height":32, - "id":13, - "name":"name: tile", - "rotation":0, - "type":"tile", - "visible":true, - "width":32, - "x":111.898147095601, - "y":48.3019211094691 - }, - { - "gid":80, - "height":32, - "id":14, - "name":"name: tile - invisible", - "rotation":0, - "type":"tile", - "visible":false, - "width":32, - "x":41.1831306127089, - "y":168.779356598841 - }, - { - "gid":2147483742, - "height":32, - "id":15, - "name":"name: tile - horizontal flipped", - "rotation":0, - "type":"tile", - "visible":true, - "width":32, - "x":197.236330567239, - "y":59.8695009662385 - }, - { - "gid":1073741918, - "height":32, - "id":16, - "name":"name: tile - vertical flipped", - "rotation":0, - "type":"tile", - "visible":true, - "width":32, - "x":32.4528816642037, - "y":60.742525861089 - }, - { - "gid":3221225558, - "height":32, - "id":17, - "name":"name: tile - both flipped", - "rotation":0, - "type":"tile", - "visible":true, - "width":32, - "x":167.553484142321, - "y":95.6635216551097 - }, - { - "gid":86, - "height":32, - "id":18, - "name":"name: tile - rotated", - "rotation":89, - "type":"tile", - "visible":true, - "width":32, - "x":85.65, - "y":142.62 - }, - { - "height":19, - "id":19, - "name":"name: text", - "rotation":0, - "text": - { - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":81.7106470956008, - "y":93.2986813686484 - }, - { - "height":19, - "id":20, - "name":"name: text - invisible", - "rotation":0, - "text": - { - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":false, - "width":92.375, - "x":8.37655592815732, - "y":112.068716607935 - }, - { - "height":19, - "id":21, - "name":"name: text - rotated", - "rotation":19, - "text": - { - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":157.882069171308, - "y":78.4572581561896 - }, - { - "height":19, - "id":22, - "name":"name: text - different font", - "rotation":0, - "text": - { - "bold":true, - "fontfamily":"DejaVu Sans", - "pixelsize":19, - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":2.70189411162896, - "y":101.592417869728 - }, - { - "height":19, - "id":23, - "name":"name: text - no word wrap", - "rotation":0, - "text": - { - "text":"Hello World" - }, - "type":"text", - "visible":true, - "width":92.375, - "x":9.90434949414573, - "y":154.192167784472 - }, - { - "height":19, - "id":24, - "name":"name: text - right bottom align", - "rotation":0, - "text": - { - "halign":"right", - "text":"Hello World", - "valign":"bottom", - "wrap":true - }, - "type":"", - "visible":true, - "width":92.375, - "x":151.989151131067, - "y":1.19455496191883 - }, - { - "height":19, - "id":25, - "name":"text: center center align", - "rotation":0, - "text": - { - "halign":"center", - "text":"Hello World", - "valign":"center", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":4.22968767761736, - "y":3.81362964647039 - }, - { - "height":19, - "id":26, - "name":"name: text - justified", - "rotation":0, - "text": - { - "halign":"justify", - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":13.8329615209731, - "y":60.7785040354666 - }, - { - "height":19, - "id":27, - "name":"name: text - red", - "rotation":0, - "text": - { - "color":"#aa0000", - "text":"Hello World", - "wrap":true - }, - "type":"text", - "visible":true, - "width":92.375, - "x":96.3338140843469, - "y":130.620495623508 - }, - { - "height":0, - "id":28, - "name":"name: rectangle - no width or height", - "rotation":0, - "type":"rectangle", - "visible":true, - "width":0, - "x":131.17199045129, - "y":53.4727748095942 - }, - { - "ellipse":true, - "height":0, - "id":29, - "name":"name: ellipse - no width or height", - "rotation":0, - "type":"ellipse", - "visible":true, - "width":0, - "x":72.4610662725929, - "y":127.679890871888 - }, - { - "height":13.7501420938956, - "id":30, - "name":"name: rectangle - properties", - "properties":[ - { - "name":"bool property", - "type":"bool", - "value":false - }, - { - "name":"color property", - "type":"color", - "value":"#ffaa0000" - }, - { - "name":"file property", - "type":"file", - "value":"..\/..\/..\/..\/..\/..\/dev\/null" - }, - { - "name":"float property", - "type":"float", - "value":42.1 - }, - { - "name":"int property", - "type":"int", - "value":8675309 - }, - { - "name":"string property", - "type":"string", - "value":"pytiled_parser rulez!1!!" - }], - "rotation":0, - "type":"rectangle", - "visible":true, - "width":21.170853700125, - "x":39.0678640445606, - "y":131.826759122428 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }], - "nextlayerid":3, - "nextobjectid":33, - "orientation":"orthogonal", - "renderorder":"right-down", - "tiledversion":"1.3.5", - "tileheight":32, - "tilesets":[ + "height": 0, + "id": 2, + "name": "name: point", + "point": true, + "rotation": 0, + "type": "point", + "visible": true, + "width": 0, + "x": 159.981811981357, + "y": 82.9373650107991 + }, { - "firstgid":1, - "source":"..\/..\/old_tests\/test_data\/tile_set_image_objects.tsx" - }, + "height": 0, + "id": 3, + "name": "name: point invisible", + "point": true, + "rotation": 0, + "type": "point", + "visible": false, + "width": 0, + "x": 109.346368080027, + "y": 95.8144822098443 + }, { - "firstgid":49, - "source":"..\/..\/old_tests\/test_data\/tile_set_image.tsx" - }], - "tilewidth":32, - "type":"map", - "version":1.2, - "width":8 -} \ No newline at end of file + "height": 32.7384335568944, + "id": 4, + "name": "name: rectangle - invisible", + "rotation": 0, + "type": "rectangle", + "visible": false, + "width": 30.9923837671934, + "x": 163.910424008185, + "y": 91.0128452881664 + }, + { + "height": 22, + "id": 5, + "name": "name: rectangle - rotated", + "rotation": 10, + "type": "rectangle", + "visible": true, + "width": 10, + "x": 183.335227918609, + "y": 23.3534159372513 + }, + { + "ellipse": true, + "height": 18.5517790155735, + "id": 6, + "name": "name: ellipse", + "rotation": 0, + "type": "ellipse", + "visible": true, + "width": 57.4013868364215, + "x": 37.5400704785722, + "y": 81.1913152210981 + }, + { + "ellipse": true, + "height": 31.4288962146186, + "id": 7, + "name": "name: ellipse - invisible", + "rotation": 0, + "type": "ellipse", + "visible": false, + "width": 6.32943048766625, + "x": 22.6986472661134, + "y": 53.9092872570194 + }, + { + "ellipse": true, + "height": 24.2264408321018, + "id": 8, + "name": "name: ellipse - rotated", + "rotation": 111, + "type": "ellipse", + "visible": true, + "width": 29.6828464249176, + "x": 35.7940206888712, + "y": 120.040923041946 + }, + { + "height": 0, + "id": 9, + "name": "name: polygon", + "polygon": [ + { + "x": 0, + "y": 0 + }, + { + "x": 19.424803910424, + "y": 27.063771740366 + }, + { + "x": 19.6430601341366, + "y": 3.05558713197681 + }, + { + "x": -2.61907468455156, + "y": 15.9327043310219 + }, + { + "x": 25.317721950665, + "y": 16.3692167784472 + } + ], + "rotation": 0, + "type": "polygon", + "visible": true, + "width": 0, + "x": 89.485051722178, + "y": 38.6313515971354 + }, + { + "height": 0, + "id": 10, + "name": "name: polygon - invisible", + "polygon": [ + { + "x": 0, + "y": 0 + }, + { + "x": -12.8771171990451, + "y": 7.63896782994203 + }, + { + "x": -14.8414232124588, + "y": -10.2580425144936 + } + ], + "rotation": 0, + "type": "polygon", + "visible": false, + "width": 0, + "x": 133.791065135842, + "y": 24.4446970558145 + }, + { + "height": 0, + "id": 11, + "name": "name: polygon - rotated", + "polygon": [ + { + "x": 0, + "y": 0 + }, + { + "x": -12.8771171990451, + "y": 0 + }, + { + "x": -6.98419915880413, + "y": 7.63896782994203 + }, + { + "x": -13.9683983176083, + "y": 16.8057292258725 + }, + { + "x": 3.71035580311468, + "y": 15.277935659884 + }, + { + "x": -3.71035580311471, + "y": 8.29373650107991 + } + ], + "rotation": 123, + "type": "polygon", + "visible": true, + "width": 0, + "x": 152.779356598841, + "y": 19.8613163578493 + }, + { + "height": 0, + "id": 12, + "name": "name: polyline", + "polyline": [ + { + "x": 0, + "y": 0 + }, + { + "x": -13.3136296464704, + "y": 41.0321700579743 + }, + { + "x": 21.3891099238377, + "y": 16.8057292258725 + } + ], + "rotation": 0, + "type": "polyline", + "visible": true, + "width": 0, + "x": 124.187791292486, + "y": 90.1398203933159 + }, + { + "height": 0, + "id": 31, + "name": "name: polyline - invisible", + "polyline": [ + { + "x": 0, + "y": 0 + }, + { + "x": -9, + "y": 20.3333333333333 + }, + { + "x": 5, + "y": 23.6666666666667 + } + ], + "rotation": 0, + "type": "polyline", + "visible": false, + "width": 0, + "x": 140, + "y": 163.333333333333 + }, + { + "height": 0, + "id": 32, + "name": "name: polyline - rotated", + "polyline": [ + { + "x": 0, + "y": 0 + }, + { + "x": 10.3333333333333, + "y": 13 + }, + { + "x": -5.33333333333331, + "y": 19.6666666666667 + } + ], + "rotation": 0, + "type": "polyline", + "visible": true, + "width": 0, + "x": 192.333333333333, + "y": 128.666666666667 + }, + { + "gid": 79, + "height": 32, + "id": 13, + "name": "name: tile", + "rotation": 0, + "type": "tile", + "visible": true, + "width": 32, + "x": 111.898147095601, + "y": 48.3019211094691 + }, + { + "gid": 80, + "height": 32, + "id": 14, + "name": "name: tile - invisible", + "rotation": 0, + "type": "tile", + "visible": false, + "width": 32, + "x": 41.1831306127089, + "y": 168.779356598841 + }, + { + "gid": 2147483742, + "height": 32, + "id": 15, + "name": "name: tile - horizontal flipped", + "rotation": 0, + "type": "tile", + "visible": true, + "width": 32, + "x": 197.236330567239, + "y": 59.8695009662385 + }, + { + "gid": 1073741918, + "height": 32, + "id": 16, + "name": "name: tile - vertical flipped", + "rotation": 0, + "type": "tile", + "visible": true, + "width": 32, + "x": 32.4528816642037, + "y": 60.742525861089 + }, + { + "gid": 3221225558, + "height": 32, + "id": 17, + "name": "name: tile - both flipped", + "rotation": 0, + "type": "tile", + "visible": true, + "width": 32, + "x": 167.553484142321, + "y": 95.6635216551097 + }, + { + "gid": 86, + "height": 32, + "id": 18, + "name": "name: tile - rotated", + "rotation": 89, + "type": "tile", + "visible": true, + "width": 32, + "x": 85.65, + "y": 142.62 + }, + { + "height": 19, + "id": 19, + "name": "name: text", + "rotation": 0, + "text": { + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 81.7106470956008, + "y": 93.2986813686484 + }, + { + "height": 19, + "id": 20, + "name": "name: text - invisible", + "rotation": 0, + "text": { + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": false, + "width": 92.375, + "x": 8.37655592815732, + "y": 112.068716607935 + }, + { + "height": 19, + "id": 21, + "name": "name: text - rotated", + "rotation": 19, + "text": { + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 157.882069171308, + "y": 78.4572581561896 + }, + { + "height": 19, + "id": 22, + "name": "name: text - different font", + "rotation": 0, + "text": { + "bold": true, + "fontfamily": "DejaVu Sans", + "pixelsize": 19, + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 2.70189411162896, + "y": 101.592417869728 + }, + { + "height": 19, + "id": 23, + "name": "name: text - no word wrap", + "rotation": 0, + "text": { + "text": "Hello World" + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 9.90434949414573, + "y": 154.192167784472 + }, + { + "height": 19, + "id": 24, + "name": "name: text - right bottom align", + "rotation": 0, + "text": { + "halign": "right", + "text": "Hello World", + "valign": "bottom", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 151.989151131067, + "y": 1.19455496191883 + }, + { + "height": 19, + "id": 25, + "name": "text: center center align", + "rotation": 0, + "text": { + "halign": "center", + "text": "Hello World", + "valign": "center", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 4.22968767761736, + "y": 3.81362964647039 + }, + { + "height": 19, + "id": 26, + "name": "name: text - justified", + "rotation": 0, + "text": { + "halign": "justify", + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 13.8329615209731, + "y": 60.7785040354666 + }, + { + "height": 19, + "id": 27, + "name": "name: text - red", + "rotation": 0, + "text": { + "color": "#aa0000", + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 96.3338140843469, + "y": 130.620495623508 + }, + { + "height": 0, + "id": 28, + "name": "name: rectangle - no width or height", + "rotation": 0, + "type": "rectangle", + "visible": true, + "width": 0, + "x": 131.17199045129, + "y": 53.4727748095942 + }, + { + "ellipse": true, + "height": 0, + "id": 29, + "name": "name: ellipse - no width or height", + "rotation": 0, + "type": "ellipse", + "visible": true, + "width": 0, + "x": 72.4610662725929, + "y": 127.679890871888 + }, + { + "height": 13.7501420938956, + "id": 30, + "name": "name: rectangle - properties", + "properties": [ + { + "name": "bool property", + "type": "bool", + "value": false + }, + { + "name": "color property", + "type": "color", + "value": "#ffaa0000" + }, + { + "name": "file property", + "type": "file", + "value": "../../../../../../dev/null" + }, + { + "name": "float property", + "type": "float", + "value": 42.1 + }, + { + "name": "int property", + "type": "int", + "value": 8675309 + }, + { + "name": "string property", + "type": "string", + "value": "pytiled_parser rulez!1!!" + } + ], + "rotation": 0, + "type": "rectangle", + "visible": true, + "width": 21.170853700125, + "x": 39.0678640445606, + "y": 131.826759122428 + } + ], + "opacity": 1, + "type": "objectgroup", + "visible": true, + "x": 0, + "y": 0 + } + ], + "nextlayerid": 3, + "nextobjectid": 33, + "orientation": "orthogonal", + "renderorder": "right-down", + "tiledversion": "1.3.5", + "tileheight": 32, + "tilesets": [ + { + "firstgid": 1, + "source": "../../old_tests/test_data/tile_set_image_objects.tsx" + }, + { + "firstgid": 49, + "source": "../../old_tests/test_data/tile_set_image.tsx" + } + ], + "tilewidth": 32, + "type": "map", + "version": 1.2, + "width": 8 +} From 6f683adc5e047481d82b8c52b336dd1727ddd60a Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 30 May 2020 22:50:22 -0400 Subject: [PATCH 022/198] tests: added missing ellipse test, implemented text tests --- tests/test_tiled_object.py | 318 ++++++++++++++++++++++++++++++++++++- 1 file changed, 317 insertions(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 2702384..5f595de 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -82,6 +82,30 @@ ELLIPSES = [ coordinates=common_types.OrderedPair(35.7940206888712, 120.040923041946), ), ), + ( + """ + { + "ellipse":true, + "height":0, + "id":29, + "name":"name: ellipse - no width or height", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":0, + "x":72.4610662725929, + "y":127.679890871888 + } + """, + tiled_object.Ellipse( + id_=29, + name="name: ellipse - no width or height", + rotation=0, + type="ellipse", + visible=True, + coordinates=common_types.OrderedPair(72.4610662725929, 127.679890871888), + ), + ), ] RECTANGLES = [ @@ -576,7 +600,299 @@ POLYLINES = [ ), ] -TEXTS = [] +TEXTS = [ + ( + """ + { + "height":19, + "id":19, + "name":"name: text", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":81.7106470956008, + "y":93.2986813686484 + } + """, + tiled_object.Text( + id_=19, + name="name: text", + text="Hello World", + type="text", + wrap=True, + rotation=0, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(81.7106470956008, 93.2986813686484), + ), + ), + ( + """ + { + "height":19, + "id":20, + "name":"name: text - invisible", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":false, + "width":92.375, + "x":8.37655592815732, + "y":112.068716607935 + } + """, + tiled_object.Text( + id_=20, + name="name: text - invisible", + text="Hello World", + wrap=True, + type="text", + rotation=0, + visible=False, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(8.37655592815732, 112.068716607935), + ), + ), + ( + """ + { + "height":19, + "id":21, + "name":"name: text - rotated", + "rotation":19, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":157.882069171308, + "y":78.4572581561896 + } + """, + tiled_object.Text( + id_=21, + name="name: text - rotated", + text="Hello World", + wrap=True, + rotation=19, + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(157.882069171308, 78.4572581561896), + ), + ), + ( + """ + { + "height":19, + "id":22, + "name":"name: text - different font", + "rotation":0, + "text": + { + "bold":true, + "fontfamily":"DejaVu Sans", + "pixelsize":19, + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":2.70189411162896, + "y":101.592417869728 + } + """, + tiled_object.Text( + id_=22, + name="name: text - different font", + text="Hello World", + wrap=True, + bold=True, + font_family="DejaVu Sans", + font_size=19, + rotation=0, + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(2.70189411162896, 101.592417869728), + ), + ), + ( + """ + { + "height":19, + "id":23, + "name":"name: text - no word wrap", + "rotation":0, + "text": + { + "text":"Hello World" + }, + "type":"text", + "visible":true, + "width":92.375, + "x":9.90434949414573, + "y":154.192167784472 + } + """, + tiled_object.Text( + id_=23, + name="name: text - no word wrap", + text="Hello World", + rotation=0, + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(9.90434949414573, 154.192167784472), + ), + ), + ( + """ + { + "height":19, + "id":24, + "name":"name: text - right bottom align", + "rotation":0, + "text": + { + "halign":"right", + "text":"Hello World", + "valign":"bottom", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":151.989151131067, + "y":1.19455496191883 + } + """, + tiled_object.Text( + id_=24, + name="name: text - right bottom align", + text="Hello World", + wrap=True, + horizontal_align="right", + vertical_align="bottom", + rotation=0, + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(151.989151131067, 1.19455496191883), + ), + ), + ( + """ + { + "height": 19, + "id": 25, + "name": "text: center center align", + "rotation": 0, + "text": { + "halign": "center", + "text": "Hello World", + "valign": "center", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 4.22968767761736, + "y": 3.81362964647039 + } + """, + tiled_object.Text( + id_=25, + name="text: center center align", + rotation=0, + text="Hello World", + wrap=True, + horizontal_align="center", + vertical_align="center", + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(4.22968767761736, 3.81362964647039), + ), + ), + ( + """ + { + "height": 19, + "id": 26, + "name": "name: text - justified", + "rotation": 0, + "text": { + "halign": "justify", + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 13.8329615209731, + "y": 60.7785040354666 + } + """, + tiled_object.Text( + id_=26, + name="name: text - justified", + rotation=0, + text="Hello World", + wrap=True, + horizontal_align="justify", + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(13.8329615209731, 60.7785040354666), + ), + ), + ( + """ + { + "height": 19, + "id": 27, + "name": "name: text - red", + "rotation": 0, + "text": { + "color": "#aa0000", + "text": "Hello World", + "wrap": true + }, + "type": "text", + "visible": true, + "width": 92.375, + "x": 96.3338140843469, + "y": 130.620495623508 + } + """, + tiled_object.Text( + id_=27, + name="name: text - red", + rotation=0, + text="Hello World", + wrap=True, + color="#aa0000", + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(96.3338140843469, 130.620495623508), + ), + ), +] OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILE_IMAGES + POLYGONS + POLYLINES + TEXTS From b5dee95bbd4a1e619b2f46eba86191ad48b3bc71 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 22:51:47 -0400 Subject: [PATCH 023/198] tests: load json before passing to caster --- tests/test_tiled_object.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 71a221f..7c3805b 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1,4 +1,5 @@ """Tests for objects""" +import json from contextlib import ExitStack as does_not_raise from pathlib import Path @@ -738,8 +739,9 @@ TEXTS = [] OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILE_IMAGES + POLYGONS + POLYLINES + TEXTS -@pytest.mark.parametrize("raw_object,expected", OBJECTS) -def test_parse_layer(raw_object, expected): +@pytest.mark.parametrize("raw_object_json,expected", OBJECTS) +def test_parse_layer(raw_object_json, expected): + raw_object = json.loads(raw_object_json) result = tiled_object._cast_tiled_object(raw_object) assert result == expected From 7d9330868866da6995d5ae41b55142e6dfb6299a Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 22:52:08 -0400 Subject: [PATCH 024/198] chore: add typing-extensions to requirements --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index dbf7dfa..d610893 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,6 +27,7 @@ setup_requires = pip >= 10 install_requires = attrs + typing-extensions [options.extras_require] tests = From 5c98e374f84db15a9650e1ff9283385ef30f533c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 23:27:57 -0400 Subject: [PATCH 025/198] rf(common_types): int is implied by float --- pytiled_parser/common_types.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index 9d88004..41c03f3 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -22,8 +22,8 @@ class Size(NamedTuple): height: The height of the object. """ - width: Union[int, float] - height: Union[int, float] + width: float + height: float class OrderedPair(NamedTuple): @@ -34,5 +34,5 @@ class OrderedPair(NamedTuple): y: Y coordinate. """ - x: Union[int, float] - y: Union[int, float] + x: float + y: float From 6bbb739bec7314eb1fa9e4766f7f4a44b84f01f1 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 23:57:14 -0400 Subject: [PATCH 026/198] tests: fix missing visibility attribute --- tests/test_tiled_object.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 5530d73..cb78949 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -785,6 +785,7 @@ TEXTS = [ type="text", wrap=True, rotation=0, + visible=True, size=common_types.Size(92.375, 19), coordinates=common_types.OrderedPair(81.7106470956008, 93.2986813686484), ), From b6812e56b55de9bf110fbb1cde7f17dcc00d822e Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 30 May 2020 23:58:34 -0400 Subject: [PATCH 027/198] wip: ellipse casting --- pytiled_parser/tiled_object.py | 105 +++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 0aff80b..425a344 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -1,8 +1,9 @@ # pylint: disable=too-few-public-methods -from typing import Callable, Dict, List, Optional, Union +from typing import Callable, Dict, List, Mapping, Optional, Union import attr +from typing_extensions import TypedDict from .common_types import OrderedPair, Size from .properties import Properties @@ -149,41 +150,121 @@ class Tile(TiledObject): gid: int -RawProperties = Dict[str, Union[str, int, float, bool]] +RawProperties = Dict[str, Union[str, float, bool]] -RawTiledObject = Dict[str, Union[str, int, float, bool, RawProperties]] +class RawTiledObject(TypedDict): + """ The keys and their types that appear in a Tiled JSON Object.""" + + id: int + gid: int + x: float + y: float + width: float + height: float + rotation: float + opacity: float + visible: bool + name: str + type: str + properties: Properties + template: Template RawTiledObjects = List[RawTiledObject] +def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: + """ Create a TiledObject containing all the attributes common to all tiled objects + + Args: + raw_tiled_object: Raw Tiled object get common attributes from + + Returns: + TiledObject: The attributes in common of all Tiled Objects + """ + + # required attributes + id_ = raw_tiled_object["id"] + coordinates = OrderedPair(x=raw_tiled_object["x"], y=raw_tiled_object["y"]) + visible = raw_tiled_object["visible"] + + common_attributes = TiledObject(id_=id_, coordinates=coordinates, visible=visible) + + # optional attributes + if any([raw_tiled_object.get("x"), raw_tiled_object.get("y")]): + # we have to check if either are truthy before we proceed to create Size + x: Union[int, float] + _x = raw_tiled_object.get("x") + if _x: + x = _x + else: + x = 0 + + y: Union[int, float] + _y = raw_tiled_object.get("y") + if _y: + y = _y + else: + y = 0 + + common_attributes.size = Size(x, y) + + if raw_tiled_object.get("rotation"): + common_attributes.rotation = raw_tiled_object["rotation"] + + if raw_tiled_object.get("opacity"): + common_attributes.opacity = raw_tiled_object["opacity"] + + if raw_tiled_object.get("name"): + common_attributes.name = raw_tiled_object["name"] + + if raw_tiled_object.get("type"): + common_attributes.name = raw_tiled_object["type"] + + if raw_tiled_object.get("properties"): + raise NotImplementedError + + if raw_tiled_object.get("template"): + raise NotImplementedError + + return common_attributes + + def _cast_ellipse(raw_tiled_object: RawTiledObject) -> Ellipse: - pass + """ Cast the raw_tiled_object to an Ellipse object. + + Args: + raw_tiled_object: Raw Tiled object to be casted to an Ellipse + + Returns: + Ellipse: The Ellipse object created from the raw_tiled_object + """ + return Ellipse(**_get_common_attributes(raw_tiled_object).__dict__) def _cast_rectangle(raw_tiled_object: RawTiledObject) -> Rectangle: - pass + raise NotImplementedError def _cast_point(raw_tiled_object: RawTiledObject) -> Point: - pass + raise NotImplementedError def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile: - pass + raise NotImplementedError def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: - pass + raise NotImplementedError def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: - pass + raise NotImplementedError def _cast_text(raw_tiled_object: RawTiledObject) -> Text: - pass + raise NotImplementedError def _get_tiled_object_caster( @@ -198,6 +279,10 @@ def _get_tiled_object_caster( Returns: Callable[[RawTiledObject], TiledObject]: The caster function. """ + if raw_tiled_object.get("ellipse"): + return _cast_ellipse + + raise RuntimeError("No caster found for TiledObject") def _cast_tiled_object(raw_tiled_object: RawTiledObject) -> TiledObject: From 8b4b2eb4fd7c59d346db59fb28e6c9ee7d74056f Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 00:26:53 -0400 Subject: [PATCH 028/198] fix: ellipse name = type --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 425a344..6e50c2f 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -220,7 +220,7 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: common_attributes.name = raw_tiled_object["name"] if raw_tiled_object.get("type"): - common_attributes.name = raw_tiled_object["type"] + common_attributes.type = raw_tiled_object["type"] if raw_tiled_object.get("properties"): raise NotImplementedError From 2fc4a44831816d2fea678af045756fed709eda31 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 00:28:03 -0400 Subject: [PATCH 029/198] rf: id attributes of objects is now `id` --- pytiled_parser/tiled_object.py | 26 +++++++------- tests/test_tiled_object.py | 64 +++++++++++++++++----------------- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 6e50c2f..fe1b711 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -32,7 +32,7 @@ class TiledObject: template: A reference to a Template tiled object FIXME """ - id_: int + id: int gid: Optional[int] = None coordinates: OrderedPair @@ -189,26 +189,24 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: coordinates = OrderedPair(x=raw_tiled_object["x"], y=raw_tiled_object["y"]) visible = raw_tiled_object["visible"] - common_attributes = TiledObject(id_=id_, coordinates=coordinates, visible=visible) + common_attributes = TiledObject(id=id_, coordinates=coordinates, visible=visible) # optional attributes - if any([raw_tiled_object.get("x"), raw_tiled_object.get("y")]): + if any([raw_tiled_object.get("width"), raw_tiled_object.get("height")]): # we have to check if either are truthy before we proceed to create Size - x: Union[int, float] - _x = raw_tiled_object.get("x") - if _x: - x = _x + _width = raw_tiled_object.get("width") + if _width: + width = _width else: - x = 0 + width = 0 - y: Union[int, float] - _y = raw_tiled_object.get("y") - if _y: - y = _y + _height = raw_tiled_object.get("height") + if _height: + height = _height else: - y = 0 + height = 0 - common_attributes.size = Size(x, y) + common_attributes.size = Size(width, height) if raw_tiled_object.get("rotation"): common_attributes.rotation = raw_tiled_object["rotation"] diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index cb78949..26624c7 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -24,7 +24,7 @@ ELLIPSES = [ } """, tiled_object.Ellipse( - id_=6, + id=6, size=common_types.Size(57.4013868364215, 18.5517790155735), name="name: ellipse", rotation=0, @@ -49,7 +49,7 @@ ELLIPSES = [ } """, tiled_object.Ellipse( - id_=7, + id=7, size=common_types.Size(6.32943048766625, 31.4288962146186), name="name: ellipse - invisible", rotation=0, @@ -74,7 +74,7 @@ ELLIPSES = [ } """, tiled_object.Ellipse( - id_=8, + id=8, size=common_types.Size(29.6828464249176, 24.2264408321018), name="name: ellipse - rotated", rotation=111, @@ -99,7 +99,7 @@ ELLIPSES = [ } """, tiled_object.Ellipse( - id_=29, + id=29, name="name: ellipse - no width or height", rotation=0, type="ellipse", @@ -125,7 +125,7 @@ RECTANGLES = [ } """, tiled_object.Rectangle( - id_=1, + id=1, size=common_types.Size(45.3972945322269, 41.4686825053996), name="name: rectangle", rotation=0, @@ -149,7 +149,7 @@ RECTANGLES = [ } """, tiled_object.Rectangle( - id_=4, + id=4, size=common_types.Size(30.9923837671934, 32.7384335568944), name="name: rectangle - invisible", rotation=0, @@ -173,7 +173,7 @@ RECTANGLES = [ }, """, tiled_object.Rectangle( - id_=5, + id=5, size=common_types.Size(10, 22), name="name: rectangle - rotated", rotation=10, @@ -197,7 +197,7 @@ RECTANGLES = [ } """, tiled_object.Rectangle( - id_=28, + id=28, size=common_types.Size(0, 0), name="name: rectangle - no width or height", rotation=0, @@ -252,7 +252,7 @@ RECTANGLES = [ } """, tiled_object.Rectangle( - id_=30, + id=30, size=common_types.Size(21.170853700125, 13.7501420938956), name="name: rectangle - properties", rotation=0, @@ -288,7 +288,7 @@ POINTS = [ } """, tiled_object.Point( - id_=2, + id=2, name="name: point", rotation=0, type="point", @@ -312,7 +312,7 @@ POINTS = [ } """, tiled_object.Point( - id_=3, + id=3, name="name:name: point invisible", rotation=0, type="point", @@ -339,7 +339,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=13, + id=13, size=common_types.Size(32, 32), name="name: tile", rotation=0, @@ -365,7 +365,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=14, + id=14, size=common_types.Size(32, 32), name="name: tile - invisible", rotation=0, @@ -391,7 +391,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=15, + id=15, size=common_types.Size(32, 32), name="name: tile - horizontal flipped", rotation=0, @@ -417,7 +417,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=16, + id=16, size=common_types.Size(32, 32), name="name: tile - vertical flipped", rotation=0, @@ -443,7 +443,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=17, + id=17, size=common_types.Size(32, 32), name="name: tile - both flipped", rotation=0, @@ -469,7 +469,7 @@ TILE_IMAGES = [ } """, tiled_object.Tile( - id_=18, + id=18, size=common_types.Size(32, 32), name="name: tile - rotated", rotation=89, @@ -518,7 +518,7 @@ POLYGONS = [ } """, tiled_object.Polygon( - id_=9, + id=9, name="name: polygon", points=[ common_types.OrderedPair(0, 0), @@ -561,7 +561,7 @@ POLYGONS = [ } """, tiled_object.Polygon( - id_=9, + id=9, name="name: polygon - invisible", points=[ common_types.OrderedPair(0, 0), @@ -614,7 +614,7 @@ POLYGONS = [ } """, tiled_object.Polygon( - id_=9, + id=9, name="name: polygon - rotated", points=[ common_types.OrderedPair(0, 0), @@ -661,7 +661,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id_=9, + id=9, name="name: polyline", points=[ common_types.OrderedPair(0, 0), @@ -702,7 +702,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id_=10, + id=10, name="name: polyline - invisible", points=[ common_types.OrderedPair(0, 0), @@ -743,7 +743,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id_=11, + id=11, name="name: polyline - rotated", points=[ common_types.OrderedPair(0, 0), @@ -779,7 +779,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=19, + id=19, name="name: text", text="Hello World", type="text", @@ -810,7 +810,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=20, + id=20, name="name: text - invisible", text="Hello World", wrap=True, @@ -841,7 +841,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=21, + id=21, name="name: text - rotated", text="Hello World", wrap=True, @@ -875,7 +875,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=22, + id=22, name="name: text - different font", text="Hello World", wrap=True, @@ -908,7 +908,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=23, + id=23, name="name: text - no word wrap", text="Hello World", rotation=0, @@ -940,7 +940,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=24, + id=24, name="name: text - right bottom align", text="Hello World", wrap=True, @@ -974,7 +974,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=25, + id=25, name="text: center center align", rotation=0, text="Hello World", @@ -1007,7 +1007,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=26, + id=26, name="name: text - justified", rotation=0, text="Hello World", @@ -1039,7 +1039,7 @@ TEXTS = [ } """, tiled_object.Text( - id_=27, + id=27, name="name: text - red", rotation=0, text="Hello World", From 69f05476caa90371fde9ff24fece53bc8e6d9765 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 00:29:38 -0400 Subject: [PATCH 030/198] tests: fix: invisible ellipse fixed test --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 26624c7..c7b677e 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -54,7 +54,7 @@ ELLIPSES = [ name="name: ellipse - invisible", rotation=0, type="ellipse", - visible=True, + visible=False, coordinates=common_types.OrderedPair(22.6986472661134, 53.9092872570194), ), ), From 16bee5191dc5dcb95228204b24e112a86ae18a65 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 00:45:47 -0400 Subject: [PATCH 031/198] Implemented Point, Rectangle, and Polygon casters --- pytiled_parser/tiled_object.py | 36 +++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index fe1b711..129793f 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -169,6 +169,7 @@ class RawTiledObject(TypedDict): type: str properties: Properties template: Template + polygon: List[Dict] RawTiledObjects = List[RawTiledObject] @@ -242,11 +243,27 @@ def _cast_ellipse(raw_tiled_object: RawTiledObject) -> Ellipse: def _cast_rectangle(raw_tiled_object: RawTiledObject) -> Rectangle: - raise NotImplementedError + """ Cast the raw_tiled_object to a Rectangle object. + + Args: + raw_tiled_object: Raw Tiled object to be casted to a Rectangle + + Returns: + Rectangle: The Rectangle object created from the raw_tiled_object + """ + return Rectangle(**_get_common_attributes(raw_tiled_object).__dict__) def _cast_point(raw_tiled_object: RawTiledObject) -> Point: - raise NotImplementedError + """ Cast the raw_tiled_object to a Point object. + + Args: + raw_tiled_object: Raw Tiled object to be casted to a Point + + Returns: + Point: The Point object created from the raw_tiled_object + """ + return Point(**_get_common_attributes(raw_tiled_object).__dict__) def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile: @@ -254,7 +271,20 @@ def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile: def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: - raise NotImplementedError + """ Cast the raw_tiled_object to a Polygon object. + + Args: + raw_tiled_object: Raw Tiled object to be casted to a Polygon + + Returns: + Polygon: The Polygon object created from the raw_tiled_object + """ + polygon = [] + if raw_tiled_object.get("polygon"): + for point in raw_tiled_object["polygon"]: + polygon.append(OrderedPair(point["x"], point["y"])) + + return Polygon(**_get_common_attributes(raw_tiled_object).__dict__, points=polygon) def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: From 3d6068cc71eb684896e89b90d15bab51e73e8d63 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 00:46:00 -0400 Subject: [PATCH 032/198] rf: remove gid from TiledObject it only appears in the Tile object --- pytiled_parser/tiled_object.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index fe1b711..e314a05 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -33,7 +33,6 @@ class TiledObject: """ id: int - gid: Optional[int] = None coordinates: OrderedPair size: Size = Size(0, 0) From 798e186947d2b4913e0685596e36c57cdd928624 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 00:46:33 -0400 Subject: [PATCH 033/198] add: _get_tiled_object_caster --- pytiled_parser/tiled_object.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index e314a05..75b0cb4 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -168,6 +168,8 @@ class RawTiledObject(TypedDict): type: str properties: Properties template: Template + ellipse: bool + point: bool RawTiledObjects = List[RawTiledObject] @@ -279,6 +281,22 @@ def _get_tiled_object_caster( if raw_tiled_object.get("ellipse"): return _cast_ellipse + if raw_tiled_object.get("point"): + return _cast_point + + if raw_tiled_object.get("gid"): + # Only Tile objects have the `gid` key (I think) + return _cast_tile + + if raw_tiled_object.get("polygon"): + return _cast_polygon + + if raw_tiled_object.get("polyline"): + return _cast_polyline + + if raw_tiled_object.get("text"): + return _cast_text + raise RuntimeError("No caster found for TiledObject") From d06525d8f20c236191bab4eb91101558c69f2780 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:00:42 -0400 Subject: [PATCH 034/198] fix(tiled_object): move kwarg to prior to dict unpacking --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 11a2efc..e0b1f39 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -285,7 +285,7 @@ def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: for point in raw_tiled_object["polygon"]: polygon.append(OrderedPair(point["x"], point["y"])) - return Polygon(**_get_common_attributes(raw_tiled_object).__dict__, points=polygon) + return Polygon(points=polygon, **_get_common_attributes(raw_tiled_object).__dict__) def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: From 51d292bdf197ade75f0c96d4aad2d042ad4b2a3d Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:01:01 -0400 Subject: [PATCH 035/198] add: rectangle caster get --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index e0b1f39..d4d72e5 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -327,7 +327,7 @@ def _get_tiled_object_caster( if raw_tiled_object.get("text"): return _cast_text - raise RuntimeError("No caster found for TiledObject") + return _cast_rectangle def _cast_tiled_object(raw_tiled_object: RawTiledObject) -> TiledObject: From 74b563621b3ab704dac3e4c18d25f223d0096756 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:02:39 -0400 Subject: [PATCH 036/198] tests: json is retarded --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index c7b677e..f0d5fda 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -170,7 +170,7 @@ RECTANGLES = [ "width":10, "x":183.335227918609, "y":23.3534159372513 - }, + } """, tiled_object.Rectangle( id=5, From a82ae5e45b341efd3360387d14ad4003d02009b0 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:11:06 -0400 Subject: [PATCH 037/198] tests: s/TILE_IMAGES/TILES --- tests/test_tiled_object.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index f0d5fda..a36636b 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -322,7 +322,7 @@ POINTS = [ ), ] -TILE_IMAGES = [ +TILES = [ ( """ { @@ -1053,7 +1053,7 @@ TEXTS = [ ), ] -OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILE_IMAGES + POLYGONS + POLYLINES + TEXTS +OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILES + POLYGONS + POLYLINES + TEXTS @pytest.mark.parametrize("raw_object_json,expected", OBJECTS) From 77d67425144538d64092ef93c9fc28fff387f3b0 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:13:07 -0400 Subject: [PATCH 038/198] add: Tile caster --- pytiled_parser/tiled_object.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index d4d72e5..6d864e1 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -268,7 +268,9 @@ def _cast_point(raw_tiled_object: RawTiledObject) -> Point: def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile: - raise NotImplementedError + gid = raw_tiled_object["gid"] + + return Tile(gid=gid, **_get_common_attributes(raw_tiled_object).__dict__) def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: From 820fb9c2a58a04c8a93f92ebde3d101a9928e287 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 01:15:22 -0400 Subject: [PATCH 039/198] fix: Removed redundant checking of polygon in caster --- pytiled_parser/tiled_object.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index d4d72e5..79f1747 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -281,9 +281,8 @@ def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: Polygon: The Polygon object created from the raw_tiled_object """ polygon = [] - if raw_tiled_object.get("polygon"): - for point in raw_tiled_object["polygon"]: - polygon.append(OrderedPair(point["x"], point["y"])) + for point in raw_tiled_object["polygon"]: + polygon.append(OrderedPair(point["x"], point["y"])) return Polygon(points=polygon, **_get_common_attributes(raw_tiled_object).__dict__) From 7437bf5687c93f8416ef638d216f5a2e5efc5209 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 01:15:48 -0400 Subject: [PATCH 040/198] fix: Mypy error on polygon type in RawTiledObject --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 79f1747..4714ef2 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -170,7 +170,7 @@ class RawTiledObject(TypedDict): template: Template ellipse: bool point: bool - polygon: List[Dict] + polygon: List[Dict[str, float]] RawTiledObjects = List[RawTiledObject] From c41599f4d690dc0c7caf1870016a30f97a3c6484 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:24:43 -0400 Subject: [PATCH 041/198] rf: use color for text --- pytiled_parser/tiled_object.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index ca74e6b..c83fe12 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -5,7 +5,7 @@ from typing import Callable, Dict, List, Mapping, Optional, Union import attr from typing_extensions import TypedDict -from .common_types import OrderedPair, Size +from .common_types import Color, OrderedPair, Size from .properties import Properties from .template import Template @@ -126,7 +126,7 @@ class Text(TiledObject): font_family: str = "sans-serif" font_size: int = 16 wrap: bool = False - color: str = "#000000" + color: Color = "#000000" bold: bool = False italic: bool = False underline: bool = False From db51136ca9a93d17fac61b1c2e7fdae717849b72 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:24:55 -0400 Subject: [PATCH 042/198] add: types to RawTiledObject --- pytiled_parser/tiled_object.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index c83fe12..58578e9 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -171,6 +171,8 @@ class RawTiledObject(TypedDict): ellipse: bool point: bool polygon: List[Dict[str, float]] + polyline: List[Dict[str, float]] + text: Dict[str, Union[float, str]] RawTiledObjects = List[RawTiledObject] From 4ba6d2eac778fb0aca788540e018ae502b264a45 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:33:15 -0400 Subject: [PATCH 043/198] tests: add font options text object --- tests/test_data/simple_objects.json | 1214 +++++++++++++-------------- 1 file changed, 569 insertions(+), 645 deletions(-) diff --git a/tests/test_data/simple_objects.json b/tests/test_data/simple_objects.json index dbf407c..d793304 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/simple_objects.json @@ -1,649 +1,573 @@ -{ - "compressionlevel": 0, - "editorsettings": { - "export": { - "target": "." - } - }, - "height": 6, - "infinite": false, - "layers": [ +{ "compressionlevel":0, + "editorsettings": { - "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 - ], - "height": 6, - "id": 1, - "name": "Tile Layer 1", - "opacity": 1, - "type": "tilelayer", - "visible": true, - "width": 8, - "x": 0, - "y": 0 - }, - { - "draworder": "topdown", - "id": 2, - "name": "Object Layer 1", - "objects": [ + "export": { - "height": 41.4686825053996, - "id": 1, - "name": "name: rectangle", - "rotation": 0, - "type": "rectangle", - "visible": true, - "width": 45.3972945322269, - "x": 27.7185404115039, - "y": 23.571672160964 - }, - { - "height": 0, - "id": 2, - "name": "name: point", - "point": true, - "rotation": 0, - "type": "point", - "visible": true, - "width": 0, - "x": 159.981811981357, - "y": 82.9373650107991 - }, - { - "height": 0, - "id": 3, - "name": "name: point invisible", - "point": true, - "rotation": 0, - "type": "point", - "visible": false, - "width": 0, - "x": 109.346368080027, - "y": 95.8144822098443 - }, - { - "height": 32.7384335568944, - "id": 4, - "name": "name: rectangle - invisible", - "rotation": 0, - "type": "rectangle", - "visible": false, - "width": 30.9923837671934, - "x": 163.910424008185, - "y": 91.0128452881664 - }, - { - "height": 22, - "id": 5, - "name": "name: rectangle - rotated", - "rotation": 10, - "type": "rectangle", - "visible": true, - "width": 10, - "x": 183.335227918609, - "y": 23.3534159372513 - }, - { - "ellipse": true, - "height": 18.5517790155735, - "id": 6, - "name": "name: ellipse", - "rotation": 0, - "type": "ellipse", - "visible": true, - "width": 57.4013868364215, - "x": 37.5400704785722, - "y": 81.1913152210981 - }, - { - "ellipse": true, - "height": 31.4288962146186, - "id": 7, - "name": "name: ellipse - invisible", - "rotation": 0, - "type": "ellipse", - "visible": false, - "width": 6.32943048766625, - "x": 22.6986472661134, - "y": 53.9092872570194 - }, - { - "ellipse": true, - "height": 24.2264408321018, - "id": 8, - "name": "name: ellipse - rotated", - "rotation": 111, - "type": "ellipse", - "visible": true, - "width": 29.6828464249176, - "x": 35.7940206888712, - "y": 120.040923041946 - }, - { - "height": 0, - "id": 9, - "name": "name: polygon", - "polygon": [ - { - "x": 0, - "y": 0 - }, - { - "x": 19.424803910424, - "y": 27.063771740366 - }, - { - "x": 19.6430601341366, - "y": 3.05558713197681 - }, - { - "x": -2.61907468455156, - "y": 15.9327043310219 - }, - { - "x": 25.317721950665, - "y": 16.3692167784472 - } - ], - "rotation": 0, - "type": "polygon", - "visible": true, - "width": 0, - "x": 89.485051722178, - "y": 38.6313515971354 - }, - { - "height": 0, - "id": 10, - "name": "name: polygon - invisible", - "polygon": [ - { - "x": 0, - "y": 0 - }, - { - "x": -12.8771171990451, - "y": 7.63896782994203 - }, - { - "x": -14.8414232124588, - "y": -10.2580425144936 - } - ], - "rotation": 0, - "type": "polygon", - "visible": false, - "width": 0, - "x": 133.791065135842, - "y": 24.4446970558145 - }, - { - "height": 0, - "id": 11, - "name": "name: polygon - rotated", - "polygon": [ - { - "x": 0, - "y": 0 - }, - { - "x": -12.8771171990451, - "y": 0 - }, - { - "x": -6.98419915880413, - "y": 7.63896782994203 - }, - { - "x": -13.9683983176083, - "y": 16.8057292258725 - }, - { - "x": 3.71035580311468, - "y": 15.277935659884 - }, - { - "x": -3.71035580311471, - "y": 8.29373650107991 - } - ], - "rotation": 123, - "type": "polygon", - "visible": true, - "width": 0, - "x": 152.779356598841, - "y": 19.8613163578493 - }, - { - "height": 0, - "id": 12, - "name": "name: polyline", - "polyline": [ - { - "x": 0, - "y": 0 - }, - { - "x": -13.3136296464704, - "y": 41.0321700579743 - }, - { - "x": 21.3891099238377, - "y": 16.8057292258725 - } - ], - "rotation": 0, - "type": "polyline", - "visible": true, - "width": 0, - "x": 124.187791292486, - "y": 90.1398203933159 - }, - { - "height": 0, - "id": 31, - "name": "name: polyline - invisible", - "polyline": [ - { - "x": 0, - "y": 0 - }, - { - "x": -9, - "y": 20.3333333333333 - }, - { - "x": 5, - "y": 23.6666666666667 - } - ], - "rotation": 0, - "type": "polyline", - "visible": false, - "width": 0, - "x": 140, - "y": 163.333333333333 - }, - { - "height": 0, - "id": 32, - "name": "name: polyline - rotated", - "polyline": [ - { - "x": 0, - "y": 0 - }, - { - "x": 10.3333333333333, - "y": 13 - }, - { - "x": -5.33333333333331, - "y": 19.6666666666667 - } - ], - "rotation": 0, - "type": "polyline", - "visible": true, - "width": 0, - "x": 192.333333333333, - "y": 128.666666666667 - }, - { - "gid": 79, - "height": 32, - "id": 13, - "name": "name: tile", - "rotation": 0, - "type": "tile", - "visible": true, - "width": 32, - "x": 111.898147095601, - "y": 48.3019211094691 - }, - { - "gid": 80, - "height": 32, - "id": 14, - "name": "name: tile - invisible", - "rotation": 0, - "type": "tile", - "visible": false, - "width": 32, - "x": 41.1831306127089, - "y": 168.779356598841 - }, - { - "gid": 2147483742, - "height": 32, - "id": 15, - "name": "name: tile - horizontal flipped", - "rotation": 0, - "type": "tile", - "visible": true, - "width": 32, - "x": 197.236330567239, - "y": 59.8695009662385 - }, - { - "gid": 1073741918, - "height": 32, - "id": 16, - "name": "name: tile - vertical flipped", - "rotation": 0, - "type": "tile", - "visible": true, - "width": 32, - "x": 32.4528816642037, - "y": 60.742525861089 - }, - { - "gid": 3221225558, - "height": 32, - "id": 17, - "name": "name: tile - both flipped", - "rotation": 0, - "type": "tile", - "visible": true, - "width": 32, - "x": 167.553484142321, - "y": 95.6635216551097 - }, - { - "gid": 86, - "height": 32, - "id": 18, - "name": "name: tile - rotated", - "rotation": 89, - "type": "tile", - "visible": true, - "width": 32, - "x": 85.65, - "y": 142.62 - }, - { - "height": 19, - "id": 19, - "name": "name: text", - "rotation": 0, - "text": { - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 81.7106470956008, - "y": 93.2986813686484 - }, - { - "height": 19, - "id": 20, - "name": "name: text - invisible", - "rotation": 0, - "text": { - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": false, - "width": 92.375, - "x": 8.37655592815732, - "y": 112.068716607935 - }, - { - "height": 19, - "id": 21, - "name": "name: text - rotated", - "rotation": 19, - "text": { - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 157.882069171308, - "y": 78.4572581561896 - }, - { - "height": 19, - "id": 22, - "name": "name: text - different font", - "rotation": 0, - "text": { - "bold": true, - "fontfamily": "DejaVu Sans", - "pixelsize": 19, - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 2.70189411162896, - "y": 101.592417869728 - }, - { - "height": 19, - "id": 23, - "name": "name: text - no word wrap", - "rotation": 0, - "text": { - "text": "Hello World" - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 9.90434949414573, - "y": 154.192167784472 - }, - { - "height": 19, - "id": 24, - "name": "name: text - right bottom align", - "rotation": 0, - "text": { - "halign": "right", - "text": "Hello World", - "valign": "bottom", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 151.989151131067, - "y": 1.19455496191883 - }, - { - "height": 19, - "id": 25, - "name": "text: center center align", - "rotation": 0, - "text": { - "halign": "center", - "text": "Hello World", - "valign": "center", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 4.22968767761736, - "y": 3.81362964647039 - }, - { - "height": 19, - "id": 26, - "name": "name: text - justified", - "rotation": 0, - "text": { - "halign": "justify", - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 13.8329615209731, - "y": 60.7785040354666 - }, - { - "height": 19, - "id": 27, - "name": "name: text - red", - "rotation": 0, - "text": { - "color": "#aa0000", - "text": "Hello World", - "wrap": true - }, - "type": "text", - "visible": true, - "width": 92.375, - "x": 96.3338140843469, - "y": 130.620495623508 - }, - { - "height": 0, - "id": 28, - "name": "name: rectangle - no width or height", - "rotation": 0, - "type": "rectangle", - "visible": true, - "width": 0, - "x": 131.17199045129, - "y": 53.4727748095942 - }, - { - "ellipse": true, - "height": 0, - "id": 29, - "name": "name: ellipse - no width or height", - "rotation": 0, - "type": "ellipse", - "visible": true, - "width": 0, - "x": 72.4610662725929, - "y": 127.679890871888 - }, - { - "height": 13.7501420938956, - "id": 30, - "name": "name: rectangle - properties", - "properties": [ - { - "name": "bool property", - "type": "bool", - "value": false - }, - { - "name": "color property", - "type": "color", - "value": "#ffaa0000" - }, - { - "name": "file property", - "type": "file", - "value": "../../../../../../dev/null" - }, - { - "name": "float property", - "type": "float", - "value": 42.1 - }, - { - "name": "int property", - "type": "int", - "value": 8675309 - }, - { - "name": "string property", - "type": "string", - "value": "pytiled_parser rulez!1!!" - } - ], - "rotation": 0, - "type": "rectangle", - "visible": true, - "width": 21.170853700125, - "x": 39.0678640445606, - "y": 131.826759122428 + "target":"." } - ], - "opacity": 1, - "type": "objectgroup", - "visible": true, - "x": 0, - "y": 0 - } - ], - "nextlayerid": 3, - "nextobjectid": 33, - "orientation": "orthogonal", - "renderorder": "right-down", - "tiledversion": "1.3.5", - "tileheight": 32, - "tilesets": [ - { - "firstgid": 1, - "source": "../../old_tests/test_data/tile_set_image_objects.tsx" }, - { - "firstgid": 49, - "source": "../../old_tests/test_data/tile_set_image.tsx" - } - ], - "tilewidth": 32, - "type": "map", - "version": 1.2, - "width": 8 -} + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":41.4686825053996, + "id":1, + "name":"name: rectangle", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":45.3972945322269, + "x":27.7185404115039, + "y":23.571672160964 + }, + { + "height":0, + "id":2, + "name":"name: point", + "point":true, + "rotation":0, + "type":"point", + "visible":true, + "width":0, + "x":159.981811981357, + "y":82.9373650107991 + }, + { + "height":0, + "id":3, + "name":"name: point invisible", + "point":true, + "rotation":0, + "type":"point", + "visible":false, + "width":0, + "x":109.346368080027, + "y":95.8144822098443 + }, + { + "height":32.7384335568944, + "id":4, + "name":"name: rectangle - invisible", + "rotation":0, + "type":"rectangle", + "visible":false, + "width":30.9923837671934, + "x":163.910424008185, + "y":91.0128452881664 + }, + { + "height":22, + "id":5, + "name":"name: rectangle - rotated", + "rotation":10, + "type":"rectangle", + "visible":true, + "width":10, + "x":183.335227918609, + "y":23.3534159372513 + }, + { + "ellipse":true, + "height":18.5517790155735, + "id":6, + "name":"name: ellipse", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":57.4013868364215, + "x":37.5400704785722, + "y":81.1913152210981 + }, + { + "ellipse":true, + "height":31.4288962146186, + "id":7, + "name":"name: ellipse - invisible", + "rotation":0, + "type":"ellipse", + "visible":false, + "width":6.32943048766625, + "x":22.6986472661134, + "y":53.9092872570194 + }, + { + "ellipse":true, + "height":24.2264408321018, + "id":8, + "name":"name: ellipse - rotated", + "rotation":111, + "type":"ellipse", + "visible":true, + "width":29.6828464249176, + "x":35.7940206888712, + "y":120.040923041946 + }, + { + "height":0, + "id":9, + "name":"name: polyline", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":19.424803910424, + "y":27.063771740366 + }, + { + "x":19.6430601341366, + "y":3.05558713197681 + }, + { + "x":-2.61907468455156, + "y":15.9327043310219 + }, + { + "x":25.317721950665, + "y":16.3692167784472 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":89.485051722178, + "y":38.6313515971354 + }, + { + "height":0, + "id":10, + "name":"name: polyline - invisible", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":7.63896782994203 + }, + { + "x":-14.8414232124588, + "y":-10.2580425144936 + }], + "rotation":0, + "type":"polyline", + "visible":false, + "width":0, + "x":133.791065135842, + "y":24.4446970558145 + }, + { + "height":0, + "id":11, + "name":"name: polyline - rotated", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-12.8771171990451, + "y":0 + }, + { + "x":-6.98419915880413, + "y":7.63896782994203 + }, + { + "x":-13.9683983176083, + "y":16.8057292258725 + }, + { + "x":3.71035580311468, + "y":15.277935659884 + }, + { + "x":-3.71035580311471, + "y":8.29373650107991 + }], + "rotation":123, + "type":"polyline", + "visible":true, + "width":0, + "x":152.779356598841, + "y":19.8613163578493 + }, + { + "height":0, + "id":12, + "name":"name: polyline - not closed", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-13.3136296464704, + "y":41.0321700579743 + }, + { + "x":21.3891099238377, + "y":16.8057292258725 + }], + "rotation":0, + "type":"polyline", + "visible":true, + "width":0, + "x":124.187791292486, + "y":90.1398203933159 + }, + { + "gid":79, + "height":32, + "id":13, + "name":"name: tile", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":111.898147095601, + "y":48.3019211094691 + }, + { + "gid":80, + "height":32, + "id":14, + "name":"name: tile - invisible", + "rotation":0, + "type":"tile", + "visible":false, + "width":32, + "x":41.1831306127089, + "y":168.779356598841 + }, + { + "gid":2147483742, + "height":32, + "id":15, + "name":"name: tile - horizontal flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":197.236330567239, + "y":59.8695009662385 + }, + { + "gid":1073741918, + "height":32, + "id":16, + "name":"name: tile - vertical flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":32.4528816642037, + "y":60.742525861089 + }, + { + "gid":3221225558, + "height":32, + "id":17, + "name":"name: tile - both flipped", + "rotation":0, + "type":"tile", + "visible":true, + "width":32, + "x":167.553484142321, + "y":95.6635216551097 + }, + { + "gid":86, + "height":32, + "id":18, + "name":"name: tile - rotated", + "rotation":89, + "type":"tile", + "visible":true, + "width":32, + "x":85.65, + "y":142.62 + }, + { + "height":19, + "id":19, + "name":"name: text", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":81.7106470956008, + "y":93.2986813686484 + }, + { + "height":19, + "id":20, + "name":"name: text - invisible", + "rotation":0, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":false, + "width":92.375, + "x":8.37655592815732, + "y":112.068716607935 + }, + { + "height":19, + "id":21, + "name":"name: text - rotated", + "rotation":19, + "text": + { + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":157.882069171308, + "y":78.4572581561896 + }, + { + "height":19, + "id":22, + "name":"name: text - different font", + "rotation":0, + "text": + { + "bold":true, + "fontfamily":"DejaVu Sans", + "pixelsize":19, + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":2.70189411162896, + "y":101.592417869728 + }, + { + "height":19, + "id":23, + "name":"name: text - no word wrap", + "rotation":0, + "text": + { + "text":"Hello World" + }, + "type":"text", + "visible":true, + "width":92.375, + "x":9.90434949414573, + "y":154.192167784472 + }, + { + "height":19, + "id":24, + "name":"name: text - right bottom align", + "rotation":0, + "text": + { + "halign":"right", + "text":"Hello World", + "valign":"bottom", + "wrap":true + }, + "type":"", + "visible":true, + "width":92.375, + "x":151.989151131067, + "y":1.19455496191883 + }, + { + "height":19, + "id":25, + "name":"text: center center align", + "rotation":0, + "text": + { + "halign":"center", + "text":"Hello World", + "valign":"center", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":4.22968767761736, + "y":3.81362964647039 + }, + { + "height":19, + "id":26, + "name":"name: text - justified", + "rotation":0, + "text": + { + "halign":"justify", + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":13.8329615209731, + "y":60.7785040354666 + }, + { + "height":19, + "id":27, + "name":"name: text - red", + "rotation":0, + "text": + { + "color":"#aa0000", + "text":"Hello World", + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":96.3338140843469, + "y":130.620495623508 + }, + { + "height":0, + "id":28, + "name":"name: rectangle - no width or height", + "rotation":0, + "type":"rectangle", + "visible":true, + "width":0, + "x":131.17199045129, + "y":53.4727748095942 + }, + { + "ellipse":true, + "height":0, + "id":29, + "name":"name: ellipse - no width or height", + "rotation":0, + "type":"ellipse", + "visible":true, + "width":0, + "x":72.4610662725929, + "y":127.679890871888 + }, + { + "height":13.7501420938956, + "id":30, + "name":"name: rectangle - properties", + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":false + }, + { + "name":"color property", + "type":"color", + "value":"#ffaa0000" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/dev\/null" + }, + { + "name":"float property", + "type":"float", + "value":42.1 + }, + { + "name":"int property", + "type":"int", + "value":8675309 + }, + { + "name":"string property", + "type":"string", + "value":"pytiled_parser rulez!1!!" + }], + "rotation":0, + "type":"rectangle", + "visible":true, + "width":21.170853700125, + "x":39.0678640445606, + "y":131.826759122428 + }, + { + "height":19, + "id":31, + "name":"name: text - font options", + "rotation":0, + "text": + { + "bold":true, + "italic":true, + "kerning":false, + "strikeout":true, + "text":"Hello World", + "underline":true, + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":33, + "y":22 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":32, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"..\/..\/old_tests\/test_data\/tile_set_image_objects.tsx" + }, + { + "firstgid":49, + "source":"..\/..\/old_tests\/test_data\/tile_set_image.tsx" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} \ No newline at end of file From 4a65ad9622548602a9f259d79af0b3963478c986 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:38:14 -0400 Subject: [PATCH 044/198] fix: kerning is True by default --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 58578e9..d0a4517 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -131,7 +131,7 @@ class Text(TiledObject): italic: bool = False underline: bool = False strike_out: bool = False - kerning: bool = False + kerning: bool = True horizontal_align: str = "left" vertical_align: str = "top" From 56f8a38c860a2620fedac329d6a37803e761c1bd Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:46:22 -0400 Subject: [PATCH 045/198] tests: add font options text test --- tests/test_tiled_object.py | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index a36636b..dfcf229 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1051,6 +1051,47 @@ TEXTS = [ coordinates=common_types.OrderedPair(96.3338140843469, 130.620495623508), ), ), + ( + """ + { + "height":19, + "id":31, + "name":"name: text - font options", + "rotation":0, + "text": + { + "bold":true, + "italic":true, + "kerning":false, + "strikeout":true, + "text":"Hello World", + "underline":true, + "wrap":true + }, + "type":"text", + "visible":true, + "width":92.375, + "x":33, + "y":22 + } + """, + tiled_object.Text( + id=31, + name="name: text - font options", + rotation=0, + bold=True, + italic=True, + kerning=False, + strike_out=True, + text="Hello World", + underline=True, + wrap=True, + type="text", + visible=True, + size=common_types.Size(92.375, 19), + coordinates=common_types.OrderedPair(33, 22), + ), + ), ] OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILES + POLYGONS + POLYLINES + TEXTS From 441ac2e130927cefb49e520696915e92542225a3 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 31 May 2020 01:46:54 -0400 Subject: [PATCH 046/198] docs: docstring for _cast_tile --- pytiled_parser/tiled_object.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index d0a4517..a761489 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -270,6 +270,14 @@ 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. + + Args: + raw_tiled_object: Raw Tiled object to be casted to a Tile + + Returns: + Tile: The Tile object created from the raw_tiled_object + """ gid = raw_tiled_object["gid"] return Tile(gid=gid, **_get_common_attributes(raw_tiled_object).__dict__) From fbfd3864b3fffebb02c09430c75c1d1de3752fc2 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 01:54:34 -0400 Subject: [PATCH 047/198] Added RawProperties import to tiled_object.py --- pytiled_parser/tiled_object.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index ca74e6b..a2d49c2 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -5,8 +5,7 @@ from typing import Callable, Dict, List, Mapping, Optional, Union import attr from typing_extensions import TypedDict -from .common_types import OrderedPair, Size -from .properties import Properties +from .properties import Properties, RawProperties from .template import Template From 6de68678882a54a679028766ef7592f2bdeb923f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 31 May 2020 01:55:09 -0400 Subject: [PATCH 048/198] Added properties type to RawTiledObject --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index a2d49c2..03dc1a6 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -165,7 +165,7 @@ class RawTiledObject(TypedDict): visible: bool name: str type: str - properties: Properties + properties: RawProperties template: Template ellipse: bool point: bool From 04c36bb355ec012950a4aea474bb112585a85075 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 20:09:05 -0400 Subject: [PATCH 049/198] feature: implemented properties casting for TiledObjects --- pytiled_parser/properties.py | 5 +++-- pytiled_parser/tiled_object.py | 13 +++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index 54728fd..4507f75 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -3,10 +3,11 @@ from typing import Dict, List, NamedTuple, Optional, Union from .common_types import Color -RawProperties = List[Dict[str, Union[str, bool, int, float]]] - Property = Union[int, float, Path, str, bool, Color] +RawProperties = List[Dict[str, Property]] + + Properties = Dict[str, Property] diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 2cf2192..b05527f 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -5,8 +5,8 @@ from typing import Callable, Dict, List, Mapping, Optional, Union import attr from typing_extensions import TypedDict -from .properties import Properties, RawProperties from .common_types import Color, OrderedPair, Size +from .properties import Properties, RawProperties from .template import Template @@ -43,7 +43,7 @@ class TiledObject: name: Optional[str] = None type: Optional[str] = None - properties: Optional[Properties] = None + properties: Properties = {} template: Optional[Template] = None @@ -190,7 +190,9 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: coordinates = OrderedPair(x=raw_tiled_object["x"], y=raw_tiled_object["y"]) visible = raw_tiled_object["visible"] - common_attributes = TiledObject(id=id_, coordinates=coordinates, visible=visible) + common_attributes = TiledObject( + id=id_, coordinates=coordinates, visible=visible, properties={} + ) # optional attributes if any([raw_tiled_object.get("width"), raw_tiled_object.get("height")]): @@ -222,7 +224,10 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: common_attributes.type = raw_tiled_object["type"] if raw_tiled_object.get("properties"): - raise NotImplementedError + for prop in raw_tiled_object["properties"]: + name = str(prop["name"]) + value = prop["value"] + common_attributes.properties[name] = prop["value"] if raw_tiled_object.get("template"): raise NotImplementedError From 86af8df23d4d596a4deacd4d0067a71f9e5d3978 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 20:16:50 -0400 Subject: [PATCH 050/198] tests: use Color object for color --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index dfcf229..3fe1b0e 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -261,7 +261,7 @@ RECTANGLES = [ coordinates=common_types.OrderedPair(39.0678640445606, 131.826759122428), properties={ "bool property": False, - "color property": "#ffaa0000", + "color property": common_types.Color("#ffaa0000"), "file property": Path("../../../../../../dev/null"), "float property": 42.1, "int property": 8675309, From 74fff843c6c439796004ddc0aaf8cd229298f501 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 20:22:02 -0400 Subject: [PATCH 051/198] rf(tiled_object): remove reduntant references to "tiled_object" in function names --- pytiled_parser/tiled_object.py | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index b05527f..34b597d 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -309,7 +309,7 @@ def _cast_text(raw_tiled_object: RawTiledObject) -> Text: raise NotImplementedError -def _get_tiled_object_caster( +def _get_caster( raw_tiled_object: RawTiledObject, ) -> Callable[[RawTiledObject], TiledObject]: """ Get the caster function for the raw tiled object. @@ -343,7 +343,7 @@ def _get_tiled_object_caster( return _cast_rectangle -def _cast_tiled_object(raw_tiled_object: RawTiledObject) -> TiledObject: +def cast(raw_tiled_object: RawTiledObject) -> TiledObject: """ Cast the raw tiled object into a pytiled_parser type Args: @@ -352,24 +352,7 @@ def _cast_tiled_object(raw_tiled_object: RawTiledObject) -> TiledObject: Returns: TiledObject: a properly typed Tiled object. """ - caster = _get_tiled_object_caster(raw_tiled_object) + caster = _get_caster(raw_tiled_object) tiled_object = caster(raw_tiled_object) return tiled_object - - -def cast_tiled_objects(raw_tiled_objects: RawTiledObjects) -> List[TiledObject]: - """Parses objects found in a 'objectgroup' element. - - Args: - object_elements: List of object elements to be parsed. - - Returns: - list: List of parsed tiled objects. - """ - tiled_objects: List[TiledObject] = [] - - for raw_tiled_object in raw_tiled_objects: - tiled_objects.append(_cast_tiled_object(raw_tiled_object)) - - return tiled_objects From ff411ee92bfd617431b02ece431bc8701f38696b Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 20:26:35 -0400 Subject: [PATCH 052/198] rf(tiled_object): remove Mapping import --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 34b597d..324791d 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -1,6 +1,6 @@ # pylint: disable=too-few-public-methods -from typing import Callable, Dict, List, Mapping, Optional, Union +from typing import Callable, Dict, List, Optional, Union import attr from typing_extensions import TypedDict From cf243729ebce4997f61f65b4ecddd62f8cb93f34 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 20:31:17 -0400 Subject: [PATCH 053/198] refactor: changed the way properties is imported in tiled_object to support new conventions --- pytiled_parser/tiled_object.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index b05527f..a3c1e4e 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -5,8 +5,8 @@ from typing import Callable, Dict, List, Mapping, Optional, Union import attr from typing_extensions import TypedDict +from . import properties from .common_types import Color, OrderedPair, Size -from .properties import Properties, RawProperties from .template import Template @@ -43,7 +43,7 @@ class TiledObject: name: Optional[str] = None type: Optional[str] = None - properties: Properties = {} + properties: properties.Properties = {} template: Optional[Template] = None @@ -163,7 +163,7 @@ class RawTiledObject(TypedDict): visible: bool name: str type: str - properties: RawProperties + properties: properties.RawProperties template: Template ellipse: bool point: bool From 0a3bb8b51a5736b3fd7e82bfb9728a61523a5ed9 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 20:51:05 -0400 Subject: [PATCH 054/198] feature: Re-implemented properties casting to support casting properties for things outside of TiledObjects --- pytiled_parser/properties.py | 16 ++++++++++++++-- pytiled_parser/tiled_object.py | 11 ++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index 4507f75..9e198af 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -3,11 +3,23 @@ from typing import Dict, List, NamedTuple, Optional, Union from .common_types import Color - Property = Union[int, float, Path, str, bool, Color] - +class RawProperties = List[Dict[str, Property]] Properties = Dict[str, Property] + + +def cast(raw: RawProperties) -> Dict[str, Property]: + final: Properties = {} + for prop in raw: + value = prop["value"] + if prop["type"] == "file": + value = Path(str(value)) + elif prop["type"] == "color": + value = Color(str(value)) + final[str(prop["name"])] = value + + return final diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index a3c1e4e..5b8f530 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -5,7 +5,7 @@ from typing import Callable, Dict, List, Mapping, Optional, Union import attr from typing_extensions import TypedDict -from . import properties +from . import properties as properties_ from .common_types import Color, OrderedPair, Size from .template import Template @@ -43,7 +43,7 @@ class TiledObject: name: Optional[str] = None type: Optional[str] = None - properties: properties.Properties = {} + properties: properties_.Properties = {} template: Optional[Template] = None @@ -163,7 +163,7 @@ class RawTiledObject(TypedDict): visible: bool name: str type: str - properties: properties.RawProperties + properties: properties_.RawProperties template: Template ellipse: bool point: bool @@ -224,10 +224,7 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: common_attributes.type = raw_tiled_object["type"] if raw_tiled_object.get("properties"): - for prop in raw_tiled_object["properties"]: - name = str(prop["name"]) - value = prop["value"] - common_attributes.properties[name] = prop["value"] + common_attributes.properties = properties_.cast(raw_tiled_object["properties"]) if raw_tiled_object.get("template"): raise NotImplementedError From d89eb914e286a5e1c107846c023afc38bc566f15 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 20:54:21 -0400 Subject: [PATCH 055/198] rf(tiled_object.Text): better organize attributes --- pytiled_parser/tiled_object.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 324791d..6d7bb88 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -123,17 +123,20 @@ class Text(TiledObject): """ text: str - font_family: str = "sans-serif" - font_size: int = 16 - wrap: bool = False color: Color = "#000000" + + font_family: str = "sans-serif" + font_size: float = 16 + bold: bool = False italic: bool = False - underline: bool = False - strike_out: bool = False kerning: bool = True + strike_out: bool = False + underline: bool = False + horizontal_align: str = "left" vertical_align: str = "top" + wrap: bool = False @attr.s(auto_attribs=True, kw_only=True) From 0011efdbc262f3c14e7a540538837cd1eb56bf54 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 21:01:23 -0400 Subject: [PATCH 056/198] fix(properties): Darren doesn't know how to use VSCode --- pytiled_parser/properties.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index 9e198af..53d89e6 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -4,7 +4,6 @@ from typing import Dict, List, NamedTuple, Optional, Union from .common_types import Color Property = Union[int, float, Path, str, bool, Color] -class RawProperties = List[Dict[str, Property]] From 106ccab685230f4e85a50354087ace80fc5a99f4 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 21:01:41 -0400 Subject: [PATCH 057/198] tests:fix: use correct name of cast function --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 3fe1b0e..02d99b1 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1100,6 +1100,6 @@ OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILES + POLYGONS + POLYLINES + TEXTS @pytest.mark.parametrize("raw_object_json,expected", OBJECTS) def test_parse_layer(raw_object_json, expected): raw_object = json.loads(raw_object_json) - result = tiled_object._cast_tiled_object(raw_object) + result = tiled_object.cast(raw_object) assert result == expected From 3745b6bea5827017f1d616b1856a232b3fc25d01 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:14:11 -0400 Subject: [PATCH 058/198] refactor: changed RawProperties in properties.py to be a TypedDict --- pytiled_parser/properties.py | 25 ++++++++++++++++++------- tests/test_tiled_object.py | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index 9e198af..bc20c30 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -1,25 +1,36 @@ from pathlib import Path from typing import Dict, List, NamedTuple, Optional, Union +from typing_extensions import TypedDict + from .common_types import Color -Property = Union[int, float, Path, str, bool, Color] -class +Property = Union[float, Path, str, bool, Color] +RawProperty = Union[float, str, bool] -RawProperties = List[Dict[str, Property]] + +class RawProperties(TypedDict): + """A dictionary of raw properties.""" + + name: str + type: str + value: RawProperty Properties = Dict[str, Property] -def cast(raw: RawProperties) -> Dict[str, Property]: +def cast(raw: List[RawProperties]) -> Dict[str, Property]: final: Properties = {} + value: Property + for prop in raw: - value = prop["value"] if prop["type"] == "file": - value = Path(str(value)) + value = Path(str(prop["value"])) elif prop["type"] == "color": - value = Color(str(value)) + value = Color(str(prop["value"])) + else: + value = prop["value"] final[str(prop["name"])] = value return final diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 3fe1b0e..02d99b1 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -1100,6 +1100,6 @@ OBJECTS = ELLIPSES + RECTANGLES + POINTS + TILES + POLYGONS + POLYLINES + TEXTS @pytest.mark.parametrize("raw_object_json,expected", OBJECTS) def test_parse_layer(raw_object_json, expected): raw_object = json.loads(raw_object_json) - result = tiled_object._cast_tiled_object(raw_object) + result = tiled_object.cast(raw_object) assert result == expected From 33010405a1f8b26a39562065c2f265bfa5a0a443 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:20:25 -0400 Subject: [PATCH 059/198] tests: fix: Fixed Point ID 3 test --- tests/test_tiled_object.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 02d99b1..ab50a05 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -313,10 +313,10 @@ POINTS = [ """, tiled_object.Point( id=3, - name="name:name: point invisible", + name="name: point invisible", rotation=0, type="point", - visible=True, + visible=False, coordinates=common_types.OrderedPair(109.346368080027, 95.8144822098443), ), ), From 6de198f8f07adbf3f576b4a9a987129165f7b781 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:21:11 -0400 Subject: [PATCH 060/198] tests: fix: fixed polygon ID 10 test --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index ab50a05..f6c3729 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -561,7 +561,7 @@ POLYGONS = [ } """, tiled_object.Polygon( - id=9, + id=10, name="name: polygon - invisible", points=[ common_types.OrderedPair(0, 0), From 99bfdbc6ae5a921610e65db08ff8cb2a6245af9f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:21:37 -0400 Subject: [PATCH 061/198] tests: fix: fixed polygon ID 20 test --- tests/test_tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index f6c3729..2ac7834 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -614,7 +614,7 @@ POLYGONS = [ } """, tiled_object.Polygon( - id=9, + id=11, name="name: polygon - rotated", points=[ common_types.OrderedPair(0, 0), From 9af16fce716f28e8c43b4a8f8f9e8f63344f8df6 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:26:29 -0400 Subject: [PATCH 062/198] feature: implemented polyline casting --- pytiled_parser/tiled_object.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 3865aed..7109350 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -302,7 +302,21 @@ def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon: def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: - raise NotImplementedError + """ Cast the raw_tiled_object to a Polyline object. + + Args: + raw_tiled_object: Raw Tiled Object to be casted to a Polyline + + Returns: + Polyline: The Polyline object created from the raw_tiled_object + """ + polyline = [] + for point in raw_tiled_object["polyline"]: + polyline.append(OrderedPair(point["x"], point["y"])) + + return Polyline( + points=polyline, **_get_common_attributes(raw_tiled_object).__dict__ + ) def _cast_text(raw_tiled_object: RawTiledObject) -> Text: From ea43d05090aa8bb3401a633cadb1779f0bbfbbbf Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:26:43 -0400 Subject: [PATCH 063/198] tests: fix: fixed all polyline tests --- tests/test_tiled_object.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 2ac7834..258e716 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -661,7 +661,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id=9, + id=12, name="name: polyline", points=[ common_types.OrderedPair(0, 0), @@ -702,7 +702,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id=10, + id=31, name="name: polyline - invisible", points=[ common_types.OrderedPair(0, 0), @@ -743,7 +743,7 @@ POLYLINES = [ } """, tiled_object.Polyline( - id=11, + id=32, name="name: polyline - rotated", points=[ common_types.OrderedPair(0, 0), From 79f36a8f257bbbb05f3dc8e568dd87a0c651dcab Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:36:26 -0400 Subject: [PATCH 064/198] fix: Changed RawTiledObject properties list to match casting requirements --- pytiled_parser/tiled_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 7109350..78b1dcc 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -166,7 +166,7 @@ class RawTiledObject(TypedDict): visible: bool name: str type: str - properties: properties_.RawProperties + properties: List[properties_.RawProperties] template: Template ellipse: bool point: bool From b7c4b3ba7668842a1865cda152be72ddec242934 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:38:08 -0400 Subject: [PATCH 065/198] refactor: Removed templates as an attribute of TiledObjects --- pytiled_parser/tiled_object.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 78b1dcc..f150693 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -7,7 +7,6 @@ from typing_extensions import TypedDict from . import properties as properties_ from .common_types import Color, OrderedPair, Size -from .template import Template @attr.s(auto_attribs=True, kw_only=True) @@ -29,7 +28,6 @@ class TiledObject: name: The name of the tiled object. type: The type of the tiled object. properties: The properties of the TiledObject. - template: A reference to a Template tiled object FIXME """ id: int @@ -44,7 +42,6 @@ class TiledObject: type: Optional[str] = None properties: properties_.Properties = {} - template: Optional[Template] = None @attr.s() @@ -167,7 +164,6 @@ class RawTiledObject(TypedDict): name: str type: str properties: List[properties_.RawProperties] - template: Template ellipse: bool point: bool polygon: List[Dict[str, float]] @@ -229,9 +225,6 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: if raw_tiled_object.get("properties"): common_attributes.properties = properties_.cast(raw_tiled_object["properties"]) - if raw_tiled_object.get("template"): - raise NotImplementedError - return common_attributes From 1a4d9a6b927d6ac5516933660f61ee2f35696b5e Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 21:41:18 -0400 Subject: [PATCH 066/198] feat(tiled_object): Text object support --- pytiled_parser/tiled_object.py | 71 +++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 7109350..f20c691 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -152,6 +152,26 @@ class Tile(TiledObject): gid: int +class RawTextDict(TypedDict): + """ The keys and their types that appear in a Text JSON Object.""" + + text: str + color: Color + + fontfamily: str + pixelsize: float # this is `font_size` in Text + + bold: bool + italic: bool + strikeout: bool + underline: bool + kerning: bool + + halign: str + valign: str + wrap: bool + + class RawTiledObject(TypedDict): """ The keys and their types that appear in a Tiled JSON Object.""" @@ -320,7 +340,56 @@ def _cast_polyline(raw_tiled_object: RawTiledObject) -> Polyline: def _cast_text(raw_tiled_object: RawTiledObject) -> Text: - raise NotImplementedError + """ Cast the raw_tiled_object to a Text object. + + Args: + raw_tiled_object: Raw Tiled object to be casted to a Text object + + Returns: + Text: The Text object created from the raw_tiled_object + """ + # required attributes + raw_text_dict: RawTextDict = raw_tiled_object["text"] + text = raw_text_dict["text"] + + # create base Text object + text_object = Text(text=text, **_get_common_attributes(raw_tiled_object).__dict__) + + # optional attributes + if raw_text_dict.get("color") is not None: + text_object.color = raw_text_dict["color"] + + if raw_text_dict.get("fontfamily") is not None: + text_object.font_family = raw_text_dict["fontfamily"] + + if raw_text_dict.get("pixelsize") is not None: + text_object.font_size = raw_text_dict["pixelsize"] + + if raw_text_dict.get("bold") is not None: + text_object.bold = raw_text_dict["bold"] + + if raw_text_dict.get("italic") is not None: + text_object.italic = raw_text_dict["italic"] + + if raw_text_dict.get("kerning") is not None: + text_object.kerning = raw_text_dict["kerning"] + + if raw_text_dict.get("strikeout") is not None: + text_object.strike_out = raw_text_dict["strikeout"] + + if raw_text_dict.get("underline") is not None: + text_object.underline = raw_text_dict["underline"] + + if raw_text_dict.get("halign") is not None: + text_object.horizontal_align = raw_text_dict["halign"] + + if raw_text_dict.get("valign") is not None: + text_object.vertical_align = raw_text_dict["valign"] + + if raw_text_dict.get("wrap") is not None: + text_object.wrap = raw_text_dict["wrap"] + + return text_object def _get_caster( From 250ebc2d7d67a073dc787096d1ecb90d4d332fbd Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 1 Jun 2020 21:42:27 -0400 Subject: [PATCH 067/198] rf(tiled_object): compare to None, not Truthy --- pytiled_parser/tiled_object.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index cccc397..dac1aa8 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -230,19 +230,19 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: common_attributes.size = Size(width, height) - if raw_tiled_object.get("rotation"): + if raw_tiled_object.get("rotation") is not None: common_attributes.rotation = raw_tiled_object["rotation"] - if raw_tiled_object.get("opacity"): + if raw_tiled_object.get("opacity") is not None: common_attributes.opacity = raw_tiled_object["opacity"] - if raw_tiled_object.get("name"): + if raw_tiled_object.get("name") is not None: common_attributes.name = raw_tiled_object["name"] - if raw_tiled_object.get("type"): + if raw_tiled_object.get("type") is not None: common_attributes.type = raw_tiled_object["type"] - if raw_tiled_object.get("properties"): + if raw_tiled_object.get("properties") is not None: common_attributes.properties = properties_.cast(raw_tiled_object["properties"]) return common_attributes From 484e1ac69c65c35dfb413345162365b4fe45b478 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 21:55:11 -0400 Subject: [PATCH 068/198] docs: added docstrings to properties module --- pytiled_parser/properties.py | 37 ++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index bc20c30..9fda86d 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -1,11 +1,22 @@ +"""Properties Module + +This module casts raw properties from Tiled maps into a dictionary of +properly typed Properties. +""" + from pathlib import Path -from typing import Dict, List, NamedTuple, Optional, Union +from typing import Dict, List, Union from typing_extensions import TypedDict from .common_types import Color Property = Union[float, Path, str, bool, Color] + + +Properties = Dict[str, Property] + + RawProperty = Union[float, str, bool] @@ -17,20 +28,26 @@ class RawProperties(TypedDict): value: RawProperty -Properties = Dict[str, Property] +def cast(raw_properties: List[RawProperties]) -> Dict[str, Property]: + """ Cast raw properties into a dictionary of completed properly typed properties. + Args: + raw_properties: The list of raw properties to cast. + + Returns: + Dict[str, Property]: The completed dictionary of casted properties. + """ -def cast(raw: List[RawProperties]) -> Dict[str, Property]: final: Properties = {} value: Property - for prop in raw: - if prop["type"] == "file": - value = Path(str(prop["value"])) - elif prop["type"] == "color": - value = Color(str(prop["value"])) + for property_ in raw_properties: + if property_["type"] == "file": + value = Path(str(property_["value"])) + elif property_["type"] == "color": + value = Color(str(property_["value"])) else: - value = prop["value"] - final[str(prop["name"])] = value + value = property_["value"] + final[str(property_["name"])] = value return final From 3e9bf10e70acfd729db14baafba02503200f2398 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 22:04:18 -0400 Subject: [PATCH 069/198] docs: updated properties.py docstrings --- pytiled_parser/properties.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index 9fda86d..d40938c 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -28,14 +28,14 @@ class RawProperties(TypedDict): value: RawProperty -def cast(raw_properties: List[RawProperties]) -> Dict[str, Property]: - """ Cast raw properties into a dictionary of completed properly typed properties. +def cast(raw_properties: List[RawProperties]) -> Properties: + """ Cast a list of `RawProperties` into `Properties` Args: - raw_properties: The list of raw properties to cast. + raw_properties: The list of `RawProperty`s to cast. Returns: - Dict[str, Property]: The completed dictionary of casted properties. + Properties: The casted `Properties`. """ final: Properties = {} From 80db745a6d491311f372e7ff4cefb5311436a562 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 1 Jun 2020 22:08:08 -0400 Subject: [PATCH 070/198] refactor: changed naming convention for RawProperty to be more clear --- pytiled_parser/properties.py | 10 +++++----- pytiled_parser/tiled_object.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index d40938c..e0c8af0 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -17,19 +17,19 @@ Property = Union[float, Path, str, bool, Color] Properties = Dict[str, Property] -RawProperty = Union[float, str, bool] +RawValue = Union[float, str, bool] -class RawProperties(TypedDict): +class RawProperty(TypedDict): """A dictionary of raw properties.""" name: str type: str - value: RawProperty + value: RawValue -def cast(raw_properties: List[RawProperties]) -> Properties: - """ Cast a list of `RawProperties` into `Properties` +def cast(raw_properties: List[RawProperty]) -> Properties: + """ Cast a list of `RawProperty`s into `Properties` Args: raw_properties: The list of `RawProperty`s to cast. diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index dac1aa8..a96141e 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -183,7 +183,7 @@ class RawTiledObject(TypedDict): visible: bool name: str type: str - properties: List[properties_.RawProperties] + properties: List[properties_.RawProperty] ellipse: bool point: bool polygon: List[Dict[str, float]] From c83f79adb0d7443e16d98e823c630202ecd8e89c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 2 Jun 2020 20:02:37 -0400 Subject: [PATCH 071/198] chore: major cleanup --- dev_requirements.txt | 11 - old_pytiled_parser/__init__.py | 4 - old_pytiled_parser/objects.py | 554 ------ old_pytiled_parser/typing_helpers.py | 6 - old_pytiled_parser/utilities.py | 69 - old_pytiled_parser/xml_parser.py | 920 --------- old_tests/__init__.py | 3 - .../test_data/images/tmw_desert_spacing.png | Bin 37830 -> 0 bytes .../test_data/test_map_image_tile_set.tmx | 91 - old_tests/test_data/test_map_infinite.tmx | 390 ---- old_tests/test_data/test_map_simple.tmx | 23 - old_tests/test_data/test_map_simple_meme.tmx | 18 - .../test_data/test_map_simple_objects.tmx | 14 - .../test_data/test_map_simple_offset.tmx | 22 - old_tests/test_data/tile_set_image.tsx | 4 - .../test_data/tile_set_image_objects.tsx | 40 - old_tests/test_infinite_maps.py | 82 - old_tests/test_parser.py | 223 --- old_tests/test_pytiled_parser_integration.py | 98 - old_tests/test_test_map_simple_offset.py | 81 - old_tests/test_typing_helpers.py | 19 - test/assets | 1 - test/collision_test.py | 69 - test/config.py | 1 - test/foo.py | 1704 ----------------- test/test2.py | 29 - test/test_attr.py | 22 - test/test_output.py | 178 -- test/test_tiled-bak.py | 32 - test/test_tiled.py | 11 - 30 files changed, 4719 deletions(-) delete mode 100644 dev_requirements.txt delete mode 100644 old_pytiled_parser/__init__.py delete mode 100644 old_pytiled_parser/objects.py delete mode 100644 old_pytiled_parser/typing_helpers.py delete mode 100644 old_pytiled_parser/utilities.py delete mode 100644 old_pytiled_parser/xml_parser.py delete mode 100644 old_tests/__init__.py delete mode 100644 old_tests/test_data/images/tmw_desert_spacing.png delete mode 100644 old_tests/test_data/test_map_image_tile_set.tmx delete mode 100644 old_tests/test_data/test_map_infinite.tmx delete mode 100644 old_tests/test_data/test_map_simple.tmx delete mode 100644 old_tests/test_data/test_map_simple_meme.tmx delete mode 100644 old_tests/test_data/test_map_simple_objects.tmx delete mode 100644 old_tests/test_data/test_map_simple_offset.tmx delete mode 100644 old_tests/test_data/tile_set_image.tsx delete mode 100644 old_tests/test_data/tile_set_image_objects.tsx delete mode 100644 old_tests/test_infinite_maps.py delete mode 100644 old_tests/test_parser.py delete mode 100644 old_tests/test_pytiled_parser_integration.py delete mode 100644 old_tests/test_test_map_simple_offset.py delete mode 100644 old_tests/test_typing_helpers.py delete mode 120000 test/assets delete mode 100644 test/collision_test.py delete mode 100644 test/config.py delete mode 100644 test/foo.py delete mode 100644 test/test2.py delete mode 100644 test/test_attr.py delete mode 100644 test/test_output.py delete mode 100644 test/test_tiled-bak.py delete mode 100644 test/test_tiled.py diff --git a/dev_requirements.txt b/dev_requirements.txt deleted file mode 100644 index 0f6ddbb..0000000 --- a/dev_requirements.txt +++ /dev/null @@ -1,11 +0,0 @@ --e . -black -pytest -sphinx -coverage -coveralls -sphinx_rtd_theme -setuptools -pytest-cov -pytest-mock -wheel diff --git a/old_pytiled_parser/__init__.py b/old_pytiled_parser/__init__.py deleted file mode 100644 index d58a1b1..0000000 --- a/old_pytiled_parser/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""init for pytiled_parser""" - -from . import objects, utilities -from .xml_parser import parse_tile_map diff --git a/old_pytiled_parser/objects.py b/old_pytiled_parser/objects.py deleted file mode 100644 index b9fab0f..0000000 --- a/old_pytiled_parser/objects.py +++ /dev/null @@ -1,554 +0,0 @@ -"""pytiled_parser objects for Tiled maps. -""" - -# pylint: disable=too-few-public-methods - -from pathlib import Path -from typing import Dict, List, NamedTuple, Optional, Union - -import attr - -# See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#data -TileLayerGrid = List[List[int]] - - -class Color(NamedTuple): - """Color object. - - 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 - - -class OrderedPair(NamedTuple): - """OrderedPair NamedTuple. - - Attributes: - x: X coordinate. - y: Y coordinate. - """ - - x: Union[int, float] - y: Union[int, float] - - -class Property(NamedTuple): - """Property NamedTuple. - - Attributes: - name: Name of property - value: Value of property - """ - - name: str - value: str - - -class Size(NamedTuple): - """Size NamedTuple. - - Attributes: - width: The width of the object. - size: The height of the object. - """ - - width: Union[int, float] - height: Union[int, float] - - -@attr.s(auto_attribs=True) -class Template: - """FIXME TODO""" - - -@attr.s(auto_attribs=True) -class Chunk: - """Chunk object for infinite maps. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#chunk - - Attributes: - location: Location of chunk in tiles. - width: The width of the chunk in tiles. - height: The height of the chunk in tiles. - layer_data: The global tile IDs in chunky according to row. - """ - - location: OrderedPair - width: int - height: int - chunk_data: TileLayerGrid - - -@attr.s(auto_attribs=True) -class Image: - """Image object. - - pytiled_parser does not support embedded data in image elements at this time, - even though the TMX format technically does. - - Attributes: - source: The reference to the tileset image file. Note that this is a relative - path compared to FIXME - trans: Defines a specific color that is treated as transparent. - width: The image width in pixels (optional, used for tile index correction when - the image changes). - height: The image height in pixels (optional). - """ - - source: str - size: Optional[Size] = None - trans: Optional[str] = None - width: Optional[int] = None - height: Optional[int] = None - - -Properties = Dict[str, Union[int, float, Color, Path, str]] - - -class Grid(NamedTuple): - """Contains info for isometric maps. - - This element is only used in case of isometric orientation, and determines how tile - overlays for terrain and collision information are rendered. - - Args: - orientation: Orientation of the grid for the tiles in this tileset (orthogonal - or isometric). - width: Width of a grid cell. - height: Height of a grid cell. - """ - - orientation: str - width: int - height: int - - -class Terrain(NamedTuple): - """Terrain object. - - Args: - name: The name of the terrain type. - tile: The local tile-id of the tile that represents the terrain visually. - """ - - name: str - tile: int - - -class Frame(NamedTuple): - """Animation Frame object. - - This is only used as a part of an animation for Tile objects. - - Args: - tile_id: The local ID of a tile within the parent tile set object. - duration: How long in milliseconds this frame should be displayed before - advancing to the next frame. - """ - - tile_id: int - duration: int - - -@attr.s(auto_attribs=True) -class TileTerrain: - """Defines each corner of a tile by Terrain index in - 'TileSet.terrain_types'. - - Defaults to 'None'. 'None' means that corner has no terrain. - - Attributes: - top_left: Top left terrain type. - top_right: Top right terrain type. - bottom_left: Bottom left terrain type. - bottom_right: Bottom right terrain type. - """ - - top_left: Optional[int] = None - top_right: Optional[int] = None - bottom_left: Optional[int] = None - bottom_right: Optional[int] = None - - -@attr.s(auto_attribs=True, kw_only=True) -class Layer: - # FIXME:this docstring appears to be innacurate - """Class that all layers inherit from. - - Args: - id: Unique ID of the layer. Each layer that added to a map gets a unique id. - Even if a layer is deleted, no layer ever gets the same ID. - name: The name of the layer object. - tiled_objects: List of tiled_objects in the layer. - offset: Rendering offset of the layer object in pixels. - opacity: Decimal value between 0 and 1 to determine opacity. 1 is completely - opaque, 0 is completely transparent. - properties: Properties for the layer. - color: The color used to display the objects in this group. - draworder: Whether the objects are drawn according to the order of the object - elements in the object group element ('manual'), or sorted by their - y-coordinate ('topdown'). Defaults to 'topdown'. - See: - https://doc.mapeditor.org/en/stable/manual/objects/#changing-stacking-order - for more info. - - """ - - id_: int - name: str - - offset: Optional[OrderedPair] - opacity: Optional[float] - properties: Optional[Properties] - - -LayerData = Union[TileLayerGrid, List[Chunk]] -"""The tile data for one layer. - -Either a 2 dimensional array of integers representing the global tile IDs - for a TileLayerGrid, or a list of chunks for an infinite map layer. -""" - - -@attr.s(auto_attribs=True, kw_only=True) -class TileLayer(Layer): - """Tile map layer containing tiles. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#layer - - Args: - size: The width of the layer in tiles. The same as the map width unless map is - infitite. - data: Either an 2 dimensional array of integers representing the global tile - IDs for the map layer, or a list of chunks for an infinite map. - """ - - size: Size - layer_data: LayerData - - -@attr.s(auto_attribs=True, kw_only=True) -class TiledObject: - """TiledObject object. - - See: - https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#object - - Args: - id: Unique ID of the object. Each object that is placed on a map gets a unique - id. Even if an object was deleted, no object gets the same ID. - gid: Global tiled object ID. - location: The location of the object in pixels. - size: The width of the object in pixels (default: (0, 0)). - rotation: The rotation of the object in degrees clockwise (default: 0). - opacity: The opacity of the object. (default: 255) - name: The name of the object. - type: The type of the object. - properties: The properties of the TiledObject. - template: A reference to a Template object FIXME - """ - - id_: int - gid: Optional[int] = None - - location: OrderedPair - size: Optional[Size] = None - rotation: Optional[float] = None - opacity: Optional[float] = None - - name: Optional[str] = None - type: Optional[str] = None - - properties: Optional[Properties] = None - template: Optional[Template] = None - - -@attr.s() -class RectangleObject(TiledObject): - """Rectangle shape defined by a point, width, and height. - - See: https://doc.mapeditor.org/en/stable/manual/objects/#insert-rectangle - (objects in tiled are rectangles by default, so there is no specific - documentation on the tmx-map-format page for it.) - """ - - -@attr.s() -class ElipseObject(TiledObject): - """Elipse shape defined by a point, width, and height. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#ellipse - """ - - -@attr.s() -class PointObject(TiledObject): - """Point defined by a point (x,y). - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#point - """ - - -@attr.s(auto_attribs=True, kw_only=True) -class TileImageObject(TiledObject): - """Polygon shape defined by a set of connections between points. - - See: https://doc.mapeditor.org/en/stable/manual/objects/#insert-tile - - Attributes: - gid: Refference to a global tile id. - """ - - gid: int - - -@attr.s(auto_attribs=True, kw_only=True) -class PolygonObject(TiledObject): - """Polygon shape defined by a set of connections between points. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#polygon - - Attributes: - points: FIXME - """ - - points: List[OrderedPair] - - -@attr.s(auto_attribs=True, kw_only=True) -class PolylineObject(TiledObject): - """Polyline defined by a set of connections between points. - - See: - https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#polyline - - Attributes: - points: List of coordinates relative to the location of the object. - """ - - points: List[OrderedPair] - - -@attr.s(auto_attribs=True, kw_only=True) -class TextObject(TiledObject): - """Text object with associated settings. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#text - and https://doc.mapeditor.org/en/stable/manual/objects/#insert-text - - Attributes: - font_family: The font family used (default: "sans-serif") - font_size: The size of the font in pixels. (default: 16) - wrap: Whether word wrapping is enabled. (default: False) - color: Color of the text. (default: #000000) - bold: Whether the font is bold. (default: False) - italic: Whether the font is italic. (default: False) - underline: Whether the text is underlined. (default: False) - strike_out: Whether the text is striked-out. (default: False) - kerning: Whether kerning should be used while rendering the text. (default: - False) - horizontal_align: Horizontal alignment of the text (default: "left") - vertical_align: Vertical alignment of the text (defalt: "top") - """ - - text: str - font_family: str = "sans-serif" - font_size: int = 16 - wrap: bool = False - color: str = "#000000" - bold: bool = False - italic: bool = False - underline: bool = False - strike_out: bool = False - kerning: bool = False - horizontal_align: str = "left" - vertical_align: str = "top" - - -@attr.s(auto_attribs=True, kw_only=True) -class ObjectLayer(Layer): - """ - TiledObject Group Object. - - The object group is in fact a map layer, and is hence called "object layer" in - Tiled. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#objectgroup - - Args: - tiled_objects: List of tiled_objects in the layer. - offset: Rendering offset of the layer object in pixels. - color: The color used to display the objects in this group. FIXME: editor only? - draworder: Whether the objects are drawn according to the order of the object - elements in the object group element ('manual'), or sorted by their - y-coordinate ('topdown'). Defaults to 'topdown'. See: - https://doc.mapeditor.org/en/stable/manual/objects/#changing-stacking-order - for more info. - - """ - - tiled_objects: List[TiledObject] - - color: Optional[str] = None - draw_order: Optional[str] = "topdown" - - -@attr.s(auto_attribs=True, kw_only=True) -class LayerGroup(Layer): - """Layer Group. - - A LayerGroup can be thought of as a layer that contains layers - (potentially including other LayerGroups). - - Offset and opacity recursively affect child layers. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group - - Attributes: - Layers: Layers in group. - """ - - layers: Optional[List[Union["LayerGroup", Layer, ObjectLayer]]] - - -@attr.s(auto_attribs=True) -class TileSet: - """Object for storing a TSX with all associated collision data. - - Args: - name: The name of this tileset. - max_tile_size: The maximum size of a tile in this tile set in pixels. - spacing: The spacing in pixels between the tiles in this tileset (applies to - the tileset image). - margin: The margin around the tiles in this tileset (applies to the tileset - image). - tile_count: The number of tiles in this tileset. - columns: The number of tile columns in the tileset. For image collection - tilesets it is editable and is used when displaying the tileset. - grid: Only used in case of isometric orientation, and determines how tile - overlays for terrain and collision information are rendered. - tileoffset: Used to specify an offset in pixels when drawing a tile from the - tileset. When not present, no offset is applied. - image: Used for spritesheet tile sets. - terrain_types: List of of terrain types which can be referenced from the - terrain attribute of the tile object. Ordered according to the terrain - element's appearance in the TSX file. - tiles: Dict of Tile objects by Tile.id. - tsx_file: Path of the file containing the tileset, None if loaded internally - from a map - parent_dir: Path of the parent directory of the file containing the tileset, - None if loaded internally from a map - """ - - name: str - max_tile_size: Size - - spacing: Optional[int] = None - margin: Optional[int] = None - tile_count: Optional[int] = None - columns: Optional[int] = None - tile_offset: Optional[OrderedPair] = None - grid: Optional[Grid] = None - properties: Optional[Properties] = None - image: Optional[Image] = None - terrain_types: Optional[List[Terrain]] = None - tiles: Optional[Dict[int, "Tile"]] = None - tsx_file: Path = None - parent_dir: Path = None - - -TileSetDict = Dict[int, TileSet] - - -@attr.s(auto_attribs=True, kw_only=True) -class Tile: - """Individual tile object. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tile - - Args: - id: The local tile ID within its tileset. - type: The type of the tile. Refers to an object type and is used by tile - objects. - terrain: Defines the terrain type of each corner of the tile. - animation: Each tile can have exactly one animation associated with it. - """ - - id_: int - type_: Optional[str] = None - terrain: Optional[TileTerrain] = None - animation: Optional[List[Frame]] = None - objectgroup: Optional[List[TiledObject]] = None - image: Optional[Image] = None - properties: Optional[List[Property]] = None - tileset: Optional[TileSet] = None - flipped_horizontally: bool = False - flipped_diagonally: bool = False - flipped_vertically: bool = False - - -@attr.s(auto_attribs=True) -class TileMap: - """Object for storing a TMX with all associated layers and properties. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#map - - Attributes: - parent_dir: The directory the TMX file is in. Used for finding relative paths - to TSX files and other assets. - version: The TMX format version. - tiledversion: The Tiled version used to save the file. May be a date (for - snapshot builds). - orientation: Map orientation. Tiled supports "orthogonal", "isometric", - "staggered" and "hexagonal" - renderorder: The order in which tiles on tile layers are rendered. Valid values - are right-down, right-up, left-down and left-up. In all cases, the map is - drawn row-by-row. (only supported for orthogonal maps at the moment) - map_size: The map width in tiles. - tile_size: The width of a tile. - infinite: If the map is infinite or not. - hexsidelength: Only for hexagonal maps. Determines the width or height - (depending on the staggered axis) of the tile's edge, in pixels. - stagger_axis: For staggered and hexagonal maps, determines which axis ("x" or - "y") is staggered. - staggerindex: For staggered and hexagonal maps, determines whether the "even" - or "odd" indexes along the staggered axis are shifted. - backgroundcolor: The background color of the map. - nextlayerid: Stores the next available ID for new layers. - nextobjectid: Stores the next available ID for new objects. - tile_sets: Dict of tile sets used in this map. Key is the first GID for the - tile set. The value is a TileSet object. - layers: List of layer objects by draw order. - """ - - parent_dir: Path - tmx_file: Union[str, Path] - - version: str - tiled_version: str - orientation: str - render_order: str - map_size: Size - tile_size: Size - infinite: bool - next_layer_id: Optional[int] - next_object_id: int - - tile_sets: TileSetDict - layers: List[Layer] - - hex_side_length: Optional[int] = None - stagger_axis: Optional[int] = None - stagger_index: Optional[int] = None - background_color: Optional[Color] = None - - properties: Optional[Properties] = None diff --git a/old_pytiled_parser/typing_helpers.py b/old_pytiled_parser/typing_helpers.py deleted file mode 100644 index cc13d40..0000000 --- a/old_pytiled_parser/typing_helpers.py +++ /dev/null @@ -1,6 +0,0 @@ -def is_float(string: str): - try: - float(string) - return True - except (ValueError, TypeError): - return False diff --git a/old_pytiled_parser/utilities.py b/old_pytiled_parser/utilities.py deleted file mode 100644 index 7d5e09c..0000000 --- a/old_pytiled_parser/utilities.py +++ /dev/null @@ -1,69 +0,0 @@ -"""Helper unitilies for pytiled_parser.""" - -from typing import List, Optional - -import pytiled_parser.objects as objects - - -def parse_color(color: str) -> objects.Color: - """Convert Tiled color format into Arcade's. - - Args: - color (str): Tiled formatted color string. - - Returns: - :Color: Color object in the format that Arcade 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 - alpha = 0xFF - red = int(color[0:2], 16) - green = int(color[2:4], 16) - blue = int(color[4:6], 16) - else: - alpha = int(color[0:2], 16) - red = int(color[2:4], 16) - green = int(color[4:6], 16) - blue = int(color[6:8], 16) - - return objects.Color(red, green, blue, alpha) - - -def _get_tile_set_key(gid: int, tile_set_keys: List[int]) -> int: - """Gets tile set key given a tile GID. - - Args: - gid (int): Global ID of the tile. - tile_set_keys (List[int]): List of tile set keys. - - Returns: - int: The key of the tile set that contains the tile for the GID. - """ - - # credit to __m4ch1n3__ on ##learnpython for this idea - return max([key for key in tile_set_keys if key <= gid]) - - -def get_tile_by_gid(gid: int, tile_sets: objects.TileSetDict) -> Optional[objects.Tile]: - """Gets correct Tile for a given global ID. - - Args: - tile_sets (objects.TileSetDict): TileSetDict from TileMap. - gid (int): Global tile ID of the tile to be returned. - - Returns: - objects.Tile: The Tile object reffered to by the global tile ID. - None: If there is no objects.Tile object in the tile_set.tiles dict for the associated gid. - """ - tile_set_key = _get_tile_set_key(gid, list(tile_sets.keys())) - tile_set = tile_sets[tile_set_key] - - if tile_set.tiles is not None: - return tile_set.tiles.get(gid - tile_set_key) - - return None diff --git a/old_pytiled_parser/xml_parser.py b/old_pytiled_parser/xml_parser.py deleted file mode 100644 index e400d53..0000000 --- a/old_pytiled_parser/xml_parser.py +++ /dev/null @@ -1,920 +0,0 @@ -"""Handle XML parsing for TMX files""" - -import base64 -import functools -import gzip -import re -import xml.etree.ElementTree as etree -import zlib -from pathlib import Path -from typing import Callable, Dict, List, Optional, Tuple, Union - -import pytiled_parser.objects as objects -import pytiled_parser.typing_helpers as TH -from pytiled_parser.utilities import parse_color - - -def _decode_base64_data( - data_text: str, layer_width: int, compression: Optional[str] = None -) -> objects.TileLayerGrid: - """Decode base64 data. - - Args: - data_text: Data to be decoded. - layer_width: Width of each layer in tiles. - compression: The type of compression for the data. - - Raises: - ValueError: If compression type is unsupported. - - Returns: - objects.TileLayerGrid: Tile grid. - """ - tile_grid: objects.TileLayerGrid = [[]] - - unencoded_data = base64.b64decode(data_text) - if compression == "zlib": - unzipped_data = zlib.decompress(unencoded_data) - elif compression == "gzip": - unzipped_data = gzip.decompress(unencoded_data) - elif compression is None: - unzipped_data = unencoded_data - else: - raise ValueError(f"Unsupported compression type: '{compression}'.") - - # Turn bytes into 4-byte integers - byte_count = 0 - int_count = 0 - int_value = 0 - row_count = 0 - for byte in unzipped_data: - int_value += byte << (byte_count * 8) - byte_count += 1 - if not byte_count % 4: - byte_count = 0 - int_count += 1 - tile_grid[row_count].append(int_value) - int_value = 0 - if not int_count % layer_width: - row_count += 1 - tile_grid.append([]) - - tile_grid.pop() - return tile_grid - - -def _decode_csv_data(data_text: str) -> objects.TileLayerGrid: - """Decodes csv encoded layer data. - - Args: - data_text: Data to be decoded. - - Returns: - objects.TileLayerGrid: Tile grid. - """ - tile_grid = [] - lines: List[str] = data_text.split("\n") - # remove erroneous empty lists due to a newline being on both ends of text - lines = lines[1:-1] - for line in lines: - line_list = line.split(",") - # FIXME: what is this for? - while "" in line_list: - line_list.remove("") - line_list_int = [int(item) for item in line_list] - tile_grid.append(line_list_int) - - return tile_grid - - -# I'm not sure if this is the best way to do this -TileLayerDecoder = Union[ - Callable[[str], objects.TileLayerGrid], - Callable[[str, int, Optional[str]], objects.TileLayerGrid], -] - - -def _decode_tile_layer_data( - element: etree.Element, - layer_width: int, - encoding: str, - compression: Optional[str] = None, -) -> objects.TileLayerGrid: - """Decodes tile layer data or chunk data. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-data - - Args: - element: Element to have text decoded. - layer_width: Number of tiles per column in this layer. Used for determining - when to cut off a row when decoding base64 encoding layers. - encoding: Encoding format of the layer data. - compression: Compression format of the layer data. - - Raises: - ValueError: Encoding type is not supported. - - Returns: - objects.TileLayerGrid: Tile grid. - """ - - data_text: str = element.text # type: ignore - - if encoding == "csv": - return _decode_csv_data(data_text) - if encoding == "base64": - return _decode_base64_data(data_text, layer_width, compression) - - raise ValueError(f"{encoding} is not a supported encoding") - - -def _parse_data(element: etree.Element, layer_width: int) -> objects.LayerData: - """Parses layer data. - - Will parse CSV, base64, gzip-base64, or zlip-base64 encoded data. - - Args: - element: Data element to parse. - layer_width: Layer width. Used for base64 decoding. - - Returns: - LayerData: Data object containing layer data or chunks of data. - """ - encoding = element.attrib["encoding"] - - compression = None - try: - compression = element.attrib["compression"] - except KeyError: - pass - - chunk_elements = element.findall("./chunk") - if chunk_elements: - chunks: List[objects.Chunk] = [] - for chunk_element in chunk_elements: - x = int(chunk_element.attrib["x"]) - y = int(chunk_element.attrib["y"]) - location = objects.OrderedPair(x, y) - width = int(chunk_element.attrib["width"]) - height = int(chunk_element.attrib["height"]) - layer_data = _decode_tile_layer_data( - chunk_element, layer_width, encoding, compression - ) - chunks.append(objects.Chunk(location, width, height, layer_data)) - return chunks - - return _decode_tile_layer_data(element, layer_width, encoding, compression) - - -def _parse_layer( - layer_element: etree.Element, -) -> Tuple[ - int, - str, - Optional[objects.OrderedPair], - Optional[float], - Optional[objects.Properties], -]: - """Parses all of the attributes for a Layer object. - - Args: - layer_element: The layer element to be parsed. - - Returns: - FIXME - """ - id_ = int(layer_element.attrib["id"]) - - name = layer_element.attrib["name"] - - offset: Optional[objects.OrderedPair] - offset_x = layer_element.attrib.get("offsetx") - offset_y = layer_element.attrib.get("offsety") - if offset_x and offset_y: - assert TH.is_float(offset_x) - assert TH.is_float(offset_y) - offset = objects.OrderedPair(float(offset_x), float(offset_y)) - else: - offset = None - - opacity: Optional[float] - opacity_attrib = layer_element.attrib.get("opacity") - if opacity_attrib: - opacity = float(opacity_attrib) - else: - opacity = None - - properties: Optional[objects.Properties] - properties_element = layer_element.find("./properties") - if properties_element is not None: - properties = _parse_properties_element(properties_element) - else: - properties = None - - return id_, name, offset, opacity, properties - - -def _parse_tile_layer(element: etree.Element,) -> objects.TileLayer: - """Parses tile layer element. - - Args: - element: The layer element to be parsed. - - Raises: - ValueError: Element has no child data element. - - Returns: - TileLayer: The tile layer object. - """ - id_, name, offset, opacity, properties = _parse_layer(element) - - width = int(element.attrib["width"]) - height = int(element.attrib["height"]) - size = objects.Size(width, height) - - data_element = element.find("./data") - assert data_element is not None - layer_data: objects.LayerData = _parse_data(data_element, width) - - return objects.TileLayer( - id_=id_, - name=name, - offset=offset, - opacity=opacity, - properties=properties, - size=size, - layer_data=layer_data, - ) - - -def _parse_tiled_objects( - object_elements: List[etree.Element], -) -> List[objects.TiledObject]: - """Parses objects found in a 'objectgroup' element. - - Args: - object_elements: List of object elements to be parsed. - - Returns: - list: List of parsed tiled objects. - """ - tiled_objects: List[objects.TiledObject] = [] - - for object_element in object_elements: - id_ = int(object_element.attrib["id"]) - location_x = float(object_element.attrib["x"]) - location_y = float(object_element.attrib["y"]) - location = objects.OrderedPair(location_x, location_y) - - tiled_object = objects.TiledObject(id_=id_, location=location) - - try: - tiled_object.gid = int(object_element.attrib["gid"]) - except KeyError: - tiled_object.gid = None - - try: - # If any dimension is provided, they both will be - width = float(object_element.attrib["width"]) - height = float(object_element.attrib["height"]) - tiled_object.size = objects.Size(width, height) - except KeyError: - pass - - try: - tiled_object.opacity = float(object_element.attrib["opacity"]) - except KeyError: - pass - - try: - tiled_object.rotation = float(object_element.attrib["rotation"]) - except KeyError: - pass - - try: - tiled_object.name = object_element.attrib["name"] - except KeyError: - pass - - try: - tiled_object.type = object_element.attrib["type"] - except KeyError: - pass - - properties_element = object_element.find("./properties") - if properties_element is not None: - tiled_object.properties = _parse_properties_element(properties_element) - - tiled_objects.append(tiled_object) - - return tiled_objects - - -def _parse_object_layer(element: etree.Element,) -> objects.ObjectLayer: - """Parse the objectgroup element given. - - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#objectgroup - - Args: - element: Element to be parsed. - - Returns: - ObjectLayer: The object layer object. - """ - id_, name, offset, opacity, properties = _parse_layer(element) - - color = None - try: - color = element.attrib["color"] - except KeyError: - pass - - draw_order = None - try: - draw_order = element.attrib["draworder"] - except KeyError: - pass - - tiled_objects = _parse_tiled_objects(element.findall("./object")) - - return objects.ObjectLayer( - id_=id_, - name=name, - offset=offset, - opacity=opacity, - properties=properties, - color=color, - draw_order=draw_order, - tiled_objects=tiled_objects, - ) - - -def _parse_layer_group(element: etree.Element,) -> objects.LayerGroup: - """Parse the objectgroup element given. - - Args: - element: Element to be parsed. - - Returns: - LayerGroup: The layer group object. - """ - id_, name, offset, opacity, properties = _parse_layer(element) - - layers = _get_layers(element) - - return objects.LayerGroup( - id_=id_, - name=name, - offset=offset, - opacity=opacity, - properties=properties, - layers=layers, - ) - - -def _get_layer_parser( - layer_tag: str, -) -> Optional[Callable[[etree.Element], objects.Layer]]: - """Gets a the parser for the layer type specified. - - Layer tags are 'layer' for a tile layer, 'objectgroup' for an object layer, and - 'group' for a layer group. If anything else is passed, returns None. - - Args: - layer_tag: Specifies the layer type to be parsed based on the element tag. - - Returns: - Callable: the function to be used to parse the layer. - None: The element is not a map layer. - """ - if layer_tag == "layer": - return _parse_tile_layer - if layer_tag == "objectgroup": - return _parse_object_layer - if layer_tag == "group": - return _parse_layer_group - return None - - -def _get_layers(map_element: etree.Element) -> List[objects.Layer]: - """Parse layer type element given. - - Retains draw order based on the returned lists index FIXME: confirm - - Args: - map_element: The element containing the layer. - - Returns: - List[Layer]: A list of the layers, ordered by draw order. FIXME: confirm - """ - layers: List[objects.Layer] = [] - for element in map_element.findall("./"): - layer_parser = _get_layer_parser(element.tag) - if layer_parser: - layers.append(layer_parser(element)) - - return layers - - -@functools.lru_cache() -def _parse_external_tile_set( - parent_dir: Path, tile_set_element: etree.Element -) -> objects.TileSet: - """Parses an external tile set. - - Caches the results to speed up subsequent maps with identical tilesets. - - Args: - parent_dir: Directory that TMX is in. - tile_set_element: Tile set element. - - Returns: - objects.Tileset: The tileset being parsed. - """ - source = Path(tile_set_element.attrib["source"]) - resolved_path = parent_dir / source - tile_set_tree = etree.parse(str(parent_dir / Path(source))).getroot() - - parsed_tile_set = _parse_tile_set(tile_set_tree) - - parsed_tile_set.tsx_file = resolved_path - parsed_tile_set.parent_dir = resolved_path.parent - - return parsed_tile_set - - -def _parse_points(point_string: str) -> List[objects.OrderedPair]: - str_pairs = point_string.split(" ") - - points = [] - for str_pair in str_pairs: - xys = str_pair.split(",") - x = float(xys[0]) - y = float(xys[1]) - points.append((x, y)) - - return points - - -def _parse_tiles(tile_element_list: List[etree.Element]) -> Dict[int, objects.Tile]: - """Parse a list of tile elements. - - Args: - tile_element_list: List of tile elements. - - Returns: - Dict[int, objects.Tile]: Dictionary containing Tile objects by their ID. - """ - tiles: Dict[int, objects.Tile] = {} - for tile_element in tile_element_list: - # id is not optional - id_ = int(tile_element.attrib["id"]) - - # optional attributes - _type = None - try: - _type = tile_element.attrib["type"] - except KeyError: - pass - - terrain = None - try: - tile_terrain_attrib = tile_element.attrib["terrain"] - except KeyError: - pass - else: - # below is an attempt to explain how terrains are handled. - # 'terrain' attribute is a comma seperated list of 4 values, - # each is either an integer or blank - - # convert to list of values - terrain_list_attrib = re.split(",", tile_terrain_attrib) - # terrain_list is list of indexes of Tileset.terrain_types - terrain_list: List[Optional[int]] = [] - # each index in terrain_list_attrib refers to a corner - for corner in terrain_list_attrib: - if not corner: - terrain_list.append(None) - else: - terrain_list.append(int(corner)) - terrain = objects.TileTerrain(*terrain_list) - - # tile element optional sub-elements - properties: Optional[List[objects.Property]] = None - tile_properties_element = tile_element.find("./properties") - if tile_properties_element: - properties = [] - property_list = tile_properties_element.findall("./property") - for property_ in property_list: - name = property_.attrib["name"] - value = property_.attrib["value"] - obj = objects.Property(name, value) - properties.append(obj) - - # tile element optional sub-elements - animation: Optional[List[objects.Frame]] = None - tile_animation_element = tile_element.find("./animation") - if tile_animation_element: - animation = [] - frames = tile_animation_element.findall("./frame") - for frame in frames: - # tileid refers to the Tile.id of the animation frame - animated_id = int(frame.attrib["tileid"]) - # duration is in MS. Should perhaps be converted to seconds. - # FIXME: make decision - duration = int(frame.attrib["duration"]) - animation.append(objects.Frame(animated_id, duration)) - - # tile element optional sub-elements - objectgroup: Optional[List[objects.TiledObject]] = None - objectgroup_element = tile_element.find("./objectgroup") - if objectgroup_element: - objectgroup = [] - object_list = objectgroup_element.findall("./object") - for object in object_list: - my_id = object.attrib["id"] - my_x = float(object.attrib["x"]) - my_y = float(object.attrib["y"]) - if "width" in object.attrib: - my_width = float(object.attrib["width"]) - else: - my_width = None - if "height" in object.attrib: - my_height = float(object.attrib["height"]) - else: - my_height = None - - # This is where it would be nice if we could assume a walrus - # operator was part of our Python distribution. - - my_object = None - - polygon = object.findall("./polygon") - - if polygon and len(polygon) > 0: - points = _parse_points(polygon[0].attrib["points"]) - my_object = objects.PolygonObject( - id_=my_id, - location=(my_x, my_y), - size=(my_width, my_height), - points=points, - ) - - if my_object is None: - polyline = object.findall("./polyline") - - if polyline and len(polyline) > 0: - points = _parse_points(polyline[0].attrib["points"]) - my_object = objects.PolylineObject( - id_=my_id, - location=(my_x, my_y), - size=(my_width, my_height), - points=points, - ) - - if my_object is None: - ellipse = object.findall("./ellipse") - - if ellipse and len(ellipse): - my_object = objects.ElipseObject( - id_=my_id, location=(my_x, my_y), size=(my_width, my_height) - ) - - if my_object is None: - if "template" in object.attrib: - print( - "Warning, this .tmx file is using an unsupported" - "'template' attribute. Ignoring." - ) - continue - - if my_object is None: - my_object = objects.RectangleObject( - id_=my_id, location=(my_x, my_y), size=(my_width, my_height) - ) - - objectgroup.append(my_object) - - # if this is None, then the Tile is part of a spritesheet - image = None - image_element = tile_element.find("./image") - if image_element is not None: - image = _parse_image_element(image_element) - - # print(f"Adding '{id_}', {image}, {objectgroup}") - - tiles[id_] = objects.Tile( - id_=id_, - type_=_type, - terrain=terrain, - animation=animation, - image=image, - properties=properties, - tileset=None, - objectgroup=objectgroup, - ) - - return tiles - - -def _parse_image_element(image_element: etree.Element) -> objects.Image: - """Parse image element given. - - Args: - image_element (etree.Element): Image element to be parsed. - - Returns: - objects.Image: FIXME what is this? - """ - # FIXME doc - image = objects.Image(image_element.attrib["source"]) - - width_attrib = image_element.attrib.get("width") - height_attrib = image_element.attrib.get("height") - - if width_attrib and height_attrib: - image.size = objects.Size(int(width_attrib), int(height_attrib)) - - try: - image.trans = image_element.attrib["trans"] - except KeyError: - pass - - return image - - -def _parse_properties_element(properties_element: etree.Element) -> objects.Properties: - # FIXME: wtf is this pseudo 'attributes' section? - """Adds Tiled property to Properties dict. - - Each property element has a number of attributes: - name: Name of property. - property_type: Type of property. Can be string, int, float, bool, color or - file. Defaults to string. - value: The value of the property. - - Args: - properties_element: Element to be parsed. - - Returns: - objects.Properties: Dict of the property values by property name. - - - """ - properties: objects.Properties = {} - for property_element in properties_element.findall("./property"): - name = property_element.attrib["name"] - try: - property_type = property_element.attrib["type"] - except KeyError: - # strings do not have an attribute in property elements - property_type = "string" - value = property_element.attrib["value"] - - property_types = ["string", "int", "float", "bool", "color", "file"] - assert property_type in property_types, f"Invalid type for property {name}" - - if property_type == "int": - properties[name] = int(value) - elif property_type == "float": - properties[name] = float(value) - elif property_type == "color": - properties[name] = value - elif property_type == "file": - properties[name] = Path(value) - elif property_type == "bool": - if value == "true": - properties[name] = True - else: - properties[name] = False - else: - properties[name] = value - - return properties - - -def _parse_tile_set(tile_set_element: etree.Element) -> objects.TileSet: - """Parses a tile set that is embedded into a TMX. - - Args: - tile_set_element: Element to be parsed. - - Returns: - objects.TileSet: Tile Set from element. - """ - # get all basic attributes - name = tile_set_element.attrib["name"] - max_tile_width = int(tile_set_element.attrib["tilewidth"]) - max_tile_height = int(tile_set_element.attrib["tileheight"]) - max_tile_size = objects.Size(max_tile_width, max_tile_height) - - spacing = None - try: - spacing = int(tile_set_element.attrib["spacing"]) - except KeyError: - pass - - margin = None - try: - margin = int(tile_set_element.attrib["margin"]) - except KeyError: - pass - - tile_count = None - try: - tile_count = int(tile_set_element.attrib["tilecount"]) - except KeyError: - pass - - columns = None - try: - columns = int(tile_set_element.attrib["columns"]) - except KeyError: - pass - - tile_offset = None - tileoffset_element = tile_set_element.find("./tileoffset") - if tileoffset_element is not None: - tile_offset_x = int(tileoffset_element.attrib["x"]) - tile_offset_y = int(tileoffset_element.attrib["y"]) - tile_offset = objects.OrderedPair(tile_offset_x, tile_offset_y) - - grid = None - grid_element = tile_set_element.find("./grid") - if grid_element is not None: - grid_orientation = grid_element.attrib["orientation"] - grid_width = int(grid_element.attrib["width"]) - grid_height = int(grid_element.attrib["height"]) - grid = objects.Grid(grid_orientation, grid_width, grid_height) - - properties = None - properties_element = tile_set_element.find("./properties") - if properties_element is not None: - properties = _parse_properties_element(properties_element) - - terrain_types: Optional[List[objects.Terrain]] = None - terrain_types_element = tile_set_element.find("./terraintypes") - if terrain_types_element is not None: - terrain_types = [] - for terrain in terrain_types_element.findall("./terrain"): - name = terrain.attrib["name"] - terrain_tile = int(terrain.attrib["tile"]) - terrain_types.append(objects.Terrain(name, terrain_tile)) - - image = None - image_element = tile_set_element.find("./image") - if image_element is not None: - image = _parse_image_element(image_element) - - tile_element_list = tile_set_element.findall("./tile") - tiles = _parse_tiles(tile_element_list) - - tileset = objects.TileSet( - name, - max_tile_size, - spacing, - margin, - tile_count, - columns, - tile_offset, - grid, - properties, - image, - terrain_types, - tiles, - ) - - # Go back and create a circular link so tiles know what tileset they are - # part of. Needed for animation. - for id_, tile in tiles.items(): - tile.tileset = tileset - - return tileset - - -def _get_tile_sets(map_element: etree.Element, parent_dir: Path) -> objects.TileSetDict: - """Get tile sets. - - Args: - map_element: Element to be parsed. - parent_dir: Directory that TMX is in. - - Returns: - objects.TileSetDict: Dict of tile sets in the TMX by first_gid - """ - # parse all tilesets - tile_sets: objects.TileSetDict = {} - tile_set_element_list = map_element.findall("./tileset") - for tile_set_element in tile_set_element_list: - # tiled docs are ambiguous about the 'firstgid' attribute - # current understanding is for the purposes of mapping the layer - # data to the tile set data, add the 'firstgid' value to each - # tile 'id'; this means that the 'firstgid' is specific to each, - # tile set as they pertain to the map, not tile set specific as - # the tiled docs can make it seem - # 'firstgid' the key for each TileMap - first_gid = int(tile_set_element.attrib["firstgid"]) - try: - # check if is an external TSX - source = tile_set_element.attrib["source"] - except KeyError: - # the tile set is embedded - name = tile_set_element.attrib["name"] - tile_sets[first_gid] = _parse_tile_set(tile_set_element) - else: - # tile set is external - tile_sets[first_gid] = _parse_external_tile_set( - parent_dir, tile_set_element - ) - - return tile_sets - - -def parse_tile_map(tmx_file: Union[str, Path]) -> objects.TileMap: - """Parse tile map. - - Args: - tmx_file: TMX file to be parsed. - - Returns: - objects.TileMap: TileMap object generated from the TMX file provided. - """ - # setting up XML parsing - map_tree = etree.parse(str(tmx_file)) - map_element = map_tree.getroot() - - # positional arguments for TileMap - parent_dir = Path(tmx_file).parent - - version = map_element.attrib["version"] - tiled_version = map_element.attrib["tiledversion"] - orientation = map_element.attrib["orientation"] - render_order = map_element.attrib["renderorder"] - - map_width = int(map_element.attrib["width"]) - map_height = int(map_element.attrib["height"]) - map_size = objects.Size(map_width, map_height) - - tile_width = int(map_element.attrib["tilewidth"]) - tile_height = int(map_element.attrib["tileheight"]) - tile_size = objects.Size(tile_width, tile_height) - - infinite_attribute = map_element.attrib["infinite"] - infinite = bool(infinite_attribute == "1") - - if "nextlayerid" in map_element.attrib: - next_layer_id = int(map_element.attrib["nextlayerid"]) - else: - next_layer_id = None - - if "nextobjectid" in map_element.attrib: - next_object_id = int(map_element.attrib["nextobjectid"]) - else: - next_object_id = None - - tile_sets = _get_tile_sets(map_element, parent_dir) - - layers = _get_layers(map_element) - - tile_map = objects.TileMap( - parent_dir, - tmx_file, - version, - tiled_version, - orientation, - render_order, - map_size, - tile_size, - infinite, - next_layer_id, - next_object_id, - tile_sets, - layers, - ) - - try: - tile_map.hex_side_length = int(map_element.attrib["hexsidelength"]) - except KeyError: - pass - - try: - tile_map.stagger_axis = map_element.attrib["staggeraxis"] - except KeyError: - pass - - try: - tile_map.stagger_index = map_element.attrib["staggerindex"] - except KeyError: - pass - - try: - color = parse_color(map_element.attrib["backgroundcolor"]) - tile_map.background_color = (color.red, color.green, color.blue) - except KeyError: - pass - - properties_element = map_tree.find("./properties") - if properties_element is not None: - tile_map.properties = _parse_properties_element(properties_element) - - return tile_map diff --git a/old_tests/__init__.py b/old_tests/__init__.py deleted file mode 100644 index 3aeeee8..0000000 --- a/old_tests/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -import pytest - -pytest.main(["--tb=native", "-s", "tests"]) diff --git a/old_tests/test_data/images/tmw_desert_spacing.png b/old_tests/test_data/images/tmw_desert_spacing.png deleted file mode 100644 index 4e9995c0d95bc53d3dcc4bca2e7ee0b9aa531550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37830 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 IM6N<$f^W5A%>V!Z diff --git a/old_tests/test_data/test_map_image_tile_set.tmx b/old_tests/test_data/test_map_image_tile_set.tmx deleted file mode 100644 index 63e60f8..0000000 --- a/old_tests/test_data/test_map_image_tile_set.tmx +++ /dev/null @@ -1,91 +0,0 @@ - - - - - -1,2,3,4,5,6,7,8,30,30, -9,10,11,12,13,14,15,16,30,30, -17,18,19,20,21,22,23,24,30,30, -25,26,27,28,29,30,31,32,30,30, -33,34,35,36,37,38,39,40,30,30, -41,42,43,44,45,46,47,48,30,30, -30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30 - - - - -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,46,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,6,7,7,7,7,7,8,0, -0,0,14,15,15,15,15,15,16,0, -0,0,22,23,23,23,23,23,24,0 - - - - - - - - -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,31,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0 - - - - -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,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,0,0,0,0,0,0,0, -9,10,11,0,0,0,0,0,0,0, -17,18,19,0,0,0,0,0,0,0 - - - - - - - - - - - - - - - - Hello World - - - - - - - - - - - - - - diff --git a/old_tests/test_data/test_map_infinite.tmx b/old_tests/test_data/test_map_infinite.tmx deleted file mode 100644 index d117bcf..0000000 --- a/old_tests/test_data/test_map_infinite.tmx +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,1,2,3, -30,30,30,30,30,30,30,30,30,30,30,30,30,9,10,11, -30,30,30,30,30,30,30,30,30,30,30,30,30,17,18,19 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -4,5,6,7,8,30,30,30,30,30,30,30,30,30,30,30, -12,13,14,15,16,30,30,30,30,30,30,30,30,30,30,30, -20,21,22,23,24,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,25,26,27, -30,30,30,30,30,30,30,30,30,30,30,30,30,33,34,35, -30,30,30,30,30,30,30,30,30,30,30,30,30,41,42,43, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -28,29,30,31,32,30,30,30,30,30,30,30,30,30,30,30, -36,37,38,39,40,30,30,30,30,30,30,30,30,30,30,30, -44,45,46,47,48,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30, -30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30 - - - - - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,21, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,29, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - -0,0,20,21,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,28,29,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -20,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -20,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -28,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - -28,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - - - - diff --git a/old_tests/test_data/test_map_simple.tmx b/old_tests/test_data/test_map_simple.tmx deleted file mode 100644 index f5e2a0d..0000000 --- a/old_tests/test_data/test_map_simple.tmx +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - -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 - - - diff --git a/old_tests/test_data/test_map_simple_meme.tmx b/old_tests/test_data/test_map_simple_meme.tmx deleted file mode 100644 index bc47bdc..0000000 --- a/old_tests/test_data/test_map_simple_meme.tmx +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - H4sIAAAAAAAAAw3DBRKCQAAAwDMRA7BQLMTE9v+vY3dmWyGEth279uwbOTB26MixExNTM6fOnLtwae7KtYUbt+7ce7D0aOXJsxev3rxb+/Dpy7cfv/782wAcvDirwAAAAA== - - - diff --git a/old_tests/test_data/test_map_simple_objects.tmx b/old_tests/test_data/test_map_simple_objects.tmx deleted file mode 100644 index 26adfbb..0000000 --- a/old_tests/test_data/test_map_simple_objects.tmx +++ /dev/null @@ -1,14 +0,0 @@ - - - - - -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 - - - diff --git a/old_tests/test_data/test_map_simple_offset.tmx b/old_tests/test_data/test_map_simple_offset.tmx deleted file mode 100644 index 400a639..0000000 --- a/old_tests/test_data/test_map_simple_offset.tmx +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - -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 - - - diff --git a/old_tests/test_data/tile_set_image.tsx b/old_tests/test_data/tile_set_image.tsx deleted file mode 100644 index 2f6ef20..0000000 --- a/old_tests/test_data/tile_set_image.tsx +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/old_tests/test_data/tile_set_image_objects.tsx b/old_tests/test_data/tile_set_image_objects.tsx deleted file mode 100644 index 6d65375..0000000 --- a/old_tests/test_data/tile_set_image_objects.tsx +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/old_tests/test_infinite_maps.py b/old_tests/test_infinite_maps.py deleted file mode 100644 index 33f5d1b..0000000 --- a/old_tests/test_infinite_maps.py +++ /dev/null @@ -1,82 +0,0 @@ -"""Tests for infinite maps""" -import os -import xml.etree.ElementTree as etree -from contextlib import ExitStack as does_not_raise -from pathlib import Path - -import pytest - -import pytiled_parser -from pytiled_parser import objects, utilities, xml_parser - -TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) -TEST_DATA = TESTS_DIR / "test_data" - - -def test_map_infinite(): - """ - TMX with a very simple spritesheet tile set and some properties. - """ - - test_map = pytiled_parser.parse_tile_map(TEST_DATA / "test_map_infinite.tmx") - - print(test_map.layers) - - # map - assert test_map.version == "1.2" - assert test_map.tiled_version == "1.2.3" - assert test_map.orientation == "orthogonal" - assert test_map.render_order == "right-down" - assert test_map.map_size == (8, 6) - assert test_map.tile_size == (32, 32) - assert test_map.infinite - assert test_map.next_layer_id == 3 - assert test_map.next_object_id == 1 - - # optional, not for orthogonal maps - assert test_map.hex_side_length == None - assert test_map.stagger_axis == None - assert test_map.stagger_index == None - assert test_map.background_color == None - - # tileset - assert test_map.tile_sets[1].name == "tile_set_image" - assert test_map.tile_sets[1].max_tile_size == (32, 32) - assert test_map.tile_sets[1].spacing == 1 - assert test_map.tile_sets[1].margin == 1 - assert test_map.tile_sets[1].tile_count == 48 - assert test_map.tile_sets[1].columns == 8 - assert test_map.tile_sets[1].tile_offset == None - assert test_map.tile_sets[1].grid == None - assert test_map.tile_sets[1].properties == None - - # unsure how to get paths to compare propperly - assert str(test_map.tile_sets[1].image.source) == ("images/tmw_desert_spacing.png") - assert test_map.tile_sets[1].image.trans == None - assert test_map.tile_sets[1].image.size == (265, 199) - - assert test_map.tile_sets[1].terrain_types == None - assert test_map.tile_sets[1].tiles == {} - - # layers - assert test_map.layers[0].id_ == 1 - assert test_map.layers[0].name == "Tile Layer 1" - assert test_map.layers[0].offset == None - assert test_map.layers[0].opacity == None - assert test_map.layers[0].properties == None - assert test_map.layers[0].size == (8, 6) - - # fmt: off - assert test_map.layers[0].layer_data == [objects.Chunk(location=objects.OrderedPair(x=-32, y=-32), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=-32), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=0, y=-32), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=16, y=-32), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-32, y=-16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=-16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 1, 2, 3], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 9, 10, 11], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 18, 19]]), objects.Chunk(location=objects.OrderedPair(x=0, y=-16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [4, 5, 6, 7, 8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [12, 13, 14, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [20, 21, 22, 23, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=16, y=-16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-32, y=0), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=0), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 26, 27], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 35], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 41, 42, 43], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=0, y=0), width=16, height=16, chunk_data=[[28, 29, 30, 31, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [36, 37, 38, 39, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [44, 45, 46, 47, 48, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=16, y=0), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-32, y=16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=0, y=16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]]), objects.Chunk(location=objects.OrderedPair(x=16, y=16), width=16, height=16, chunk_data=[[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], [30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]])] - # fmt: on - - assert test_map.layers[1].id_ == 2 - assert test_map.layers[1].name == "Tile Layer 2" - assert test_map.layers[1].offset == None - assert test_map.layers[1].opacity == None - assert test_map.layers[1].properties == None - assert test_map.layers[1].size == (8, 6) - - # fmt: off - assert test_map.layers[1].layer_data == [objects.Chunk(location=objects.OrderedPair(x=-32, y=-16), width=16, height=16, chunk_data=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), objects.Chunk(location=objects.OrderedPair(x=16, y=-16), width=16, height=16, chunk_data=[[0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=0), width=16, height=16, chunk_data=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), objects.Chunk(location=objects.OrderedPair(x=16, y=0), width=16, height=16, chunk_data=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), objects.Chunk(location=objects.OrderedPair(x=-16, y=16), width=16, height=16, chunk_data=[[28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])] - # fmt: on diff --git a/old_tests/test_parser.py b/old_tests/test_parser.py deleted file mode 100644 index dcad131..0000000 --- a/old_tests/test_parser.py +++ /dev/null @@ -1,223 +0,0 @@ -"""Unit tests for pytiled_parser""" - -import xml.etree.ElementTree as etree -from contextlib import ExitStack as does_not_raise - -import pytest - -from pytiled_parser import objects, utilities, xml_parser - -LAYER_DATA = [ - ( - '' + "", - (int(1), "Tile Layer 1", None, None, None), - ), - ( - '' - + "", - (int(2), "Tile Layer 2", None, float(0.5), None), - ), - ( - '' - + "" - + "" - + "", - (int(5), "Tile Layer 4", objects.OrderedPair(49, -50), None, "properties",), - ), -] - - -@pytest.mark.parametrize("xml,expected", LAYER_DATA) -def test_parse_layer(xml, expected, monkeypatch): - def mockreturn(*args): - return "properties" - - monkeypatch.setattr(xml_parser, "_parse_properties_element", mockreturn) - - result = xml_parser._parse_layer(etree.fromstring(xml)) - - assert result == expected - - -@pytest.mark.parametrize( - "test_input,expected", - [ - ("#001122", (0x00, 0x11, 0x22, 0xFF)), - ("001122", (0x00, 0x11, 0x22, 0xFF)), - ("#FF001122", (0x00, 0x11, 0x22, 0xFF)), - ("FF001122", (0x00, 0x11, 0x22, 0xFF)), - ("FF001122", (0x00, 0x11, 0x22, 0xFF)), - ], -) -def test_color_parsing(test_input, expected): - assert utilities.parse_color(test_input) == expected - - -layer_data = [ - ( - etree.fromstring( - "\n1,2,3,4,5,6,7,8,\n" - "9,10,11,12,13,14,15,16,\n" - "17,18,19,20,21,22,23,24,\n" - "25,26,27,28,29,30,31,32,\n" - "33,34,35,36,37,38,39,40,\n" - "41,42,43,44,45,46,47,48\n" - ), - 8, - "csv", - None, - [ - [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], - ], - does_not_raise(), - ), - ( - etree.fromstring("\n0,0,0,0,0\n"), - 5, - "csv", - None, - [[0, 0, 0, 0, 0]], - does_not_raise(), - ), - ( - etree.fromstring( - "AQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAB0AAAAeAAAAHwAAACAAAAAhAAAAIgAAACMAAAAkAAAAJQAAACYAAAAnAAAAKAAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAA" - ), - 8, - "base64", - None, - [ - [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], - ], - does_not_raise(), - ), - ( - etree.fromstring( - "eJwNwwUSgkAAAMAzEQOwUCzExPb/r2N3ZlshhLYdu/bsGzkwdujIsRMTUzOnzpy7cGnuyrWFG7fu3Huw9GjlybMXr968W/vw6cu3H7/+/NsAMw8EmQ==" - ), - 8, - "base64", - "zlib", - [ - [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], - ], - does_not_raise(), - ), - ( - etree.fromstring( - "H4sIAAAAAAAAAw3DBRKCQAAAwDMRA7BQLMTE9v+vY3dmWyGEth279uwbOTB26MixExNTM6fOnLtwae7KtYUbt+7ce7D0aOXJsxev3rxb+/Dpy7cfv/782wAcvDirwAAAAA==" - ), - 8, - "base64", - "gzip", - [ - [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], - ], - does_not_raise(), - ), - ( - etree.fromstring("SGVsbG8gV29ybGQh"), - 8, - "base64", - "lzma", - [ - [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], - ], - pytest.raises(ValueError), - ), - ( - etree.fromstring( - "/ .---- --..-- ..--- --..-- ...-- --..-- ....- --..-- ..... --..-- -.... --..-- --... --..-- ---.. --..-- / ----. --..-- .---- ----- --..-- .---- .---- --..-- .---- ..--- --..-- .---- ...-- --..-- .---- ....- --..-- .---- ..... --..-- .---- -.... --..-- / .---- --... --..-- .---- ---.. --..-- .---- ----. --..-- ..--- ----- --..-- ..--- .---- --..-- ..--- ..--- --..-- ..--- ...-- --..-- ..--- ....- --..-- / ..--- ..... --..-- ..--- -.... --..-- ..--- --... --..-- ..--- ---.. --..-- ..--- ----. --..-- ...-- ----- --..-- ...-- .---- --..-- ...-- ..--- --..-- / ...-- ...-- --..-- ...-- ....- --..-- ...-- ..... --..-- ...-- -.... --..-- ...-- --... --..-- ...-- ---.. --..-- ...-- ----. --..-- ....- ----- --..-- / ....- .---- --..-- ....- ..--- --..-- ....- ...-- --..-- ....- ....- --..-- ....- ..... --..-- ....- -.... --..-- ....- --... --..-- ....- ---.." - ), - 8, - "morse", - None, - [ - [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], - ], - pytest.raises(ValueError), - ), -] - - -@pytest.mark.parametrize( - "layer_data,width,encoding,compression,expected,raises", layer_data -) -def test_decode_layer_data(layer_data, width, encoding, compression, expected, raises): - with raises: - assert ( - xml_parser._decode_tile_layer_data(layer_data, width, encoding, compression) - == expected - ) - - -# FIXME: use hypothesis for this -def create_tile_set(qty_of_tiles): - """ Create tile set of specific size. - """ - tile_set = objects.TileSet(None, None) - - if qty_of_tiles == 0: - return tile_set - - tiles = {} - - for tile_id in range(qty_of_tiles): - tiles[tile_id] = objects.Tile(id_=tile_id) - - tile_set.tiles = tiles - - return tile_set - - -tile_by_gid = [ - (1, {1: create_tile_set(0)}, None), - (1, {1: create_tile_set(1)}, objects.Tile(id_=0)), - (1, {1: create_tile_set(2)}, objects.Tile(id_=0)), - (2, {1: create_tile_set(1)}, None), - (10, {1: create_tile_set(10)}, objects.Tile(id_=9)), - (1, {1: create_tile_set(1), 2: create_tile_set(1)}, objects.Tile(id_=0)), - (2, {1: create_tile_set(1), 2: create_tile_set(1)}, objects.Tile(id_=0)), - (3, {1: create_tile_set(1), 2: create_tile_set(1)}, None), - (15, {1: create_tile_set(5), 6: create_tile_set(10)}, objects.Tile(id_=9)), - ( - 20, - {1: create_tile_set(5), 6: create_tile_set(10), 16: create_tile_set(10),}, - objects.Tile(id_=4), - ), -] - - -@pytest.mark.parametrize("gid,tile_sets,expected", tile_by_gid) -def test_get_tile_by_gid(gid, tile_sets, expected): - assert utilities.get_tile_by_gid(gid, tile_sets) == expected diff --git a/old_tests/test_pytiled_parser_integration.py b/old_tests/test_pytiled_parser_integration.py deleted file mode 100644 index 8022cde..0000000 --- a/old_tests/test_pytiled_parser_integration.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -from pathlib import Path - -import pytest - -import pytiled_parser - -TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) -TEST_DATA = TESTS_DIR / "test_data" - - -def test_map_simple(): - """ - TMX with a very simple spritesheet tile set and some properties. - """ - - test_map = pytiled_parser.parse_tile_map(TEST_DATA / "test_map_simple.tmx") - - # map - # unsure how to get paths to compare propperly - assert test_map.parent_dir == TEST_DATA - assert test_map.version == "1.2" - assert test_map.tiled_version == "1.2.3" - assert test_map.orientation == "orthogonal" - assert test_map.render_order == "right-down" - assert test_map.map_size == (8, 6) - assert test_map.tile_size == (32, 32) - assert test_map.infinite == False - assert test_map.next_layer_id == 2 - assert test_map.next_object_id == 1 - - # optional, not for orthogonal maps - assert test_map.hex_side_length == None - assert test_map.stagger_axis == None - assert test_map.stagger_index == None - assert test_map.background_color == None - - assert test_map.properties == { - "bool property - false": False, - "bool property - true": True, - "color property": "#ff49fcff", - "file property": Path("/var/log/syslog"), - "float property": 1.23456789, - "int property": 13, - "string property": "Hello, World!!", - } - - # tileset - assert test_map.tile_sets[1].name == "tile_set_image" - assert test_map.tile_sets[1].max_tile_size == (32, 32) - assert test_map.tile_sets[1].spacing == 1 - assert test_map.tile_sets[1].margin == 1 - assert test_map.tile_sets[1].tile_count == 48 - assert test_map.tile_sets[1].columns == 8 - assert test_map.tile_sets[1].tile_offset == None - assert test_map.tile_sets[1].grid == None - assert test_map.tile_sets[1].properties == None - - # unsure how to get paths to compare propperly - assert str(test_map.tile_sets[1].image.source) == ("images/tmw_desert_spacing.png") - assert test_map.tile_sets[1].image.trans == None - assert test_map.tile_sets[1].image.size == (265, 199) - - assert test_map.tile_sets[1].terrain_types == None - assert test_map.tile_sets[1].tiles == {} - - # layers - assert test_map.layers[0].layer_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], - ] - assert test_map.layers[0].id_ == 1 - assert test_map.layers[0].name == "Tile Layer 1" - assert test_map.layers[0].offset == None - assert test_map.layers[0].opacity == None - assert test_map.layers[0].properties == None - assert test_map.layers[0].size == (8, 6) - - -@pytest.mark.parametrize( - "test_input,expected", - [ - ("#001122", (0x00, 0x11, 0x22, 0xFF)), - ("001122", (0x00, 0x11, 0x22, 0xFF)), - ("#FF001122", (0x00, 0x11, 0x22, 0xFF)), - ("FF001122", (0x00, 0x11, 0x22, 0xFF)), - ("FF001122", (0x00, 0x11, 0x22, 0xFF)), - ], -) -def test_color_parsing(test_input, expected): - """ - Tiled has a few different types of color representations. - """ - assert pytiled_parser.utilities.parse_color(test_input) == expected diff --git a/old_tests/test_test_map_simple_offset.py b/old_tests/test_test_map_simple_offset.py deleted file mode 100644 index e3ba1b9..0000000 --- a/old_tests/test_test_map_simple_offset.py +++ /dev/null @@ -1,81 +0,0 @@ -"""test test_map_simple_offset.tmx""" -import os -from pathlib import Path - -import pytiled_parser - -TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) -TEST_DATA = TESTS_DIR / "test_data" - - -def test_map_simple(): - """ - TMX with a very simple spritesheet tile set and some properties. - """ - - test_map = pytiled_parser.parse_tile_map(TEST_DATA / "test_map_simple_offset.tmx") - - # map - # unsure how to get paths to compare propperly - assert test_map.parent_dir == TEST_DATA - assert test_map.version == "1.2" - assert test_map.tiled_version == "1.3.1" - assert test_map.orientation == "orthogonal" - assert test_map.render_order == "right-down" - assert test_map.map_size == (8, 6) - assert test_map.tile_size == (32, 32) - assert test_map.infinite == False - assert test_map.next_layer_id == 2 - assert test_map.next_object_id == 1 - - # optional, not for orthogonal maps - assert test_map.hex_side_length == None - assert test_map.stagger_axis == None - assert test_map.stagger_index == None - assert test_map.background_color == None - - assert test_map.properties == { - "bool property - false": False, - "bool property - true": True, - "color property": "#ff49fcff", - "float property": 1.23456789, - "int property": 13, - "string property": "Hello, World!!", - } - - # tileset - assert test_map.tile_sets[1].name == "tile_set_image" - assert test_map.tile_sets[1].max_tile_size == (32, 32) - assert test_map.tile_sets[1].spacing == 1 - assert test_map.tile_sets[1].margin == 1 - assert test_map.tile_sets[1].tile_count == 48 - assert test_map.tile_sets[1].columns == 8 - assert test_map.tile_sets[1].tile_offset == None - assert test_map.tile_sets[1].grid == None - assert test_map.tile_sets[1].properties == None - - # unsure how to get paths to compare propperly - assert str(test_map.tile_sets[1].image.source) == ("images/tmw_desert_spacing.png") - assert test_map.tile_sets[1].image.trans == None - assert test_map.tile_sets[1].image.size == (265, 199) - - assert test_map.tile_sets[1].terrain_types == None - assert test_map.tile_sets[1].tiles == {} - - # layers - assert test_map.layers[0].layer_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], - ] - assert test_map.layers[0].id_ == 1 - assert test_map.layers[0].name == "Tile Layer 1" - assert test_map.layers[0].offset == pytiled_parser.objects.OrderedPair( - x=16.0, y=-16.42 - ) - assert test_map.layers[0].opacity == None - assert test_map.layers[0].properties == None - assert test_map.layers[0].size == (8, 6) diff --git a/old_tests/test_typing_helpers.py b/old_tests/test_typing_helpers.py deleted file mode 100644 index e9b9183..0000000 --- a/old_tests/test_typing_helpers.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Tests for typing helpers""" - -import pytest - -from pytiled_parser import typing_helpers as TH - -TEST_IS_FLOAT_PARAMS = [ - (1, True), - ("1", True), - (1.1, True), - ("1.1", True), - ("one", False), - (None, False), -] - - -@pytest.mark.parametrize("string,expected", TEST_IS_FLOAT_PARAMS) -def test_is_float(string, expected): - assert TH.is_float(string) == expected diff --git a/test/assets b/test/assets deleted file mode 120000 index 87a867e..0000000 --- a/test/assets +++ /dev/null @@ -1 +0,0 @@ -../../../the_decay_factor_assets/the-decay-factor---assets/assets/ \ No newline at end of file diff --git a/test/collision_test.py b/test/collision_test.py deleted file mode 100644 index b7cfb83..0000000 --- a/test/collision_test.py +++ /dev/null @@ -1,69 +0,0 @@ -import os -import arcade -import arcade.tiled - -SCREEN_WIDTH = 800 -SCREEN_HEIGHT = 600 - -SPRITE_SCALING = 1 -GRAVITY = 1.1 - - -class BasicTestWindow(arcade.Window): - def __init__(self, width, height, title, map_name): - super().__init__(width, height, title) - file_path = os.path.dirname(os.path.abspath(__file__)) - os.chdir(file_path) - - self.layers = [] - my_map = arcade.tiled.read_tiled_map(map_name, 1) - for layer in my_map.layers: - self.layers.append( - arcade.tiled.generate_sprites( - my_map, layer, 1, "../arcade/arcade/examples/" - ) - ) - - def on_draw(self): - arcade.start_render() - for layer in self.layers: - layer.draw() - - -class CollisionTestWindow(BasicTestWindow): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.frame_count = 0 - - self.player_list = arcade.SpriteList() - self.player_sprite = arcade.Sprite( - "../arcade/arcade/examples/images/character.png", SPRITE_SCALING - ) - self.player_sprite.center_x = 400 - self.player_sprite.center_y = 800 - self.player_list.append(self.player_sprite) - - self.physics_engine = arcade.PhysicsEnginePlatformer( - self.player_sprite, self.layers[0], gravity_constant=GRAVITY - ) - - def on_draw(self): - super().on_draw() - self.frame_count += 1 - - self.player_list.draw() - - if self.frame_count == 20: - print(self.player_sprite.center_x, self.player_sprite.center_y) - - def update(self, delta_time): - self.physics_engine.update() - - -window = CollisionTestWindow( - SCREEN_WIDTH, - SCREEN_HEIGHT, - "Test Text", - "../arcade/arcade/examples/map_polyline_collision.tmx", -) -arcade.run() diff --git a/test/config.py b/test/config.py deleted file mode 100644 index 12c5f86..0000000 --- a/test/config.py +++ /dev/null @@ -1 +0,0 @@ -MAP_NAME = "assets/tiled_test_4.tmx" diff --git a/test/foo.py b/test/foo.py deleted file mode 100644 index e808462..0000000 --- a/test/foo.py +++ /dev/null @@ -1,1704 +0,0 @@ -{ - "Coins": [ - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="4", - tilewidth=128, - tileheight=128, - source="images/coin_01.png", - points=None, - ), - center_x=704, - center_y=704, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="4", - tilewidth=128, - tileheight=128, - source="images/coin_01.png", - points=None, - ), - center_x=4032, - center_y=704, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="4", - tilewidth=128, - tileheight=128, - source="images/coin_01.png", - points=None, - ), - center_x=5440, - center_y=576, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="4", - tilewidth=128, - tileheight=128, - source="images/coin_01.png", - points=None, - ), - center_x=3392, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - ], - "Platforms": [ - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=3264, - center_y=832, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3392, - center_y=832, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=3520, - center_y=832, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - ], - [ - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=64, - center_y=576, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=2624, - center_y=576, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2752, - center_y=576, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=2880, - center_y=576, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=3904, - center_y=576, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4032, - center_y=576, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=4160, - center_y=576, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=6336, - center_y=576, - ), - ], - [ - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=64, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=576, - center_y=448, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=704, - center_y=448, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=832, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=2112, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=4032, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5440, - center_y=448, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=6336, - center_y=448, - ), - ], - [ - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=64, - center_y=320, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=2112, - center_y=320, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=2240, - center_y=320, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=3264, - center_y=320, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3392, - center_y=320, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=3520, - center_y=320, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=4032, - center_y=320, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5312, - center_y=320, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5440, - center_y=320, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5568, - center_y=320, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=6336, - center_y=320, - ), - ], - [ - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=64, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=1216, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=1984, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=2112, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=2240, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=4032, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=4416, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5184, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5312, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5440, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5568, - center_y=192, - ), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=5696, - center_y=192, - ), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation(tile=None, center_x=None, center_y=None), - GridLocation( - tile=Tile( - gid="0", - tilewidth=128, - tileheight=128, - source="images/boxCrate_double.png", - points=None, - ), - center_x=6336, - center_y=192, - ), - ], - [ - GridLocation( - tile=Tile( - gid="1", - tilewidth=128, - tileheight=128, - source="images/grassLeft.png", - points=None, - ), - center_x=64, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=192, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=320, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=448, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=576, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=704, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=832, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=960, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1088, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1216, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1344, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1472, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1600, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1728, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1856, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=1984, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2112, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2240, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2368, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2496, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2624, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2752, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=2880, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3008, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3136, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3264, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3392, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3520, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3648, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3776, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=3904, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4032, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4160, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4288, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4416, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4544, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4672, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4800, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=4928, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5056, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5184, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5312, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5440, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5568, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5696, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5824, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=5952, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=6080, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="2", - tilewidth=128, - tileheight=128, - source="images/grassMid.png", - points=None, - ), - center_x=6208, - center_y=64, - ), - GridLocation( - tile=Tile( - gid="3", - tilewidth=128, - tileheight=128, - source="images/grassRight.png", - points=None, - ), - center_x=6336, - center_y=64, - ), - ], - ], -} diff --git a/test/test2.py b/test/test2.py deleted file mode 100644 index bc84afc..0000000 --- a/test/test2.py +++ /dev/null @@ -1,29 +0,0 @@ -import arcade - -import config - -from arcade.tiled import read_tiled_map - - -class MyTestWindow(arcade.Window): - def __init__(self, width, height, title): - super().__init__(width, height, title) - self.map = arcade.generate_sprites(my_map, "Tile Layer 1", 1, "./assets/") - - def on_draw(self): - arcade.start_render() - self.map.draw() - - -MAP_NAME = "assets/tiled_test_4.tmx" -my_map = arcade.read_tiled_map(config.MAP_NAME, 1) - -for row in my_map.layers["Tile Layer 1"]: - for grid_object in row: - print(grid_object) - print( - f"{grid_object.tile.local_id}, {grid_object.center_x}, {grid_object.center_y}" - ) -test = MyTestWindow(640, 800, "meme") -test.test() -test.close() diff --git a/test/test_attr.py b/test/test_attr.py deleted file mode 100644 index e3de7d1..0000000 --- a/test/test_attr.py +++ /dev/null @@ -1,22 +0,0 @@ -import attr - - -@attr.s(auto_attribs=True, kw_only=True) -class Foo: - x: int - y: int - - a: int = 5 - - -@attr.s(auto_attribs=True, kw_only=True) -class Bar(Foo): - z: int - - -foo = Foo(x=1, y=2) - -bar = Bar(x=1, y=2, z=3) - -print(foo) -print(bar) diff --git a/test/test_output.py b/test/test_output.py deleted file mode 100644 index e6228d5..0000000 --- a/test/test_output.py +++ /dev/null @@ -1,178 +0,0 @@ -{ - "parent_dir": PosixPath( - "/home/ben/Projects/pytiled_parser/pytiled_parser-venv/pytiled_parser/tests/test_data" - ), - "version": "1.2", - "tiled_version": "1.2.3", - "orientation": "orthogonal", - "render_order": "right-down", - "map_size": Size(width=8, height=6), - "tile_size": Size(width=32, height=32), - "infinite": False, - "next_layer_id": 2, - "next_object_id": 1, - "tile_sets": { - 1: TileSet( - name="tile_set_image", - max_tile_size=Size(width=32, height=32), - spacing=1, - margin=1, - tile_count=48, - columns=8, - tile_offset=None, - grid=None, - properties=None, - image=Image( - source="images/tmw_desert_spacing.png", - size=Size(width=265, height=199), - trans=None, - ), - terrain_types=None, - tiles={ - 9: Tile( - id=9, - type=None, - terrain=None, - animation=None, - image=None, - hitboxes=[ - TiledObject( - id=2, - location=OrderedPair(x=1.0, y=1.0), - size=Size(width=32.0, height=32.0), - rotation=1, - opacity=1, - name="wall", - type="rectangle type", - properties=None, - template=None, - ) - ], - ), - 19: Tile( - id=19, - type=None, - terrain=None, - animation=None, - image=None, - hitboxes=[ - TiledObject( - id=1, - location=OrderedPair(x=32.0, y=1.0), - size=Size(width=0, height=0), - rotation=1, - opacity=1, - name="wall corner", - type="polygon type", - properties=None, - template=None, - ) - ], - ), - 20: Tile( - id=20, - type=None, - terrain=None, - animation=None, - image=None, - hitboxes=[ - TiledObject( - id=1, - location=OrderedPair(x=1.45455, y=1.45455), - size=Size(width=0, height=0), - rotation=1, - opacity=1, - name="polyline", - type="polyline type", - properties=None, - template=None, - ) - ], - ), - 31: Tile( - id=31, - type=None, - terrain=None, - animation=None, - image=None, - hitboxes=[ - TiledObject( - id=1, - location=OrderedPair(x=5.09091, y=2.54545), - size=Size(width=19.6364, height=19.2727), - rotation=1, - opacity=1, - name="rock 1", - type="elipse type", - properties=None, - template=None, - ), - TiledObject( - id=2, - location=OrderedPair(x=16.1818, y=22.0), - size=Size(width=8.54545, height=8.36364), - rotation=-1, - opacity=1, - name="rock 2", - type="elipse type", - properties=None, - template=None, - ), - ], - ), - 45: Tile( - id=45, - type=None, - terrain=None, - animation=None, - image=None, - hitboxes=[ - TiledObject( - id=1, - location=OrderedPair(x=14.7273, y=26.3636), - size=Size(width=0, height=0), - rotation=0, - opacity=1, - name="sign", - type="point type", - properties=None, - template=None, - ) - ], - ), - }, - ) - }, - "layers": [ - TileLayer( - id=1, - name="Tile Layer 1", - offset=None, - opacity=None, - properties=None, - size=Size(width=8, height=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], - ], - ) - ], - "hex_side_length": None, - "stagger_axis": None, - "stagger_index": None, - "background_color": None, - "properties": { - "bool property - false": False, - "bool property - true": True, - "color property": "#ff49fcff", - "file property": PosixPath("../../../../../../../../var/log/syslog"), - "float property": 1.23456789, - "int property": 13, - "string property": "Hello, World!!", - }, -} -e diff --git a/test/test_tiled-bak.py b/test/test_tiled-bak.py deleted file mode 100644 index 9da9391..0000000 --- a/test/test_tiled-bak.py +++ /dev/null @@ -1,32 +0,0 @@ -import arcade -import arcade.tiled - -import pprint - -pp = pprint.PrettyPrinter(indent=4, compact=True, width=200) - - -class MyTestWindow(arcade.Window): - def __init__(self, width, height, title, map_name): - super().__init__(width, height, title) - - self.layers = [] - my_map = arcade.tiled.read_tiled_map(map_name, 1) - pp.pprint(my_map.layers_int_data) - for layer in my_map.layers_int_data: - self.layers.append( - arcade.tiled.generate_sprites( - my_map, layer, 1, "../arcade/arcade/examples/" - ) - ) - - def on_draw(self): - arcade.start_render() - for layer in self.layers: - layer.draw() - - -MAP_NAME = "../arcade/arcade/examples/map_base64_gzip.tmx" - -test = MyTestWindow(640, 800, "meme", MAP_NAME) -arcade.run() diff --git a/test/test_tiled.py b/test/test_tiled.py deleted file mode 100644 index 589aa21..0000000 --- a/test/test_tiled.py +++ /dev/null @@ -1,11 +0,0 @@ -import pickle -import pprint -from io import StringIO - -import pytiled_parser - -MAP_NAME = "/home/ben/Projects/pytiled_parser/pytiled_parser-venv/pytiled_parser/tests/test_data/test_map_simple_hitboxes.tmx" - -map = pytiled_parser.parse_tile_map(MAP_NAME) - -print(map.__dict__) From 60b991542f0b590d053ad348c7e9a627d9c1602f Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 2 Jun 2020 20:07:39 -0400 Subject: [PATCH 072/198] test:add: maps and tilesets for testing --- tests/test_data/test_map_image_tile_set.json | 255 +++++++++++++++++++ tests/test_data/test_map_infinite.json | 195 ++++++++++++++ tests/test_data/test_map_simple.json | 68 +++++ tests/test_data/test_map_simple_meme.json | 70 +++++ tests/test_data/test_map_simple_offset.json | 4 +- tests/test_data/tile_set_image.json | 14 + tests/test_data/tile_set_image_objects.json | 192 ++++++++++++++ 7 files changed, 796 insertions(+), 2 deletions(-) create mode 100644 tests/test_data/test_map_image_tile_set.json create mode 100644 tests/test_data/test_map_infinite.json create mode 100644 tests/test_data/test_map_simple.json create mode 100644 tests/test_data/test_map_simple_meme.json create mode 100644 tests/test_data/tile_set_image.json create mode 100644 tests/test_data/tile_set_image_objects.json diff --git a/tests/test_data/test_map_image_tile_set.json b/tests/test_data/test_map_image_tile_set.json new file mode 100644 index 0000000..954d5c5 --- /dev/null +++ b/tests/test_data/test_map_image_tile_set.json @@ -0,0 +1,255 @@ +{ "compressionlevel":0, + "height":10, + "infinite":false, + "layers":[ + { + "data":[1, 2, 3, 4, 5, 6, 7, 8, 30, 30, 9, 10, 11, 12, 13, 14, 15, 16, 30, 30, 17, 18, 19, 20, 21, 22, 23, 24, 30, 30, 25, 26, 27, 28, 29, 30, 31, 32, 30, 30, 33, 34, 35, 36, 37, 38, 39, 40, 30, 30, 41, 42, 43, 44, 45, 46, 47, 48, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":10, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":10, + "x":0, + "y":0 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 8, 0, 0, 0, 14, 15, 15, 15, 15, 15, 16, 0, 0, 0, 22, 23, 23, 23, 23, 23, 24, 0], + "height":10, + "id":2, + "name":"Tile Layer 2", + "opacity":0.5, + "type":"tilelayer", + "visible":true, + "width":10, + "x":0, + "y":0 + }, + { + "id":3, + "layers":[ + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":10, + "id":5, + "name":"Tile Layer 4", + "offsetx":49, + "offsety":-50, + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":10, + "x":0, + "y":0 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0], + "height":10, + "id":4, + "name":"Tile Layer 3", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":10, + "x":0, + "y":0 + }], + "name":"Group 1", + "opacity":1, + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":true + }], + "type":"group", + "visible":true, + "x":0, + "y":0 + }, + { + "color":"#000000", + "draworder":"index", + "id":6, + "name":"Object Layer 1", + "objects":[ + { + "height":25, + "id":1, + "name":"rectangle 1", + "rotation":15, + "type":"rectangle type", + "visible":true, + "width":47.25, + "x":200.25, + "y":210.75 + }, + { + "height":0, + "id":2, + "name":"polygon 1", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-41.25, + "y":24.25 + }, + { + "x":-11, + "y":67.25 + }, + { + "x":25.75, + "y":39.75 + }, + { + "x":-9, + "y":37.75 + }], + "rotation":-21, + "type":"polygon type", + "visible":true, + "width":0, + "x":252.5, + "y":87.75 + }, + { + "ellipse":true, + "height":14.25, + "id":3, + "name":"elipse 1", + "rotation":0, + "type":"elipse type", + "visible":true, + "width":17.75, + "x":198.75, + "y":102.5 + }, + { + "height":0, + "id":4, + "name":"point 1", + "point":true, + "rotation":0, + "type":"point type", + "visible":true, + "width":0, + "x":174.25, + "y":186 + }, + { + "height":27.25, + "id":7, + "name":"insert text 1", + "rotation":0, + "text": + { + "color":"#b40303", + "fontfamily":"Sans Serif", + "italic":true, + "pixelsize":17, + "strikeout":true, + "text":"Hello World", + "underline":true, + "wrap":true + }, + "type":"insert text type", + "visible":true, + "width":107.625, + "x":11.3958, + "y":48.5833 + }, + { + "gid":3221225503, + "height":53, + "id":6, + "name":"inserted tile 1", + "properties":[ + { + "name":"tile property bool", + "type":"bool", + "value":true + }], + "rotation":31, + "type":"inserted tile type", + "visible":true, + "width":47, + "x":47.25, + "y":72.5 + }, + { + "height":0, + "id":8, + "name":"polyline 1", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":-14.3333, + "y":35.6667 + }, + { + "x":15.3333, + "y":18.3333 + }], + "rotation":0, + "type":"polyline type", + "visible":true, + "width":0, + "x":144.667, + "y":112 + }, + { + "height":0, + "id":9, + "name":"polygon 2", + "polygon":[ + { + "x":-3.25, + "y":-17.25 + }, + { + "x":-15, + "y":10.75 + }, + { + "x":20.75, + "y":4.5 + }], + "rotation":0, + "type":"polygon type", + "visible":true, + "width":0, + "x":69.8333, + "y":168.333 + }], + "offsetx":4.66667, + "offsety":-4.33333, + "opacity":0.9, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":16, + "nextobjectid":10, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tile_set_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":10 +} diff --git a/tests/test_data/test_map_infinite.json b/tests/test_data/test_map_infinite.json new file mode 100644 index 0000000..01d9432 --- /dev/null +++ b/tests/test_data/test_map_infinite.json @@ -0,0 +1,195 @@ +{ "compressionlevel":0, + "height":6, + "infinite":true, + "layers":[ + { + "chunks":[ + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-32, + "y":-32 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-16, + "y":-32 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":0, + "y":-32 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":16, + "y":-32 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-32, + "y":-16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 1, 2, 3, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 9, 10, 11, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 17, 18, 19], + "height":16, + "width":16, + "x":-16, + "y":-16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 4, 5, 6, 7, 8, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 12, 13, 14, 15, 16, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 20, 21, 22, 23, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":0, + "y":-16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":16, + "y":-16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-32, + "y":0 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 25, 26, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 33, 34, 35, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 41, 42, 43, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-16, + "y":0 + }, + { + "data":[28, 29, 30, 31, 32, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 36, 37, 38, 39, 40, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 44, 45, 46, 47, 48, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":0, + "y":0 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":16, + "y":0 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-32, + "y":16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":-16, + "y":16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":0, + "y":16 + }, + { + "data":[30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], + "height":16, + "width":16, + "x":16, + "y":16 + }], + "height":64, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "startx":-32, + "starty":-32, + "type":"tilelayer", + "visible":true, + "width":64, + "x":0, + "y":0 + }, + { + "chunks":[ + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":-32, + "y":-16 + }, + { + "data":[0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":16, + "y":-16 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":-16, + "y":0 + }, + { + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":16, + "y":0 + }, + { + "data":[28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":-16, + "y":16 + }], + "height":48, + "id":2, + "name":"Tile Layer 2", + "opacity":1, + "startx":-32, + "starty":-16, + "type":"tilelayer", + "visible":true, + "width":64, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tile_set_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} diff --git a/tests/test_data/test_map_simple.json b/tests/test_data/test_map_simple.json new file mode 100644 index 0000000..56f0c67 --- /dev/null +++ b/tests/test_data/test_map_simple.json @@ -0,0 +1,68 @@ +{ "compressionlevel":0, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/var\/log\/syslog" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tile_set_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} diff --git a/tests/test_data/test_map_simple_meme.json b/tests/test_data/test_map_simple_meme.json new file mode 100644 index 0000000..858702a --- /dev/null +++ b/tests/test_data/test_map_simple_meme.json @@ -0,0 +1,70 @@ +{ "compressionlevel":0, + "height":6, + "infinite":false, + "layers":[ + { + "compression":"gzip", + "data":"H4sIAAAAAAAEAw3DBRKCQAAAwDMRA7BQLMTE9v+vY3dmWyGEth279uwbOTB26MixExNTM6fOnLtwae7KtYUbt+7ce7D0aOXJsxev3rxb+\/Dpy7cfv\/782wAcvDirwAAAAA==", + "encoding":"base64", + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/..\/..\/var\/log\/syslog" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tile_set_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} diff --git a/tests/test_data/test_map_simple_offset.json b/tests/test_data/test_map_simple_offset.json index bc3f4f5..0a23653 100644 --- a/tests/test_data/test_map_simple_offset.json +++ b/tests/test_data/test_map_simple_offset.json @@ -71,10 +71,10 @@ "tilesets":[ { "firstgid":1, - "source":"..\/..\/old_tests\/test_data\/tile_set_image.tsx" + "source":"tile_set_image.json" }], "tilewidth":32, "type":"map", "version":1.2, "width":8 -} \ No newline at end of file +} diff --git a/tests/test_data/tile_set_image.json b/tests/test_data/tile_set_image.json new file mode 100644 index 0000000..25b87a2 --- /dev/null +++ b/tests/test_data/tile_set_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/tile_set_image_objects.json b/tests/test_data/tile_set_image_objects.json new file mode 100644 index 0000000..83a46ff --- /dev/null +++ b/tests/test_data/tile_set_image_objects.json @@ -0,0 +1,192 @@ +{ "columns":8, + "image":"images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tiles":[ + { + "id":9, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":32, + "id":2, + "name":"wall", + "rotation":1, + "type":"rectangle type", + "visible":true, + "width":32, + "x":1, + "y":1 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":19, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"wall corner", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-32, + "y":0 + }, + { + "x":-32, + "y":32 + }, + { + "x":-16, + "y":32.1818 + }, + { + "x":-15.8182, + "y":16.9091 + }, + { + "x":0.181818, + "y":17.0909 + }], + "rotation":1, + "type":"polygon type", + "visible":true, + "width":0, + "x":32, + "y":1 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":20, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"polyline", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":25.0909, + "y":21.2727 + }, + { + "x":9.63636, + "y":28.3636 + }], + "rotation":1, + "type":"polyline type", + "visible":true, + "width":0, + "x":1.45455, + "y":1.45455 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":31, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "ellipse":true, + "height":19.2727, + "id":1, + "name":"rock 1", + "rotation":1, + "type":"elipse type", + "visible":true, + "width":19.6364, + "x":5.09091, + "y":2.54545 + }, + { + "ellipse":true, + "height":8.36364, + "id":2, + "name":"rock 2", + "rotation":-1, + "type":"elipse type", + "visible":true, + "width":8.54545, + "x":16.1818, + "y":22 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":45, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"sign", + "point":true, + "rotation":0, + "type":"point type", + "visible":true, + "width":0, + "x":14.7273, + "y":26.3636 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }], + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file From c68a939cf9a5114311ffc3da14b3011310fd89e2 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 2 Jun 2020 20:35:42 -0400 Subject: [PATCH 073/198] test:chore: organized all the current test maps --- .../all_objects.json} | 4 +- .../tileset_image.json} | 2 +- .../tileset_image_objects.json} | 6 +- .../simple_external_tileset/map.json | 68 ----- .../map_simple_external_tileset.json} | 2 +- .../tileset_image.json} | 4 +- .../map_infinite.json} | 2 +- .../simple_infinite/tileset_image.json | 14 + .../map_simple_offset.json} | 2 +- .../simple_offset/tileset_image.json | 14 + tests/test_data/test_map_image_tile_set.json | 255 ------------------ tests/test_data/test_map_simple_meme.json | 70 ----- 12 files changed, 39 insertions(+), 404 deletions(-) rename tests/test_data/{simple_objects.json => all_objects/all_objects.json} (99%) rename tests/test_data/{simple_external_tileset/tile_set.json => all_objects/tileset_image.json} (99%) rename tests/test_data/{tile_set_image_objects.json => all_objects/tileset_image_objects.json} (98%) delete mode 100644 tests/test_data/simple_external_tileset/map.json rename tests/test_data/{test_map_simple.json => simple_external_tileset/map_simple_external_tileset.json} (97%) rename tests/test_data/{tile_set_image.json => simple_external_tileset/tileset_image.json} (81%) rename tests/test_data/{test_map_infinite.json => simple_infinite/map_infinite.json} (99%) create mode 100644 tests/test_data/simple_infinite/tileset_image.json rename tests/test_data/{test_map_simple_offset.json => simple_offset/map_simple_offset.json} (97%) create mode 100644 tests/test_data/simple_offset/tileset_image.json delete mode 100644 tests/test_data/test_map_image_tile_set.json delete mode 100644 tests/test_data/test_map_simple_meme.json diff --git a/tests/test_data/simple_objects.json b/tests/test_data/all_objects/all_objects.json similarity index 99% rename from tests/test_data/simple_objects.json rename to tests/test_data/all_objects/all_objects.json index dbf407c..c75c2ea 100644 --- a/tests/test_data/simple_objects.json +++ b/tests/test_data/all_objects/all_objects.json @@ -635,11 +635,11 @@ "tilesets": [ { "firstgid": 1, - "source": "../../old_tests/test_data/tile_set_image_objects.tsx" + "source": "tileset_image_objects.json" }, { "firstgid": 49, - "source": "../../old_tests/test_data/tile_set_image.tsx" + "source": "tileset_image.json" } ], "tilewidth": 32, diff --git a/tests/test_data/simple_external_tileset/tile_set.json b/tests/test_data/all_objects/tileset_image.json similarity index 99% rename from tests/test_data/simple_external_tileset/tile_set.json rename to tests/test_data/all_objects/tileset_image.json index c1431bb..8f3b73e 100644 --- a/tests/test_data/simple_external_tileset/tile_set.json +++ b/tests/test_data/all_objects/tileset_image.json @@ -11,4 +11,4 @@ "tilewidth":32, "type":"tileset", "version":1.2 -} \ No newline at end of file +} diff --git a/tests/test_data/tile_set_image_objects.json b/tests/test_data/all_objects/tileset_image_objects.json similarity index 98% rename from tests/test_data/tile_set_image_objects.json rename to tests/test_data/all_objects/tileset_image_objects.json index 83a46ff..6ceb5be 100644 --- a/tests/test_data/tile_set_image_objects.json +++ b/tests/test_data/all_objects/tileset_image_objects.json @@ -1,11 +1,11 @@ { "columns":8, - "image":"images\/tmw_desert_spacing.png", + "image":"..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, "name":"tile_set_image", "spacing":1, - "tilecount":48, + "tilecount":5, "tiledversion":"1.3.1", "tileheight":32, "tiles":[ @@ -189,4 +189,4 @@ "tilewidth":32, "type":"tileset", "version":1.2 -} \ No newline at end of file +} diff --git a/tests/test_data/simple_external_tileset/map.json b/tests/test_data/simple_external_tileset/map.json deleted file mode 100644 index 1b89be4..0000000 --- a/tests/test_data/simple_external_tileset/map.json +++ /dev/null @@ -1,68 +0,0 @@ -{ "compressionlevel":0, - "height":6, - "infinite":false, - "layers":[ - { - "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], - "height":6, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":8, - "x":0, - "y":0 - }], - "nextlayerid":2, - "nextobjectid":1, - "orientation":"orthogonal", - "properties":[ - { - "name":"bool property - false", - "type":"bool", - "value":false - }, - { - "name":"bool property - true", - "type":"bool", - "value":true - }, - { - "name":"color property", - "type":"color", - "value":"#ff49fcff" - }, - { - "name":"file property", - "type":"file", - "value":"..\/..\/..\/..\/..\/..\/..\/var\/log\/syslog" - }, - { - "name":"float property", - "type":"float", - "value":1.23456789 - }, - { - "name":"int property", - "type":"int", - "value":13 - }, - { - "name":"string property", - "type":"string", - "value":"Hello, World!!" - }], - "renderorder":"right-down", - "tiledversion":"1.3.1", - "tileheight":32, - "tilesets":[ - { - "firstgid":1, - "source":"tile_set.json" - }], - "tilewidth":32, - "type":"map", - "version":1.2, - "width":8 -} \ No newline at end of file diff --git a/tests/test_data/test_map_simple.json b/tests/test_data/simple_external_tileset/map_simple_external_tileset.json similarity index 97% rename from tests/test_data/test_map_simple.json rename to tests/test_data/simple_external_tileset/map_simple_external_tileset.json index 56f0c67..e68a7f7 100644 --- a/tests/test_data/test_map_simple.json +++ b/tests/test_data/simple_external_tileset/map_simple_external_tileset.json @@ -59,7 +59,7 @@ "tilesets":[ { "firstgid":1, - "source":"tile_set_image.json" + "source":"tileset_image.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/tile_set_image.json b/tests/test_data/simple_external_tileset/tileset_image.json similarity index 81% rename from tests/test_data/tile_set_image.json rename to tests/test_data/simple_external_tileset/tileset_image.json index 25b87a2..8f3b73e 100644 --- a/tests/test_data/tile_set_image.json +++ b/tests/test_data/simple_external_tileset/tileset_image.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"images\/tmw_desert_spacing.png", + "image":"..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, @@ -11,4 +11,4 @@ "tilewidth":32, "type":"tileset", "version":1.2 -} \ No newline at end of file +} diff --git a/tests/test_data/test_map_infinite.json b/tests/test_data/simple_infinite/map_infinite.json similarity index 99% rename from tests/test_data/test_map_infinite.json rename to tests/test_data/simple_infinite/map_infinite.json index 01d9432..2543f7b 100644 --- a/tests/test_data/test_map_infinite.json +++ b/tests/test_data/simple_infinite/map_infinite.json @@ -186,7 +186,7 @@ "tilesets":[ { "firstgid":1, - "source":"tile_set_image.json" + "source":"tileset_image.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/simple_infinite/tileset_image.json b/tests/test_data/simple_infinite/tileset_image.json new file mode 100644 index 0000000..8f3b73e --- /dev/null +++ b/tests/test_data/simple_infinite/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_data/test_map_simple_offset.json b/tests/test_data/simple_offset/map_simple_offset.json similarity index 97% rename from tests/test_data/test_map_simple_offset.json rename to tests/test_data/simple_offset/map_simple_offset.json index 0a23653..bea06b9 100644 --- a/tests/test_data/test_map_simple_offset.json +++ b/tests/test_data/simple_offset/map_simple_offset.json @@ -71,7 +71,7 @@ "tilesets":[ { "firstgid":1, - "source":"tile_set_image.json" + "source":"tileset_image.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/simple_offset/tileset_image.json b/tests/test_data/simple_offset/tileset_image.json new file mode 100644 index 0000000..8f3b73e --- /dev/null +++ b/tests/test_data/simple_offset/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_data/test_map_image_tile_set.json b/tests/test_data/test_map_image_tile_set.json deleted file mode 100644 index 954d5c5..0000000 --- a/tests/test_data/test_map_image_tile_set.json +++ /dev/null @@ -1,255 +0,0 @@ -{ "compressionlevel":0, - "height":10, - "infinite":false, - "layers":[ - { - "data":[1, 2, 3, 4, 5, 6, 7, 8, 30, 30, 9, 10, 11, 12, 13, 14, 15, 16, 30, 30, 17, 18, 19, 20, 21, 22, 23, 24, 30, 30, 25, 26, 27, 28, 29, 30, 31, 32, 30, 30, 33, 34, 35, 36, 37, 38, 39, 40, 30, 30, 41, 42, 43, 44, 45, 46, 47, 48, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], - "height":10, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":10, - "x":0, - "y":0 - }, - { - "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 8, 0, 0, 0, 14, 15, 15, 15, 15, 15, 16, 0, 0, 0, 22, 23, 23, 23, 23, 23, 24, 0], - "height":10, - "id":2, - "name":"Tile Layer 2", - "opacity":0.5, - "type":"tilelayer", - "visible":true, - "width":10, - "x":0, - "y":0 - }, - { - "id":3, - "layers":[ - { - "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - "height":10, - "id":5, - "name":"Tile Layer 4", - "offsetx":49, - "offsety":-50, - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":10, - "x":0, - "y":0 - }, - { - "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 9, 10, 11, 0, 0, 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0], - "height":10, - "id":4, - "name":"Tile Layer 3", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":10, - "x":0, - "y":0 - }], - "name":"Group 1", - "opacity":1, - "properties":[ - { - "name":"bool property", - "type":"bool", - "value":true - }], - "type":"group", - "visible":true, - "x":0, - "y":0 - }, - { - "color":"#000000", - "draworder":"index", - "id":6, - "name":"Object Layer 1", - "objects":[ - { - "height":25, - "id":1, - "name":"rectangle 1", - "rotation":15, - "type":"rectangle type", - "visible":true, - "width":47.25, - "x":200.25, - "y":210.75 - }, - { - "height":0, - "id":2, - "name":"polygon 1", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":-41.25, - "y":24.25 - }, - { - "x":-11, - "y":67.25 - }, - { - "x":25.75, - "y":39.75 - }, - { - "x":-9, - "y":37.75 - }], - "rotation":-21, - "type":"polygon type", - "visible":true, - "width":0, - "x":252.5, - "y":87.75 - }, - { - "ellipse":true, - "height":14.25, - "id":3, - "name":"elipse 1", - "rotation":0, - "type":"elipse type", - "visible":true, - "width":17.75, - "x":198.75, - "y":102.5 - }, - { - "height":0, - "id":4, - "name":"point 1", - "point":true, - "rotation":0, - "type":"point type", - "visible":true, - "width":0, - "x":174.25, - "y":186 - }, - { - "height":27.25, - "id":7, - "name":"insert text 1", - "rotation":0, - "text": - { - "color":"#b40303", - "fontfamily":"Sans Serif", - "italic":true, - "pixelsize":17, - "strikeout":true, - "text":"Hello World", - "underline":true, - "wrap":true - }, - "type":"insert text type", - "visible":true, - "width":107.625, - "x":11.3958, - "y":48.5833 - }, - { - "gid":3221225503, - "height":53, - "id":6, - "name":"inserted tile 1", - "properties":[ - { - "name":"tile property bool", - "type":"bool", - "value":true - }], - "rotation":31, - "type":"inserted tile type", - "visible":true, - "width":47, - "x":47.25, - "y":72.5 - }, - { - "height":0, - "id":8, - "name":"polyline 1", - "polyline":[ - { - "x":0, - "y":0 - }, - { - "x":-14.3333, - "y":35.6667 - }, - { - "x":15.3333, - "y":18.3333 - }], - "rotation":0, - "type":"polyline type", - "visible":true, - "width":0, - "x":144.667, - "y":112 - }, - { - "height":0, - "id":9, - "name":"polygon 2", - "polygon":[ - { - "x":-3.25, - "y":-17.25 - }, - { - "x":-15, - "y":10.75 - }, - { - "x":20.75, - "y":4.5 - }], - "rotation":0, - "type":"polygon type", - "visible":true, - "width":0, - "x":69.8333, - "y":168.333 - }], - "offsetx":4.66667, - "offsety":-4.33333, - "opacity":0.9, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }], - "nextlayerid":16, - "nextobjectid":10, - "orientation":"orthogonal", - "renderorder":"right-down", - "tiledversion":"1.3.1", - "tileheight":32, - "tilesets":[ - { - "firstgid":1, - "source":"tile_set_image.json" - }], - "tilewidth":32, - "type":"map", - "version":1.2, - "width":10 -} diff --git a/tests/test_data/test_map_simple_meme.json b/tests/test_data/test_map_simple_meme.json deleted file mode 100644 index 858702a..0000000 --- a/tests/test_data/test_map_simple_meme.json +++ /dev/null @@ -1,70 +0,0 @@ -{ "compressionlevel":0, - "height":6, - "infinite":false, - "layers":[ - { - "compression":"gzip", - "data":"H4sIAAAAAAAEAw3DBRKCQAAAwDMRA7BQLMTE9v+vY3dmWyGEth279uwbOTB26MixExNTM6fOnLtwae7KtYUbt+7ce7D0aOXJsxev3rxb+\/Dpy7cfv\/782wAcvDirwAAAAA==", - "encoding":"base64", - "height":6, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":8, - "x":0, - "y":0 - }], - "nextlayerid":2, - "nextobjectid":1, - "orientation":"orthogonal", - "properties":[ - { - "name":"bool property - false", - "type":"bool", - "value":false - }, - { - "name":"bool property - true", - "type":"bool", - "value":true - }, - { - "name":"color property", - "type":"color", - "value":"#ff49fcff" - }, - { - "name":"file property", - "type":"file", - "value":"..\/..\/..\/..\/..\/..\/..\/..\/var\/log\/syslog" - }, - { - "name":"float property", - "type":"float", - "value":1.23456789 - }, - { - "name":"int property", - "type":"int", - "value":13 - }, - { - "name":"string property", - "type":"string", - "value":"Hello, World!!" - }], - "renderorder":"right-down", - "tiledversion":"1.3.1", - "tileheight":32, - "tilesets":[ - { - "firstgid":1, - "source":"tile_set_image.json" - }], - "tilewidth":32, - "type":"map", - "version":1.2, - "width":8 -} From f09abd1f48e503f1e91d8e192fe2f442cc2811b4 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 2 Jun 2020 20:44:23 -0400 Subject: [PATCH 074/198] rf(tileset): underscore appended to attribute this is unnessesary for attributes, as it does not overwrite the built-in --- pytiled_parser/tileset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 15d4523..8d30e06 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -112,8 +112,8 @@ class Tile: animation: Each tile can have exactly one animation associated with it. """ - id_: int - type_: Optional[str] = None + id: int + type: Optional[str] = None terrain: Optional[TileTerrain] = None animation: Optional[List[Frame]] = None objectgroup: Optional[List[TiledObject]] = None From d3fe310d7ff75f64d3007d5337d7595c30fa9d6b Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 2 Jun 2020 20:45:33 -0400 Subject: [PATCH 075/198] Implemented TypedDicts for the raw data of all classes within TileSet --- pytiled_parser/tileset.py | 92 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 15d4523..f21f7fd 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -3,10 +3,11 @@ from pathlib import Path from typing import Dict, List, NamedTuple, Optional import attr +from typing_extensions import TypedDict -from pytiled_parser import OrderedPair, Size -from pytiled_parser.properties import Properties, Property -from pytiled_parser.tiled_object import TiledObject +from . import properties as properties_ +from .common_types import OrderedPair, Size +from .tiled_object import TiledObject class Grid(NamedTuple): @@ -118,7 +119,7 @@ class Tile: animation: Optional[List[Frame]] = None objectgroup: Optional[List[TiledObject]] = None image: Optional[Image] = None - properties: Optional[List[Property]] = None + properties: Optional[List[properties_.Property]] = None tileset: Optional["TileSet"] = None flipped_horizontally: bool = False flipped_diagonally: bool = False @@ -163,7 +164,7 @@ class TileSet: columns: Optional[int] = None tile_offset: Optional[OrderedPair] = None grid: Optional[Grid] = None - properties: Optional[Properties] = None + properties: Optional[properties_.Properties] = None image: Optional[Image] = None terrain_types: Optional[List[Terrain]] = None tiles: Optional[Dict[int, Tile]] = None @@ -171,5 +172,84 @@ class TileSet: parent_dir: Path = None -def parse(): +class RawFrame(TypedDict): + """ The keys and their types that appear in a Frame JSON Object.""" + + duration: int + tileid: int + + +class RawTileOffset(TypedDict): + """ The keys and their types that appear in a TileOffset JSON Object.""" + + x: int + y: int + + +class RawTerrain(TypedDict): + """ The keys and their types that appear in a Terrain JSON Object.""" + + name: str + properties: List[properties_.RawProperty] + tile: int + + +class RawTile(TypedDict): + """ The keys and their types that appear in a Tile JSON Object. + FIXME Implement objectgroup, can't be done until TileLayer's are implemented""" + + animation: List[RawFrame] + id: int + image: str + imageheight: int + imagewidth: int + probability: float + properties: List[properties_.RawProperty] + terrain: List[RawTerrain] + type: str + + +class RawGrid(TypedDict): + """ The keys and their types that appear in a Grid JSON Object.""" + + height: int + width: int + orientation: str + + +class RawTileSet(TypedDict): + """ The keys and their types that appear in a TileSet JSON Object.""" + + backgroundcolor: str + columns: int + firstgid: int + grid: RawGrid + image: str + imageheight: int + imagewidth: int + margin: int + name: str + properties: List[properties_.RawProperty] + source: str + spacing: int + terrains: List[RawTerrain] + tilecount: int + tiledversion: str + tileheight: int + tileoffset: RawTileOffset + tiles: List[RawTile] + tilewidth: int + transparentcolor: str + type: str + version: float + + +def cast(raw_tileset: RawTileSet) -> TileSet: + """ Cast the raw tileset into a pytiled_parser type + + Args: + raw_tileset: Raw Tileset to be cast. + + Returns: + TileSet: a properly typed TileSet. pass From b735857fe64500de433fbc006b7807e8964688ed Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 20:10:40 -0400 Subject: [PATCH 076/198] test: tileset stuff --- pytiled_parser/tileset.py | 2 +- tests/test_data/tilesets/tileset_image.json | 14 ++ .../tilesets/tileset_image_objects.json | 192 ++++++++++++++++++ tests/test_tileset.py | 23 +++ 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 tests/test_data/tilesets/tileset_image.json create mode 100644 tests/test_data/tilesets/tileset_image_objects.json create mode 100644 tests/test_tileset.py diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 8d30e06..c615813 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -171,5 +171,5 @@ class TileSet: parent_dir: Path = None -def parse(): +def cast(): pass diff --git a/tests/test_data/tilesets/tileset_image.json b/tests/test_data/tilesets/tileset_image.json new file mode 100644 index 0000000..8f3b73e --- /dev/null +++ b/tests/test_data/tilesets/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_data/tilesets/tileset_image_objects.json b/tests/test_data/tilesets/tileset_image_objects.json new file mode 100644 index 0000000..6ceb5be --- /dev/null +++ b/tests/test_data/tilesets/tileset_image_objects.json @@ -0,0 +1,192 @@ +{ "columns":8, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":5, + "tiledversion":"1.3.1", + "tileheight":32, + "tiles":[ + { + "id":9, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":32, + "id":2, + "name":"wall", + "rotation":1, + "type":"rectangle type", + "visible":true, + "width":32, + "x":1, + "y":1 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":19, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"wall corner", + "polygon":[ + { + "x":0, + "y":0 + }, + { + "x":-32, + "y":0 + }, + { + "x":-32, + "y":32 + }, + { + "x":-16, + "y":32.1818 + }, + { + "x":-15.8182, + "y":16.9091 + }, + { + "x":0.181818, + "y":17.0909 + }], + "rotation":1, + "type":"polygon type", + "visible":true, + "width":0, + "x":32, + "y":1 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":20, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"polyline", + "polyline":[ + { + "x":0, + "y":0 + }, + { + "x":25.0909, + "y":21.2727 + }, + { + "x":9.63636, + "y":28.3636 + }], + "rotation":1, + "type":"polyline type", + "visible":true, + "width":0, + "x":1.45455, + "y":1.45455 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":31, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "ellipse":true, + "height":19.2727, + "id":1, + "name":"rock 1", + "rotation":1, + "type":"elipse type", + "visible":true, + "width":19.6364, + "x":5.09091, + "y":2.54545 + }, + { + "ellipse":true, + "height":8.36364, + "id":2, + "name":"rock 2", + "rotation":-1, + "type":"elipse type", + "visible":true, + "width":8.54545, + "x":16.1818, + "y":22 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }, + { + "id":45, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":0, + "id":1, + "name":"sign", + "point":true, + "rotation":0, + "type":"point type", + "visible":true, + "width":0, + "x":14.7273, + "y":26.3636 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + } + }], + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_tileset.py b/tests/test_tileset.py new file mode 100644 index 0000000..63f313e --- /dev/null +++ b/tests/test_tileset.py @@ -0,0 +1,23 @@ +"""Tests for tilesets""" +import json +import os +from pathlib import Path + +import pytest + +from pytiled_parser import tileset + +TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) +TEST_DATA = TESTS_DIR / "test_data" +TILE_SETS = TEST_DATA / "tilesets" + + +ALL_TILESETS = TILE_SETS.glob("*.json") + + +@pytest.mark.parametrize("raw_tileset", ALL_TILESETS) +def test_tilesets_integration(raw_tileset): + """ This could be redundant, but it is useful just to ensure that anything in there + is at least sanity checked""" + tileset_ = tileset.cast(json.loads(raw_tileset)) + assert tileset_ is not None From f658e763ebfb99f972ecfdd20c448530ea58447f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 20:15:07 -0400 Subject: [PATCH 077/198] Updates to tileset casting --- pytiled_parser/tileset.py | 175 ++++++++++++++++++++++++++++++-------- 1 file changed, 139 insertions(+), 36 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 0f78d96..c82a782 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -6,7 +6,7 @@ import attr from typing_extensions import TypedDict from . import properties as properties_ -from .common_types import OrderedPair, Size +from .common_types import Color, OrderedPair, Size from .tiled_object import TiledObject @@ -28,29 +28,6 @@ class Grid(NamedTuple): height: int -@attr.s(auto_attribs=True) -class Image: - """Image object. - - pytiled_parser does not support embedded data in image elements at this time, - even though the TMX format technically does. - - Attributes: - source: The reference to the tileset image file. Note that this is a relative - path compared to FIXME - trans: Defines a specific color that is treated as transparent. - width: The image width in pixels (optional, used for tile index correction when - the image changes). - height: The image height in pixels (optional). - """ - - source: str - size: Optional[Size] = None - trans: Optional[str] = None - width: Optional[int] = None - height: Optional[int] = None - - class Terrain(NamedTuple): """Terrain object. @@ -61,6 +38,7 @@ class Terrain(NamedTuple): name: str tile: int + properties: properties_.Properties = {} @attr.s(auto_attribs=True) @@ -118,8 +96,10 @@ class Tile: terrain: Optional[TileTerrain] = None animation: Optional[List[Frame]] = None objectgroup: Optional[List[TiledObject]] = None - image: Optional[Image] = None - properties: Optional[List[properties_.Property]] = None + image: Optional[str] = None + image_width: Optional[int] = None + image_height: Optional[int] = None + properties: Optional[properties_.Properties] = None tileset: Optional["TileSet"] = None flipped_horizontally: bool = False flipped_diagonally: bool = False @@ -156,20 +136,32 @@ class TileSet: """ name: str - max_tile_size: Size + tile_width: int + tile_height: int + firstgid: int + + image: str + image_width: int + image_height: int + + tile_count: int + columns: int + + background_color: Color + + source_file: Path + + tiled_version: int + + spacing: int = 0 + margin: int = 0 - spacing: Optional[int] = None - margin: Optional[int] = None - tile_count: Optional[int] = None - columns: Optional[int] = None tile_offset: Optional[OrderedPair] = None + transparent_color: Optional[Color] = None grid: Optional[Grid] = None properties: Optional[properties_.Properties] = None - image: Optional[Image] = None terrain_types: Optional[List[Terrain]] = None - tiles: Optional[Dict[int, Tile]] = None - tsx_file: Path = None - parent_dir: Path = None + tiles: Optional[List[Tile]] = None class RawFrame(TypedDict): @@ -205,7 +197,7 @@ class RawTile(TypedDict): imagewidth: int probability: float properties: List[properties_.RawProperty] - terrain: List[RawTerrain] + terrain: List[int] type: str @@ -252,4 +244,115 @@ def cast(raw_tileset: RawTileSet) -> TileSet: Returns: TileSet: a properly typed TileSet. + """ + pass + + +def _cast_frame(raw_frame: RawFrame) -> Frame: + """ Cast the raw_frame to a Frame. + + Args: + raw_frame: RawFrame to be casted to a Frame + + Returns: + Frame: The Frame created from the raw_frame + """ + + return Frame(duration=raw_frame["duration"], tile_id=raw_frame["tileid"]) + + +def _cast_tile_offset(raw_tile_offset: RawTileOffset) -> OrderedPair: + """ Cast the raw_tile_offset to an OrderedPair. + + Args: + raw_tile_offset: RawTileOffset to be casted to an OrderedPair + + Returns: + OrderedPair: The OrderedPair created from the raw_tile_offset + """ + + return OrderedPair(raw_tile_offset["x"], raw_tile_offset["y"]) + + +def _cast_terrain(raw_terrain: RawTerrain) -> Terrain: + """ Cast the raw_terrain to a Terrain object. + + Args: + raw_terrain: RawTerrain to be casted to a Terrain + + Returns: + Terrain: The Terrain created from the raw_terrain + """ + + if raw_terrain.get("properties") is not None: + return Terrain( + name=raw_terrain["name"], + tile=raw_terrain["tile"], + properties=properties_.cast(raw_terrain["properties"]), + ) + else: + 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. + + Args: + raw_tile: RawTile to be casted to a Tile + + Returns: + Tile: The Tile created from the raw_tile + """ + + id_ = raw_tile["id"] + tile = Tile(id=id_) + + if raw_tile.get("animation") is not None: + tile.animation = [] + for frame in raw_tile["animation"]: + tile.animation.append(_cast_frame(frame)) + + if raw_tile.get("properties") is not None: + tile.properties = properties_.cast(raw_tile["properties"]) + + if raw_tile.get("image") is not None: + tile.image = raw_tile["image"] + + if raw_tile.get("imagewidth") is not None: + tile.image_width = raw_tile["imagewidth"] + + if raw_tile.get("imageheight") is not None: + tile.image_height = raw_tile["imageheight"] + + if raw_tile.get("terrain") is not None: + raw_terrain = raw_tile["terrain"] + terrain = TileTerrain( + top_left=raw_terrain[0], + top_right=raw_terrain[1], + bottom_left=raw_terrain[2], + bottom_right=raw_terrain[3], + ) + tile.terrain = terrain + + if raw_tile.get("type") is not None: + tile.type = raw_tile["type"] + + return tile + + +def _cast_grid(raw_grid: RawGrid) -> Grid: + """ Cast the raw_grid to a Grid object. + + Args: + raw_grid: RawGrid to be casted to a Grid + + Returns: + Grid: The Grid created from the raw_grid + """ + + return Grid( + orientation=raw_grid["orientation"], + width=raw_grid["width"], + height=raw_grid["height"], + ) From 8d25142f482919440dbae46513f91d5bc7943f49 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 20:42:11 -0400 Subject: [PATCH 078/198] add(layer): the missing objects --- pytiled_parser/layer.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 76c3632..ef0be1f 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -6,6 +6,7 @@ import attr from .common_types import OrderedPair, Size from .properties import Properties +from .tiled_object import TiledObject @attr.s(auto_attribs=True, kw_only=True) @@ -83,3 +84,41 @@ class TileLayer(Layer): size: Size layer_data: LayerData + + +@attr.s(auto_attribs=True, kw_only=True) +class ObjectLayer(Layer): + """ + TiledObject Group Object. + The object group is in fact a map layer, and is hence called "object layer" in + Tiled. + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#objectgroup + Args: + tiled_objects: List of tiled_objects in the layer. + offset: Rendering offset of the layer object in pixels. + color: The color used to display the objects in this group. FIXME: editor only? + draworder: Whether the objects are drawn according to the order of the object + elements in the object group element ('manual'), or sorted by their + y-coordinate ('topdown'). Defaults to 'topdown'. See: + https://doc.mapeditor.org/en/stable/manual/objects/#changing-stacking-order + for more info. + """ + + tiled_objects: List[TiledObject] + + color: Optional[str] = None + draw_order: Optional[str] = "topdown" + + +@attr.s(auto_attribs=True, kw_only=True) +class LayerGroup(Layer): + """Layer Group. + A LayerGroup can be thought of as a layer that contains layers + (potentially including other LayerGroups). + Offset and opacity recursively affect child layers. + See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group + Attributes: + Layers: Layers in group. + """ + + layers: Optional[List[Union["LayerGroup", Layer, ObjectLayer]]] From e9999ad9fe5cc6e0a22553418161245f04655ca1 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 20:44:53 -0400 Subject: [PATCH 079/198] Implemented tileset casting --- pytiled_parser/tileset.py | 84 ++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index c82a782..5195fc6 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -138,30 +138,29 @@ class TileSet: name: str tile_width: int tile_height: int - firstgid: int - image: str + image: Path image_width: int image_height: int tile_count: int columns: int - background_color: Color - - source_file: Path - - tiled_version: int + tiled_version: str + version: float spacing: int = 0 margin: int = 0 + firstgid: Optional[int] = None + background_color: Optional[Color] = None tile_offset: Optional[OrderedPair] = None transparent_color: Optional[Color] = None grid: Optional[Grid] = None properties: Optional[properties_.Properties] = None terrain_types: Optional[List[Terrain]] = None tiles: Optional[List[Tile]] = None + source_file: Optional[Path] = None class RawFrame(TypedDict): @@ -212,7 +211,7 @@ class RawGrid(TypedDict): class RawTileSet(TypedDict): """ The keys and their types that appear in a TileSet JSON Object.""" - backgroundcolor: str + backgroundcolor: Color columns: int firstgid: int grid: RawGrid @@ -231,7 +230,7 @@ class RawTileSet(TypedDict): tileoffset: RawTileOffset tiles: List[RawTile] tilewidth: int - transparentcolor: str + transparentcolor: Color type: str version: float @@ -246,7 +245,72 @@ def cast(raw_tileset: RawTileSet) -> TileSet: TileSet: a properly typed TileSet. """ - pass + name = raw_tileset["name"] + + tile_count = raw_tileset["tilecount"] + tile_width = raw_tileset["tilewidth"] + tile_height = raw_tileset["tileheight"] + columns = raw_tileset["columns"] + + spacing = raw_tileset["spacing"] + margin = raw_tileset["margin"] + + version = raw_tileset["version"] + tiled_version = raw_tileset["tiledversion"] + + image = Path(raw_tileset["image"]) + image_width = raw_tileset["imagewidth"] + image_height = raw_tileset["imageheight"] + + tileset = TileSet( + name=name, + tile_count=tile_count, + tile_width=tile_width, + tile_height=tile_height, + columns=columns, + spacing=spacing, + margin=margin, + version=version, + tiled_version=tiled_version, + image=image, + image_width=image_width, + image_height=image_height, + ) + + if raw_tileset.get("firstgid") is not None: + tileset.firstgid = raw_tileset["firstgid"] + + if raw_tileset.get("backgroundcolor") is not None: + tileset.background_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"] + + if raw_tileset.get("grid") is not None: + tileset.grid = _cast_grid(raw_tileset["grid"]) + + if raw_tileset.get("properties") is not None: + tileset.properties = properties_.cast(raw_tileset["properties"]) + + if raw_tileset.get("terrains") is not None: + terrains = [] + for raw_terrain in raw_tileset["terrains"]: + terrains.append(_cast_terrain(raw_terrain)) + tileset.terrain_types = terrains + + if raw_tileset.get("tiles") is not None: + tiles = [] + for raw_tile in raw_tileset["tiles"]: + tiles.append(_cast_tile(raw_tile)) + tileset.tiles = tiles + + if raw_tileset.get("source") is not None: + tileset.source_file = Path(raw_tileset["source"]) + + return tileset def _cast_frame(raw_frame: RawFrame) -> Frame: From 99b4befcb431079ba471a6f84be0caf36be2345e Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 20:45:30 -0400 Subject: [PATCH 080/198] chore(test): move maps to a subdir --- .../{ => maps}/all_objects/all_objects.json | 0 .../{ => maps}/all_objects/tileset_image.json | 0 .../all_objects/tileset_image_objects.json | 0 .../{ => maps}/images/tmw_desert_spacing.png | Bin .../map_simple_external_tileset.json | 0 .../simple_external_tileset/tileset_image.json | 0 .../{ => maps}/simple_infinite/map_infinite.json | 0 .../{ => maps}/simple_infinite/tileset_image.json | 0 .../{ => maps}/simple_offset/map_simple_offset.json | 0 .../{ => maps}/simple_offset/tileset_image.json | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename tests/test_data/{ => maps}/all_objects/all_objects.json (100%) rename tests/test_data/{ => maps}/all_objects/tileset_image.json (100%) rename tests/test_data/{ => maps}/all_objects/tileset_image_objects.json (100%) rename tests/test_data/{ => maps}/images/tmw_desert_spacing.png (100%) rename tests/test_data/{ => maps}/simple_external_tileset/map_simple_external_tileset.json (100%) rename tests/test_data/{ => maps}/simple_external_tileset/tileset_image.json (100%) rename tests/test_data/{ => maps}/simple_infinite/map_infinite.json (100%) rename tests/test_data/{ => maps}/simple_infinite/tileset_image.json (100%) rename tests/test_data/{ => maps}/simple_offset/map_simple_offset.json (100%) rename tests/test_data/{ => maps}/simple_offset/tileset_image.json (100%) diff --git a/tests/test_data/all_objects/all_objects.json b/tests/test_data/maps/all_objects/all_objects.json similarity index 100% rename from tests/test_data/all_objects/all_objects.json rename to tests/test_data/maps/all_objects/all_objects.json diff --git a/tests/test_data/all_objects/tileset_image.json b/tests/test_data/maps/all_objects/tileset_image.json similarity index 100% rename from tests/test_data/all_objects/tileset_image.json rename to tests/test_data/maps/all_objects/tileset_image.json diff --git a/tests/test_data/all_objects/tileset_image_objects.json b/tests/test_data/maps/all_objects/tileset_image_objects.json similarity index 100% rename from tests/test_data/all_objects/tileset_image_objects.json rename to tests/test_data/maps/all_objects/tileset_image_objects.json diff --git a/tests/test_data/images/tmw_desert_spacing.png b/tests/test_data/maps/images/tmw_desert_spacing.png similarity index 100% rename from tests/test_data/images/tmw_desert_spacing.png rename to tests/test_data/maps/images/tmw_desert_spacing.png diff --git a/tests/test_data/simple_external_tileset/map_simple_external_tileset.json b/tests/test_data/maps/simple_external_tileset/map_simple_external_tileset.json similarity index 100% rename from tests/test_data/simple_external_tileset/map_simple_external_tileset.json rename to tests/test_data/maps/simple_external_tileset/map_simple_external_tileset.json diff --git a/tests/test_data/simple_external_tileset/tileset_image.json b/tests/test_data/maps/simple_external_tileset/tileset_image.json similarity index 100% rename from tests/test_data/simple_external_tileset/tileset_image.json rename to tests/test_data/maps/simple_external_tileset/tileset_image.json diff --git a/tests/test_data/simple_infinite/map_infinite.json b/tests/test_data/maps/simple_infinite/map_infinite.json similarity index 100% rename from tests/test_data/simple_infinite/map_infinite.json rename to tests/test_data/maps/simple_infinite/map_infinite.json diff --git a/tests/test_data/simple_infinite/tileset_image.json b/tests/test_data/maps/simple_infinite/tileset_image.json similarity index 100% rename from tests/test_data/simple_infinite/tileset_image.json rename to tests/test_data/maps/simple_infinite/tileset_image.json diff --git a/tests/test_data/simple_offset/map_simple_offset.json b/tests/test_data/maps/simple_offset/map_simple_offset.json similarity index 100% rename from tests/test_data/simple_offset/map_simple_offset.json rename to tests/test_data/maps/simple_offset/map_simple_offset.json diff --git a/tests/test_data/simple_offset/tileset_image.json b/tests/test_data/maps/simple_offset/tileset_image.json similarity index 100% rename from tests/test_data/simple_offset/tileset_image.json rename to tests/test_data/maps/simple_offset/tileset_image.json From 9bb66296b9f06be84c86d91b87c1b2c977230087 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 20:53:53 -0400 Subject: [PATCH 081/198] test: set up structure for tilesets --- tests/test_data/tilesets/image/expected.py | 0 .../test_data/tilesets/{tileset_image.json => image/tileset.json} | 0 tests/test_data/tilesets/image_objects/expected.py | 0 .../{tileset_image_objects.json => image_objects/tileset.json} | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/test_data/tilesets/image/expected.py rename tests/test_data/tilesets/{tileset_image.json => image/tileset.json} (100%) create mode 100644 tests/test_data/tilesets/image_objects/expected.py rename tests/test_data/tilesets/{tileset_image_objects.json => image_objects/tileset.json} (100%) diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_data/tilesets/tileset_image.json b/tests/test_data/tilesets/image/tileset.json similarity index 100% rename from tests/test_data/tilesets/tileset_image.json rename to tests/test_data/tilesets/image/tileset.json diff --git a/tests/test_data/tilesets/image_objects/expected.py b/tests/test_data/tilesets/image_objects/expected.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_data/tilesets/tileset_image_objects.json b/tests/test_data/tilesets/image_objects/tileset.json similarity index 100% rename from tests/test_data/tilesets/tileset_image_objects.json rename to tests/test_data/tilesets/image_objects/tileset.json From e2157ffa20195bda0c86b3f5773868efcaa8a9a9 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:23:11 -0400 Subject: [PATCH 082/198] tests: implemented multiple tileset tests --- tests/test_data/tilesets/image/expected.py | 18 +++++++ tests/test_data/tilesets/image/tileset.json | 14 ++++-- .../image_background_color/expected.py | 20 ++++++++ .../image_background_color/tileset.json | 23 +++++++++ .../tilesets/image_objects/tileset.json | 16 +++++-- .../tilesets/image_properties/tileset.json | 48 +++++++++++++++++++ .../image_transparent_color/expected.py | 20 ++++++++ .../image_transparent_color/tileset.json | 15 ++++++ 8 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 tests/test_data/tilesets/image_background_color/expected.py create mode 100644 tests/test_data/tilesets/image_background_color/tileset.json create mode 100644 tests/test_data/tilesets/image_properties/tileset.json create mode 100644 tests/test_data/tilesets/image_transparent_color/expected.py create mode 100644 tests/test_data/tilesets/image_transparent_color/tileset.json diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index e69de29..c43c909 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -0,0 +1,18 @@ +from pathlib import Path + +from pytiled_parser import tileset + +expected = tileset.TileSet( + columns=8, + image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.1", + tile_height=32, + tile_width=32, + version=1.2, +) diff --git a/tests/test_data/tilesets/image/tileset.json b/tests/test_data/tilesets/image/tileset.json index 8f3b73e..40b712c 100644 --- a/tests/test_data/tilesets/image/tileset.json +++ b/tests/test_data/tilesets/image/tileset.json @@ -1,14 +1,22 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, "name":"tile_set_image", "spacing":1, "tilecount":48, - "tiledversion":"1.3.1", + "tiledversion":"1.3.5", "tileheight":32, "tilewidth":32, "type":"tileset", "version":1.2 -} +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py new file mode 100644 index 0000000..1387f15 --- /dev/null +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -0,0 +1,20 @@ +from pathlib import Path + +from pytiled_parser import tileset +from pytiled_parser.common_types import Color + +expected = tileset.TileSet( + columns=8, + image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.1", + tile_height=32, + tile_width=32, + version=1.2, + background_color=Color("#5500ff"), +) diff --git a/tests/test_data/tilesets/image_background_color/tileset.json b/tests/test_data/tilesets/image_background_color/tileset.json new file mode 100644 index 0000000..a72c388 --- /dev/null +++ b/tests/test_data/tilesets/image_background_color/tileset.json @@ -0,0 +1,23 @@ +{ "backgroundcolor":"#5500ff", + "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"..\/image" + } + }, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":0, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_objects/tileset.json b/tests/test_data/tilesets/image_objects/tileset.json index 6ceb5be..e670b61 100644 --- a/tests/test_data/tilesets/image_objects/tileset.json +++ b/tests/test_data/tilesets/image_objects/tileset.json @@ -1,12 +1,20 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, "name":"tile_set_image", "spacing":1, - "tilecount":5, - "tiledversion":"1.3.1", + "tilecount":48, + "tiledversion":"1.3.5", "tileheight":32, "tiles":[ { @@ -189,4 +197,4 @@ "tilewidth":32, "type":"tileset", "version":1.2 -} +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_properties/tileset.json b/tests/test_data/tilesets/image_properties/tileset.json new file mode 100644 index 0000000..785c164 --- /dev/null +++ b/tests/test_data/tilesets/image_properties/tileset.json @@ -0,0 +1,48 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"..\/image" + } + }, + "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff0000ff" + }, + { + "name":"float property", + "type":"float", + "value":5.6 + }, + { + "name":"int property", + "type":"int", + "value":5 + }, + { + "name":"string property", + "type":"string", + "value":"testing" + }], + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py new file mode 100644 index 0000000..cb0c9bb --- /dev/null +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -0,0 +1,20 @@ +from pathlib import Path + +from pytiled_parser import tileset +from pytiled_parser.common_types import Color + +expected = tileset.TileSet( + columns=8, + image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.1", + tile_height=32, + tile_width=32, + version=1.2, + transparent_color=Color("#ff00ff"), +) diff --git a/tests/test_data/tilesets/image_transparent_color/tileset.json b/tests/test_data/tilesets/image_transparent_color/tileset.json new file mode 100644 index 0000000..6d3ec40 --- /dev/null +++ b/tests/test_data/tilesets/image_transparent_color/tileset.json @@ -0,0 +1,15 @@ +{ "columns":8, + "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tileset", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "transparentcolor":"#ff00ff", + "type":"tileset", + "version":1.2 +} \ No newline at end of file From 4c504549c0e9d66ac6e1010da5bab4271da0fb82 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:26:43 -0400 Subject: [PATCH 083/198] tests: implemented tileset with properties test --- .../tilesets/image_properties/expected.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/test_data/tilesets/image_properties/expected.py diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py new file mode 100644 index 0000000..8eb3bea --- /dev/null +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -0,0 +1,26 @@ +from pathlib import Path + +from pytiled_parser import tileset +from pytiled_parser.common_types import Color + +expected = tileset.TileSet( + columns=8, + image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.1", + tile_height=32, + tile_width=32, + version=1.2, + properties={ + "bool property": True, + "color property": Color("#ff0000ff"), + "float property": 5.6, + "int property": 5, + "string property": "testing", + }, +) From 6d64db1aaf9a036ff7fb01422687fcb0ef3ca9a9 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 21:28:34 -0400 Subject: [PATCH 084/198] test(tileset): add tests --- tests/test_tileset.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 63f313e..1e6f458 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -1,4 +1,5 @@ """Tests for tilesets""" +import importlib.util import json import os from pathlib import Path @@ -12,12 +13,24 @@ TEST_DATA = TESTS_DIR / "test_data" TILE_SETS = TEST_DATA / "tilesets" -ALL_TILESETS = TILE_SETS.glob("*.json") +ALL_TILESET_DIRS = TILE_SETS.glob("*") -@pytest.mark.parametrize("raw_tileset", ALL_TILESETS) -def test_tilesets_integration(raw_tileset): +@pytest.mark.parametrize("tileset_dir", ALL_TILESET_DIRS) +def test_tilesets_integration(tileset_dir): """ This could be redundant, but it is useful just to ensure that anything in there is at least sanity checked""" - tileset_ = tileset.cast(json.loads(raw_tileset)) - assert tileset_ is not None + # it's a PITA to import like this, don't do it + # https://stackoverflow.com/a/67692/1342874 + spec = importlib.util.spec_from_file_location( + "expected", tileset_dir / "expected.py" + ) + expected = importlib.util.module_from_spec(spec) + spec.loader.exec_module(expected) + + raw_tileset_path = tileset_dir / "tileset.json" + + with open(raw_tileset_path) as raw_tileset: + tileset_ = tileset.cast(json.loads(raw_tileset)) + + assert tileset_ == expected.EXPECTED From 107bf406bc69f7666470b439716a87ebd31bd3b1 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:28:35 -0400 Subject: [PATCH 085/198] tests: updated expected variable in all expected.py files --- tests/test_data/tilesets/image/expected.py | 2 +- tests/test_data/tilesets/image_background_color/expected.py | 2 +- tests/test_data/tilesets/image_properties/expected.py | 2 +- tests/test_data/tilesets/image_transparent_color/expected.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index c43c909..95e8db7 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import tileset -expected = tileset.TileSet( +EXPECTED = tileset.TileSet( columns=8, image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index 1387f15..bc940aa 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -expected = tileset.TileSet( +EXPECTED = tileset.TileSet( columns=8, image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index 8eb3bea..1109340 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -expected = tileset.TileSet( +EXPECTED = tileset.TileSet( columns=8, image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index cb0c9bb..a6f4ce7 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -expected = tileset.TileSet( +EXPECTED = tileset.TileSet( columns=8, image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), image_height=199, From 20eb9a4a59f7623c71efdbf5be4517eeae2780ba Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 21:30:48 -0400 Subject: [PATCH 086/198] test:fix: properly read tileset --- tests/test_tileset.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 1e6f458..0aaebd2 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -18,8 +18,6 @@ ALL_TILESET_DIRS = TILE_SETS.glob("*") @pytest.mark.parametrize("tileset_dir", ALL_TILESET_DIRS) def test_tilesets_integration(tileset_dir): - """ This could be redundant, but it is useful just to ensure that anything in there - is at least sanity checked""" # it's a PITA to import like this, don't do it # https://stackoverflow.com/a/67692/1342874 spec = importlib.util.spec_from_file_location( @@ -31,6 +29,6 @@ def test_tilesets_integration(tileset_dir): raw_tileset_path = tileset_dir / "tileset.json" with open(raw_tileset_path) as raw_tileset: - tileset_ = tileset.cast(json.loads(raw_tileset)) + tileset_ = tileset.cast(json.loads(raw_tileset.read())) assert tileset_ == expected.EXPECTED From b860e88f15f61c7bbd88fc9b6d7cbd0ff191b4ad Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 21:35:01 -0400 Subject: [PATCH 087/198] test:fix(image_transparent_color): darren messed up big tim --- .../test_data/tilesets/image_transparent_color/expected.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index a6f4ce7..6583b5a 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -5,14 +5,14 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image=Path("../../maps/images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, spacing=1, - name="tile_set_image", + name="tileset", tile_count=48, - tiled_version="1.3.1", + tiled_version="1.3.5", tile_height=32, tile_width=32, version=1.2, From 7c4071c0f24dc95a1b45433a17140972b4642e07 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:45:39 -0400 Subject: [PATCH 088/198] tests: all currently implemented tileset tests passing. --- tests/test_data/tilesets/image/expected.py | 4 +- .../image_background_color/expected.py | 4 +- .../image_background_color/tileset.json | 39 ++++++++----------- .../tilesets/image_properties/expected.py | 4 +- .../image_transparent_color/expected.py | 4 +- 5 files changed, 24 insertions(+), 31 deletions(-) diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index 95e8db7..629ea1c 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -4,14 +4,14 @@ from pytiled_parser import tileset EXPECTED = tileset.TileSet( columns=8, - image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image=Path("../../maps/images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, spacing=1, name="tile_set_image", tile_count=48, - tiled_version="1.3.1", + tiled_version="1.3.5", tile_height=32, tile_width=32, version=1.2, diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index bc940aa..220ee83 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -5,14 +5,14 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image=Path("../../maps/images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, spacing=1, name="tile_set_image", tile_count=48, - tiled_version="1.3.1", + tiled_version="1.3.5", tile_height=32, tile_width=32, version=1.2, diff --git a/tests/test_data/tilesets/image_background_color/tileset.json b/tests/test_data/tilesets/image_background_color/tileset.json index a72c388..64fbc87 100644 --- a/tests/test_data/tilesets/image_background_color/tileset.json +++ b/tests/test_data/tilesets/image_background_color/tileset.json @@ -1,23 +1,16 @@ -{ "backgroundcolor":"#5500ff", - "columns":8, - "editorsettings": - { - "export": - { - "format":"", - "target":"..\/image" - } - }, - "image":"..\/images\/tmw_desert_spacing.png", - "imageheight":199, - "imagewidth":265, - "margin":1, - "name":"tile_set_image", - "spacing":1, - "tilecount":0, - "tiledversion":"1.3.5", - "tileheight":32, - "tilewidth":32, - "type":"tileset", - "version":1.2 -} \ No newline at end of file +{ + "backgroundcolor": "#5500ff", + "columns": 8, + "image": "../../maps/images/tmw_desert_spacing.png", + "imageheight": 199, + "imagewidth": 265, + "margin": 1, + "name": "tile_set_image", + "spacing": 1, + "tilecount": 48, + "tiledversion": "1.3.5", + "tileheight": 32, + "tilewidth": 32, + "type": "tileset", + "version": 1.2 +} diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index 1109340..5ea2fe0 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -5,14 +5,14 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path(r"..\/..\/maps\/images\/tmw_desert_spacing.png"), + image=Path("../../maps/images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, spacing=1, name="tile_set_image", tile_count=48, - tiled_version="1.3.1", + tiled_version="1.3.5", tile_height=32, tile_width=32, version=1.2, diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index a6f4ce7..d588f2d 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -10,9 +10,9 @@ EXPECTED = tileset.TileSet( image_width=265, margin=1, spacing=1, - name="tile_set_image", + name="tileset", tile_count=48, - tiled_version="1.3.1", + tiled_version="1.3.5", tile_height=32, tile_width=32, version=1.2, From 2ed04ae204136ea0b4a45e459203a1ae65f09851 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:46:13 -0400 Subject: [PATCH 089/198] tests: refactored the way tileset test directories are handled. Switching from finding all directories to manually listing. --- tests/test_tileset.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 0aaebd2..0e3a3aa 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -13,7 +13,12 @@ TEST_DATA = TESTS_DIR / "test_data" TILE_SETS = TEST_DATA / "tilesets" -ALL_TILESET_DIRS = TILE_SETS.glob("*") +ALL_TILESET_DIRS = [ + TILE_SETS / "image", + TILE_SETS / "image_background_color", + TILE_SETS / "image_properties", + TILE_SETS / "image_transparent_color", +] @pytest.mark.parametrize("tileset_dir", ALL_TILESET_DIRS) From 9c45223e1017d767172f87e9f471ec4647d4c27f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 21:50:52 -0400 Subject: [PATCH 090/198] tests: implemented tile_offset test --- tests/test_data/tilesets/image/tileset.json | 43 +++++++++---------- .../tilesets/image_tile_offset/expected.py | 20 +++++++++ .../tilesets/image_tile_offset/tileset.json | 27 ++++++++++++ tests/test_tileset.py | 1 + 4 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 tests/test_data/tilesets/image_tile_offset/expected.py create mode 100644 tests/test_data/tilesets/image_tile_offset/tileset.json diff --git a/tests/test_data/tilesets/image/tileset.json b/tests/test_data/tilesets/image/tileset.json index 40b712c..279e059 100644 --- a/tests/test_data/tilesets/image/tileset.json +++ b/tests/test_data/tilesets/image/tileset.json @@ -1,22 +1,21 @@ -{ "columns":8, - "editorsettings": - { - "export": - { - "format":"", - "target":"." - } - }, - "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", - "imageheight":199, - "imagewidth":265, - "margin":1, - "name":"tile_set_image", - "spacing":1, - "tilecount":48, - "tiledversion":"1.3.5", - "tileheight":32, - "tilewidth":32, - "type":"tileset", - "version":1.2 -} \ No newline at end of file +{ + "columns": 8, + "editorsettings": { + "export": { + "format": "", + "target": "." + } + }, + "image": "../../maps/images/tmw_desert_spacing.png", + "imageheight": 199, + "imagewidth": 265, + "margin": 1, + "name": "tile_set_image", + "spacing": 1, + "tilecount": 48, + "tiledversion": "1.3.5", + "tileheight": 32, + "tilewidth": 32, + "type": "tileset", + "version": 1.2 +} diff --git a/tests/test_data/tilesets/image_tile_offset/expected.py b/tests/test_data/tilesets/image_tile_offset/expected.py new file mode 100644 index 0000000..3d57844 --- /dev/null +++ b/tests/test_data/tilesets/image_tile_offset/expected.py @@ -0,0 +1,20 @@ +from pathlib import Path + +from pytiled_parser import tileset +from pytiled_parser.common_types import Color, OrderedPair + +EXPECTED = tileset.TileSet( + columns=8, + image=Path("../../maps/images/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.5", + tile_height=32, + tile_width=32, + version=1.2, + tile_offset=OrderedPair(3, 5), +) diff --git a/tests/test_data/tilesets/image_tile_offset/tileset.json b/tests/test_data/tilesets/image_tile_offset/tileset.json new file mode 100644 index 0000000..a5893b2 --- /dev/null +++ b/tests/test_data/tilesets/image_tile_offset/tileset.json @@ -0,0 +1,27 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"..\/image" + } + }, + "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tileoffset": + { + "x":3, + "y":5 + }, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 0e3a3aa..f2bf962 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -18,6 +18,7 @@ ALL_TILESET_DIRS = [ TILE_SETS / "image_background_color", TILE_SETS / "image_properties", TILE_SETS / "image_transparent_color", + TILE_SETS / "image_tile_offset", ] From f9118444563f3023f12f8649265f46aa91746a46 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 4 Jun 2020 21:52:07 -0400 Subject: [PATCH 091/198] tests: move image up a level --- pytiled_parser/tileset.py | 5 +- .../{maps => }/images/tmw_desert_spacing.png | Bin .../map_simple_external_tileset.json | 68 ++++++++++++++++++ .../layers/ten_layers/tileset_image.json | 14 ++++ .../maps/all_objects/tileset_image.json | 2 +- .../all_objects/tileset_image_objects.json | 2 +- .../tileset_image.json | 2 +- .../maps/simple_infinite/tileset_image.json | 2 +- .../maps/simple_offset/tileset_image.json | 2 +- 9 files changed, 90 insertions(+), 7 deletions(-) rename tests/test_data/{maps => }/images/tmw_desert_spacing.png (100%) create mode 100644 tests/test_data/layers/ten_layers/map_simple_external_tileset.json create mode 100644 tests/test_data/layers/ten_layers/tileset_image.json diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 5195fc6..c307afe 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -186,8 +186,9 @@ class RawTerrain(TypedDict): class RawTile(TypedDict): - """ The keys and their types that appear in a Tile JSON Object. - FIXME Implement objectgroup, can't be done until TileLayer's are implemented""" + """ The keys and their types that appear in a Tile JSON Object.""" + + # FIXME: Implement objectgroup, can't be done until TileLayer's are implemented animation: List[RawFrame] id: int diff --git a/tests/test_data/maps/images/tmw_desert_spacing.png b/tests/test_data/images/tmw_desert_spacing.png similarity index 100% rename from tests/test_data/maps/images/tmw_desert_spacing.png rename to tests/test_data/images/tmw_desert_spacing.png diff --git a/tests/test_data/layers/ten_layers/map_simple_external_tileset.json b/tests/test_data/layers/ten_layers/map_simple_external_tileset.json new file mode 100644 index 0000000..e68a7f7 --- /dev/null +++ b/tests/test_data/layers/ten_layers/map_simple_external_tileset.json @@ -0,0 +1,68 @@ +{ "compressionlevel":0, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/var\/log\/syslog" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} diff --git a/tests/test_data/layers/ten_layers/tileset_image.json b/tests/test_data/layers/ten_layers/tileset_image.json new file mode 100644 index 0000000..8f3b73e --- /dev/null +++ b/tests/test_data/layers/ten_layers/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_data/maps/all_objects/tileset_image.json b/tests/test_data/maps/all_objects/tileset_image.json index 8f3b73e..e88a3f1 100644 --- a/tests/test_data/maps/all_objects/tileset_image.json +++ b/tests/test_data/maps/all_objects/tileset_image.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/maps/all_objects/tileset_image_objects.json b/tests/test_data/maps/all_objects/tileset_image_objects.json index 6ceb5be..6ed0287 100644 --- a/tests/test_data/maps/all_objects/tileset_image_objects.json +++ b/tests/test_data/maps/all_objects/tileset_image_objects.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/maps/simple_external_tileset/tileset_image.json b/tests/test_data/maps/simple_external_tileset/tileset_image.json index 8f3b73e..e88a3f1 100644 --- a/tests/test_data/maps/simple_external_tileset/tileset_image.json +++ b/tests/test_data/maps/simple_external_tileset/tileset_image.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/maps/simple_infinite/tileset_image.json b/tests/test_data/maps/simple_infinite/tileset_image.json index 8f3b73e..e88a3f1 100644 --- a/tests/test_data/maps/simple_infinite/tileset_image.json +++ b/tests/test_data/maps/simple_infinite/tileset_image.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/maps/simple_offset/tileset_image.json b/tests/test_data/maps/simple_offset/tileset_image.json index 8f3b73e..e88a3f1 100644 --- a/tests/test_data/maps/simple_offset/tileset_image.json +++ b/tests/test_data/maps/simple_offset/tileset_image.json @@ -1,5 +1,5 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, From e2e3873b1d9b5fce9c4fd3559cb3c26c721dd1dd Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 14:55:38 -0400 Subject: [PATCH 092/198] chore: moved location of tileset.cast in the code. --- pytiled_parser/tileset.py | 156 +++++++++++++++++++------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index c307afe..a0d6422 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -236,84 +236,6 @@ class RawTileSet(TypedDict): version: float -def cast(raw_tileset: RawTileSet) -> TileSet: - """ Cast the raw tileset into a pytiled_parser type - - Args: - raw_tileset: Raw Tileset to be cast. - - Returns: - TileSet: a properly typed TileSet. - """ - - name = raw_tileset["name"] - - tile_count = raw_tileset["tilecount"] - tile_width = raw_tileset["tilewidth"] - tile_height = raw_tileset["tileheight"] - columns = raw_tileset["columns"] - - spacing = raw_tileset["spacing"] - margin = raw_tileset["margin"] - - version = raw_tileset["version"] - tiled_version = raw_tileset["tiledversion"] - - image = Path(raw_tileset["image"]) - image_width = raw_tileset["imagewidth"] - image_height = raw_tileset["imageheight"] - - tileset = TileSet( - name=name, - tile_count=tile_count, - tile_width=tile_width, - tile_height=tile_height, - columns=columns, - spacing=spacing, - margin=margin, - version=version, - tiled_version=tiled_version, - image=image, - image_width=image_width, - image_height=image_height, - ) - - if raw_tileset.get("firstgid") is not None: - tileset.firstgid = raw_tileset["firstgid"] - - if raw_tileset.get("backgroundcolor") is not None: - tileset.background_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"] - - if raw_tileset.get("grid") is not None: - tileset.grid = _cast_grid(raw_tileset["grid"]) - - if raw_tileset.get("properties") is not None: - tileset.properties = properties_.cast(raw_tileset["properties"]) - - if raw_tileset.get("terrains") is not None: - terrains = [] - for raw_terrain in raw_tileset["terrains"]: - terrains.append(_cast_terrain(raw_terrain)) - tileset.terrain_types = terrains - - if raw_tileset.get("tiles") is not None: - tiles = [] - for raw_tile in raw_tileset["tiles"]: - tiles.append(_cast_tile(raw_tile)) - tileset.tiles = tiles - - if raw_tileset.get("source") is not None: - tileset.source_file = Path(raw_tileset["source"]) - - return tileset - - def _cast_frame(raw_frame: RawFrame) -> Frame: """ Cast the raw_frame to a Frame. @@ -421,3 +343,81 @@ def _cast_grid(raw_grid: RawGrid) -> Grid: width=raw_grid["width"], height=raw_grid["height"], ) + + +def cast(raw_tileset: RawTileSet) -> TileSet: + """ Cast the raw tileset into a pytiled_parser type + + Args: + raw_tileset: Raw Tileset to be cast. + + Returns: + TileSet: a properly typed TileSet. + """ + + name = raw_tileset["name"] + + tile_count = raw_tileset["tilecount"] + tile_width = raw_tileset["tilewidth"] + tile_height = raw_tileset["tileheight"] + columns = raw_tileset["columns"] + + spacing = raw_tileset["spacing"] + margin = raw_tileset["margin"] + + version = raw_tileset["version"] + tiled_version = raw_tileset["tiledversion"] + + image = Path(raw_tileset["image"]) + image_width = raw_tileset["imagewidth"] + image_height = raw_tileset["imageheight"] + + tileset = TileSet( + name=name, + tile_count=tile_count, + tile_width=tile_width, + tile_height=tile_height, + columns=columns, + spacing=spacing, + margin=margin, + version=version, + tiled_version=tiled_version, + image=image, + image_width=image_width, + image_height=image_height, + ) + + if raw_tileset.get("firstgid") is not None: + tileset.firstgid = raw_tileset["firstgid"] + + if raw_tileset.get("backgroundcolor") is not None: + tileset.background_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"] + + if raw_tileset.get("grid") is not None: + tileset.grid = _cast_grid(raw_tileset["grid"]) + + if raw_tileset.get("properties") is not None: + tileset.properties = properties_.cast(raw_tileset["properties"]) + + if raw_tileset.get("terrains") is not None: + terrains = [] + for raw_terrain in raw_tileset["terrains"]: + terrains.append(_cast_terrain(raw_terrain)) + tileset.terrain_types = terrains + + if raw_tileset.get("tiles") is not None: + tiles = [] + for raw_tile in raw_tileset["tiles"]: + tiles.append(_cast_tile(raw_tile)) + tileset.tiles = tiles + + if raw_tileset.get("source") is not None: + tileset.source_file = Path(raw_tileset["source"]) + + return tileset From b97930fecec642ce184dde65f55dc5815db52e99 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 14:56:04 -0400 Subject: [PATCH 093/198] rf(map): cast, not parse --- pytiled_parser/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index eaf0b99..19343fc 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -71,5 +71,5 @@ class Map: properties: Optional[Properties] = None -def parse() -> Map: +def cast() -> Map: pass From 99054c4a8d4fb8a9e7ac55569c8d12654b768379 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 14:58:26 -0400 Subject: [PATCH 094/198] chore: fixed too many local variables in tileset.cast --- pytiled_parser/tileset.py | 45 ++++++++++++--------------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index a0d6422..b898e77 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -1,12 +1,12 @@ # pylint: disable=too-few-public-methods from pathlib import Path -from typing import Dict, List, NamedTuple, Optional +from typing import List, NamedTuple, Optional import attr from typing_extensions import TypedDict from . import properties as properties_ -from .common_types import Color, OrderedPair, Size +from .common_types import Color, OrderedPair from .tiled_object import TiledObject @@ -355,36 +355,19 @@ def cast(raw_tileset: RawTileSet) -> TileSet: TileSet: a properly typed TileSet. """ - name = raw_tileset["name"] - - tile_count = raw_tileset["tilecount"] - tile_width = raw_tileset["tilewidth"] - tile_height = raw_tileset["tileheight"] - columns = raw_tileset["columns"] - - spacing = raw_tileset["spacing"] - margin = raw_tileset["margin"] - - version = raw_tileset["version"] - tiled_version = raw_tileset["tiledversion"] - - image = Path(raw_tileset["image"]) - image_width = raw_tileset["imagewidth"] - image_height = raw_tileset["imageheight"] - tileset = TileSet( - name=name, - tile_count=tile_count, - tile_width=tile_width, - tile_height=tile_height, - columns=columns, - spacing=spacing, - margin=margin, - version=version, - tiled_version=tiled_version, - image=image, - image_width=image_width, - image_height=image_height, + name=raw_tileset["name"], + tile_count=raw_tileset["tilecount"], + tile_width=raw_tileset["tilewidth"], + tile_height=raw_tileset["tileheight"], + columns=raw_tileset["columns"], + spacing=raw_tileset["spacing"], + margin=raw_tileset["margin"], + version=raw_tileset["version"], + tiled_version=raw_tileset["tiledversion"], + image=Path(raw_tileset["image"]), + image_width=raw_tileset["imagewidth"], + image_height=raw_tileset["imageheight"], ) if raw_tileset.get("firstgid") is not None: From 6c3e6af0a65aa076277825e21dac897aac7da06f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 15:08:35 -0400 Subject: [PATCH 095/198] tests: fix tileset tests to work with new test_data file structure --- tests/test_data/tilesets/image/expected.py | 2 +- tests/test_data/tilesets/image/tileset.json | 43 ++++++++++--------- .../image_background_color/expected.py | 2 +- .../image_background_color/tileset.json | 39 ++++++++++------- .../tilesets/image_objects/tileset.json | 2 +- .../tilesets/image_properties/expected.py | 2 +- .../tilesets/image_properties/tileset.json | 2 +- .../tilesets/image_tile_offset/expected.py | 2 +- .../tilesets/image_tile_offset/tileset.json | 2 +- .../image_transparent_color/expected.py | 2 +- .../image_transparent_color/tileset.json | 10 ++++- 11 files changed, 62 insertions(+), 46 deletions(-) diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index 629ea1c..9ad94d3 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -4,7 +4,7 @@ from pytiled_parser import tileset EXPECTED = tileset.TileSet( columns=8, - image=Path("../../maps/images/tmw_desert_spacing.png"), + image=Path("../../images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, diff --git a/tests/test_data/tilesets/image/tileset.json b/tests/test_data/tilesets/image/tileset.json index 279e059..8df9f18 100644 --- a/tests/test_data/tilesets/image/tileset.json +++ b/tests/test_data/tilesets/image/tileset.json @@ -1,21 +1,22 @@ -{ - "columns": 8, - "editorsettings": { - "export": { - "format": "", - "target": "." - } - }, - "image": "../../maps/images/tmw_desert_spacing.png", - "imageheight": 199, - "imagewidth": 265, - "margin": 1, - "name": "tile_set_image", - "spacing": 1, - "tilecount": 48, - "tiledversion": "1.3.5", - "tileheight": 32, - "tilewidth": 32, - "type": "tileset", - "version": 1.2 -} +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index 220ee83..458435b 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -5,7 +5,7 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path("../../maps/images/tmw_desert_spacing.png"), + image=Path("../../images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, diff --git a/tests/test_data/tilesets/image_background_color/tileset.json b/tests/test_data/tilesets/image_background_color/tileset.json index 64fbc87..83ae8dd 100644 --- a/tests/test_data/tilesets/image_background_color/tileset.json +++ b/tests/test_data/tilesets/image_background_color/tileset.json @@ -1,16 +1,23 @@ -{ - "backgroundcolor": "#5500ff", - "columns": 8, - "image": "../../maps/images/tmw_desert_spacing.png", - "imageheight": 199, - "imagewidth": 265, - "margin": 1, - "name": "tile_set_image", - "spacing": 1, - "tilecount": 48, - "tiledversion": "1.3.5", - "tileheight": 32, - "tilewidth": 32, - "type": "tileset", - "version": 1.2 -} +{ "backgroundcolor":"#5500ff", + "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/tilesets/image_objects/tileset.json b/tests/test_data/tilesets/image_objects/tileset.json index e670b61..f490b17 100644 --- a/tests/test_data/tilesets/image_objects/tileset.json +++ b/tests/test_data/tilesets/image_objects/tileset.json @@ -7,7 +7,7 @@ "target":"." } }, - "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index 5ea2fe0..98013d9 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -5,7 +5,7 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path("../../maps/images/tmw_desert_spacing.png"), + image=Path("../../images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, diff --git a/tests/test_data/tilesets/image_properties/tileset.json b/tests/test_data/tilesets/image_properties/tileset.json index 785c164..a5aa95b 100644 --- a/tests/test_data/tilesets/image_properties/tileset.json +++ b/tests/test_data/tilesets/image_properties/tileset.json @@ -7,7 +7,7 @@ "target":"..\/image" } }, - "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/tilesets/image_tile_offset/expected.py b/tests/test_data/tilesets/image_tile_offset/expected.py index 3d57844..78a36bf 100644 --- a/tests/test_data/tilesets/image_tile_offset/expected.py +++ b/tests/test_data/tilesets/image_tile_offset/expected.py @@ -5,7 +5,7 @@ from pytiled_parser.common_types import Color, OrderedPair EXPECTED = tileset.TileSet( columns=8, - image=Path("../../maps/images/tmw_desert_spacing.png"), + image=Path("../../images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, diff --git a/tests/test_data/tilesets/image_tile_offset/tileset.json b/tests/test_data/tilesets/image_tile_offset/tileset.json index a5893b2..61e3017 100644 --- a/tests/test_data/tilesets/image_tile_offset/tileset.json +++ b/tests/test_data/tilesets/image_tile_offset/tileset.json @@ -7,7 +7,7 @@ "target":"..\/image" } }, - "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index 6583b5a..7fa5bd3 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -5,7 +5,7 @@ from pytiled_parser.common_types import Color EXPECTED = tileset.TileSet( columns=8, - image=Path("../../maps/images/tmw_desert_spacing.png"), + image=Path("../../images/tmw_desert_spacing.png"), image_height=199, image_width=265, margin=1, diff --git a/tests/test_data/tilesets/image_transparent_color/tileset.json b/tests/test_data/tilesets/image_transparent_color/tileset.json index 6d3ec40..fe318c3 100644 --- a/tests/test_data/tilesets/image_transparent_color/tileset.json +++ b/tests/test_data/tilesets/image_transparent_color/tileset.json @@ -1,5 +1,13 @@ { "columns":8, - "image":"..\/..\/maps\/images\/tmw_desert_spacing.png", + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, From b07f30fd0d17e385817adefc258f99c65ee051b7 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 15:28:15 -0400 Subject: [PATCH 096/198] implemented RawLayer class --- pytiled_parser/layer.py | 45 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index ef0be1f..4cba0de 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -3,10 +3,11 @@ from typing import List, Optional, Union import attr +from typing_extensions import TypedDict +from . import properties as properties_ from .common_types import OrderedPair, Size -from .properties import Properties -from .tiled_object import TiledObject +from .tiled_object import RawTiledObject, TiledObject @attr.s(auto_attribs=True, kw_only=True) @@ -37,7 +38,7 @@ class Layer: offset: Optional[OrderedPair] opacity: Optional[float] - properties: Optional[Properties] + properties: Optional[properties_.Properties] TileLayerGrid = List[List[int]] @@ -122,3 +123,41 @@ class LayerGroup(Layer): """ layers: Optional[List[Union["LayerGroup", Layer, ObjectLayer]]] + + +class RawChunk(TypedDict): + """ The keys and their types that appear in a Chunk JSON Object.""" + + data: Union[List[int], str] + height: int + width: int + x: int + y: int + + +class RawLayer(TypedDict): + """ The keys and their types that appear in a Layer JSON Object.""" + + chunks: List[RawChunk] + compression: str + data: Union[List[int], str] + draworder: str + encoding: str + height: int + id: int + image: str + layers: List[RawLayer] + name: str + objects: List[RawTiledObject] + offsetx: float + offsety: float + opacity: float + properties: List[properties_.RawProperty] + startx: int + starty: int + transparentcolor: str + type: str + visible: bool + width: int + x: int + y: int From d92276a766692f04d13ccef0fa742219ebe68d49 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 17:12:17 -0400 Subject: [PATCH 097/198] build out more of the map module --- pytiled_parser/map.py | 45 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 19343fc..7786394 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -4,11 +4,12 @@ from pathlib import Path from typing import Dict, List, NamedTuple, Optional, Union import attr +from typing_extensions import TypedDict from .common_types import Color, Size from .layer import Layer -from .properties import Properties -from .tileset import TileSet +from .properties import Properties, RawProperty +from .tileset import RawTileSet, TileSet TileSetDict = Dict[int, TileSet] @@ -71,5 +72,41 @@ class Map: properties: Optional[Properties] = None -def cast() -> Map: - pass +class _RawTiledMap(TypedDict): + """ 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 + height: int + hexsidelength: int + infinite: bool + layers: List[RawLayer] + nextlayerid: int + nextobjectid: int + orientation: str + properties: List[RawProperty] + renderorder: str + staggeraxis: str + staggerindex: str + tiledversion: str + tileheight: int + tilesets: List[RawTileSet] + tilewidth: int + type: str + version: str + width: int + + +def cast(raw_tiled_map: _RawTiledMap) -> Map: + """ Cast the raw Tiled map into a pytiled_parser type + + Args: + raw_tiled_map: Raw JSON Formatted Tiled Map to be cast. + + Returns: + TileSet: a properly typed TileSet. + """ From 200b2271372f5a1eb73ce36dcee1bac728c05319 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 17:45:58 -0400 Subject: [PATCH 098/198] fix: added missing import for RawLayer --- pytiled_parser/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 7786394..1a40fcb 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -7,7 +7,7 @@ import attr from typing_extensions import TypedDict from .common_types import Color, Size -from .layer import Layer +from .layer import Layer, RawLayer from .properties import Properties, RawProperty from .tileset import RawTileSet, TileSet From a2b0c2a31250783a25e1b0905b53d4ea5a642379 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 17:47:41 -0400 Subject: [PATCH 099/198] Temporarily remove layers attribute from RawLayer until it can be fixed properly --- pytiled_parser/layer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 4cba0de..4b6e1f3 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -136,7 +136,10 @@ class RawChunk(TypedDict): class RawLayer(TypedDict): - """ The keys and their types that appear in a Layer JSON Object.""" + """ + FIXME Make the layers attribute function + + The keys and their types that appear in a Layer JSON Object.""" chunks: List[RawChunk] compression: str @@ -146,7 +149,7 @@ class RawLayer(TypedDict): height: int id: int image: str - layers: List[RawLayer] + # layers: List[RawLayer] name: str objects: List[RawTiledObject] offsetx: float From c81785eb77047b71c52d5c6228e09530d8c87ad2 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 17:48:05 -0400 Subject: [PATCH 100/198] tests: Added tileset_grid test --- .../test_data/tilesets/image_grid/expected.py | 19 ++++++++++++++ .../tilesets/image_grid/tileset.json | 26 +++++++++++++++++++ tests/test_tileset.py | 1 + 3 files changed, 46 insertions(+) create mode 100644 tests/test_data/tilesets/image_grid/expected.py create mode 100644 tests/test_data/tilesets/image_grid/tileset.json diff --git a/tests/test_data/tilesets/image_grid/expected.py b/tests/test_data/tilesets/image_grid/expected.py new file mode 100644 index 0000000..efc9ef5 --- /dev/null +++ b/tests/test_data/tilesets/image_grid/expected.py @@ -0,0 +1,19 @@ +from pathlib import Path + +from pytiled_parser import tileset + +EXPECTED = tileset.TileSet( + columns=8, + image=Path("../../images/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + margin=1, + spacing=1, + name="tile_set_image", + tile_count=48, + tiled_version="1.3.5", + tile_height=32, + tile_width=32, + version=1.2, + grid=tileset.Grid(orientation="isometric", width=32, height=32), +) diff --git a/tests/test_data/tilesets/image_grid/tileset.json b/tests/test_data/tilesets/image_grid/tileset.json new file mode 100644 index 0000000..4afdde1 --- /dev/null +++ b/tests/test_data/tilesets/image_grid/tileset.json @@ -0,0 +1,26 @@ +{ + "columns": 8, + "editorsettings": { + "export": { + "format": "", + "target": "../image" + } + }, + "grid": { + "height": 32, + "orientation": "isometric", + "width": 32 + }, + "image": "../../images/tmw_desert_spacing.png", + "imageheight": 199, + "imagewidth": 265, + "margin": 1, + "name": "tile_set_image", + "spacing": 1, + "tilecount": 48, + "tiledversion": "1.3.5", + "tileheight": 32, + "tilewidth": 32, + "type": "tileset", + "version": 1.2 +} diff --git a/tests/test_tileset.py b/tests/test_tileset.py index f2bf962..2d72dc1 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -16,6 +16,7 @@ TILE_SETS = TEST_DATA / "tilesets" ALL_TILESET_DIRS = [ TILE_SETS / "image", TILE_SETS / "image_background_color", + TILE_SETS / "image_grid", TILE_SETS / "image_properties", TILE_SETS / "image_transparent_color", TILE_SETS / "image_tile_offset", From f9d1ca989330c73b97c0eb9fa7d8ad56aa24624c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:00:50 -0400 Subject: [PATCH 101/198] rf(map): don't mess with the default of the format --- pytiled_parser/map.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 1a40fcb..7da73f8 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -43,8 +43,7 @@ class Map: background_color: The background color of the map. next_layer_id: Stores the next available ID for new layers. next_object_id: Stores the next available ID for new objects. - tile_sets: Dict of tile sets used in this map. Key is the first GID for the - tile set. The value is a TileSet object. + tile_sets: Tilesets used in this map. layers: List of layer objects by draw order. """ @@ -61,7 +60,7 @@ class Map: next_layer_id: Optional[int] next_object_id: int - tile_sets: TileSetDict + tile_sets: List[TileSet] layers: List[Layer] hex_side_length: Optional[int] = None From cb22d613b09e430bf32acd4becd93d8266200258 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:01:10 -0400 Subject: [PATCH 102/198] rf(map): this feature will need rethought --- pytiled_parser/map.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 7da73f8..a3220d6 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -47,9 +47,6 @@ class Map: layers: List of layer objects by draw order. """ - parent_dir: Path - tmx_file: Union[str, Path] - version: str tiled_version: str orientation: str From 373204eb862f5eb5c1ff7aceb6b1f96d56b9c642 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:08:25 -0400 Subject: [PATCH 103/198] rf(map): alphabetize --- pytiled_parser/map.py | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index a3220d6..809b10a 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -47,25 +47,23 @@ class Map: layers: List of layer objects by draw order. """ - version: str - tiled_version: str - orientation: str - render_order: str - map_size: Size - tile_size: Size infinite: bool + layers: List[Layer] + map_size: Size next_layer_id: Optional[int] next_object_id: int - + orientation: str + render_order: str + tiled_version: str + tile_size: Size tile_sets: List[TileSet] - layers: List[Layer] + version: str + background_color: Optional[Color] = None + properties: Optional[Properties] = None hex_side_length: Optional[int] = None stagger_axis: Optional[int] = None stagger_index: Optional[int] = None - background_color: Optional[Color] = None - - properties: Optional[Properties] = None class _RawTiledMap(TypedDict): From 27f4cd86a0167b8f168a7551536c7b19b9a3f8cc Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:22:36 -0400 Subject: [PATCH 104/198] doc(map): switch TMX to JSON --- pytiled_parser/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 809b10a..16b1967 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -23,7 +23,7 @@ class Map: Attributes: parent_dir: The directory the TMX file is in. Used for finding relative paths to TSX files and other assets. - version: The TMX format version. + version: The JSON format version. tiled_version: The Tiled version used to save the file. May be a date (for snapshot builds). orientation: Map orientation. Tiled supports "orthogonal", "isometric", From b820dc5a4d1d966972076e7a202ac179757694a2 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:29:41 -0400 Subject: [PATCH 105/198] doc(map): alphabetize the attributes --- pytiled_parser/map.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 16b1967..6f616c1 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -21,30 +21,29 @@ class Map: See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#map Attributes: - parent_dir: The directory the TMX file is in. Used for finding relative paths - to TSX files and other assets. - version: The JSON format version. - tiled_version: The Tiled version used to save the file. May be a date (for - snapshot builds). + infinite: If the map is infinite or not. + layers: List of layer objects by draw order. + map_size: The map width in tiles. + next_layer_id: Stores the next available ID for new layers. + next_object_id: Stores the next available ID for new objects. orientation: Map orientation. Tiled supports "orthogonal", "isometric", "staggered" and "hexagonal" render_order: The order in which tiles on tile layers are rendered. Valid values are right-down, right-up, left-down and left-up. In all cases, the map is + tiled_version: The Tiled version used to save the file. May be a date (for + snapshot builds). drawn row-by-row. (only supported for orthogonal maps at the moment) - map_size: The map width in tiles. tile_size: The width of a tile. - infinite: If the map is infinite or not. + tile_sets: Tilesets used in this map. + version: The JSON format version. + background_color: The background color of the map. + properties: The properties of the Map. hex_side_length: Only for hexagonal maps. Determines the width or height (depending on the staggered axis) of the tile's edge, in pixels. stagger_axis: For staggered and hexagonal maps, determines which axis ("x" or "y") is staggered. stagger_index: For staggered and hexagonal maps, determines whether the "even" or "odd" indexes along the staggered axis are shifted. - background_color: The background color of the map. - next_layer_id: Stores the next available ID for new layers. - next_object_id: Stores the next available ID for new objects. - tile_sets: Tilesets used in this map. - layers: List of layer objects by draw order. """ infinite: bool From 1b3e0e1e848c50dd72e24930c07a1a6d8a616f4c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:31:23 -0400 Subject: [PATCH 106/198] doc(map): size of a tile, not width --- pytiled_parser/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 6f616c1..e0be958 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -33,7 +33,7 @@ class Map: tiled_version: The Tiled version used to save the file. May be a date (for snapshot builds). drawn row-by-row. (only supported for orthogonal maps at the moment) - tile_size: The width of a tile. + tile_size: The size of a tile. tile_sets: Tilesets used in this map. version: The JSON format version. background_color: The background color of the map. From 3087842cca687eb4a369681602345432aed48171 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 6 Jun 2020 18:37:31 -0400 Subject: [PATCH 107/198] feat(layer): stub cast --- pytiled_parser/layer.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 4b6e1f3..5bf5592 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -164,3 +164,7 @@ class RawLayer(TypedDict): width: int x: int y: int + + +def cast(*args, **kwargs): + pass From 6753262328e14ecefea449d28e5c8f46957f52e4 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 19:45:10 -0400 Subject: [PATCH 108/198] chore: moved FIXME outside of docstring so pylint catches it --- pytiled_parser/layer.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 4b6e1f3..dc59a26 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -136,10 +136,8 @@ class RawChunk(TypedDict): class RawLayer(TypedDict): - """ - FIXME Make the layers attribute function - - The keys and their types that appear in a Layer JSON Object.""" + # FIXME Make the layers attribute function + """ The keys and their types that appear in a Layer JSON Object.""" chunks: List[RawChunk] compression: str From a0ce33a563b7c7796d30c4a177a44459d2f34060 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 19:45:42 -0400 Subject: [PATCH 109/198] tests: created a new tileset for individual image tiles with animations and properties --- tests/test_data/images/tile_01.png | Bin 0 -> 2575 bytes tests/test_data/images/tile_02.png | Bin 0 -> 2172 bytes tests/test_data/images/tile_03.png | Bin 0 -> 2527 bytes tests/test_data/images/tile_04.png | Bin 0 -> 2905 bytes .../tilesets/individual_images/tileset.json | 129 ++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 tests/test_data/images/tile_01.png create mode 100644 tests/test_data/images/tile_02.png create mode 100644 tests/test_data/images/tile_03.png create mode 100644 tests/test_data/images/tile_04.png create mode 100644 tests/test_data/tilesets/individual_images/tileset.json diff --git a/tests/test_data/images/tile_01.png b/tests/test_data/images/tile_01.png new file mode 100644 index 0000000000000000000000000000000000000000..a612e69ef7e766ba377c68743361217b5713d600 GIT binary patch literal 2575 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 literal 0 HcmV?d00001 diff --git a/tests/test_data/images/tile_02.png b/tests/test_data/images/tile_02.png new file mode 100644 index 0000000000000000000000000000000000000000..26508f6eb44c61c0d90b47e85784b0eecb9e8f6c GIT binary patch literal 2172 zcmV-?2!r>DP)EX>4Tx04R}tkv&MmKp2MKrfO9x4ptCx$WWauh!t^^ zDi*;)X)CnqU~=h?(4-+rad8w}3l9D)RvlcNb#-tR1i>E=Cr2km7b)?(q|hS9JC1vJ z?|WbFz5|4MnW<*S1fXh`k&4H}Y;HviyrPTdAfo7zn5iey3mJHhuY36Teiz|c-gSSD zJ|%B5z$X&VGTpF<*NLY$EuHf|afp>9h4`F!+@K2*KXP4m`HgeYVS#6cj7(~dI7BQK z+gNU6Rx(uLDdMoAYLqWzT~;`6aaPM!*1RWwVKA>Pr@2mR1aT}Pfh0u8sA2U zyKw^epMfi_<*(F%nNQMdEiHTm^lt+f*DX!n11@)fp(kB3BuDbo5()+2{fxdT2MpW- zy{m5Dn&&uu05a68r5oVj5Ev^`_L|4LyW9KrZ%wm*KXRvXr{j|kQvd(}24YJ`L;(K) z{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jm6@6*nL3$dwWR0013y zMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HRA^-&M@dak?_?!z000I*NklA6O z6~}+?zR#IAGj{xu#z~x-e4q-V8Wlw#B}kSK3J@w9BqWOkNFcFc!wSKo0)D0h- zY+1BySyW;Hm8uFbB%rFe#4xV^p4%F5!&TSUD>b_aFN+Z`I`mb8&l0hxBU z-N2ABTYCXlFU^yNN7$~<)?R?2{_!h?%0Wq_0%6*vzoIBYWdjr@!g5RZNTskH7bPWD zc)Ulgxqy-&EG;ZC5vGmj0oT6;o39Ta-z1j`Q>NIizLI5oO`_hRcA0-3+Wo^0fq}INA!=L01!qAf}Hy7MJ;T4Z0#H%^AsgB04;2K433|I3_&FbUmk%~ zqvkotJS9BdBO3G|k63CX2-C%IhOZ!O$Rp~l#gn3-9{xs=$87E#a((&y@GeDKTck20 z9~`p1pRls%VA>985~H#N|J()b1Emy(RU=IXgkeOhQ6~v|IQ}`1IUuX04YI+>QrC_e zDo?RZf!(MhmB6XBO4k-6O%sUwWf+%*PbOUqa%7&8N(hg483a#9E0nOYZKuq_G)>6T z7?DXx!X9asA?!M~0Dtx(_3Wg2rfD*w?CPa?Y}>)I-Lq@bcRthN!A8JYeCzh@Rl42j zvHoCVlNVpSeyV~88=F}7zP!$poeu!`%fq(-Mij1p^LrEg>K^0gKYn@Y6?*-c_I@xD z_Y?fb0alS+r;RiDE?6(U^gIBa&VXJ&rs2C(Q@qm|jGPK^^V63Jg8oS$RnvCd#oZhjm2-tWNnu?z(a-=*^|a^@P*Ai#D!Y_F+vDNoB387W9uH84Ho;3JJM zMF|)lCKYV%9`ngdGh+x^F|Im<4ZQZZT3jnsSe_06eA;PqYdWS?&MAU7Q z#(g;2L>QEZXGusD4O^Z(0%0N*$o3;WE0E~`83%CfzD~iV7HQlkPb0$a0a5P|Lp}Vh zV&yCF{u{_VBTGW0(%qUlO#W&fcMl#T+*$JI2+M2o-*(LPB_G>ug5^OLO?V=W``Y~g zN{)EK=>73kWm*oqT~iZ_dS}()qrW0&u91Yj@`*gJ1*QO%Yr}*MhN-{-CFl}dqpT+}(u(W4~9i%NN!No=DvllCTr)1f#KVo>6gjoN1 z+ULD@-khpytNi-?snzIj3@Im{C`Gr|Nj=bg9Jzn|h{fScF zZ2A-5RsPOyTlZH}nj>NKzE1FVts!Q5e83KxUj;7@!&A>E#FY$cs*1b|u@hduv0^`?i-79f??bbb3 yZ`>gW`mEl#Q!1@`a9Ss_dgD$hyL#ge0RIDnFLiD!b^ZEX>4Tx04R}tkv&MmKp2MKrfO9x4ptCx$WWauh!t^^ zDi*;)X)CnqU~=h?(4-+rad8w}3l9D)RvlcNb#-tR1i>E=Cr2km7b)?(q|hS9JC1vJ z?|WbFz5|4MnW<*S1fXh`k&4H}Y;HviyrPTdAfo7zn5iey3mJHhuY36Teiz|c-gSSD zJ|%B5z$X&VGTpF<*NLY$EuHf|afp>9h4`F!+@K2*KXP4m`HgeYVS#6cj7(~dI7BQK z+gNU6Rx(uLDdMoAYLqWzT~;`6aaPM!*1RWwVKA>Pr@2mR1aT}Pfh0u8sA2U zyKw^epMfi_<*(F%nNQMdEiHTm^lt+f*DX!n11@)fp(kB3BuDbo5()+2{fxdT2MpW- zy{m5Dn&&uu05a68r5oVj5Ev^`_L|4LyW9KrZ%wm*KXRvXr{j|kQvd(}24YJ`L;(K) z{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jm6@6*oK3%W=a10013y zMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HRA^-&M@dak?_?!z000M~Nkl)z^mboV?xu|0M&85Q3#LVL{SpWjK^_2_ISoUGu>TX?|WI??&|K09g!oIx~r=1Irn_$`_4V> zn0H?>NxwtToG0n-Awb~Z01&hnaX-2fUwrfL*JvJo%9(Hd6d8Ic*4j85Z{V1BUoqf- zP~bR7U1>_K@st6;`N8+s48ZSx_FaSut&guh^DM$u=wdMP0oqYi=>esNAeseT03e1T zsmhEz=@A4Gn>X(QpsNCTO+C%+o1bv`%3HKr5ohD8eB(P`2cZyv_}gD!WqtFHtbh1E zQ>H7lw9n}b9k19X*9Wc~3=8Q4!#A}AAt+n}{@nmkLv^`T5^CjuE- z4|#$Yw4h2YY`~z`86!2a*Dk(9ksP1`i-o*!;fea?haX)BU7#8fJp3YD`vdYn@4OAb z;_(%mof{#l7&hKSR~ce$?JGR>)I;M&4Sv^Fxx}9@2|Yjff)aST6_c=bst}JjPlOdFY@vZG00j4TYu0S%A*S7LT+L%^n|fUM7 zW2^P|w7+i`3yJUh3=Z$$H|G$Z?a^|izWX^);R3F7YY@YkC6FOHI|LabM;*7*8PJb2 zno)zNA3M+GD{om9$9HfXcc_J?ja&|>v_YA|5~Eg;?_>yf{*9hFL!R{O68U}`Tmh!C8xsl~ z*P<}2JM)hoEl=lz>F1*{tmc5QuuHFDAx>>j*YhnmjK&oLbYb~1!Hv(_pu3BZ0j~0< z-WS;bA*4lih=?@00@ueBDPE&797=OO=~SFr4DiDRc<2S#xP<*}!_F7?2s}z8oIN@5 z-Wzw7Ml`kYGEb1#c49t$=g;@_wON0A+~s1v*DX3pkw*kjKuAmH+4?4}Ial zyhI4i z<2M4*?wxwd6zz7z+B4s-5g1*g31jk4!{sY)(d)$=9Q13a&%JN~UD>fsxXQL(1Vy}C p|93*#WQ57_f*Jhkz&EX>4Tx04R}tkv&MmKp2MKrfO9x4ptCx$WWauh!t^^ zDi*;)X)CnqU~=h?(4-+rad8w}3l9D)RvlcNb#-tR1i>E=Cr2km7b)?(q|hS9JC1vJ z?|WbFz5|4MnW<*S1fXh`k&4H}Y;HviyrPTdAfo7zn5iey3mJHhuY36Teiz|c-gSSD zJ|%B5z$X&VGTpF<*NLY$EuHf|afp>9h4`F!+@K2*KXP4m`HgeYVS#6cj7(~dI7BQK z+gNU6Rx(uLDdMoAYLqWzT~;`6aaPM!*1RWwVKA>Pr@2mR1aT}Pfh0u8sA2U zyKw^epMfi_<*(F%nNQMdEiHTm^lt+f*DX!n11@)fp(kB3BuDbo5()+2{fxdT2MpW- zy{m5Dn&&uu05a68r5oVj5Ev^`_L|4LyW9KrZ%wm*KXRvXr{j|kQvd(}24YJ`L;(K) z{{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jm6@6*v+V;q_nu0013y zMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HRA^-&M@dak?_?!z000RbNkl2DP0 z9mhZO%s#s_yXzAJHV_Wm1Qa0M5K%}YRjL%BwxVhSB}I{wEk~?caz={!x(R9jf=rxP zA`r8U(<>shQu-!+RaH$wtisX&Q8?T{2qreh=g!XVTz&EE&e~)p%i5ji{QkbjZ?xB5 zIu^ZfU_EBGo$~xWgq7dPTW4+oU^aIkAOzs*tx2MupCPDyHm%N}-S{h7R2+&x10g}v z5MdBv7cM|pg`k2K{qxrmEt?1f4T5u#Ndk8kKZLjbat$k=Qv>Zn z5rCo7V^qrvm}Z83d%FSDveuD3)CXl+)$-k4%^)N~m+0-rs^eBZ$79<%&4=KJ^homkj^$3%v3y2pRuRH?`N$7ZNL=9| z2A|KxWwG)(T-PP?9ip;B|1Y+JUk2dV{`J^}BENd32hI7{@yKlIAPV92cZxB7){#95 zvfll0{r$N3K^QfF0E9G}unR>h&I|+3?}}*@f3CleS1HBhkTR(z3kf|>*D9GX!7pPM ziVQxVBb+P}wQfeHGE^%r8bQ1x2@}xpN>hCC{I`4 zR3!fx5K%2JkTezO*5M~03Y1>XUAzmxrxz!%4)4N#`xC4qdpLLDHiLcJfCxR?(eKrWVen!p@`JC4SQsa{)4>`xV*4`9Ydp+(UMv0LQ!E;(^?&Hg`i*N z$4_lwX!J7H;aw1VF(U__%VD4Tn7!ZcV&lprcA?0z{p%^ss8efEaVUxh_dQCv?9!Y~ zFQN2K>JF)RPy?_IwOuGG+5%D+oIZ1vFcMh#o$548CVO5LuQU~ZFFVr+E1y%K9#$ewz!oY)`pW@6<;Z;gVvz5~Q zui`Y2W-Iv0Aw6fB@reb*VBd~-fJilCzx)d6=9S3w3JAT}@9S0yAu?$qQyIF~wl}DZ zZZr(Jro^ka?$OCNZ*Yh@|ppz1>`M{PA@&1R}{B?_S~2o&++PCh#k) zXfa6`tt5>!30*m~G%{$(Cc^4Gk!~yrxWL0L&2sYW*YqFQfRSw@j0Ba%NiN|gV4aty?~KzTXyUlcjgE^Wv~e&+Xmc(8)ui4 z64rIDz;mVvF21dx6G;r`5~5=}J!@KGtYR(HCn~M)!3#r%3!gq_U<7-laGoL$Br4EAkjX!H{O2YWg3-gO3^eT3mZTv=8gfTIU` z3EWvu|NWk_u|u1YsU}sP2ki@#Dvc(!#_99y+uN-gDIj6L{R#aCCTeO_{%WMNSVzBy zed;3y`?ldO&Me7??}9F{&s>k=4^3y{+C}yK{uOB7+Spw;kSPJv>h}i&OaLe*gX=6R zgZDk`QyfTX%5cz3Zxj463noWO@bGZ(n72^uN6L+zvE7MOW{3weeEF zUShTB)-@REZ0z6lzqxz&F`8E?Q;b6VN(sF^z3w=`p2ya(JJ-qXTqke5dj;#r9%Mpb zkBqT<{Vcn4YtRxVTI4|#E~~HSmWVW+FbvRzw(R-ssTrCxCJ0GW#~KJKHK9ZZU8+#6 z*Rn3HdP+U$0R%2rZ%wjkbq25EDAzVyktTTMS-grvP*FTelx`BWZl)t6aTezwtRgcj z(C%L$v2uHSKrJf18KEcRSacUvx(yuK%>HtXtU@*FOw=G@+wu z+P6vpFn(u_?zQd9TKC47Bni84KJG~xguKb{pVW)Now<z_oLuI?>FewogV zy^SE%rFt1lH6wJ%#+3=xx`ZBnwTv@2iB~D%F3#XqJly$7oY^}#60>bRMy6$1{f(Bj7%3BXelkW+WZOF98msrW#>;}0&vD|t8x2T9FJ^yvZbErL zr9>Eb>g`#VwRTP5m8KdNUgMRBswB-8jG&f^zQg|kLaTNGG5m|O00000NkvXXu0mjf D)cspc literal 0 HcmV?d00001 diff --git a/tests/test_data/tilesets/individual_images/tileset.json b/tests/test_data/tilesets/individual_images/tileset.json new file mode 100644 index 0000000..7e27721 --- /dev/null +++ b/tests/test_data/tilesets/individual_images/tileset.json @@ -0,0 +1,129 @@ +{ "columns":0, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "grid": + { + "height":1, + "orientation":"orthogonal", + "width":1 + }, + "margin":0, + "name":"tileset", + "spacing":0, + "tilecount":4, + "tiledversion":"1.3.5", + "tileheight":32, + "tiles":[ + { + "animation":[ + { + "duration":100, + "tileid":0 + }, + { + "duration":100, + "tileid":1 + }, + { + "duration":100, + "tileid":2 + }, + { + "duration":100, + "tileid":3 + }], + "id":0, + "image":"..\/..\/images\/tile_01.png", + "imageheight":32, + "imagewidth":32, + "properties":[ + { + "name":"float property", + "type":"float", + "value":2.2 + }], + "type":"tile" + }, + { + "id":1, + "image":"..\/..\/images\/tile_02.png", + "imageheight":32, + "imagewidth":32, + "objectgroup": + { + "draworder":"index", + "name":"", + "objects":[ + { + "height":13.7196924896511, + "id":2, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":14.4766410408043, + "x":13.4358367829687, + "y":13.5304553518628 + }, + { + "ellipse":true, + "height":11.070372560615, + "id":3, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":14.287403903016, + "x":13.8143110585452, + "y":1.98698994677705 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + "properties":[ + { + "name":"string property", + "type":"string", + "value":"testing" + }], + "type":"tile" + }, + { + "id":2, + "image":"..\/..\/images\/tile_03.png", + "imageheight":32, + "imagewidth":32, + "properties":[ + { + "name":"bool property", + "type":"bool", + "value":true + }], + "type":"tile" + }, + { + "id":3, + "image":"..\/..\/images\/tile_04.png", + "imageheight":32, + "imagewidth":32, + "properties":[ + { + "name":"color property", + "type":"color", + "value":"#ff5500ff" + }], + "type":"tile" + }], + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file From 9c373dd815b68c62c5342077d40db2e1dbd36929 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 19:57:47 -0400 Subject: [PATCH 110/198] tests: Started on test for animated tiles with collision shapes. Can't finish until Layer casting is finished --- .../tilesets/individual_images/expected.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/test_data/tilesets/individual_images/expected.py diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py new file mode 100644 index 0000000..383a49f --- /dev/null +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -0,0 +1,62 @@ +from pathlib import Path + +from pytiled_parser import common_types, tiled_object, tileset + +EXPECTED = tileset.TileSet( + columns=0, + margin=0, + spacing=0, + name="tileset", + tile_count=4, + tiled_version="1.3.5", + tile_height=32, + tile_width=32, + version=1.2, + type="tileset", + tiles=[ + tileset.Tile( + animation=[ + tileset.Frame(duration=100, tile_id=0), + tileset.Frame(duration=100, tile_id=1), + tileset.Frame(duration=100, tile_id=2), + tileset.Frame(duration=100, tile_id=3), + ], + id=0, + image=Path("../../images/tile_01.png"), + image_height=32, + image_width=32, + properties={"float property": 2.2}, + type="tile", + ), + tileset.Tile( + id=1, + image=Path("../../images/tile_02.png"), + image_height=32, + image_width=32, + objects=[ + tiled_object.Rectangle( + id=2, + size=common_types.Size(14.4766410408043, 13.7196924896511), + name="", + rotation=0, + type="", + visible=True, + coordinates=common_types.OrderedPair( + 13.4358367829687, 13.5304553518628 + ), + ), + tiled_object.Ellipse( + id=3, + size=common_types.Size(14.287403903016, 11.070372560615), + name="", + rotation=0, + type="", + visible=True, + coordinates=common_types.OrderedPair( + 13.8143110585452, 1.98698994677705 + ), + ), + ], + ), + ], +) From b85fc3cb1f7b8846a5308b38559b0d5673ce5720 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 6 Jun 2020 19:59:01 -0400 Subject: [PATCH 111/198] fix: changes to support animated tile with collision shapes casting based on test files generated from Tiled as it seems the documentation was wrong about that. --- pytiled_parser/tileset.py | 45 +++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index b898e77..a9ee5a0 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -6,8 +6,8 @@ import attr from typing_extensions import TypedDict from . import properties as properties_ +from . import tiled_object from .common_types import Color, OrderedPair -from .tiled_object import TiledObject class Grid(NamedTuple): @@ -92,11 +92,12 @@ class Tile: """ id: int + opacity: int = 1 type: Optional[str] = None terrain: Optional[TileTerrain] = None animation: Optional[List[Frame]] = None - objectgroup: Optional[List[TiledObject]] = None - image: Optional[str] = None + objects: Optional[List[tiled_object.TiledObject]] = None + image: Optional[Path] = None image_width: Optional[int] = None image_height: Optional[int] = None properties: Optional[properties_.Properties] = None @@ -139,10 +140,6 @@ class TileSet: tile_width: int tile_height: int - image: Path - image_width: int - image_height: int - tile_count: int columns: int @@ -152,6 +149,11 @@ class TileSet: spacing: int = 0 margin: int = 0 + image: Optional[Path] = None + image_width: Optional[int] = None + image_height: Optional[int] = None + + type: Optional[str] = None firstgid: Optional[int] = None background_color: Optional[Color] = None tile_offset: Optional[OrderedPair] = None @@ -160,7 +162,6 @@ class TileSet: properties: Optional[properties_.Properties] = None terrain_types: Optional[List[Terrain]] = None tiles: Optional[List[Tile]] = None - source_file: Optional[Path] = None class RawFrame(TypedDict): @@ -195,8 +196,9 @@ class RawTile(TypedDict): image: str imageheight: int imagewidth: int - probability: float + opacity: float properties: List[properties_.RawProperty] + objects: List[tiled_object.RawTiledObject] terrain: List[int] type: str @@ -300,11 +302,16 @@ def _cast_tile(raw_tile: RawTile) -> Tile: for frame in raw_tile["animation"]: tile.animation.append(_cast_frame(frame)) + if raw_tile.get("objects") is not None: + tile.objects = [] + for object_ in raw_tile["objects"]: + tile.objects.append(tiled_object.cast(object_)) + if raw_tile.get("properties") is not None: tile.properties = properties_.cast(raw_tile["properties"]) if raw_tile.get("image") is not None: - tile.image = raw_tile["image"] + tile.image = Path(raw_tile["image"]) if raw_tile.get("imagewidth") is not None: tile.image_width = raw_tile["imagewidth"] @@ -365,11 +372,17 @@ def cast(raw_tileset: RawTileSet) -> TileSet: margin=raw_tileset["margin"], version=raw_tileset["version"], tiled_version=raw_tileset["tiledversion"], - image=Path(raw_tileset["image"]), - image_width=raw_tileset["imagewidth"], - image_height=raw_tileset["imageheight"], ) + if raw_tileset.get("image") is not None: + tileset.image = Path(raw_tileset["image"]) + + if raw_tileset.get("imagewidth") is not None: + tileset.image_width = raw_tileset["imagewidth"] + + if raw_tileset.get("imageheight") is not None: + tileset.image_height = raw_tileset["imageheight"] + if raw_tileset.get("firstgid") is not None: tileset.firstgid = raw_tileset["firstgid"] @@ -382,6 +395,9 @@ def cast(raw_tileset: RawTileSet) -> TileSet: if raw_tileset.get("transparentcolor") is not None: tileset.transparent_color = raw_tileset["transparentcolor"] + if raw_tileset.get("type") is not None: + tileset.type = raw_tileset["type"] + if raw_tileset.get("grid") is not None: tileset.grid = _cast_grid(raw_tileset["grid"]) @@ -400,7 +416,4 @@ def cast(raw_tileset: RawTileSet) -> TileSet: tiles.append(_cast_tile(raw_tile)) tileset.tiles = tiles - if raw_tileset.get("source") is not None: - tileset.source_file = Path(raw_tileset["source"]) - return tileset From d8b005a83cbc62b54c72ec33cd3d113465169f74 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 14:45:38 -0400 Subject: [PATCH 112/198] FIXME: rename to Tileset --- pytiled_parser/tileset.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index a9ee5a0..f1ef6b8 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -109,6 +109,7 @@ class Tile: @attr.s(auto_attribs=True) class TileSet: + # FIXME: rename to Tileset """Object for storing a TSX with all associated collision data. Args: From 9a205829d9aceaeabd2c9ca10d3974da4185d1bf Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 14:53:50 -0400 Subject: [PATCH 113/198] tests: Added type key to all existing tileset tests --- tests/test_data/tilesets/image/expected.py | 1 + tests/test_data/tilesets/image_background_color/expected.py | 1 + tests/test_data/tilesets/image_grid/expected.py | 1 + tests/test_data/tilesets/image_properties/expected.py | 1 + tests/test_data/tilesets/image_tile_offset/expected.py | 1 + tests/test_data/tilesets/image_transparent_color/expected.py | 1 + 6 files changed, 6 insertions(+) diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index 9ad94d3..29b1cfc 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -15,4 +15,5 @@ EXPECTED = tileset.TileSet( tile_height=32, tile_width=32, version=1.2, + type="tileset", ) diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index 458435b..23b0cee 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -17,4 +17,5 @@ EXPECTED = tileset.TileSet( tile_width=32, version=1.2, background_color=Color("#5500ff"), + type="tileset", ) diff --git a/tests/test_data/tilesets/image_grid/expected.py b/tests/test_data/tilesets/image_grid/expected.py index efc9ef5..948bc13 100644 --- a/tests/test_data/tilesets/image_grid/expected.py +++ b/tests/test_data/tilesets/image_grid/expected.py @@ -16,4 +16,5 @@ EXPECTED = tileset.TileSet( tile_width=32, version=1.2, grid=tileset.Grid(orientation="isometric", width=32, height=32), + type="tileset", ) diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index 98013d9..ab6aa5a 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -23,4 +23,5 @@ EXPECTED = tileset.TileSet( "int property": 5, "string property": "testing", }, + type="tileset", ) diff --git a/tests/test_data/tilesets/image_tile_offset/expected.py b/tests/test_data/tilesets/image_tile_offset/expected.py index 78a36bf..2ac339c 100644 --- a/tests/test_data/tilesets/image_tile_offset/expected.py +++ b/tests/test_data/tilesets/image_tile_offset/expected.py @@ -17,4 +17,5 @@ EXPECTED = tileset.TileSet( tile_width=32, version=1.2, tile_offset=OrderedPair(3, 5), + type="tileset", ) diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index 7fa5bd3..56a45ea 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -17,4 +17,5 @@ EXPECTED = tileset.TileSet( tile_width=32, version=1.2, transparent_color=Color("#ff00ff"), + type="tileset", ) From bb3a8ca1f1cfb6b92719e916ec3a46c09fc32524 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 16:01:25 -0400 Subject: [PATCH 114/198] created a base for implementing Layer casting. Also made the types of Layer classes more accurate to Tiled's documentation --- pytiled_parser/layer.py | 118 +++++++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 19 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 1f5fb4c..ecb25d5 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -1,12 +1,13 @@ # pylint: disable=too-few-public-methods -from typing import List, Optional, Union +from pathlib import Path +from typing import Any, List, Optional, Union import attr from typing_extensions import TypedDict from . import properties as properties_ -from .common_types import OrderedPair, Size +from .common_types import Color, OrderedPair, Size from .tiled_object import RawTiledObject, TiledObject @@ -36,9 +37,14 @@ class Layer: id_: int name: str - offset: Optional[OrderedPair] - opacity: Optional[float] - properties: Optional[properties_.Properties] + height: int + width: int + + offset: Optional[OrderedPair] = None + opacity: Optional[float] = 1 + properties: Optional[properties_.Properties] = None + start: Optional[OrderedPair] = None + visible: Optional[bool] = True TileLayerGrid = List[List[int]] @@ -51,16 +57,15 @@ class Chunk: See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#chunk Attributes: - location: Location of chunk in tiles. - width: The width of the chunk in tiles. - height: The height of the chunk in tiles. - layer_data: The global tile IDs in chunky according to row. + coordinates: Location of chunk in tiles. + size: The size of the chunk in tiles. + data: The global tile IDs in chunky according to row. """ - location: OrderedPair - width: int - height: int - chunk_data: TileLayerGrid + coordinates: OrderedPair + size: Size + + data: Optional[Union[List[int], str]] = None LayerData = Union[TileLayerGrid, List[Chunk]] @@ -83,8 +88,11 @@ class TileLayer(Layer): IDs for the map layer, or a list of chunks for an infinite map. """ - size: Size - layer_data: LayerData + encoding: str = "csv" + + compression: Optional[str] = None + chunks: Optional[List[Chunk]] = None + data: Optional[Union[List[int], str]] = None @attr.s(auto_attribs=True, kw_only=True) @@ -107,10 +115,24 @@ class ObjectLayer(Layer): tiled_objects: List[TiledObject] - color: Optional[str] = None draw_order: Optional[str] = "topdown" +@attr.s(auto_attribs=True, kw_only=True) +class ImageLayer(Layer): + """Map layer containing images. + + See: https://doc.mapeditor.org/en/stable/manual/layers/#image-layers + + Attributes: + image: The image used by this layer. + transparent_color: Color that is to be made transparent on this layer. + """ + + image: Path + transparent_color: Optional[Color] = None + + @attr.s(auto_attribs=True, kw_only=True) class LayerGroup(Layer): """Layer Group. @@ -122,7 +144,7 @@ class LayerGroup(Layer): Layers: Layers in group. """ - layers: Optional[List[Union["LayerGroup", Layer, ObjectLayer]]] + layers: Optional[List[Union["LayerGroup", ImageLayer, ObjectLayer, TileLayer]]] class RawChunk(TypedDict): @@ -147,7 +169,7 @@ class RawLayer(TypedDict): height: int id: int image: str - # layers: List[RawLayer] + layers: List[Any] name: str objects: List[RawTiledObject] offsetx: float @@ -164,5 +186,63 @@ class RawLayer(TypedDict): y: int -def cast(*args, **kwargs): +def _cast_chunk(raw_chunk: RawChunk) -> Chunk: + """ Cast the raw_chunk to a Chunk. + + Args: + raw_chunk: RawChunk to be casted to a Chunk + + Returns: + Chunk: The Chunk created from the raw_chunk + """ + + chunk = Chunk( + coordinates=OrderedPair(raw_chunk["x"], raw_chunk["y"]), + size=Size(raw_chunk["width"], raw_chunk["height"]), + ) + + if raw_chunk.get("data") is not None: + chunk.data = raw_chunk["data"] + + return chunk + + +def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: pass + + +def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: + pass + + +def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: + pass + + +def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: + pass + + +def cast(raw_layer: RawLayer) -> Layer: + + layer: Layer + + if raw_layer.get("type") is not None: + if raw_layer["type"] == "tilelayer": + # Tile Layer + layer = _cast_tile_layer(raw_layer) + elif raw_layer["type"] == "objectgroup": + # Object Layer + layer = _cast_object_layer(raw_layer) + elif raw_layer["type"] == "imagelayer": + # Image Layer + layer = _cast_image_layer(raw_layer) + elif raw_layer["type"] == "group": + # Layer Group + layer = _cast_group_layer(raw_layer) + else: + raise AttributeError + else: + raise AttributeError + + return layer From 9caaf209b471cc327bab2d7245f6017afe2c9f57 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 17:13:19 -0400 Subject: [PATCH 115/198] stub(map): undo changes to tilesets --- pytiled_parser/map.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index e0be958..7ec5702 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -34,7 +34,7 @@ class Map: snapshot builds). drawn row-by-row. (only supported for orthogonal maps at the moment) tile_size: The size of a tile. - tile_sets: Tilesets used in this map. + tilesets: Dict of Tileset where Key is the firstgid and the value is the Tileset version: The JSON format version. background_color: The background color of the map. properties: The properties of the Map. @@ -55,13 +55,13 @@ class Map: render_order: str tiled_version: str tile_size: Size - tile_sets: List[TileSet] + tilesets: TilesetDict version: str background_color: Optional[Color] = None properties: Optional[Properties] = None hex_side_length: Optional[int] = None - stagger_axis: Optional[int] = None + stagger_axis: Optional[str] = None stagger_index: Optional[int] = None From 718b4ec0a8729bb6bba6acca604b6d0bef502053 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 17:13:34 -0400 Subject: [PATCH 116/198] rf: tileset, not tile set --- pytiled_parser/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 7ec5702..cf85a7e 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -11,7 +11,7 @@ from .layer import Layer, RawLayer from .properties import Properties, RawProperty from .tileset import RawTileSet, TileSet -TileSetDict = Dict[int, TileSet] +TilesetDict = Dict[int, TileSet] @attr.s(auto_attribs=True) From c248f0eafc71c29d673c7a8080dc7b9056477933 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 19:37:18 -0400 Subject: [PATCH 117/198] feat(map): map parsing --- pytiled_parser/map.py | 69 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index cf85a7e..a232081 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -1,11 +1,14 @@ # pylint: disable=too-few-public-methods +import json from pathlib import Path from typing import Dict, List, NamedTuple, Optional, Union +from typing import cast as typing_cast import attr from typing_extensions import TypedDict +from . import layer, properties, tileset from .common_types import Color, Size from .layer import Layer, RawLayer from .properties import Properties, RawProperty @@ -62,12 +65,19 @@ class Map: properties: Optional[Properties] = None hex_side_length: Optional[int] = None stagger_axis: Optional[str] = None - stagger_index: Optional[int] = None + stagger_index: Optional[str] = None + + +class _RawTilesetMapping(TypedDict): + """ The way that tilesets are stored in the Tiled JSON formatted map.""" + + firstgid: int + source: str class _RawTiledMap(TypedDict): """ The keys and their types that appear in a Tiled JSON Map. - + Keys: compressionlevel: not documented - https://github.com/bjorn/tiled/issues/2815 """ @@ -87,13 +97,34 @@ class _RawTiledMap(TypedDict): staggerindex: str tiledversion: str tileheight: int - tilesets: List[RawTileSet] + tilesets: List[_RawTilesetMapping] tilewidth: int type: str version: str width: int +def _cast_raw_tilesets(raw_tilesets: List[_RawTilesetMapping]) -> TilesetDict: + """ Cast a list of raw tileset mappings to a Tileset dictionary. + + Args: + raw_tilesets: the list of Tileset mappings to be cast into a TilesetDict + + Returns: + TilesetDict: containing all tilesets by `firstgid` + """ + + tilesets: TilesetDict = {} + + for raw_tileset_mapping in raw_tilesets: + with open(Path(raw_tileset_mapping["source"])) as raw_tileset_file: + raw_tileset = typing_cast(RawTileSet, json.load(raw_tileset_file)) + + tilesets[raw_tileset_mapping["firstgid"]] = tileset.cast(raw_tileset) + + return tilesets + + def cast(raw_tiled_map: _RawTiledMap) -> Map: """ Cast the raw Tiled map into a pytiled_parser type @@ -103,3 +134,35 @@ def cast(raw_tiled_map: _RawTiledMap) -> Map: Returns: TileSet: a properly typed TileSet. """ + + # `map` is a built-in function + map_ = Map( + 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"]), + next_layer_id=raw_tiled_map["nextlayerid"], + next_object_id=raw_tiled_map["nextobjectid"], + orientation=raw_tiled_map["orientation"], + render_order=raw_tiled_map["renderorder"], + tiled_version=raw_tiled_map["tiledversion"], + tile_size=Size(raw_tiled_map["tilewidth"], raw_tiled_map["tileheight"]), + tilesets=_cast_raw_tilesets(raw_tiled_map["tilesets"]), + version=raw_tiled_map["version"], + ) + + if raw_tiled_map.get("backgroundcolor") is not None: + map_.background_color = raw_tiled_map["backgroundcolor"] + + if raw_tiled_map.get("properties") is not None: + map_.properties = properties.cast(raw_tiled_map["properties"]) + + if raw_tiled_map.get("hexsidelength") is not None: + map_.hex_side_length = raw_tiled_map["hexsidelength"] + + if raw_tiled_map.get("staggeraxis") is not None: + map_.stagger_axis = raw_tiled_map["staggeraxis"] + + if raw_tiled_map.get("staggerindex") is not None: + map_.stagger_index = raw_tiled_map["staggerindex"] + + return map_ From e94906039cd7c50cc30f2b6c11256080928567ca Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:05:25 -0400 Subject: [PATCH 118/198] changed width and height to not check if they are truthy, as they should always be expected to be so --- pytiled_parser/tiled_object.py | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index a96141e..c21a383 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -207,29 +207,13 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: # required attributes id_ = raw_tiled_object["id"] coordinates = OrderedPair(x=raw_tiled_object["x"], y=raw_tiled_object["y"]) + size = Size(raw_tiled_object["width"], raw_tiled_object["height"]) visible = raw_tiled_object["visible"] common_attributes = TiledObject( - id=id_, coordinates=coordinates, visible=visible, properties={} + id=id_, coordinates=coordinates, visible=visible, size=size ) - # optional attributes - if any([raw_tiled_object.get("width"), raw_tiled_object.get("height")]): - # we have to check if either are truthy before we proceed to create Size - _width = raw_tiled_object.get("width") - if _width: - width = _width - else: - width = 0 - - _height = raw_tiled_object.get("height") - if _height: - height = _height - else: - height = 0 - - common_attributes.size = Size(width, height) - if raw_tiled_object.get("rotation") is not None: common_attributes.rotation = raw_tiled_object["rotation"] From 0dbb7b33fba2c5a1812c21d544eb3bb523724cad Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:08:59 -0400 Subject: [PATCH 119/198] removed opacity attribute from TiledObject as that is not actually a possible attribute of Tiled Objects. --- pytiled_parser/tiled_object.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index c21a383..186a18a 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -35,7 +35,6 @@ class TiledObject: coordinates: OrderedPair size: Size = Size(0, 0) rotation: float = 0 - opacity: float = 1 visible: bool name: Optional[str] = None @@ -179,7 +178,6 @@ class RawTiledObject(TypedDict): width: float height: float rotation: float - opacity: float visible: bool name: str type: str @@ -217,9 +215,6 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: if raw_tiled_object.get("rotation") is not None: common_attributes.rotation = raw_tiled_object["rotation"] - if raw_tiled_object.get("opacity") is not None: - common_attributes.opacity = raw_tiled_object["opacity"] - if raw_tiled_object.get("name") is not None: common_attributes.name = raw_tiled_object["name"] From 802959c290a2130654a6be4fca846ef409fb543b Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:16:38 -0400 Subject: [PATCH 120/198] removed checking rotation and name as they will always be defined in the JSON format --- pytiled_parser/tiled_object.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 186a18a..06796ab 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -201,23 +201,15 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: Returns: TiledObject: The attributes in common of all Tiled Objects """ - - # required attributes - id_ = raw_tiled_object["id"] - coordinates = OrderedPair(x=raw_tiled_object["x"], y=raw_tiled_object["y"]) - size = Size(raw_tiled_object["width"], raw_tiled_object["height"]) - visible = raw_tiled_object["visible"] - common_attributes = TiledObject( - id=id_, coordinates=coordinates, visible=visible, size=size + id=raw_tiled_object["id"], + coordinates=OrderedPair(raw_tiled_object["x"], raw_tiled_object["y"]), + visible=raw_tiled_object["visible"], + size=Size(raw_tiled_object["width"], raw_tiled_object["height"]), + rotation=raw_tiled_object["rotation"], + name=raw_tiled_object["name"], ) - if raw_tiled_object.get("rotation") is not None: - common_attributes.rotation = raw_tiled_object["rotation"] - - if raw_tiled_object.get("name") is not None: - common_attributes.name = raw_tiled_object["name"] - if raw_tiled_object.get("type") is not None: common_attributes.type = raw_tiled_object["type"] From 58018e9871843eb066a9236bc0c65b18e4cfee81 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 20:20:11 -0400 Subject: [PATCH 121/198] stub(layer): get correct caster --- pytiled_parser/layer.py | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index ecb25d5..b84ec53 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -1,7 +1,7 @@ # pylint: disable=too-few-public-methods from pathlib import Path -from typing import Any, List, Optional, Union +from typing import Any, Callable, List, Optional, Union import attr from typing_extensions import TypedDict @@ -223,26 +223,17 @@ def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: pass +def _get_group_caster(type_: str) -> Callable[[RawLayer], Layer]: + casters = { + "tilelayer": _cast_tile_layer, + "objectgroup": _cast_object_layer, + "imagelayer": _cast_image_layer, + "group": _cast_group_layer, + } + return casters[type_] + + def cast(raw_layer: RawLayer) -> Layer: + caster = _get_group_caster(raw_layer["type"]) - layer: Layer - - if raw_layer.get("type") is not None: - if raw_layer["type"] == "tilelayer": - # Tile Layer - layer = _cast_tile_layer(raw_layer) - elif raw_layer["type"] == "objectgroup": - # Object Layer - layer = _cast_object_layer(raw_layer) - elif raw_layer["type"] == "imagelayer": - # Image Layer - layer = _cast_image_layer(raw_layer) - elif raw_layer["type"] == "group": - # Layer Group - layer = _cast_group_layer(raw_layer) - else: - raise AttributeError - else: - raise AttributeError - - return layer + return caster(raw_layer) From 97bd12de8376cc0e679f72bb8aa4cbd819661130 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:21:35 -0400 Subject: [PATCH 122/198] removed checking for type attribute as it should always appear in the JSON format. --- pytiled_parser/tiled_object.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index 06796ab..fe092af 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -201,6 +201,7 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: Returns: TiledObject: The attributes in common of all Tiled Objects """ + common_attributes = TiledObject( id=raw_tiled_object["id"], coordinates=OrderedPair(raw_tiled_object["x"], raw_tiled_object["y"]), @@ -208,11 +209,9 @@ def _get_common_attributes(raw_tiled_object: RawTiledObject) -> TiledObject: size=Size(raw_tiled_object["width"], raw_tiled_object["height"]), rotation=raw_tiled_object["rotation"], name=raw_tiled_object["name"], + type=raw_tiled_object["type"], ) - if raw_tiled_object.get("type") is not None: - common_attributes.type = raw_tiled_object["type"] - if raw_tiled_object.get("properties") is not None: common_attributes.properties = properties_.cast(raw_tiled_object["properties"]) From 77d42246a9cc2dedf172e2eb5d62175314065e66 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 20:31:18 -0400 Subject: [PATCH 123/198] rf(layer): s/_get_layer/_get_group_layer --- pytiled_parser/layer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index b84ec53..4ac0073 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -223,7 +223,7 @@ def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: pass -def _get_group_caster(type_: str) -> Callable[[RawLayer], Layer]: +def _get_caster(type_: str) -> Callable[[RawLayer], Layer]: casters = { "tilelayer": _cast_tile_layer, "objectgroup": _cast_object_layer, @@ -234,6 +234,6 @@ def _get_group_caster(type_: str) -> Callable[[RawLayer], Layer]: def cast(raw_layer: RawLayer) -> Layer: - caster = _get_group_caster(raw_layer["type"]) + caster = _get_caster(raw_layer["type"]) return caster(raw_layer) From 40616a78fd85854c6c40b426f4bb72e2300a73af Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 20:31:30 -0400 Subject: [PATCH 124/198] doc(layer): _get_caster docstring --- pytiled_parser/layer.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 4ac0073..2376744 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -224,6 +224,14 @@ def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: def _get_caster(type_: str) -> Callable[[RawLayer], Layer]: + """ Get the caster function for the raw layer. + + Args: + type_: the type of the layer + + Returns: + Callable[[RawLayer], Layer]: The caster function. + """ casters = { "tilelayer": _cast_tile_layer, "objectgroup": _cast_object_layer, From 0ec3c90d8088e5b3ebaf6647bf72396ec19aa1e2 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 20:34:57 -0400 Subject: [PATCH 125/198] rf(layer): s/id/id_ --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 2376744..5e2fe57 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -34,7 +34,7 @@ class Layer: for more info. """ - id_: int + id: int name: str height: int From 1a49382278c542487fe5308df7763bb02a7ea023 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:37:32 -0400 Subject: [PATCH 126/198] updated objectgroup layer casting to be accurate. It was previously being done as a list of TiledObjects rather than a Layer --- pytiled_parser/tileset.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index f1ef6b8..bce92a6 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -5,6 +5,7 @@ from typing import List, NamedTuple, Optional import attr from typing_extensions import TypedDict +from . import layer from . import properties as properties_ from . import tiled_object from .common_types import Color, OrderedPair @@ -96,7 +97,7 @@ class Tile: type: Optional[str] = None terrain: Optional[TileTerrain] = None animation: Optional[List[Frame]] = None - objects: Optional[List[tiled_object.TiledObject]] = None + objects: Optional[layer.Layer] = None image: Optional[Path] = None image_width: Optional[int] = None image_height: Optional[int] = None @@ -199,7 +200,7 @@ class RawTile(TypedDict): imagewidth: int opacity: float properties: List[properties_.RawProperty] - objects: List[tiled_object.RawTiledObject] + objectgroup: layer.RawLayer terrain: List[int] type: str @@ -303,10 +304,8 @@ def _cast_tile(raw_tile: RawTile) -> Tile: for frame in raw_tile["animation"]: tile.animation.append(_cast_frame(frame)) - if raw_tile.get("objects") is not None: - tile.objects = [] - for object_ in raw_tile["objects"]: - tile.objects.append(tiled_object.cast(object_)) + if raw_tile.get("objectgroup") is not None: + tile.objects = layer.cast(raw_tile["objectgroup"]) if raw_tile.get("properties") is not None: tile.properties = properties_.cast(raw_tile["properties"]) From 68ec66a2278bfae19ab4052938a84e19ec0ae2d8 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:39:47 -0400 Subject: [PATCH 127/198] changed id attribute of Layer to be optional because of it not being present in embedded object layers. --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 5e2fe57..615b41b 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -34,12 +34,12 @@ class Layer: for more info. """ - id: int name: str height: int width: int + id: Optional[int] = None offset: Optional[OrderedPair] = None opacity: Optional[float] = 1 properties: Optional[properties_.Properties] = None From e0d157ab86d1392d383045e2f12fb1d930b4a62a Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 20:45:10 -0400 Subject: [PATCH 128/198] changed width and height attributes of Layer to be optional to accurately reflect the JSON format --- pytiled_parser/layer.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 615b41b..1286796 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -36,10 +36,9 @@ class Layer: name: str - height: int - width: int - id: Optional[int] = None + width: Optional[int] = 0 + height: Optional[int] = 0 offset: Optional[OrderedPair] = None opacity: Optional[float] = 1 properties: Optional[properties_.Properties] = None From a2aa9d986574e4081e830df1825036612470f594 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:00:37 -0400 Subject: [PATCH 129/198] rf(layer): remove extra line --- pytiled_parser/layer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 615b41b..3ce20f7 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -35,7 +35,6 @@ class Layer: """ name: str - height: int width: int From e2651bfbc0fc81448e09ded6f0888da08ce9ce91 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 7 Jun 2020 21:07:35 -0400 Subject: [PATCH 130/198] tests: implemented idnividual image tileset test with animated tiles and collision objects layer. --- .../tilesets/individual_images/expected.py | 70 +++++++++++++------ 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py index 383a49f..48487cb 100644 --- a/tests/test_data/tilesets/individual_images/expected.py +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -1,6 +1,6 @@ from pathlib import Path -from pytiled_parser import common_types, tiled_object, tileset +from pytiled_parser import common_types, layer, tiled_object, tileset EXPECTED = tileset.TileSet( columns=0, @@ -33,30 +33,54 @@ EXPECTED = tileset.TileSet( image=Path("../../images/tile_02.png"), image_height=32, image_width=32, - objects=[ - tiled_object.Rectangle( - id=2, - size=common_types.Size(14.4766410408043, 13.7196924896511), - name="", - rotation=0, - type="", - visible=True, - coordinates=common_types.OrderedPair( - 13.4358367829687, 13.5304553518628 + objects=layer.ObjectLayer( + name="", + opacity=1, + visible=True, + draw_order="index", + tiled_objects=[ + tiled_object.Rectangle( + id=2, + name="", + size=common_types.Size(14.4766410408043, 13.7196924896511), + rotation=0, + type="", + visible=True, + coordinates=common_types.OrderedPair( + 13.4358367829687, 13.5304553518628 + ), ), - ), - tiled_object.Ellipse( - id=3, - size=common_types.Size(14.287403903016, 11.070372560615), - name="", - rotation=0, - type="", - visible=True, - coordinates=common_types.OrderedPair( - 13.8143110585452, 1.98698994677705 + tiled_object.Ellipse( + id=3, + name="", + size=common_types.Size(14.287403903016, 11.070372560615), + rotation=0, + type="", + visible=True, + coordinates=common_types.OrderedPair( + 13.8143110585452, 1.98698994677705 + ), ), - ), - ], + ], + ), + properties={"string property": "testing"}, + type="tile", + ), + tileset.Tile( + id=2, + image=Path("../../images/tile_03.png"), + image_height=32, + image_width=32, + properties={"bool property": True}, + type="tile", + ), + tileset.Tile( + id=3, + image=Path("../../images/tile_04.png"), + image_height=32, + image_width=32, + properties={"color property": common_types.Color("#ff5500ff")}, + type="tile", ), ], ) From cc5ddd1f548f265ee066dea1eec55c873e22470f Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:33:38 -0400 Subject: [PATCH 131/198] doc(layer): cast docstring --- pytiled_parser/layer.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 1286796..d0add67 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -241,6 +241,14 @@ def _get_caster(type_: str) -> Callable[[RawLayer], Layer]: def cast(raw_layer: RawLayer) -> Layer: + """ Cast the raw Tiled layer into a pytiled_parser type + + Args: + raw_layer: Raw layer to be cast. + + Returns: + Layer: a properly typed Layer. + """ caster = _get_caster(raw_layer["type"]) return caster(raw_layer) From be0a3812e3bd49245756c957cde65b96b5b9e4e3 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:33:55 -0400 Subject: [PATCH 132/198] stub(layer): get common attributes --- pytiled_parser/layer.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index d0add67..06d7a27 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -206,6 +206,17 @@ def _cast_chunk(raw_chunk: RawChunk) -> Chunk: return chunk +def _get_common_attributes(raw_layer: RawLayer) -> Layer: + """ Create a Layer containing all the attributes common to all layers + + Args: + raw_layer: Raw Tiled object get common attributes from + + Returns: + Layer: The attributes in common of all layers + """ + + def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: pass From d27b564bbc79cdb8f956d264e6226831c0127789 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:46:29 -0400 Subject: [PATCH 133/198] stub(layer.Layer): the tiled docs need work --- pytiled_parser/layer.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 06d7a27..558f961 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -35,15 +35,14 @@ class Layer: """ name: str + opacity: float + visible: bool id: Optional[int] = None - width: Optional[int] = 0 - height: Optional[int] = 0 + size: Optional[Size] = None offset: Optional[OrderedPair] = None - opacity: Optional[float] = 1 properties: Optional[properties_.Properties] = None - start: Optional[OrderedPair] = None - visible: Optional[bool] = True + coordinates: Optional[OrderedPair] = None TileLayerGrid = List[List[int]] From 34e898f3ef37640691b9ff9900e18f774b5e09c2 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:47:05 -0400 Subject: [PATCH 134/198] rf(layer.Layer): alphabetize --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 558f961..43781d2 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -38,11 +38,11 @@ class Layer: opacity: float visible: bool + coordinates: Optional[OrderedPair] = None id: Optional[int] = None size: Optional[Size] = None offset: Optional[OrderedPair] = None properties: Optional[properties_.Properties] = None - coordinates: Optional[OrderedPair] = None TileLayerGrid = List[List[int]] From abc73fdf0649bb0ba1bdfa0d0941416891b91002 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sun, 7 Jun 2020 21:48:34 -0400 Subject: [PATCH 135/198] feat(layer): build out _get_common_attributes --- pytiled_parser/layer.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 43781d2..3e7cb9c 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -214,6 +214,29 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer: Returns: Layer: The attributes in common of all layers """ + common_attributes = Layer(name=raw_layer["name"]) + + if raw_layer.get("startx") is not None: + common_attributes.coordinates = OrderedPair( + raw_layer["startx"], raw_layer["starty"] + ) + + if raw_layer.get("id") is not None: + common_attributes.id = raw_layer["id"] + + # if either width or height is present, they both are + if raw_layer.get("width") is not None: + common_attributes.size = Size(raw_layer["width"], raw_layer["height"]) + + if raw_layer.get("offsetx") is not None: + common_attributes.offset = OrderedPair( + raw_layer["offsetx"], raw_layer["offsety"] + ) + + if raw_layer.get("properties") is not None: + common_attributes.properties = properties_.cast(raw_layer["properties"]) + + return common_attributes def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: From 452e8a29db3868880a39b8e7a2cd04f16bc3580a Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:13:28 -0400 Subject: [PATCH 136/198] test(layer): example stubs --- .../test_data/layers/all_layer_types/map.json | 63 +++++++++++++++++ .../tileset.json} | 14 +++- .../map_simple_external_tileset.json | 68 ------------------- 3 files changed, 74 insertions(+), 71 deletions(-) create mode 100644 tests/test_data/layers/all_layer_types/map.json rename tests/test_data/layers/{ten_layers/tileset_image.json => all_layer_types/tileset.json} (50%) delete mode 100644 tests/test_data/layers/ten_layers/map_simple_external_tileset.json diff --git a/tests/test_data/layers/all_layer_types/map.json b/tests/test_data/layers/all_layer_types/map.json new file mode 100644 index 0000000..6aa83c4 --- /dev/null +++ b/tests/test_data/layers/all_layer_types/map.json @@ -0,0 +1,63 @@ +{ "compressionlevel":-1, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":3, + "image":"", + "name":"Image Layer 1", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "layers":[], + "name":"Group 1", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":5, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layers/ten_layers/tileset_image.json b/tests/test_data/layers/all_layer_types/tileset.json similarity index 50% rename from tests/test_data/layers/ten_layers/tileset_image.json rename to tests/test_data/layers/all_layer_types/tileset.json index 8f3b73e..8df9f18 100644 --- a/tests/test_data/layers/ten_layers/tileset_image.json +++ b/tests/test_data/layers/all_layer_types/tileset.json @@ -1,14 +1,22 @@ { "columns":8, - "image":"..\/images\/tmw_desert_spacing.png", + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", "imageheight":199, "imagewidth":265, "margin":1, "name":"tile_set_image", "spacing":1, "tilecount":48, - "tiledversion":"1.3.1", + "tiledversion":"1.3.5", "tileheight":32, "tilewidth":32, "type":"tileset", "version":1.2 -} +} \ No newline at end of file diff --git a/tests/test_data/layers/ten_layers/map_simple_external_tileset.json b/tests/test_data/layers/ten_layers/map_simple_external_tileset.json deleted file mode 100644 index e68a7f7..0000000 --- a/tests/test_data/layers/ten_layers/map_simple_external_tileset.json +++ /dev/null @@ -1,68 +0,0 @@ -{ "compressionlevel":0, - "height":6, - "infinite":false, - "layers":[ - { - "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], - "height":6, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":8, - "x":0, - "y":0 - }], - "nextlayerid":2, - "nextobjectid":1, - "orientation":"orthogonal", - "properties":[ - { - "name":"bool property - false", - "type":"bool", - "value":false - }, - { - "name":"bool property - true", - "type":"bool", - "value":true - }, - { - "name":"color property", - "type":"color", - "value":"#ff49fcff" - }, - { - "name":"file property", - "type":"file", - "value":"..\/..\/..\/..\/..\/..\/var\/log\/syslog" - }, - { - "name":"float property", - "type":"float", - "value":1.23456789 - }, - { - "name":"int property", - "type":"int", - "value":13 - }, - { - "name":"string property", - "type":"string", - "value":"Hello, World!!" - }], - "renderorder":"right-down", - "tiledversion":"1.3.1", - "tileheight":32, - "tilesets":[ - { - "firstgid":1, - "source":"tileset_image.json" - }], - "tilewidth":32, - "type":"map", - "version":1.2, - "width":8 -} From e805230b1628980076d1c769853e47f9dadbb2d1 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:16:13 -0400 Subject: [PATCH 137/198] chore(pylintrc): `id` is an acceptable var name --- .pylintrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index c0ded7d..6bcf70a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -305,7 +305,8 @@ good-names=i, y, ex, Run, - _ + _, + id # Include a hint for the correct naming format with invalid-name. include-naming-hint=no From 6721bef2919a4e516ecd818f9cfc5e35d37f5dd3 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:16:43 -0400 Subject: [PATCH 138/198] fix(layer): `common_attributes` required attributes --- pytiled_parser/layer.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 3e7cb9c..15f2b5c 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -214,7 +214,11 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer: Returns: Layer: The attributes in common of all layers """ - common_attributes = Layer(name=raw_layer["name"]) + common_attributes = Layer( + name=raw_layer["name"], + opacity=raw_layer["opacity"], + visible=raw_layer["visible"], + ) if raw_layer.get("startx") is not None: common_attributes.coordinates = OrderedPair( From fefab2a1a2748958d712ec1f878373efb6bd4c78 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:23:07 -0400 Subject: [PATCH 139/198] feat(map): TileLayer casting --- pytiled_parser/layer.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 15f2b5c..617e803 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -244,7 +244,30 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer: def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: - pass + """ Cast the raw_layer to a TileLayer. + + Args: + raw_layer: RawLayer to be casted to a TileLayer + + Returns: + TileLayer: The TileLayer created from raw_layer + """ + tile_layer = TileLayer(**_get_common_attributes(raw_layer).__dict__) + + tile_layer.encoding = raw_layer["encoding"] + + if raw_layer.get("compression") is not None: + tile_layer.compression = raw_layer["compression"] + + if raw_layer.get("chunks") is not None: + tile_layer.chunks = [] + for chunk in raw_layer["chunks"]: + tile_layer.chunks.append(_cast_chunk(chunk)) + + if raw_layer.get("data") is not None: + tile_layer.data = raw_layer["data"] + + return tile_layer def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: From 54ad9633eb4409eca52d4078bf39095c28704e4a Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:26:54 -0400 Subject: [PATCH 140/198] rf(layer): remove extra tab --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 617e803..8d00eb9 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -245,7 +245,7 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer: def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: """ Cast the raw_layer to a TileLayer. - + Args: raw_layer: RawLayer to be casted to a TileLayer From 2d6e9ac0d06eb87517e8db753ceb966bb9e74c7d Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:32:07 -0400 Subject: [PATCH 141/198] feat(layer): Implemented ObjectLayer casting --- pytiled_parser/layer.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 617e803..2ead0b5 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -7,8 +7,8 @@ import attr from typing_extensions import TypedDict from . import properties as properties_ +from . import tiled_object from .common_types import Color, OrderedPair, Size -from .tiled_object import RawTiledObject, TiledObject @attr.s(auto_attribs=True, kw_only=True) @@ -111,7 +111,7 @@ class ObjectLayer(Layer): for more info. """ - tiled_objects: List[TiledObject] + tiled_objects: List[tiled_object.TiledObject] draw_order: Optional[str] = "topdown" @@ -252,6 +252,7 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: Returns: TileLayer: The TileLayer created from raw_layer """ + tile_layer = TileLayer(**_get_common_attributes(raw_layer).__dict__) tile_layer.encoding = raw_layer["encoding"] @@ -271,7 +272,24 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: - pass + """ Cast the raw_layer to an ObjectLayer. + + Args: + raw_layer: RawLayer to be casted to an ObjectLayer + + Returns: + ObjectLayer: The ObjectLayer created from raw_layer + """ + + tiled_objects = [] + for tiled_object_ in raw_layer["objects"]: + tiled_objects.append(tiled_object.cast(tiled_object_)) + + return ObjectLayer( + tiled_objects=tiled_objects, + draw_order=raw_layer["draworder"], + **_get_common_attributes(raw_layer).__dict__ + ) def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: From 290bdb70ea7fbe01efa78bfeaad0ae57c13bf0fd Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:36:34 -0400 Subject: [PATCH 142/198] feat(layer): Implemented LayerGroup casting --- pytiled_parser/layer.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index b4f9f1d..e49ee80 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -142,7 +142,7 @@ class LayerGroup(Layer): Layers: Layers in group. """ - layers: Optional[List[Union["LayerGroup", ImageLayer, ObjectLayer, TileLayer]]] + layers: Optional[List[Layer]] class RawChunk(TypedDict): @@ -169,7 +169,7 @@ class RawLayer(TypedDict): image: str layers: List[Any] name: str - objects: List[RawTiledObject] + objects: List[tiled_object.RawTiledObject] offsetx: float offsety: float opacity: float @@ -297,7 +297,21 @@ def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: - pass + """ Cast the raw_layer to a LayerGroup. + + Args: + raw_layer: RawLayer to be casted to a LayerGroup + + Returns: + LayerGroup: The LayerGroup created from raw_layer + """ + + layers = [] + + for layer in raw_layer["layers"]: + layers.append(cast(layer)) + + return LayerGroup(layers=layers, **_get_common_attributes(raw_layer).__dict__) def _get_caster(type_: str) -> Callable[[RawLayer], Layer]: From 8782903fe5a34a59210ffd89accc699f1fdc2a30 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:36:54 -0400 Subject: [PATCH 143/198] feat(layer): imagelayer --- pytiled_parser/layer.py | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index e49ee80..e032a53 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -7,8 +7,8 @@ import attr from typing_extensions import TypedDict from . import properties as properties_ -from . import tiled_object from .common_types import Color, OrderedPair, Size +from .tiled_object import RawTiledObject, TiledObject @attr.s(auto_attribs=True, kw_only=True) @@ -111,7 +111,7 @@ class ObjectLayer(Layer): for more info. """ - tiled_objects: List[tiled_object.TiledObject] + tiled_objects: List[TiledObject] draw_order: Optional[str] = "topdown" @@ -252,7 +252,6 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: Returns: TileLayer: The TileLayer created from raw_layer """ - tile_layer = TileLayer(**_get_common_attributes(raw_layer).__dict__) tile_layer.encoding = raw_layer["encoding"] @@ -272,28 +271,26 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: - """ Cast the raw_layer to an ObjectLayer. - - Args: - raw_layer: RawLayer to be casted to an ObjectLayer - - Returns: - ObjectLayer: The ObjectLayer created from raw_layer - """ - - tiled_objects = [] - for tiled_object_ in raw_layer["objects"]: - tiled_objects.append(tiled_object.cast(tiled_object_)) - - return ObjectLayer( - tiled_objects=tiled_objects, - draw_order=raw_layer["draworder"], - **_get_common_attributes(raw_layer).__dict__ - ) + pass def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: - pass + """ Cast the raw_layer to a ImageLayer. + + Args: + raw_layer: RawLayer to be casted to a ImageLayer + + Returns: + ImageLayer: The ImageLayer created from raw_layer + """ + image_layer = ImageLayer( + image=Path(raw_layer["image"]), **_get_common_attributes(raw_layer).__dict__ + ) + + if raw_layer.get("transparentcolor") is not None: + image_layer.transparent_color = Color(raw_layer["transparentcolor"]) + + return image_layer def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: From 03f9744e24d1e68ed9df69ba3921fe6e996a6667 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:39:39 -0400 Subject: [PATCH 144/198] feat(layer): Reimplemented ObjectLayer casting --- pytiled_parser/layer.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index e032a53..99a1d7e 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -271,7 +271,23 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: - pass + """ Cast the raw_layer to an ObjectLayer. + + Args: + raw_layer: RawLayer to be casted to an ObjectLayer + Returns: + ObjectLayer: The ObjectLayer created from raw_layer + """ + + tiled_objects = [] + for tiled_object_ in raw_layer["objects"]: + tiled_objects.append(tiled_object.cast(tiled_object_)) + + return ObjectLayer( + tiled_objects=tiled_objects, + draw_order=raw_layer["draworder"], + **_get_common_attributes(raw_layer).__dict__ + ) def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: From 7cf9e025ce4bd248272cfed82d270a09b9d8efff Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:40:29 -0400 Subject: [PATCH 145/198] fix(layer): Fixed tiled_object import --- pytiled_parser/layer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 99a1d7e..ba141a6 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -7,8 +7,8 @@ import attr from typing_extensions import TypedDict from . import properties as properties_ +from . import tiled_object from .common_types import Color, OrderedPair, Size -from .tiled_object import RawTiledObject, TiledObject @attr.s(auto_attribs=True, kw_only=True) @@ -111,7 +111,7 @@ class ObjectLayer(Layer): for more info. """ - tiled_objects: List[TiledObject] + tiled_objects: List[tiled_object.TiledObject] draw_order: Optional[str] = "topdown" From a1bd3c372a248955717b888473f891d37aa10a6c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:41:09 -0400 Subject: [PATCH 146/198] fix(layer): darren is bad at not leaving extra whitespace --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index ba141a6..eb88894 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -272,7 +272,7 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: """ Cast the raw_layer to an ObjectLayer. - + Args: raw_layer: RawLayer to be casted to an ObjectLayer Returns: From 241127c6f11d893d9b4d356ba8971945788b6f18 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:41:54 -0400 Subject: [PATCH 147/198] fix(layer): darren is bad at leaving extra whitespace 2: electric boog --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index eb88894..b10e442 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -311,7 +311,7 @@ def _cast_image_layer(raw_layer: RawLayer) -> ImageLayer: def _cast_group_layer(raw_layer: RawLayer) -> LayerGroup: """ Cast the raw_layer to a LayerGroup. - + Args: raw_layer: RawLayer to be casted to a LayerGroup From 41071ba5319a4e2134a208ef78523a6847a44143 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Tue, 9 Jun 2020 21:45:15 -0400 Subject: [PATCH 148/198] chore(test): rename layers dir to layer_tests --- tests/test_data/{layers => layer_tests}/all_layer_types/map.json | 0 .../{layers => layer_tests}/all_layer_types/tileset.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/test_data/{layers => layer_tests}/all_layer_types/map.json (100%) rename tests/test_data/{layers => layer_tests}/all_layer_types/tileset.json (100%) diff --git a/tests/test_data/layers/all_layer_types/map.json b/tests/test_data/layer_tests/all_layer_types/map.json similarity index 100% rename from tests/test_data/layers/all_layer_types/map.json rename to tests/test_data/layer_tests/all_layer_types/map.json diff --git a/tests/test_data/layers/all_layer_types/tileset.json b/tests/test_data/layer_tests/all_layer_types/tileset.json similarity index 100% rename from tests/test_data/layers/all_layer_types/tileset.json rename to tests/test_data/layer_tests/all_layer_types/tileset.json From 452101521cfa8aa5ff3e4aa38527777034d23621 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 9 Jun 2020 21:59:03 -0400 Subject: [PATCH 149/198] tests: Implemented more tileset testing. Only missing terrains and wang sets at this point. --- tests/test_data/tilesets/individual_images/expected.py | 1 + tests/test_tileset.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py index 48487cb..c64f252 100644 --- a/tests/test_data/tilesets/individual_images/expected.py +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -13,6 +13,7 @@ EXPECTED = tileset.TileSet( tile_width=32, version=1.2, type="tileset", + grid=tileset.Grid(orientation="orthogonal", width=1, height=1), tiles=[ tileset.Tile( animation=[ diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 2d72dc1..12f1656 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -20,6 +20,7 @@ ALL_TILESET_DIRS = [ TILE_SETS / "image_properties", TILE_SETS / "image_transparent_color", TILE_SETS / "image_tile_offset", + TILE_SETS / "individual_images", ] From 3112e562eb72b13c38c8c8ccd586196dff31e6c9 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 14 Jun 2020 12:19:40 -0400 Subject: [PATCH 150/198] fix: changed properties list of Terrain object in tileset to be optional --- pytiled_parser/tileset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index bce92a6..502aaa9 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -39,7 +39,7 @@ class Terrain(NamedTuple): name: str tile: int - properties: properties_.Properties = {} + properties: Optional[properties_.Properties] = None @attr.s(auto_attribs=True) From 87916d6332dbe71a25e8f8faa2923b6bd6b197bf Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 14 Jun 2020 12:21:18 -0400 Subject: [PATCH 151/198] tests: removed color property from individual_images test to increase branch coverage --- tests/test_data/tilesets/individual_images/expected.py | 1 - tests/test_data/tilesets/individual_images/tileset.json | 8 +------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py index c64f252..54625d2 100644 --- a/tests/test_data/tilesets/individual_images/expected.py +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -80,7 +80,6 @@ EXPECTED = tileset.TileSet( image=Path("../../images/tile_04.png"), image_height=32, image_width=32, - properties={"color property": common_types.Color("#ff5500ff")}, type="tile", ), ], diff --git a/tests/test_data/tilesets/individual_images/tileset.json b/tests/test_data/tilesets/individual_images/tileset.json index 7e27721..a22186e 100644 --- a/tests/test_data/tilesets/individual_images/tileset.json +++ b/tests/test_data/tilesets/individual_images/tileset.json @@ -115,15 +115,9 @@ "image":"..\/..\/images\/tile_04.png", "imageheight":32, "imagewidth":32, - "properties":[ - { - "name":"color property", - "type":"color", - "value":"#ff5500ff" - }], "type":"tile" }], "tilewidth":32, "type":"tileset", "version":1.2 -} \ No newline at end of file +} From f54093a17135074dbc1310a072be2234d4471e65 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 14 Jun 2020 12:22:13 -0400 Subject: [PATCH 152/198] tests: implemented terrain test for tilesets --- tests/test_data/tilesets/terrain/expected.py | 267 ++++++++++++ tests/test_data/tilesets/terrain/tileset.json | 395 ++++++++++++++++++ tests/test_tileset.py | 1 + 3 files changed, 663 insertions(+) create mode 100644 tests/test_data/tilesets/terrain/expected.py create mode 100644 tests/test_data/tilesets/terrain/tileset.json diff --git a/tests/test_data/tilesets/terrain/expected.py b/tests/test_data/tilesets/terrain/expected.py new file mode 100644 index 0000000..c60195c --- /dev/null +++ b/tests/test_data/tilesets/terrain/expected.py @@ -0,0 +1,267 @@ +from pathlib import Path + +from pytiled_parser import common_types, layer, tileset + +EXPECTED = tileset.TileSet( + columns=8, + margin=1, + spacing=1, + name="tileset", + image=Path("../../images/tmw_desert_spacing.png"), + image_height=199, + image_width=265, + tile_count=48, + tiled_version="1.3.5", + tile_height=32, + tile_width=32, + version=1.2, + type="tileset", + terrain_types=[ + tileset.Terrain(name="Sand", tile=29), + tileset.Terrain(name="Cobblestone", tile=29), + tileset.Terrain(name="Pavement", tile=29), + tileset.Terrain(name="Dirt", tile=29), + ], + tiles=[ + tileset.Tile( + id=0, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=0, bottom_right=1 + ), + ), + tileset.Tile( + id=1, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=1, bottom_right=1 + ), + ), + tileset.Tile( + id=2, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=1, bottom_right=0 + ), + ), + tileset.Tile( + id=3, + terrain=tileset.TileTerrain( + top_left=3, top_right=3, bottom_left=3, bottom_right=0 + ), + ), + tileset.Tile( + id=4, + terrain=tileset.TileTerrain( + top_left=3, top_right=3, bottom_left=0, bottom_right=3 + ), + ), + tileset.Tile( + id=5, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=0, bottom_right=3 + ), + ), + tileset.Tile( + id=6, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=3, bottom_right=3 + ), + ), + tileset.Tile( + id=7, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=3, bottom_right=0 + ), + ), + tileset.Tile( + id=8, + terrain=tileset.TileTerrain( + top_left=0, top_right=1, bottom_left=0, bottom_right=1 + ), + ), + tileset.Tile( + id=9, + terrain=tileset.TileTerrain( + top_left=1, top_right=1, bottom_left=1, bottom_right=1 + ), + ), + tileset.Tile( + id=10, + terrain=tileset.TileTerrain( + top_left=1, top_right=0, bottom_left=1, bottom_right=0 + ), + ), + tileset.Tile( + id=11, + terrain=tileset.TileTerrain( + top_left=3, top_right=0, bottom_left=3, bottom_right=3 + ), + ), + tileset.Tile( + id=12, + terrain=tileset.TileTerrain( + top_left=0, top_right=3, bottom_left=3, bottom_right=3 + ), + ), + tileset.Tile( + id=13, + terrain=tileset.TileTerrain( + top_left=0, top_right=3, bottom_left=0, bottom_right=3 + ), + ), + tileset.Tile( + id=14, + terrain=tileset.TileTerrain( + top_left=3, top_right=3, bottom_left=3, bottom_right=3 + ), + ), + tileset.Tile( + id=15, + terrain=tileset.TileTerrain( + top_left=3, top_right=0, bottom_left=3, bottom_right=0 + ), + ), + tileset.Tile( + id=16, + terrain=tileset.TileTerrain( + top_left=0, top_right=1, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=17, + terrain=tileset.TileTerrain( + top_left=1, top_right=1, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=18, + terrain=tileset.TileTerrain( + top_left=1, top_right=0, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=19, + terrain=tileset.TileTerrain( + top_left=1, top_right=1, bottom_left=1, bottom_right=0 + ), + ), + tileset.Tile( + id=20, + terrain=tileset.TileTerrain( + top_left=1, top_right=1, bottom_left=0, bottom_right=1 + ), + ), + tileset.Tile( + id=21, + terrain=tileset.TileTerrain( + top_left=0, top_right=3, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=22, + terrain=tileset.TileTerrain( + top_left=3, top_right=3, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=23, + terrain=tileset.TileTerrain( + top_left=3, top_right=0, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=24, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=0, bottom_right=2 + ), + ), + tileset.Tile( + id=25, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=2, bottom_right=2 + ), + ), + tileset.Tile( + id=26, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=2, bottom_right=0 + ), + ), + tileset.Tile( + id=27, + terrain=tileset.TileTerrain( + top_left=1, top_right=0, bottom_left=1, bottom_right=1 + ), + ), + tileset.Tile( + id=28, + terrain=tileset.TileTerrain( + top_left=0, top_right=1, bottom_left=1, bottom_right=1 + ), + ), + tileset.Tile( + id=29, + terrain=tileset.TileTerrain( + top_left=0, top_right=0, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=32, + terrain=tileset.TileTerrain( + top_left=0, top_right=2, bottom_left=0, bottom_right=2 + ), + ), + tileset.Tile( + id=33, + terrain=tileset.TileTerrain( + top_left=2, top_right=2, bottom_left=2, bottom_right=2 + ), + ), + tileset.Tile( + id=34, + terrain=tileset.TileTerrain( + top_left=2, top_right=0, bottom_left=2, bottom_right=0 + ), + ), + tileset.Tile( + id=35, + terrain=tileset.TileTerrain( + top_left=2, top_right=2, bottom_left=2, bottom_right=0 + ), + ), + tileset.Tile( + id=36, + terrain=tileset.TileTerrain( + top_left=2, top_right=2, bottom_left=0, bottom_right=2 + ), + ), + tileset.Tile( + id=40, + terrain=tileset.TileTerrain( + top_left=0, top_right=2, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=41, + terrain=tileset.TileTerrain( + top_left=2, top_right=2, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=42, + terrain=tileset.TileTerrain( + top_left=2, top_right=0, bottom_left=0, bottom_right=0 + ), + ), + tileset.Tile( + id=43, + terrain=tileset.TileTerrain( + top_left=2, top_right=0, bottom_left=2, bottom_right=2 + ), + ), + tileset.Tile( + id=44, + terrain=tileset.TileTerrain( + top_left=0, top_right=2, bottom_left=2, bottom_right=2 + ), + ), + ], +) diff --git a/tests/test_data/tilesets/terrain/tileset.json b/tests/test_data/tilesets/terrain/tileset.json new file mode 100644 index 0000000..a2b1667 --- /dev/null +++ b/tests/test_data/tilesets/terrain/tileset.json @@ -0,0 +1,395 @@ +{ + "columns": 8, + "image": "..\/..\/images\/tmw_desert_spacing.png", + "imageheight": 199, + "imagewidth": 265, + "margin": 1, + "name": "tileset", + "spacing": 1, + "terrains": [ + { + "name": "Sand", + "tile": 29 + }, + { + "name": "Cobblestone", + "tile": 29 + }, + { + "name": "Pavement", + "tile": 29 + }, + { + "name": "Dirt", + "tile": 29 + } + ], + "tilecount": 48, + "tiledversion": "1.3.5", + "tileheight": 32, + "tiles": [ + { + "id": 0, + "terrain": [ + 0, + 0, + 0, + 1 + ] + }, + { + "id": 1, + "terrain": [ + 0, + 0, + 1, + 1 + ] + }, + { + "id": 2, + "terrain": [ + 0, + 0, + 1, + 0 + ] + }, + { + "id": 3, + "terrain": [ + 3, + 3, + 3, + 0 + ] + }, + { + "id": 4, + "terrain": [ + 3, + 3, + 0, + 3 + ] + }, + { + "id": 5, + "terrain": [ + 0, + 0, + 0, + 3 + ] + }, + { + "id": 6, + "terrain": [ + 0, + 0, + 3, + 3 + ] + }, + { + "id": 7, + "terrain": [ + 0, + 0, + 3, + 0 + ] + }, + { + "id": 8, + "terrain": [ + 0, + 1, + 0, + 1 + ] + }, + { + "id": 9, + "terrain": [ + 1, + 1, + 1, + 1 + ] + }, + { + "id": 10, + "terrain": [ + 1, + 0, + 1, + 0 + ] + }, + { + "id": 11, + "terrain": [ + 3, + 0, + 3, + 3 + ] + }, + { + "id": 12, + "terrain": [ + 0, + 3, + 3, + 3 + ] + }, + { + "id": 13, + "terrain": [ + 0, + 3, + 0, + 3 + ] + }, + { + "id": 14, + "terrain": [ + 3, + 3, + 3, + 3 + ] + }, + { + "id": 15, + "terrain": [ + 3, + 0, + 3, + 0 + ] + }, + { + "id": 16, + "terrain": [ + 0, + 1, + 0, + 0 + ] + }, + { + "id": 17, + "terrain": [ + 1, + 1, + 0, + 0 + ] + }, + { + "id": 18, + "terrain": [ + 1, + 0, + 0, + 0 + ] + }, + { + "id": 19, + "terrain": [ + 1, + 1, + 1, + 0 + ] + }, + { + "id": 20, + "terrain": [ + 1, + 1, + 0, + 1 + ] + }, + { + "id": 21, + "terrain": [ + 0, + 3, + 0, + 0 + ] + }, + { + "id": 22, + "terrain": [ + 3, + 3, + 0, + 0 + ] + }, + { + "id": 23, + "terrain": [ + 3, + 0, + 0, + 0 + ] + }, + { + "id": 24, + "terrain": [ + 0, + 0, + 0, + 2 + ] + }, + { + "id": 25, + "terrain": [ + 0, + 0, + 2, + 2 + ] + }, + { + "id": 26, + "terrain": [ + 0, + 0, + 2, + 0 + ] + }, + { + "id": 27, + "terrain": [ + 1, + 0, + 1, + 1 + ] + }, + { + "id": 28, + "terrain": [ + 0, + 1, + 1, + 1 + ] + }, + { + "id": 29, + "terrain": [ + 0, + 0, + 0, + 0 + ] + }, + { + "id": 32, + "terrain": [ + 0, + 2, + 0, + 2 + ] + }, + { + "id": 33, + "terrain": [ + 2, + 2, + 2, + 2 + ] + }, + { + "id": 34, + "terrain": [ + 2, + 0, + 2, + 0 + ] + }, + { + "id": 35, + "terrain": [ + 2, + 2, + 2, + 0 + ] + }, + { + "id": 36, + "terrain": [ + 2, + 2, + 0, + 2 + ] + }, + { + "id": 40, + "terrain": [ + 0, + 2, + 0, + 0 + ] + }, + { + "id": 41, + "terrain": [ + 2, + 2, + 0, + 0 + ] + }, + { + "id": 42, + "terrain": [ + 2, + 0, + 0, + 0 + ] + }, + { + "id": 43, + "terrain": [ + 2, + 0, + 2, + 2 + ] + }, + { + "id": 44, + "terrain": [ + 0, + 2, + 2, + 2 + ] + } + ], + "tilewidth": 32, + "type": "tileset", + "version": 1.2 +} diff --git a/tests/test_tileset.py b/tests/test_tileset.py index 12f1656..f8a83a1 100644 --- a/tests/test_tileset.py +++ b/tests/test_tileset.py @@ -21,6 +21,7 @@ ALL_TILESET_DIRS = [ TILE_SETS / "image_transparent_color", TILE_SETS / "image_tile_offset", TILE_SETS / "individual_images", + TILE_SETS / "terrain", ] From 1864162cfb293bc0abc2136e32ce08ed98729cb2 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 14 Jun 2020 14:23:06 -0400 Subject: [PATCH 153/198] fix: changes type attribute of TileSet to not be optional. It is provided as 'tileset' by default from Tiled. --- pytiled_parser/tileset.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 502aaa9..d2bf9a4 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -139,6 +139,7 @@ class TileSet: """ name: str + type: str tile_width: int tile_height: int @@ -155,7 +156,6 @@ class TileSet: image_width: Optional[int] = None image_height: Optional[int] = None - type: Optional[str] = None firstgid: Optional[int] = None background_color: Optional[Color] = None tile_offset: Optional[OrderedPair] = None @@ -372,6 +372,7 @@ def cast(raw_tileset: RawTileSet) -> TileSet: margin=raw_tileset["margin"], version=raw_tileset["version"], tiled_version=raw_tileset["tiledversion"], + type=raw_tileset["type"], ) if raw_tileset.get("image") is not None: @@ -395,9 +396,6 @@ def cast(raw_tileset: RawTileSet) -> TileSet: if raw_tileset.get("transparentcolor") is not None: tileset.transparent_color = raw_tileset["transparentcolor"] - if raw_tileset.get("type") is not None: - tileset.type = raw_tileset["type"] - if raw_tileset.get("grid") is not None: tileset.grid = _cast_grid(raw_tileset["grid"]) From ab685c891720463439c04770c4adb8ade541f601 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 14 Jun 2020 14:23:26 -0400 Subject: [PATCH 154/198] tests: added terrain with properties test --- tests/test_data/tilesets/terrain/expected.py | 6 +- tests/test_data/tilesets/terrain/tileset.json | 601 ++++++------------ 2 files changed, 211 insertions(+), 396 deletions(-) diff --git a/tests/test_data/tilesets/terrain/expected.py b/tests/test_data/tilesets/terrain/expected.py index c60195c..89051ae 100644 --- a/tests/test_data/tilesets/terrain/expected.py +++ b/tests/test_data/tilesets/terrain/expected.py @@ -17,7 +17,11 @@ EXPECTED = tileset.TileSet( version=1.2, type="tileset", terrain_types=[ - tileset.Terrain(name="Sand", tile=29), + tileset.Terrain( + name="Sand", + tile=29, + properties={"terrain property": "test terrain property"}, + ), tileset.Terrain(name="Cobblestone", tile=29), tileset.Terrain(name="Pavement", tile=29), tileset.Terrain(name="Dirt", tile=29), diff --git a/tests/test_data/tilesets/terrain/tileset.json b/tests/test_data/tilesets/terrain/tileset.json index a2b1667..4bd9d32 100644 --- a/tests/test_data/tilesets/terrain/tileset.json +++ b/tests/test_data/tilesets/terrain/tileset.json @@ -1,395 +1,206 @@ -{ - "columns": 8, - "image": "..\/..\/images\/tmw_desert_spacing.png", - "imageheight": 199, - "imagewidth": 265, - "margin": 1, - "name": "tileset", - "spacing": 1, - "terrains": [ - { - "name": "Sand", - "tile": 29 - }, - { - "name": "Cobblestone", - "tile": 29 - }, - { - "name": "Pavement", - "tile": 29 - }, - { - "name": "Dirt", - "tile": 29 - } - ], - "tilecount": 48, - "tiledversion": "1.3.5", - "tileheight": 32, - "tiles": [ - { - "id": 0, - "terrain": [ - 0, - 0, - 0, - 1 - ] - }, - { - "id": 1, - "terrain": [ - 0, - 0, - 1, - 1 - ] - }, - { - "id": 2, - "terrain": [ - 0, - 0, - 1, - 0 - ] - }, - { - "id": 3, - "terrain": [ - 3, - 3, - 3, - 0 - ] - }, - { - "id": 4, - "terrain": [ - 3, - 3, - 0, - 3 - ] - }, - { - "id": 5, - "terrain": [ - 0, - 0, - 0, - 3 - ] - }, - { - "id": 6, - "terrain": [ - 0, - 0, - 3, - 3 - ] - }, - { - "id": 7, - "terrain": [ - 0, - 0, - 3, - 0 - ] - }, - { - "id": 8, - "terrain": [ - 0, - 1, - 0, - 1 - ] - }, - { - "id": 9, - "terrain": [ - 1, - 1, - 1, - 1 - ] - }, - { - "id": 10, - "terrain": [ - 1, - 0, - 1, - 0 - ] - }, - { - "id": 11, - "terrain": [ - 3, - 0, - 3, - 3 - ] - }, - { - "id": 12, - "terrain": [ - 0, - 3, - 3, - 3 - ] - }, - { - "id": 13, - "terrain": [ - 0, - 3, - 0, - 3 - ] - }, - { - "id": 14, - "terrain": [ - 3, - 3, - 3, - 3 - ] - }, - { - "id": 15, - "terrain": [ - 3, - 0, - 3, - 0 - ] - }, - { - "id": 16, - "terrain": [ - 0, - 1, - 0, - 0 - ] - }, - { - "id": 17, - "terrain": [ - 1, - 1, - 0, - 0 - ] - }, - { - "id": 18, - "terrain": [ - 1, - 0, - 0, - 0 - ] - }, - { - "id": 19, - "terrain": [ - 1, - 1, - 1, - 0 - ] - }, - { - "id": 20, - "terrain": [ - 1, - 1, - 0, - 1 - ] - }, - { - "id": 21, - "terrain": [ - 0, - 3, - 0, - 0 - ] - }, - { - "id": 22, - "terrain": [ - 3, - 3, - 0, - 0 - ] - }, - { - "id": 23, - "terrain": [ - 3, - 0, - 0, - 0 - ] - }, - { - "id": 24, - "terrain": [ - 0, - 0, - 0, - 2 - ] - }, - { - "id": 25, - "terrain": [ - 0, - 0, - 2, - 2 - ] - }, - { - "id": 26, - "terrain": [ - 0, - 0, - 2, - 0 - ] - }, - { - "id": 27, - "terrain": [ - 1, - 0, - 1, - 1 - ] - }, - { - "id": 28, - "terrain": [ - 0, - 1, - 1, - 1 - ] - }, - { - "id": 29, - "terrain": [ - 0, - 0, - 0, - 0 - ] - }, - { - "id": 32, - "terrain": [ - 0, - 2, - 0, - 2 - ] - }, - { - "id": 33, - "terrain": [ - 2, - 2, - 2, - 2 - ] - }, - { - "id": 34, - "terrain": [ - 2, - 0, - 2, - 0 - ] - }, - { - "id": 35, - "terrain": [ - 2, - 2, - 2, - 0 - ] - }, - { - "id": 36, - "terrain": [ - 2, - 2, - 0, - 2 - ] - }, - { - "id": 40, - "terrain": [ - 0, - 2, - 0, - 0 - ] - }, - { - "id": 41, - "terrain": [ - 2, - 2, - 0, - 0 - ] - }, - { - "id": 42, - "terrain": [ - 2, - 0, - 0, - 0 - ] - }, - { - "id": 43, - "terrain": [ - 2, - 0, - 2, - 2 - ] - }, - { - "id": 44, - "terrain": [ - 0, - 2, - 2, - 2 - ] - } - ], - "tilewidth": 32, - "type": "tileset", - "version": 1.2 -} +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tileset", + "spacing":1, + "terrains":[ + { + "name":"Sand", + "properties":[ + { + "name":"terrain property", + "type":"string", + "value":"test terrain property" + }], + "tile":29 + }, + { + "name":"Cobblestone", + "tile":29 + }, + { + "name":"Pavement", + "tile":29 + }, + { + "name":"Dirt", + "tile":29 + }], + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tiles":[ + { + "id":0, + "terrain":[0, 0, 0, 1] + }, + { + "id":1, + "terrain":[0, 0, 1, 1] + }, + { + "id":2, + "terrain":[0, 0, 1, 0] + }, + { + "id":3, + "terrain":[3, 3, 3, 0] + }, + { + "id":4, + "terrain":[3, 3, 0, 3] + }, + { + "id":5, + "terrain":[0, 0, 0, 3] + }, + { + "id":6, + "terrain":[0, 0, 3, 3] + }, + { + "id":7, + "terrain":[0, 0, 3, 0] + }, + { + "id":8, + "terrain":[0, 1, 0, 1] + }, + { + "id":9, + "terrain":[1, 1, 1, 1] + }, + { + "id":10, + "terrain":[1, 0, 1, 0] + }, + { + "id":11, + "terrain":[3, 0, 3, 3] + }, + { + "id":12, + "terrain":[0, 3, 3, 3] + }, + { + "id":13, + "terrain":[0, 3, 0, 3] + }, + { + "id":14, + "terrain":[3, 3, 3, 3] + }, + { + "id":15, + "terrain":[3, 0, 3, 0] + }, + { + "id":16, + "terrain":[0, 1, 0, 0] + }, + { + "id":17, + "terrain":[1, 1, 0, 0] + }, + { + "id":18, + "terrain":[1, 0, 0, 0] + }, + { + "id":19, + "terrain":[1, 1, 1, 0] + }, + { + "id":20, + "terrain":[1, 1, 0, 1] + }, + { + "id":21, + "terrain":[0, 3, 0, 0] + }, + { + "id":22, + "terrain":[3, 3, 0, 0] + }, + { + "id":23, + "terrain":[3, 0, 0, 0] + }, + { + "id":24, + "terrain":[0, 0, 0, 2] + }, + { + "id":25, + "terrain":[0, 0, 2, 2] + }, + { + "id":26, + "terrain":[0, 0, 2, 0] + }, + { + "id":27, + "terrain":[1, 0, 1, 1] + }, + { + "id":28, + "terrain":[0, 1, 1, 1] + }, + { + "id":29, + "terrain":[0, 0, 0, 0] + }, + { + "id":32, + "terrain":[0, 2, 0, 2] + }, + { + "id":33, + "terrain":[2, 2, 2, 2] + }, + { + "id":34, + "terrain":[2, 0, 2, 0] + }, + { + "id":35, + "terrain":[2, 2, 2, 0] + }, + { + "id":36, + "terrain":[2, 2, 0, 2] + }, + { + "id":40, + "terrain":[0, 2, 0, 0] + }, + { + "id":41, + "terrain":[2, 2, 0, 0] + }, + { + "id":42, + "terrain":[2, 0, 0, 0] + }, + { + "id":43, + "terrain":[2, 0, 2, 2] + }, + { + "id":44, + "terrain":[0, 2, 2, 2] + }], + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file From 393be05d68b08d31aff184501d0be4bfb9077017 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 23 Jul 2020 21:15:29 -0400 Subject: [PATCH 155/198] chore(setup.cfg): specify isort version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d610893..6c87d5f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ tests = black pylint mypy - isort + isort<5,>=4.2.5 [coverage:run] branch = True From b7a513641e6ff7ad4f1f1b4b0b1efeb75e77965e Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 23 Jul 2020 21:35:50 -0400 Subject: [PATCH 156/198] feat(wangsets): Initial Implementation of wang sets --- pytiled_parser/wang_set.py | 57 ++ tests/test_data/images/walkways.png | Bin 0 -> 4579 bytes tests/test_data/tilesets/wangsets/map.json | 32 + .../test_data/tilesets/wangsets/tileset.json | 607 ++++++++++++++++++ 4 files changed, 696 insertions(+) create mode 100644 pytiled_parser/wang_set.py create mode 100644 tests/test_data/images/walkways.png create mode 100644 tests/test_data/tilesets/wangsets/map.json create mode 100644 tests/test_data/tilesets/wangsets/tileset.json diff --git a/pytiled_parser/wang_set.py b/pytiled_parser/wang_set.py new file mode 100644 index 0000000..04ef559 --- /dev/null +++ b/pytiled_parser/wang_set.py @@ -0,0 +1,57 @@ +from typing import List, NamedTuple, Optional + +import attr +from typing_extensions import TypedDict + +from . import properties as properties_ +from .common_types import Color, OrderedPair + + +class WangTile(NamedTuple): + + id: int + dflip: bool = False + hflip: bool = False + vflip: bool = False + wang_ids: List[int] = [] + + +class WangColor(NamedTuple): + + color: Color + name: str + probability: float + tile: int + + +class WangSet(NamedTuple): + + cornercolors: List[WangColor] + edgecolors: List[WangColor] + name: str + tile: int + wang_tiles: List[WangTile] + properties: Optional[properties_.Properties] = None + + +class RawWangTile(TypedDict): + """ The keys and their types that appear in a Wang Tile JSON Object.""" + + tileid: int + dflip: bool + hflip: bool + vflip: bool + wangid: List[int] + + +class RawWangColor(TypedDict): + """ The keys and their types that appear in a Wang Color JSON Object.""" + + color: str + name: str + probability: float + tile: int + + +class RawWangSet(TypedDict): + """ The keys and their types that appear in a Wang Set JSON Object.""" diff --git a/tests/test_data/images/walkways.png b/tests/test_data/images/walkways.png new file mode 100644 index 0000000000000000000000000000000000000000..e9cfbe7cbe625343f783cc69f382243705ac00d7 GIT binary patch literal 4579 zcmZ8ld00~0*FGSMng(WF(o)bY?OqF0@3o%;9Mn?Ffo#xnAW^eHvm6=(1c%BYr<;`x zDo$yZm8qE%*wsSIaxOJfe`$&X5h{it@L~7+<9oh8&OUp+>s@Q_=bYzx_gXud=+aLwkmYtD=gm)807kC)u1iv+HHuluZ5w~D9c5R;!w=X! z`ABVknRqn5+?I4fE|(v4BJ6ZN_PA*q_cO_v@8l%+KcJmhqJdv}s76_tGeW>_mKgHE;3`_lD#OW{g)Dc-8B zVui!?$4!;$0nQ8P^Z;@D#QCC8Km0X$ zn()PaO6I%-#%_sQ<63cTUNKJ}QL~28%Yj$?9G8cl1D~2;I&m*IAO|yg4dggXg279` zK0nW~bb~8?z2z$}-OK^T-tFg!oUx^tLkQ7*tp`lT% zTjA+D9PxJL=+75I!_K&!JM-rU9Mn0K#QbSDKB`h(8v|%hECyqHaT&aG&$fvur>{M% z3EL|%YzmgPFeXFxtw)w$gIHJV@Ja#m6&uE5{Vv#l>@>Ox-iP4TGx=yG%kN=oU=GW4 z%vHqi)bgd2Qx%X_S07lZ3UzIF_Q!I*I0l4U%b@9Vm%8 zWpgtAzB~5#U4vZ&KLz$jDAeJzw6?{#ZDxnd>`EvDreLz`MVPa3zSN8* z(QGPWou1vrZiYRF6hO`7hUO*lyY=X40>b>*m7TiC4d}!~_V5KNaWm5<1+fpl*fO5* zH$*B@BzSb-Yr-2eV{l)#hM+>P|#Z83felfBGW$6en`|N0by9QfBMrp zbZZ(rCw9lGnfiatx&@^@vkG^%4W3wy1Li&Aa_jal*0ze6!^?4n!qZ$x6aFF}`&gFs z+rJ!ty$0J46jU^BGlFC-w+IpSjlMm7H(n?q% z;?coH<>5&SRCNt+yEwk@faJb>Ykh)%w0!$K05Vx&%GyR+H674n1`Ka7RX$T~KfYHJ zQ0=Y#Tg@HL=B~6US6^#nXedNx@^DaKp6y<)j|JUBqu^uGs6q7GddKjiatxCfIs_t1 zA}dNnNV}ngBWI4vO_(7R>V16|?ge0nilGn_0C(x(QFp5`6O zf3)YHP-Ta9!F?%APxy4r$tU7Kx0|U=ZauZ{SXxIv$JJ zJGD*qI^r#&RR$!-a3DkS@X*iWA*p&WMsJ-Ol`@_%uT;5o&r$eY6teA-QBb;K z4Wm_gWzfe`TY@3u>haMh;*|^{sl-@JmUNpxe8nL@Xy=;UPcXh#+srzeJ4YA7eg##H zwh3>&_khJ#)tio4<)D-L-`7qOW%_}(chM(LZ^jI;yu&FU=r?~7On28MbBlcH6dI=7 zwG{{(YGh0-tzm9b4$}8mndE2DMA(}A@AP1hD$BD3r^1_DokI)~@#6AG#_XOlIQs~VULK%Ha`zBBP z+_0I{L4$k4mCfiw`D~{nC)vkhFv6A&8}*PLue!#<%bVi>}fVP!Bzl_|B+Y^%V&Aj>c>SsO=+P8>n1IlGpfcp5mg zoX{*LPkOy0O3kVQtYK}|M~}}V43>7ZotZ#DXH$=AmhrcCOIPfdID@`2gG%~%RlDgR zi76%%;Z>~L&KDQf)aA<}m#-Deyr4n-s1{0Jhx%ztc4oeA+&jFHFkgp==tCvgmTi(R;6c;2m=3leIO5g{0i^9}bb9|7P@b4V#N2|CrL&X#lSdWD;6WPpj(aKRaypPG zB58Kjv2s4OJmhcf?FTAl7D_WsV)CVXGnDoyYkC*Z)@RjJ)-C&NOZAl>e!3^=E!uJ= z1dd~GL!RzcJKw&!R7?)a@WXz5f6W(j%A=w3>(rIR3sL58Tek^F!jh~CfD8$4LkICE zv^gaG%vc!{w-lOZytr8XJZ~$VXvws5;!cl}B9g^1iX96WyX`&bGHJ=JvZo>K=xo5* zG0D5IewC??x!Tp6e_olpu0Og$Ox{Z+qEwS~G9Cjyg)g2QA$24nX5xYK<5K00KNz>m zDrObm>T7~G7)sTuk7s)2!SV=MHV^(j&l%iErcG#?p7=X(9< z>xDU5hmqK8mH$KLx9G4Go-%qR5q@ND< z$f`no&;NVvn^5@^+7>K$OHAI>URmnroALrNm;ZOCrrRoB<*2~#{UsW^UCHO=XCv~$ zB%y+$J~7!IoYc^fe3!Y{M7?@}Eniy`LEH6#RYmvA;60lo1+E%R^q%tA!~ymjG5J1? zA}>a?J*TG$U+$3n%qAZd0*ppBHSRpRW#s^~=eSWqx+c;$cXgu)!Vz z5wb6VBR1d6Xnvr(^vQ8BR*HR@VPFD_fr$O+%b+6bAqX`{01`;7>^V zlIMU;uzx9!A|Rys;59H4)9%!aHEmms(Ad%a0sQRCxi9!|>`P$_V4wFLhQ7quY(Fo6 zP_|FxJ_n6?O5J+yQZq(oX%!<>flpH&_BCx@FC%|KD5+kyUaM+kgzn^(M2)x{r2J`y zYb!^qSb7)(dQ1^UaOo_zB(j{q>u(k@$EJ``jX!)-7Baq z{`+{LICGo{q$|>p8Pe^)Plsqv?J9v7P#$V%9m*0AOqmTCh_CwJ_EV9ypSJ)1+L8Ki zLHYAH^!hwJm-RKla321}i%N8qF(oO86z7acl7LVPa0>+lt>uL8rnt6_)tWO$l>6jY z1)3vbBBeXW6YLiot|QcY_`7f>uIv^OlPLZEHK9=0kc>#_=NscpJUg|~#rX|e?Eal* zs}Vh^#Ns?-95-ej{>?o@TL+!3+139Ik#Zd|W3j$7B^7a6f^$J6#Rkk#mX98;8mn81 zGre@2ntp1_Uc{X(A)}q0HT{IO#)=&Pw_m@;xr zSs!W~xG5&jLh6^rg#cI(vd9TXq` zXT>o=dP;OHQzcF9 zN8OVi{MAqzx_Uts4dp{I*;tNaE~_7t>ryoQ#&+ww($@fvuhn)eVGoi*1^lx|JW$;S zGYZyt(VpH@(S%d(21kOq#D zLt9tf4AGZn-ioWI_f%l7BJZwvO_E*>ygIJB6XYlR*^BdbRrq3>{;A)1HAtw7u z%|75f<+Du61y%7i$otN0F4Q*n5%x{Lao}8_kbMY|A0Xe*tvH>DEmjfFSR1|auUF>V z(2?JNb&$!*FRi^u9Um`)>C)llgmeE=8PNIhguD`lnWSz3ULZRUvi(njFWj%OZJmJU zyr~c9MDfpzyx9_7^9Dw}E~bP2eT9%ip9ziqIhsy=Y#wcmI|&5MY#I!__YHl0w7r=l zBngitmWi1E#k={bwi!%t_*^`ESvJj0|MCPi>r2gCZZ)MXa->t2|5jPK{R8ztN@75O Zt8M4t#SPFx#ia@0vd7)=iT&~T{{ch1)_wp0 literal 0 HcmV?d00001 diff --git a/tests/test_data/tilesets/wangsets/map.json b/tests/test_data/tilesets/wangsets/map.json new file mode 100644 index 0000000..d2fe741 --- /dev/null +++ b/tests/test_data/tilesets/wangsets/map.json @@ -0,0 +1,32 @@ +{ "compressionlevel":-1, + "height":20, + "infinite":false, + "layers":[ + { + "data":[35, 1, 57, 49, 48, 67, 75, 7, 61, 52, 70, 44, 81, 55, 59, 63, 10, 68, 63, 81, 22, 23, 72, 60, 61, 52, 79, 26, 72, 60, 53, 54, 54, 72, 60, 34, 22, 77, 60, 52, 59, 64, 75, 70, 61, 71, 78, 71, 46, 29, 30, 35, 33, 53, 63, 42, 35, 9, 69, 58, 55, 74, 5, 9, 28, 2, 77, 54, 55, 39, 25, 25, 26, 63, 63, 78, 25, 26, 54, 72, 65, 50, 45, 27, 24, 26, 1, 66, 61, 7, 70, 62, 72, 33, 34, 52, 70, 70, 70, 8, 48, 34, 7, 62, 60, 67, 23, 54, 64, 23, 46, 32, 73, 21, 25, 70, 80, 78, 7, 43, 71, 42, 13, 56, 66, 7, 31, 59, 6, 62, 63, 18, 46, 30, 31, 48, 80, 54, 42, 53, 79, 7, 16, 62, 54, 19, 11, 59, 42, 35, 36, 42, 61, 16, 43, 71, 51, 34, 4, 59, 76, 41, 37, 30, 61, 70, 13, 57, 80, 18, 15, 53, 36, 42, 52, 7, 70, 25, 13, 29, 79, 53, 6, 44, 64, 77, 42, 70, 80, 24, 22, 68, 24, 52, 70, 26, 54, 55, 39, 26, 54, 60, 17, 1, 5, 6, 80, 51, 76, 56, 65, 75, 34, 58, 5, 28, 56, 59, 51, 70, 61, 67, 14, 18, 24, 16, 49, 59, 81, 36, 9, 51, 26, 69, 40, 20, 32, 64, 66, 52, 33, 76, 21, 22, 68, 19, 59, 55, 50, 10, 21, 70, 70, 8, 51, 71, 18, 54, 78, 70, 42, 8, 60, 70, 4, 30, 31, 30, 31, 38, 32, 54, 46, 38, 57, 80, 24, 70, 53, 1, 53, 24, 58, 48, 43, 17, 18, 24, 43, 52, 22, 59, 33, 80, 63, 54, 33, 49, 59, 15, 35, 72, 33, 67, 75, 17, 42, 35, 1, 29, 68, 72, 42, 52, 61, 61, 26, 63, 36, 45, 45, 54, 42, 53, 73, 23, 73, 21, 44, 42, 76, 48, 76, 57, 62, 60, 70, 58, 23, 78, 48, 67, 75, 61, 79, 61, 52, 61, 79, 53, 54, 55, 75, 70, 34, 70, 7, 58, 66, 52, 33, 53, 51, 61, 8, 72, 60, 31, 74, 57, 70, 67, 3, 79, 22, 47, 12, 62, 51, 31, 43, 58, 68, 63, 15, 76, 65, 23, 54, 63, 6, 8, 19, 74, 57, 62, 24, 35, 60, 43], + "height":20, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":20, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.3.5", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.2, + "width":20 +} \ No newline at end of file diff --git a/tests/test_data/tilesets/wangsets/tileset.json b/tests/test_data/tilesets/wangsets/tileset.json new file mode 100644 index 0000000..76ab027 --- /dev/null +++ b/tests/test_data/tilesets/wangsets/tileset.json @@ -0,0 +1,607 @@ +{ "columns":9, + "image":"..\/..\/images\/walkways.png", + "imageheight":288, + "imagewidth":288, + "margin":0, + "name":"tileset", + "spacing":0, + "tilecount":81, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2, + "wangsets":[ + { + "cornercolors":[], + "edgecolors":[ + { + "color":"#ff0000", + "name":"Path", + "probability":1, + "tile":-1 + }, + { + "color":"#00ff00", + "name":"Grass", + "probability":0.75, + "tile":-1 + }, + { + "color":"#0000ff", + "name":"WalkWay", + "probability":0.5, + "tile":-1 + }], + "name":"My Wang Set", + "tile":-1, + "wangtiles":[ + { + "dflip":false, + "hflip":false, + "tileid":0, + "vflip":false, + "wangid":[2, 0, 3, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":1, + "vflip":false, + "wangid":[2, 0, 3, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":2, + "vflip":false, + "wangid":[2, 0, 1, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":3, + "vflip":false, + "wangid":[2, 0, 3, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":4, + "vflip":false, + "wangid":[2, 0, 2, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":5, + "vflip":false, + "wangid":[2, 0, 1, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":6, + "vflip":false, + "wangid":[2, 0, 1, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":7, + "vflip":false, + "wangid":[2, 0, 2, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":8, + "vflip":false, + "wangid":[2, 0, 2, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":9, + "vflip":false, + "wangid":[3, 0, 3, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":10, + "vflip":false, + "wangid":[3, 0, 3, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":11, + "vflip":false, + "wangid":[3, 0, 1, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":12, + "vflip":false, + "wangid":[3, 0, 3, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":13, + "vflip":false, + "wangid":[3, 0, 2, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":14, + "vflip":false, + "wangid":[3, 0, 1, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":15, + "vflip":false, + "wangid":[3, 0, 1, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":16, + "vflip":false, + "wangid":[3, 0, 2, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":17, + "vflip":false, + "wangid":[3, 0, 2, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":18, + "vflip":false, + "wangid":[3, 0, 3, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":19, + "vflip":false, + "wangid":[3, 0, 3, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":20, + "vflip":false, + "wangid":[3, 0, 1, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":21, + "vflip":false, + "wangid":[3, 0, 3, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":22, + "vflip":false, + "wangid":[3, 0, 2, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":23, + "vflip":false, + "wangid":[3, 0, 1, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":24, + "vflip":false, + "wangid":[3, 0, 1, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":25, + "vflip":false, + "wangid":[3, 0, 2, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":26, + "vflip":false, + "wangid":[3, 0, 2, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":27, + "vflip":false, + "wangid":[1, 0, 3, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":28, + "vflip":false, + "wangid":[1, 0, 3, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":29, + "vflip":false, + "wangid":[1, 0, 1, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":30, + "vflip":false, + "wangid":[1, 0, 3, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":31, + "vflip":false, + "wangid":[1, 0, 2, 0, 3, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":32, + "vflip":false, + "wangid":[1, 0, 1, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":33, + "vflip":false, + "wangid":[1, 0, 1, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":34, + "vflip":false, + "wangid":[1, 0, 2, 0, 3, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":35, + "vflip":false, + "wangid":[1, 0, 2, 0, 3, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":36, + "vflip":false, + "wangid":[3, 0, 3, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":37, + "vflip":false, + "wangid":[3, 0, 3, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":38, + "vflip":false, + "wangid":[3, 0, 1, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":39, + "vflip":false, + "wangid":[3, 0, 3, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":40, + "vflip":false, + "wangid":[3, 0, 2, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":41, + "vflip":false, + "wangid":[3, 0, 1, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":42, + "vflip":false, + "wangid":[3, 0, 1, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":43, + "vflip":false, + "wangid":[3, 0, 2, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":44, + "vflip":false, + "wangid":[3, 0, 2, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":45, + "vflip":false, + "wangid":[2, 0, 3, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":46, + "vflip":false, + "wangid":[2, 0, 3, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":47, + "vflip":false, + "wangid":[2, 0, 1, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":48, + "vflip":false, + "wangid":[2, 0, 3, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":49, + "vflip":false, + "wangid":[2, 0, 2, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":50, + "vflip":false, + "wangid":[2, 0, 1, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":51, + "vflip":false, + "wangid":[2, 0, 1, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":52, + "vflip":false, + "wangid":[2, 0, 2, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":53, + "vflip":false, + "wangid":[2, 0, 2, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":54, + "vflip":false, + "wangid":[1, 0, 3, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":55, + "vflip":false, + "wangid":[1, 0, 3, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":56, + "vflip":false, + "wangid":[1, 0, 1, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":57, + "vflip":false, + "wangid":[1, 0, 3, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":58, + "vflip":false, + "wangid":[1, 0, 2, 0, 1, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":59, + "vflip":false, + "wangid":[1, 0, 1, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":60, + "vflip":false, + "wangid":[1, 0, 1, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":61, + "vflip":false, + "wangid":[1, 0, 2, 0, 1, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":62, + "vflip":false, + "wangid":[1, 0, 2, 0, 1, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":63, + "vflip":false, + "wangid":[1, 0, 3, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":64, + "vflip":false, + "wangid":[1, 0, 3, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":65, + "vflip":false, + "wangid":[1, 0, 1, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":66, + "vflip":false, + "wangid":[1, 0, 3, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":67, + "vflip":false, + "wangid":[1, 0, 2, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":68, + "vflip":false, + "wangid":[1, 0, 1, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":69, + "vflip":false, + "wangid":[1, 0, 1, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":70, + "vflip":false, + "wangid":[1, 0, 2, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":71, + "vflip":false, + "wangid":[1, 0, 2, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":72, + "vflip":false, + "wangid":[2, 0, 3, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":73, + "vflip":false, + "wangid":[2, 0, 3, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":74, + "vflip":false, + "wangid":[2, 0, 1, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":75, + "vflip":false, + "wangid":[2, 0, 3, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":76, + "vflip":false, + "wangid":[2, 0, 2, 0, 2, 0, 3, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":77, + "vflip":false, + "wangid":[2, 0, 1, 0, 2, 0, 2, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":78, + "vflip":false, + "wangid":[2, 0, 1, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":79, + "vflip":false, + "wangid":[2, 0, 2, 0, 2, 0, 1, 0] + }, + { + "dflip":false, + "hflip":false, + "tileid":80, + "vflip":false, + "wangid":[2, 0, 2, 0, 2, 0, 2, 0] + }] + }] +} \ No newline at end of file From b708de98b32198fcb58f3b887731302682502b84 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 25 Jul 2020 00:00:57 -0400 Subject: [PATCH 157/198] test(layer_tests): add b64 and csv examples with compression --- .../layer_tests/all_layer_types/expected.py | 3 + tests/test_data/layer_tests/b64/expected.py | 3 + tests/test_data/layer_tests/b64/map.json | 72 +++++++++++++++++++ tests/test_data/layer_tests/b64/tileset.json | 22 ++++++ .../layer_tests/b64_gzip/expected.py | 3 + tests/test_data/layer_tests/b64_gzip/map.json | 72 +++++++++++++++++++ .../layer_tests/b64_gzip/tileset.json | 22 ++++++ .../layer_tests/b64_lzib/expected.py | 3 + tests/test_data/layer_tests/b64_lzib/map.json | 72 +++++++++++++++++++ .../layer_tests/b64_lzib/tileset.json | 22 ++++++ tests/test_data/layer_tests/csv/expected.py | 3 + tests/test_data/layer_tests/csv/map.json | 70 ++++++++++++++++++ tests/test_data/layer_tests/csv/tileset.json | 22 ++++++ 13 files changed, 389 insertions(+) create mode 100644 tests/test_data/layer_tests/all_layer_types/expected.py create mode 100644 tests/test_data/layer_tests/b64/expected.py create mode 100644 tests/test_data/layer_tests/b64/map.json create mode 100644 tests/test_data/layer_tests/b64/tileset.json create mode 100644 tests/test_data/layer_tests/b64_gzip/expected.py create mode 100644 tests/test_data/layer_tests/b64_gzip/map.json create mode 100644 tests/test_data/layer_tests/b64_gzip/tileset.json create mode 100644 tests/test_data/layer_tests/b64_lzib/expected.py create mode 100644 tests/test_data/layer_tests/b64_lzib/map.json create mode 100644 tests/test_data/layer_tests/b64_lzib/tileset.json create mode 100644 tests/test_data/layer_tests/csv/expected.py create mode 100644 tests/test_data/layer_tests/csv/map.json create mode 100644 tests/test_data/layer_tests/csv/tileset.json diff --git a/tests/test_data/layer_tests/all_layer_types/expected.py b/tests/test_data/layer_tests/all_layer_types/expected.py new file mode 100644 index 0000000..6643112 --- /dev/null +++ b/tests/test_data/layer_tests/all_layer_types/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/b64/expected.py b/tests/test_data/layer_tests/b64/expected.py new file mode 100644 index 0000000..6643112 --- /dev/null +++ b/tests/test_data/layer_tests/b64/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/b64/map.json b/tests/test_data/layer_tests/b64/map.json new file mode 100644 index 0000000..baa3bc6 --- /dev/null +++ b/tests/test_data/layer_tests/b64/map.json @@ -0,0 +1,72 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[ + { + "compression":"", + "data":"AQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAJAAAACgAAAAsAAAAMAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABcAAAAYAAAAGQAAABoAAAAbAAAAHAAAAB0AAAAeAAAAHwAAACAAAAAhAAAAIgAAACMAAAAkAAAAJQAAACYAAAAnAAAAKAAAACkAAAAqAAAAKwAAACwAAAAtAAAALgAAAC8AAAAwAAAA", + "encoding":"base64", + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":3, + "image":"", + "name":"Image Layer 1", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "layers":[], + "name":"Group 1", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":5, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/b64/tileset.json b/tests/test_data/layer_tests/b64/tileset.json new file mode 100644 index 0000000..8df9f18 --- /dev/null +++ b/tests/test_data/layer_tests/b64/tileset.json @@ -0,0 +1,22 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/b64_gzip/expected.py b/tests/test_data/layer_tests/b64_gzip/expected.py new file mode 100644 index 0000000..6643112 --- /dev/null +++ b/tests/test_data/layer_tests/b64_gzip/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/b64_gzip/map.json b/tests/test_data/layer_tests/b64_gzip/map.json new file mode 100644 index 0000000..5c35f68 --- /dev/null +++ b/tests/test_data/layer_tests/b64_gzip/map.json @@ -0,0 +1,72 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[ + { + "compression":"gzip", + "data":"H4sIAAAAAAAAAw3DBRKCQAAAwDMRA7BQLMTE9v+vY3dmWyGEth279uwbOTB26MixExNTM6fOnLtwae7KtYUbt+7ce7D0aOXJsxev3rxb+\/Dpy7cfv\/782wAcvDirwAAAAA==", + "encoding":"base64", + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":3, + "image":"", + "name":"Image Layer 1", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "layers":[], + "name":"Group 1", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":5, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/b64_gzip/tileset.json b/tests/test_data/layer_tests/b64_gzip/tileset.json new file mode 100644 index 0000000..8df9f18 --- /dev/null +++ b/tests/test_data/layer_tests/b64_gzip/tileset.json @@ -0,0 +1,22 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/b64_lzib/expected.py b/tests/test_data/layer_tests/b64_lzib/expected.py new file mode 100644 index 0000000..6643112 --- /dev/null +++ b/tests/test_data/layer_tests/b64_lzib/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/b64_lzib/map.json b/tests/test_data/layer_tests/b64_lzib/map.json new file mode 100644 index 0000000..bc8786e --- /dev/null +++ b/tests/test_data/layer_tests/b64_lzib/map.json @@ -0,0 +1,72 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[ + { + "compression":"zlib", + "data":"eJwNwwUSgkAAAMAzEQOwUCzExPb\/r2N3ZlshhLYdu\/bsGzkwdujIsRMTUzOnzpy7cGnuyrWFG7fu3Huw9GjlybMXr968W\/vw6cu3H7\/+\/NsAMw8EmQ==", + "encoding":"base64", + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":3, + "image":"", + "name":"Image Layer 1", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "layers":[], + "name":"Group 1", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":5, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/b64_lzib/tileset.json b/tests/test_data/layer_tests/b64_lzib/tileset.json new file mode 100644 index 0000000..8df9f18 --- /dev/null +++ b/tests/test_data/layer_tests/b64_lzib/tileset.json @@ -0,0 +1,22 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/csv/expected.py b/tests/test_data/layer_tests/csv/expected.py new file mode 100644 index 0000000..6643112 --- /dev/null +++ b/tests/test_data/layer_tests/csv/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/csv/map.json b/tests/test_data/layer_tests/csv/map.json new file mode 100644 index 0000000..b0adc34 --- /dev/null +++ b/tests/test_data/layer_tests/csv/map.json @@ -0,0 +1,70 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[ + { + "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], + "height":6, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }, + { + "id":3, + "image":"", + "name":"Image Layer 1", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 + }, + { + "id":4, + "layers":[], + "name":"Group 1", + "opacity":1, + "type":"group", + "visible":true, + "x":0, + "y":0 + }], + "nextlayerid":5, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/csv/tileset.json b/tests/test_data/layer_tests/csv/tileset.json new file mode 100644 index 0000000..8df9f18 --- /dev/null +++ b/tests/test_data/layer_tests/csv/tileset.json @@ -0,0 +1,22 @@ +{ "columns":8, + "editorsettings": + { + "export": + { + "format":"", + "target":"." + } + }, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.5", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} \ No newline at end of file From 50c3ffae0ddb1b180dad6b0fa1ac6ebcb2878082 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sat, 25 Jul 2020 00:17:04 -0400 Subject: [PATCH 158/198] feat(layer): base64 decoding --- pytiled_parser/layer.py | 52 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index b10e442..a9f8ee1 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -1,5 +1,8 @@ # pylint: disable=too-few-public-methods +import base64 +import gzip +import zlib from pathlib import Path from typing import Any, Callable, List, Optional, Union @@ -184,6 +187,50 @@ class RawLayer(TypedDict): y: int +def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: + """Decode Base64 Encoded Tile Data. Supports gzip and zlib compression. + + Args: + tile_layer: The TileLayer to decode the data for + + Returns: + TileLayer: The TileLayer with the decoded data + + Raises: + ValueError: For an unsupported compression type. + """ + if not isinstance(tile_layer.data, str): + return tile_layer + + unencoded_data = base64.b64decode(tile_layer.data) + if tile_layer.compression == "zlib": + unzipped_data = zlib.decompress(unencoded_data) + elif tile_layer.compression == "gzip": + unzipped_data = gzip.decompress(unencoded_data) + elif tile_layer.compression is None: + unzipped_data = unencoded_data + else: + raise ValueError(f"Unsupported compression type: '{tile_layer.compression}'.") + + tile_grid = [] + + byte_count = 0 + int_count = 0 + int_value = 0 + for byte in unzipped_data: + int_value += byte << (byte_count * 8) + byte_count += 1 + if not byte_count % 4: + byte_count = 0 + int_count += 1 + tile_grid.append(int_value) + int_value = 0 + + tile_grid.pop() + tile_layer.data = tile_grid + return tile_layer + + def _cast_chunk(raw_chunk: RawChunk) -> Chunk: """ Cast the raw_chunk to a Chunk. @@ -267,6 +314,9 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: if raw_layer.get("data") is not None: tile_layer.data = raw_layer["data"] + if tile_layer.encoding == "base64": + _decode_tile_layer_data(tile_layer) + return tile_layer @@ -286,7 +336,7 @@ def _cast_object_layer(raw_layer: RawLayer) -> ObjectLayer: return ObjectLayer( tiled_objects=tiled_objects, draw_order=raw_layer["draworder"], - **_get_common_attributes(raw_layer).__dict__ + **_get_common_attributes(raw_layer).__dict__, ) From 013ff7b07dc338bb614ef652c621377328347deb Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 25 Jul 2020 15:19:10 -0400 Subject: [PATCH 159/198] docs(layer): fix url --- pytiled_parser/layer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index a9f8ee1..ff3f85a 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -80,7 +80,7 @@ LayerData = Union[TileLayerGrid, List[Chunk]] class TileLayer(Layer): """Tile map layer containing tiles. - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#layer + See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer Args: size: The width of the layer in tiles. The same as the map width unless map is From 91ff654bf0aeb1d87203383ff99d1bcd905e18f0 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Sat, 25 Jul 2020 15:19:40 -0400 Subject: [PATCH 160/198] fixme --- pytiled_parser/layer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index ff3f85a..bbcb294 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -78,6 +78,7 @@ LayerData = Union[TileLayerGrid, List[Chunk]] @attr.s(auto_attribs=True, kw_only=True) class TileLayer(Layer): + # FIXME:this docstring appears to be innacurate """Tile map layer containing tiles. See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer From 64e4c2adb10d98d8a8d88f9063dd57d6033e99c6 Mon Sep 17 00:00:00 2001 From: Jordan Geiser Date: Sat, 25 Jul 2020 16:04:21 -0400 Subject: [PATCH 161/198] add comment to _get_common_attributes --- pytiled_parser/layer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index bbcb294..05c4132 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -268,6 +268,7 @@ def _get_common_attributes(raw_layer: RawLayer) -> Layer: visible=raw_layer["visible"], ) + # if startx is present, starty is present if raw_layer.get("startx") is not None: common_attributes.coordinates = OrderedPair( raw_layer["startx"], raw_layer["starty"] From 153dcad8637bb3934278cd487799b55309ab9fe6 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 19:32:53 -0400 Subject: [PATCH 162/198] fix(layer): encoding key is not required --- pytiled_parser/layer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 05c4132..79a9f20 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -303,7 +303,8 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: """ tile_layer = TileLayer(**_get_common_attributes(raw_layer).__dict__) - tile_layer.encoding = raw_layer["encoding"] + if raw_layer.get("encoding") is not None: + tile_layer.encoding = raw_layer["encoding"] if raw_layer.get("compression") is not None: tile_layer.compression = raw_layer["compression"] From 456fbb1e9c728423ccaf7499472baa8eafc89949 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 19:33:04 -0400 Subject: [PATCH 163/198] tests(layer): stub --- tests/test_layer.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/test_layer.py diff --git a/tests/test_layer.py b/tests/test_layer.py new file mode 100644 index 0000000..6e03281 --- /dev/null +++ b/tests/test_layer.py @@ -0,0 +1,37 @@ +"""Tests for tilesets""" +import importlib.util +import json +import os +from pathlib import Path + +import pytest + +from pytiled_parser import layer + +TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) +TEST_DATA = TESTS_DIR / "test_data" +LAYER_TESTS = TEST_DATA / "layer_tests" + + +ALL_LAYER_TESTS = [ + LAYER_TESTS / "all_layer_types", +] + + +@pytest.mark.parametrize("layer_test", ALL_LAYER_TESTS) +def test_layer_integration(layer_test): + # it's a PITA to import like this, don't do it + # https://stackoverflow.com/a/67692/1342874 + spec = importlib.util.spec_from_file_location( + "expected", layer_test / "expected.py" + ) + expected = importlib.util.module_from_spec(spec) + spec.loader.exec_module(expected) + + raw_layers_path = layer_test / "map.json" + + with open(raw_layers_path) as raw_layers_file: + raw_layers = json.load(raw_layers_file)["layers"] + layers = [layer.cast(raw_layer) for raw_layer in raw_layers] + + assert layers == expected.EXPECTED From 82b352d85eaef109ab4efa435eaa0c3b704c31bd Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 19:57:27 -0400 Subject: [PATCH 164/198] mv(test_data): maps -> example_maps --- .../test_data/{maps => example_maps}/all_objects/all_objects.json | 0 .../{maps => example_maps}/all_objects/tileset_image.json | 0 .../{maps => example_maps}/all_objects/tileset_image_objects.json | 0 .../simple_external_tileset/map_simple_external_tileset.json | 0 .../simple_external_tileset/tileset_image.json | 0 .../{maps => example_maps}/simple_infinite/map_infinite.json | 0 .../{maps => example_maps}/simple_infinite/tileset_image.json | 0 .../{maps => example_maps}/simple_offset/map_simple_offset.json | 0 .../{maps => example_maps}/simple_offset/tileset_image.json | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename tests/test_data/{maps => example_maps}/all_objects/all_objects.json (100%) rename tests/test_data/{maps => example_maps}/all_objects/tileset_image.json (100%) rename tests/test_data/{maps => example_maps}/all_objects/tileset_image_objects.json (100%) rename tests/test_data/{maps => example_maps}/simple_external_tileset/map_simple_external_tileset.json (100%) rename tests/test_data/{maps => example_maps}/simple_external_tileset/tileset_image.json (100%) rename tests/test_data/{maps => example_maps}/simple_infinite/map_infinite.json (100%) rename tests/test_data/{maps => example_maps}/simple_infinite/tileset_image.json (100%) rename tests/test_data/{maps => example_maps}/simple_offset/map_simple_offset.json (100%) rename tests/test_data/{maps => example_maps}/simple_offset/tileset_image.json (100%) diff --git a/tests/test_data/maps/all_objects/all_objects.json b/tests/test_data/example_maps/all_objects/all_objects.json similarity index 100% rename from tests/test_data/maps/all_objects/all_objects.json rename to tests/test_data/example_maps/all_objects/all_objects.json diff --git a/tests/test_data/maps/all_objects/tileset_image.json b/tests/test_data/example_maps/all_objects/tileset_image.json similarity index 100% rename from tests/test_data/maps/all_objects/tileset_image.json rename to tests/test_data/example_maps/all_objects/tileset_image.json diff --git a/tests/test_data/maps/all_objects/tileset_image_objects.json b/tests/test_data/example_maps/all_objects/tileset_image_objects.json similarity index 100% rename from tests/test_data/maps/all_objects/tileset_image_objects.json rename to tests/test_data/example_maps/all_objects/tileset_image_objects.json diff --git a/tests/test_data/maps/simple_external_tileset/map_simple_external_tileset.json b/tests/test_data/example_maps/simple_external_tileset/map_simple_external_tileset.json similarity index 100% rename from tests/test_data/maps/simple_external_tileset/map_simple_external_tileset.json rename to tests/test_data/example_maps/simple_external_tileset/map_simple_external_tileset.json diff --git a/tests/test_data/maps/simple_external_tileset/tileset_image.json b/tests/test_data/example_maps/simple_external_tileset/tileset_image.json similarity index 100% rename from tests/test_data/maps/simple_external_tileset/tileset_image.json rename to tests/test_data/example_maps/simple_external_tileset/tileset_image.json diff --git a/tests/test_data/maps/simple_infinite/map_infinite.json b/tests/test_data/example_maps/simple_infinite/map_infinite.json similarity index 100% rename from tests/test_data/maps/simple_infinite/map_infinite.json rename to tests/test_data/example_maps/simple_infinite/map_infinite.json diff --git a/tests/test_data/maps/simple_infinite/tileset_image.json b/tests/test_data/example_maps/simple_infinite/tileset_image.json similarity index 100% rename from tests/test_data/maps/simple_infinite/tileset_image.json rename to tests/test_data/example_maps/simple_infinite/tileset_image.json diff --git a/tests/test_data/maps/simple_offset/map_simple_offset.json b/tests/test_data/example_maps/simple_offset/map_simple_offset.json similarity index 100% rename from tests/test_data/maps/simple_offset/map_simple_offset.json rename to tests/test_data/example_maps/simple_offset/map_simple_offset.json diff --git a/tests/test_data/maps/simple_offset/tileset_image.json b/tests/test_data/example_maps/simple_offset/tileset_image.json similarity index 100% rename from tests/test_data/maps/simple_offset/tileset_image.json rename to tests/test_data/example_maps/simple_offset/tileset_image.json From 45aae7e8edb330fca6e28e2b1f31000b9a056011 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 20:08:51 -0400 Subject: [PATCH 165/198] rf(map): alphabetize branches --- pytiled_parser/map.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index a232081..2187b10 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -153,12 +153,12 @@ def cast(raw_tiled_map: _RawTiledMap) -> Map: if raw_tiled_map.get("backgroundcolor") is not None: map_.background_color = raw_tiled_map["backgroundcolor"] - if raw_tiled_map.get("properties") is not None: - map_.properties = properties.cast(raw_tiled_map["properties"]) - if raw_tiled_map.get("hexsidelength") is not None: map_.hex_side_length = raw_tiled_map["hexsidelength"] + if raw_tiled_map.get("properties") is not None: + map_.properties = properties.cast(raw_tiled_map["properties"]) + if raw_tiled_map.get("staggeraxis") is not None: map_.stagger_axis = raw_tiled_map["staggeraxis"] From 72cfff01d1322252813296e025cb2ec7d0ccb995 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 20:09:28 -0400 Subject: [PATCH 166/198] tests(test_data): add no_layers map --- .../test_data/map_tests/no_layers/expected.py | 0 .../map_tests/no_layers/map_no_layers.json | 63 +++++++++++++++++++ .../map_tests/no_layers/tileset_image.json | 14 +++++ 3 files changed, 77 insertions(+) create mode 100644 tests/test_data/map_tests/no_layers/expected.py create mode 100644 tests/test_data/map_tests/no_layers/map_no_layers.json create mode 100644 tests/test_data/map_tests/no_layers/tileset_image.json diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_data/map_tests/no_layers/map_no_layers.json b/tests/test_data/map_tests/no_layers/map_no_layers.json new file mode 100644 index 0000000..ac423c0 --- /dev/null +++ b/tests/test_data/map_tests/no_layers/map_no_layers.json @@ -0,0 +1,63 @@ +{ "compressionlevel":0, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/var\/log\/syslog" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/map_tests/no_layers/tileset_image.json b/tests/test_data/map_tests/no_layers/tileset_image.json new file mode 100644 index 0000000..e88a3f1 --- /dev/null +++ b/tests/test_data/map_tests/no_layers/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} From a1d4cbda3698182c70b8ecf9fe1bae4d8e34a2c9 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 27 Jul 2020 20:14:31 -0400 Subject: [PATCH 167/198] refactor(layer): make coordinates default to 0,0 because they are always set to that from Tiled --- pytiled_parser/layer.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 79a9f20..ca87c3f 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -41,7 +41,8 @@ class Layer: opacity: float visible: bool - coordinates: Optional[OrderedPair] = None + coordinates: OrderedPair = OrderedPair(0, 0) + id: Optional[int] = None size: Optional[Size] = None offset: Optional[OrderedPair] = None From 2a9f5daaeed121db2207bd775d221ff6b3fbb97b Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 27 Jul 2020 20:31:18 -0400 Subject: [PATCH 168/198] tests(layer): First layer test with no compression or encoding completed --- .../layer_tests/all_layer_types/expected.py | 98 ++++++++++++++++++- .../layer_tests/all_layer_types/map.json | 69 ++++++++----- 2 files changed, 140 insertions(+), 27 deletions(-) diff --git a/tests/test_data/layer_tests/all_layer_types/expected.py b/tests/test_data/layer_tests/all_layer_types/expected.py index 6643112..9e27994 100644 --- a/tests/test_data/layer_tests/all_layer_types/expected.py +++ b/tests/test_data/layer_tests/all_layer_types/expected.py @@ -1,3 +1,97 @@ -from pytiled_parser import common_types, layer +from pathlib import Path -EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + 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, + ], + ), + layer.LayerGroup( + name="Group 1", + opacity=1, + visible=True, + id=4, + layers=[ + layer.ObjectLayer( + name="Object Layer 1", + opacity=1, + visible=True, + id=2, + draw_order="topdown", + tiled_objects=[ + tiled_object.Rectangle( + id=1, + name="", + rotation=0, + size=common_types.Size(69.3333333333333, 52.6666666666667), + coordinates=common_types.OrderedPair(46.3333333333333, 39), + visible=True, + type="", + ) + ], + ), + ], + ), + layer.ImageLayer( + name="Image Layer 1", + opacity=1, + visible=True, + id=3, + image=Path("../../images/tile_04.png"), + transparent_color=common_types.Color("#000000"), + ), +] diff --git a/tests/test_data/layer_tests/all_layer_types/map.json b/tests/test_data/layer_tests/all_layer_types/map.json index 6aa83c4..9ea084c 100644 --- a/tests/test_data/layer_tests/all_layer_types/map.json +++ b/tests/test_data/layer_tests/all_layer_types/map.json @@ -1,4 +1,11 @@ { "compressionlevel":-1, + "editorsettings": + { + "export": + { + "target":"." + } + }, "height":6, "infinite":false, "layers":[ @@ -14,42 +21,54 @@ "x":0, "y":0 }, - { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }, - { - "id":3, - "image":"", - "name":"Image Layer 1", - "opacity":1, - "type":"imagelayer", - "visible":true, - "x":0, - "y":0 - }, { "id":4, - "layers":[], + "layers":[ + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":52.6666666666667, + "id":1, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":69.3333333333333, + "x":46.3333333333333, + "y":39 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], "name":"Group 1", "opacity":1, "type":"group", "visible":true, "x":0, "y":0 + }, + { + "id":3, + "image":"..\/..\/images\/tile_04.png", + "name":"Image Layer 1", + "opacity":1, + "transparentcolor":"#000000", + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 }], "nextlayerid":5, - "nextobjectid":1, + "nextobjectid":3, "orientation":"orthogonal", "renderorder":"right-down", - "tiledversion":"1.3.1", + "tiledversion":"1.4.1", "tileheight":32, "tilesets":[ { @@ -58,6 +77,6 @@ }], "tilewidth":32, "type":"map", - "version":1.2, + "version":1.4, "width":8 } \ No newline at end of file From 2b54089f40603f362fc718d9dff1b58721944524 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 20:36:17 -0400 Subject: [PATCH 169/198] mv(test_data): map_no_layers.json -> map.json --- .../map_tests/no_layers/{map_no_layers.json => map.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/test_data/map_tests/no_layers/{map_no_layers.json => map.json} (100%) diff --git a/tests/test_data/map_tests/no_layers/map_no_layers.json b/tests/test_data/map_tests/no_layers/map.json similarity index 100% rename from tests/test_data/map_tests/no_layers/map_no_layers.json rename to tests/test_data/map_tests/no_layers/map.json From ba9b8dabe0308cce4c3c80f0ecde119ef3956871 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 20:41:15 -0400 Subject: [PATCH 170/198] tests(layer): no_layers --- .../layer_tests/no_layers/expected.py | 3 + .../test_data/layer_tests/no_layers/map.json | 63 +++++++++++++++++++ .../layer_tests/no_layers/tileset_image.json | 14 +++++ tests/test_layer.py | 1 + 4 files changed, 81 insertions(+) create mode 100644 tests/test_data/layer_tests/no_layers/expected.py create mode 100644 tests/test_data/layer_tests/no_layers/map.json create mode 100644 tests/test_data/layer_tests/no_layers/tileset_image.json diff --git a/tests/test_data/layer_tests/no_layers/expected.py b/tests/test_data/layer_tests/no_layers/expected.py new file mode 100644 index 0000000..28461fd --- /dev/null +++ b/tests/test_data/layer_tests/no_layers/expected.py @@ -0,0 +1,3 @@ +from pytiled_parser import common_types, layer + +EXPECTED = [] diff --git a/tests/test_data/layer_tests/no_layers/map.json b/tests/test_data/layer_tests/no_layers/map.json new file mode 100644 index 0000000..ac423c0 --- /dev/null +++ b/tests/test_data/layer_tests/no_layers/map.json @@ -0,0 +1,63 @@ +{ "compressionlevel":0, + "editorsettings": + { + "export": + { + "target":"." + } + }, + "height":6, + "infinite":false, + "layers":[], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "name":"bool property - false", + "type":"bool", + "value":false + }, + { + "name":"bool property - true", + "type":"bool", + "value":true + }, + { + "name":"color property", + "type":"color", + "value":"#ff49fcff" + }, + { + "name":"file property", + "type":"file", + "value":"..\/..\/..\/..\/..\/..\/var\/log\/syslog" + }, + { + "name":"float property", + "type":"float", + "value":1.23456789 + }, + { + "name":"int property", + "type":"int", + "value":13 + }, + { + "name":"string property", + "type":"string", + "value":"Hello, World!!" + }], + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset_image.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/no_layers/tileset_image.json b/tests/test_data/layer_tests/no_layers/tileset_image.json new file mode 100644 index 0000000..e88a3f1 --- /dev/null +++ b/tests/test_data/layer_tests/no_layers/tileset_image.json @@ -0,0 +1,14 @@ +{ "columns":8, + "image":"..\/..\/images\/tmw_desert_spacing.png", + "imageheight":199, + "imagewidth":265, + "margin":1, + "name":"tile_set_image", + "spacing":1, + "tilecount":48, + "tiledversion":"1.3.1", + "tileheight":32, + "tilewidth":32, + "type":"tileset", + "version":1.2 +} diff --git a/tests/test_layer.py b/tests/test_layer.py index 6e03281..06233d6 100644 --- a/tests/test_layer.py +++ b/tests/test_layer.py @@ -15,6 +15,7 @@ LAYER_TESTS = TEST_DATA / "layer_tests" ALL_LAYER_TESTS = [ LAYER_TESTS / "all_layer_types", + LAYER_TESTS / "no_layers", ] From 1745117e87d57f56ec9f35dba78171ee89566ebd Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Mon, 27 Jul 2020 20:49:17 -0400 Subject: [PATCH 171/198] rf(no_layers): add typing info --- tests/test_data/layer_tests/no_layers/expected.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_data/layer_tests/no_layers/expected.py b/tests/test_data/layer_tests/no_layers/expected.py index 28461fd..932a0bf 100644 --- a/tests/test_data/layer_tests/no_layers/expected.py +++ b/tests/test_data/layer_tests/no_layers/expected.py @@ -1,3 +1,5 @@ -from pytiled_parser import common_types, layer +from typing import List -EXPECTED = [] +from pytiled_parser import layer + +EXPECTED: List[layer.Layer] = [] From 7211a14c98f86f7088126af02180eb263d1f6535 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 27 Jul 2020 20:57:18 -0400 Subject: [PATCH 172/198] tests(layer): Base64 with uncompressed, gzip, and zlib type tests. --- pytiled_parser/layer.py | 3 +- .../layer_tests/all_layer_types/map.json | 7 -- tests/test_data/layer_tests/b64/expected.py | 100 +++++++++++++++++- tests/test_data/layer_tests/b64/map.json | 67 ++++++------ .../layer_tests/b64_gzip/expected.py | 100 +++++++++++++++++- tests/test_data/layer_tests/b64_gzip/map.json | 67 ++++++------ .../layer_tests/b64_lzib/expected.py | 3 - .../layer_tests/b64_zlib/expected.py | 99 +++++++++++++++++ .../{b64_lzib => b64_zlib}/map.json | 67 ++++++------ .../{b64_lzib => b64_zlib}/tileset.json | 0 tests/test_data/layer_tests/csv/expected.py | 3 - tests/test_data/layer_tests/csv/map.json | 70 ------------ tests/test_data/layer_tests/csv/tileset.json | 22 ---- tests/test_layer.py | 3 + 14 files changed, 407 insertions(+), 204 deletions(-) delete mode 100644 tests/test_data/layer_tests/b64_lzib/expected.py create mode 100644 tests/test_data/layer_tests/b64_zlib/expected.py rename tests/test_data/layer_tests/{b64_lzib => b64_zlib}/map.json (53%) rename tests/test_data/layer_tests/{b64_lzib => b64_zlib}/tileset.json (100%) delete mode 100644 tests/test_data/layer_tests/csv/expected.py delete mode 100644 tests/test_data/layer_tests/csv/map.json delete mode 100644 tests/test_data/layer_tests/csv/tileset.json diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index ca87c3f..cf7c5cf 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -209,7 +209,7 @@ def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: unzipped_data = zlib.decompress(unencoded_data) elif tile_layer.compression == "gzip": unzipped_data = gzip.decompress(unencoded_data) - elif tile_layer.compression is None: + elif not tile_layer.compression: unzipped_data = unencoded_data else: raise ValueError(f"Unsupported compression type: '{tile_layer.compression}'.") @@ -228,7 +228,6 @@ def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: tile_grid.append(int_value) int_value = 0 - tile_grid.pop() tile_layer.data = tile_grid return tile_layer diff --git a/tests/test_data/layer_tests/all_layer_types/map.json b/tests/test_data/layer_tests/all_layer_types/map.json index 9ea084c..125eae5 100644 --- a/tests/test_data/layer_tests/all_layer_types/map.json +++ b/tests/test_data/layer_tests/all_layer_types/map.json @@ -1,11 +1,4 @@ { "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, "height":6, "infinite":false, "layers":[ diff --git a/tests/test_data/layer_tests/b64/expected.py b/tests/test_data/layer_tests/b64/expected.py index 6643112..05f89cc 100644 --- a/tests/test_data/layer_tests/b64/expected.py +++ b/tests/test_data/layer_tests/b64/expected.py @@ -1,3 +1,99 @@ -from pytiled_parser import common_types, layer +from pathlib import Path -EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + id=1, + size=common_types.Size(8, 6), + encoding="base64", + compression="", + 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, + ], + ), + layer.LayerGroup( + name="Group 1", + opacity=1, + visible=True, + id=4, + layers=[ + layer.ObjectLayer( + name="Object Layer 1", + opacity=1, + visible=True, + id=2, + draw_order="topdown", + tiled_objects=[ + tiled_object.Rectangle( + id=1, + name="", + rotation=0, + size=common_types.Size(69.3333333333333, 52.6666666666667), + coordinates=common_types.OrderedPair(46.3333333333333, 39), + visible=True, + type="", + ) + ], + ), + ], + ), + layer.ImageLayer( + name="Image Layer 1", + opacity=1, + visible=True, + id=3, + image=Path("../../images/tile_04.png"), + transparent_color=common_types.Color("#000000"), + ), +] diff --git a/tests/test_data/layer_tests/b64/map.json b/tests/test_data/layer_tests/b64/map.json index baa3bc6..cdc7cd4 100644 --- a/tests/test_data/layer_tests/b64/map.json +++ b/tests/test_data/layer_tests/b64/map.json @@ -1,11 +1,4 @@ { "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, "height":6, "infinite":false, "layers":[ @@ -23,39 +16,51 @@ "x":0, "y":0 }, - { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }, - { - "id":3, - "image":"", - "name":"Image Layer 1", - "opacity":1, - "type":"imagelayer", - "visible":true, - "x":0, - "y":0 - }, { "id":4, - "layers":[], + "layers":[ + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":52.6666666666667, + "id":1, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":69.3333333333333, + "x":46.3333333333333, + "y":39 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], "name":"Group 1", "opacity":1, "type":"group", "visible":true, "x":0, "y":0 + }, + { + "id":3, + "image":"..\/..\/images\/tile_04.png", + "name":"Image Layer 1", + "opacity":1, + "transparentcolor":"#000000", + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 }], "nextlayerid":5, - "nextobjectid":1, + "nextobjectid":3, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.4.1", @@ -63,7 +68,7 @@ "tilesets":[ { "firstgid":1, - "source":"tileset.json" + "source":"..\/all_layer_types\/tileset.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/layer_tests/b64_gzip/expected.py b/tests/test_data/layer_tests/b64_gzip/expected.py index 6643112..75415b7 100644 --- a/tests/test_data/layer_tests/b64_gzip/expected.py +++ b/tests/test_data/layer_tests/b64_gzip/expected.py @@ -1,3 +1,99 @@ -from pytiled_parser import common_types, layer +from pathlib import Path -EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + id=1, + size=common_types.Size(8, 6), + encoding="base64", + compression="gzip", + 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, + ], + ), + layer.LayerGroup( + name="Group 1", + opacity=1, + visible=True, + id=4, + layers=[ + layer.ObjectLayer( + name="Object Layer 1", + opacity=1, + visible=True, + id=2, + draw_order="topdown", + tiled_objects=[ + tiled_object.Rectangle( + id=1, + name="", + rotation=0, + size=common_types.Size(69.3333333333333, 52.6666666666667), + coordinates=common_types.OrderedPair(46.3333333333333, 39), + visible=True, + type="", + ) + ], + ), + ], + ), + layer.ImageLayer( + name="Image Layer 1", + opacity=1, + visible=True, + id=3, + image=Path("../../images/tile_04.png"), + transparent_color=common_types.Color("#000000"), + ), +] diff --git a/tests/test_data/layer_tests/b64_gzip/map.json b/tests/test_data/layer_tests/b64_gzip/map.json index 5c35f68..eda44d8 100644 --- a/tests/test_data/layer_tests/b64_gzip/map.json +++ b/tests/test_data/layer_tests/b64_gzip/map.json @@ -1,11 +1,4 @@ { "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, "height":6, "infinite":false, "layers":[ @@ -23,39 +16,51 @@ "x":0, "y":0 }, - { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }, - { - "id":3, - "image":"", - "name":"Image Layer 1", - "opacity":1, - "type":"imagelayer", - "visible":true, - "x":0, - "y":0 - }, { "id":4, - "layers":[], + "layers":[ + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":52.6666666666667, + "id":1, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":69.3333333333333, + "x":46.3333333333333, + "y":39 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], "name":"Group 1", "opacity":1, "type":"group", "visible":true, "x":0, "y":0 + }, + { + "id":3, + "image":"..\/..\/images\/tile_04.png", + "name":"Image Layer 1", + "opacity":1, + "transparentcolor":"#000000", + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 }], "nextlayerid":5, - "nextobjectid":1, + "nextobjectid":3, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.4.1", @@ -63,7 +68,7 @@ "tilesets":[ { "firstgid":1, - "source":"tileset.json" + "source":"..\/all_layer_types\/tileset.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/layer_tests/b64_lzib/expected.py b/tests/test_data/layer_tests/b64_lzib/expected.py deleted file mode 100644 index 6643112..0000000 --- a/tests/test_data/layer_tests/b64_lzib/expected.py +++ /dev/null @@ -1,3 +0,0 @@ -from pytiled_parser import common_types, layer - -EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/b64_zlib/expected.py b/tests/test_data/layer_tests/b64_zlib/expected.py new file mode 100644 index 0000000..bafa15d --- /dev/null +++ b/tests/test_data/layer_tests/b64_zlib/expected.py @@ -0,0 +1,99 @@ +from pathlib import Path + +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + id=1, + size=common_types.Size(8, 6), + encoding="base64", + compression="zlib", + 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, + ], + ), + layer.LayerGroup( + name="Group 1", + opacity=1, + visible=True, + id=4, + layers=[ + layer.ObjectLayer( + name="Object Layer 1", + opacity=1, + visible=True, + id=2, + draw_order="topdown", + tiled_objects=[ + tiled_object.Rectangle( + id=1, + name="", + rotation=0, + size=common_types.Size(69.3333333333333, 52.6666666666667), + coordinates=common_types.OrderedPair(46.3333333333333, 39), + visible=True, + type="", + ) + ], + ), + ], + ), + layer.ImageLayer( + name="Image Layer 1", + opacity=1, + visible=True, + id=3, + image=Path("../../images/tile_04.png"), + transparent_color=common_types.Color("#000000"), + ), +] diff --git a/tests/test_data/layer_tests/b64_lzib/map.json b/tests/test_data/layer_tests/b64_zlib/map.json similarity index 53% rename from tests/test_data/layer_tests/b64_lzib/map.json rename to tests/test_data/layer_tests/b64_zlib/map.json index bc8786e..5809c61 100644 --- a/tests/test_data/layer_tests/b64_lzib/map.json +++ b/tests/test_data/layer_tests/b64_zlib/map.json @@ -1,11 +1,4 @@ { "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, "height":6, "infinite":false, "layers":[ @@ -23,39 +16,51 @@ "x":0, "y":0 }, - { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }, - { - "id":3, - "image":"", - "name":"Image Layer 1", - "opacity":1, - "type":"imagelayer", - "visible":true, - "x":0, - "y":0 - }, { "id":4, - "layers":[], + "layers":[ + { + "draworder":"topdown", + "id":2, + "name":"Object Layer 1", + "objects":[ + { + "height":52.6666666666667, + "id":1, + "name":"", + "rotation":0, + "type":"", + "visible":true, + "width":69.3333333333333, + "x":46.3333333333333, + "y":39 + }], + "opacity":1, + "type":"objectgroup", + "visible":true, + "x":0, + "y":0 + }], "name":"Group 1", "opacity":1, "type":"group", "visible":true, "x":0, "y":0 + }, + { + "id":3, + "image":"..\/..\/images\/tile_04.png", + "name":"Image Layer 1", + "opacity":1, + "transparentcolor":"#000000", + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 }], "nextlayerid":5, - "nextobjectid":1, + "nextobjectid":3, "orientation":"orthogonal", "renderorder":"right-down", "tiledversion":"1.4.1", @@ -63,7 +68,7 @@ "tilesets":[ { "firstgid":1, - "source":"tileset.json" + "source":"..\/all_layer_types\/tileset.json" }], "tilewidth":32, "type":"map", diff --git a/tests/test_data/layer_tests/b64_lzib/tileset.json b/tests/test_data/layer_tests/b64_zlib/tileset.json similarity index 100% rename from tests/test_data/layer_tests/b64_lzib/tileset.json rename to tests/test_data/layer_tests/b64_zlib/tileset.json diff --git a/tests/test_data/layer_tests/csv/expected.py b/tests/test_data/layer_tests/csv/expected.py deleted file mode 100644 index 6643112..0000000 --- a/tests/test_data/layer_tests/csv/expected.py +++ /dev/null @@ -1,3 +0,0 @@ -from pytiled_parser import common_types, layer - -EXPECTED = [layer.TileLayer(name="Tile Layer 1", opacity=1, visible=True)] diff --git a/tests/test_data/layer_tests/csv/map.json b/tests/test_data/layer_tests/csv/map.json deleted file mode 100644 index b0adc34..0000000 --- a/tests/test_data/layer_tests/csv/map.json +++ /dev/null @@ -1,70 +0,0 @@ -{ "compressionlevel":-1, - "editorsettings": - { - "export": - { - "target":"." - } - }, - "height":6, - "infinite":false, - "layers":[ - { - "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], - "height":6, - "id":1, - "name":"Tile Layer 1", - "opacity":1, - "type":"tilelayer", - "visible":true, - "width":8, - "x":0, - "y":0 - }, - { - "draworder":"topdown", - "id":2, - "name":"Object Layer 1", - "objects":[], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - }, - { - "id":3, - "image":"", - "name":"Image Layer 1", - "opacity":1, - "type":"imagelayer", - "visible":true, - "x":0, - "y":0 - }, - { - "id":4, - "layers":[], - "name":"Group 1", - "opacity":1, - "type":"group", - "visible":true, - "x":0, - "y":0 - }], - "nextlayerid":5, - "nextobjectid":1, - "orientation":"orthogonal", - "renderorder":"right-down", - "tiledversion":"1.4.1", - "tileheight":32, - "tilesets":[ - { - "firstgid":1, - "source":"tileset.json" - }], - "tilewidth":32, - "type":"map", - "version":1.4, - "width":8 -} \ No newline at end of file diff --git a/tests/test_data/layer_tests/csv/tileset.json b/tests/test_data/layer_tests/csv/tileset.json deleted file mode 100644 index 8df9f18..0000000 --- a/tests/test_data/layer_tests/csv/tileset.json +++ /dev/null @@ -1,22 +0,0 @@ -{ "columns":8, - "editorsettings": - { - "export": - { - "format":"", - "target":"." - } - }, - "image":"..\/..\/images\/tmw_desert_spacing.png", - "imageheight":199, - "imagewidth":265, - "margin":1, - "name":"tile_set_image", - "spacing":1, - "tilecount":48, - "tiledversion":"1.3.5", - "tileheight":32, - "tilewidth":32, - "type":"tileset", - "version":1.2 -} \ No newline at end of file diff --git a/tests/test_layer.py b/tests/test_layer.py index 6e03281..bca9bf4 100644 --- a/tests/test_layer.py +++ b/tests/test_layer.py @@ -15,6 +15,9 @@ LAYER_TESTS = TEST_DATA / "layer_tests" ALL_LAYER_TESTS = [ LAYER_TESTS / "all_layer_types", + LAYER_TESTS / "b64", + LAYER_TESTS / "b64_gzip", + LAYER_TESTS / "b64_zlib", ] From 99c6964e9b4402f23ff1ebc26f9f0018cca7a67c Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Mon, 27 Jul 2020 21:06:53 -0400 Subject: [PATCH 173/198] tests(layer): increased branch coverage of layer tests --- pytiled_parser/layer.py | 4 +--- .../layer_tests/all_layer_types/expected.py | 9 +++++++++ .../layer_tests/all_layer_types/map.json | 20 ++++++++++++++++++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index cf7c5cf..1477f7a 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -209,10 +209,8 @@ def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: unzipped_data = zlib.decompress(unencoded_data) elif tile_layer.compression == "gzip": unzipped_data = gzip.decompress(unencoded_data) - elif not tile_layer.compression: - unzipped_data = unencoded_data else: - raise ValueError(f"Unsupported compression type: '{tile_layer.compression}'.") + unzipped_data = unencoded_data tile_grid = [] diff --git a/tests/test_data/layer_tests/all_layer_types/expected.py b/tests/test_data/layer_tests/all_layer_types/expected.py index 9e27994..d3442ff 100644 --- a/tests/test_data/layer_tests/all_layer_types/expected.py +++ b/tests/test_data/layer_tests/all_layer_types/expected.py @@ -9,6 +9,8 @@ EXPECTED = [ visible=True, id=1, size=common_types.Size(8, 6), + offset=common_types.OrderedPair(1, 3), + properties={"test": "test property",}, data=[ 1, 2, @@ -94,4 +96,11 @@ EXPECTED = [ image=Path("../../images/tile_04.png"), transparent_color=common_types.Color("#000000"), ), + layer.ImageLayer( + name="Image Layer 2", + opacity=1, + visible=True, + id=5, + image=Path("../../images/tile_04.png"), + ), ] diff --git a/tests/test_data/layer_tests/all_layer_types/map.json b/tests/test_data/layer_tests/all_layer_types/map.json index 125eae5..18e6848 100644 --- a/tests/test_data/layer_tests/all_layer_types/map.json +++ b/tests/test_data/layer_tests/all_layer_types/map.json @@ -7,7 +7,15 @@ "height":6, "id":1, "name":"Tile Layer 1", + "offsetx":1, + "offsety":3, "opacity":1, + "properties":[ + { + "name":"test", + "type":"string", + "value":"test property" + }], "type":"tilelayer", "visible":true, "width":8, @@ -56,8 +64,18 @@ "visible":true, "x":0, "y":0 + }, + { + "id":5, + "image":"..\/..\/images\/tile_04.png", + "name":"Image Layer 2", + "opacity":1, + "type":"imagelayer", + "visible":true, + "x":0, + "y":0 }], - "nextlayerid":5, + "nextlayerid":6, "nextobjectid":3, "orientation":"orthogonal", "renderorder":"right-down", From f23b5cd0a62c331de52be4436c8d1c866490b6c7 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 5 Aug 2020 23:14:15 -0400 Subject: [PATCH 174/198] feat(layer): refactor to support infinite maps --- pytiled_parser/layer.py | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 1477f7a..72692d3 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -5,6 +5,7 @@ import gzip import zlib from pathlib import Path from typing import Any, Callable, List, Optional, Union +from typing import cast as type_cast import attr from typing_extensions import TypedDict @@ -66,8 +67,7 @@ class Chunk: coordinates: OrderedPair size: Size - - data: Optional[Union[List[int], str]] = None + data: List[int] LayerData = Union[TileLayerGrid, List[Chunk]] @@ -90,18 +90,14 @@ class TileLayer(Layer): data: Either an 2 dimensional array of integers representing the global tile IDs for the map layer, or a list of chunks for an infinite map. """ - - encoding: str = "csv" - - compression: Optional[str] = None chunks: Optional[List[Chunk]] = None - data: Optional[Union[List[int], str]] = None + data: Optional[List[int]] = None @attr.s(auto_attribs=True, kw_only=True) class ObjectLayer(Layer): - """ - TiledObject Group Object. + """TiledObject Group Object. + The object group is in fact a map layer, and is hence called "object layer" in Tiled. See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#objectgroup @@ -189,11 +185,12 @@ class RawLayer(TypedDict): y: int -def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: +def _decode_tile_layer_data(data: str, compression: str) -> List[int]: """Decode Base64 Encoded Tile Data. Supports gzip and zlib compression. Args: - tile_layer: The TileLayer to decode the data for + data: The base64 encoded data + compression: Either zlib, gzip, or empty. If empty no decompression is done. Returns: TileLayer: The TileLayer with the decoded data @@ -201,13 +198,10 @@ def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: Raises: ValueError: For an unsupported compression type. """ - if not isinstance(tile_layer.data, str): - return tile_layer - - unencoded_data = base64.b64decode(tile_layer.data) - if tile_layer.compression == "zlib": + unencoded_data = base64.b64decode(data) + if compression == "zlib": unzipped_data = zlib.decompress(unencoded_data) - elif tile_layer.compression == "gzip": + elif compression == "gzip": unzipped_data = gzip.decompress(unencoded_data) else: unzipped_data = unencoded_data @@ -226,11 +220,12 @@ def _decode_tile_layer_data(tile_layer: TileLayer) -> TileLayer: tile_grid.append(int_value) int_value = 0 - tile_layer.data = tile_grid - return tile_layer + return tile_grid -def _cast_chunk(raw_chunk: RawChunk) -> Chunk: +def _cast_chunk( + raw_chunk: RawChunk, encoding: str = None, compression: str = None +) -> Chunk: """ Cast the raw_chunk to a Chunk. Args: @@ -239,15 +234,18 @@ def _cast_chunk(raw_chunk: RawChunk) -> 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) chunk = Chunk( coordinates=OrderedPair(raw_chunk["x"], raw_chunk["y"]), size=Size(raw_chunk["width"], raw_chunk["height"]), + data=data, ) - if raw_chunk.get("data") is not None: - chunk.data = raw_chunk["data"] - return chunk @@ -301,22 +299,24 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer: """ tile_layer = TileLayer(**_get_common_attributes(raw_layer).__dict__) - if raw_layer.get("encoding") is not None: - tile_layer.encoding = raw_layer["encoding"] - - if raw_layer.get("compression") is not None: - tile_layer.compression = raw_layer["compression"] - if raw_layer.get("chunks") is not None: tile_layer.chunks = [] for chunk in raw_layer["chunks"]: - tile_layer.chunks.append(_cast_chunk(chunk)) + if raw_layer.get("encoding") is not None: + tile_layer.chunks.append( + _cast_chunk(chunk, raw_layer["encoding"], raw_layer["compression"]) + ) + else: + tile_layer.chunks.append(_cast_chunk(chunk)) if raw_layer.get("data") is not None: - tile_layer.data = raw_layer["data"] - - if tile_layer.encoding == "base64": - _decode_tile_layer_data(tile_layer) + if raw_layer.get("encoding") is not None: + tile_layer.data = _decode_tile_layer_data( + data=type_cast(str, raw_layer["data"]), + compression=raw_layer["compression"], + ) + else: + tile_layer.data = type_cast(List[int], raw_layer["data"]) return tile_layer From 612bd52653cae81281a511351ba4f72d4232705e Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 5 Aug 2020 23:14:31 -0400 Subject: [PATCH 175/198] tests(layer): infinite map tests --- tests/test_data/layer_tests/b64/expected.py | 2 - .../layer_tests/b64_gzip/expected.py | 2 - .../layer_tests/b64_zlib/expected.py | 2 - .../layer_tests/infinite_map/expected.py | 93 ++++++ .../layer_tests/infinite_map/map.json | 68 +++++ .../layer_tests/infinite_map_b64/expected.py | 279 ++++++++++++++++++ .../layer_tests/infinite_map_b64/map.json | 51 ++++ tests/test_layer.py | 2 + 8 files changed, 493 insertions(+), 6 deletions(-) create mode 100644 tests/test_data/layer_tests/infinite_map/expected.py create mode 100644 tests/test_data/layer_tests/infinite_map/map.json create mode 100644 tests/test_data/layer_tests/infinite_map_b64/expected.py create mode 100644 tests/test_data/layer_tests/infinite_map_b64/map.json diff --git a/tests/test_data/layer_tests/b64/expected.py b/tests/test_data/layer_tests/b64/expected.py index 05f89cc..9e27994 100644 --- a/tests/test_data/layer_tests/b64/expected.py +++ b/tests/test_data/layer_tests/b64/expected.py @@ -9,8 +9,6 @@ EXPECTED = [ visible=True, id=1, size=common_types.Size(8, 6), - encoding="base64", - compression="", data=[ 1, 2, diff --git a/tests/test_data/layer_tests/b64_gzip/expected.py b/tests/test_data/layer_tests/b64_gzip/expected.py index 75415b7..9e27994 100644 --- a/tests/test_data/layer_tests/b64_gzip/expected.py +++ b/tests/test_data/layer_tests/b64_gzip/expected.py @@ -9,8 +9,6 @@ EXPECTED = [ visible=True, id=1, size=common_types.Size(8, 6), - encoding="base64", - compression="gzip", data=[ 1, 2, diff --git a/tests/test_data/layer_tests/b64_zlib/expected.py b/tests/test_data/layer_tests/b64_zlib/expected.py index bafa15d..9e27994 100644 --- a/tests/test_data/layer_tests/b64_zlib/expected.py +++ b/tests/test_data/layer_tests/b64_zlib/expected.py @@ -9,8 +9,6 @@ EXPECTED = [ visible=True, id=1, size=common_types.Size(8, 6), - encoding="base64", - compression="zlib", data=[ 1, 2, diff --git a/tests/test_data/layer_tests/infinite_map/expected.py b/tests/test_data/layer_tests/infinite_map/expected.py new file mode 100644 index 0000000..e6db30c --- /dev/null +++ b/tests/test_data/layer_tests/infinite_map/expected.py @@ -0,0 +1,93 @@ +from pathlib import Path + +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + id=1, + size=common_types.Size(16, 16), + offset=common_types.OrderedPair(163.089434111595, 116.462603878116), + 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, + ], + ), + 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, + ], + ), + ], + ) +] diff --git a/tests/test_data/layer_tests/infinite_map/map.json b/tests/test_data/layer_tests/infinite_map/map.json new file mode 100644 index 0000000..f506453 --- /dev/null +++ b/tests/test_data/layer_tests/infinite_map/map.json @@ -0,0 +1,68 @@ +{ "compressionlevel":-1, + "editorsettings": + { + "chunksize": + { + "height":8, + "width":4 + }, + "export": + { + "target":"..\/all_layer_types" + } + }, + "height":6, + "infinite":true, + "layers":[ + { + "chunks":[ + { + "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], + "height":8, + "width":4, + "x":0, + "y":0 + }, + { + "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], + "height":8, + "width":4, + "x":4, + "y":0 + }], + "height":16, + "id":1, + "name":"Tile Layer 1", + "offsetx":163.089434111595, + "offsety":116.462603878116, + "opacity":1, + "properties":[ + { + "name":"test", + "type":"string", + "value":"test property" + }], + "startx":0, + "starty":0, + "type":"tilelayer", + "visible":true, + "width":16, + "x":0, + "y":0 + }], + "nextlayerid":6, + "nextobjectid":3, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"..\/all_layer_types\/tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/layer_tests/infinite_map_b64/expected.py b/tests/test_data/layer_tests/infinite_map_b64/expected.py new file mode 100644 index 0000000..16be791 --- /dev/null +++ b/tests/test_data/layer_tests/infinite_map_b64/expected.py @@ -0,0 +1,279 @@ +from pathlib import Path + +from pytiled_parser import common_types, layer, tiled_object + +EXPECTED = [ + layer.TileLayer( + name="Tile Layer 1", + opacity=1, + visible=True, + id=1, + size=common_types.Size(16, 16), + offset=common_types.OrderedPair(1, 3), + 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, + ], + ) + ], + ) +] diff --git a/tests/test_data/layer_tests/infinite_map_b64/map.json b/tests/test_data/layer_tests/infinite_map_b64/map.json new file mode 100644 index 0000000..54c3852 --- /dev/null +++ b/tests/test_data/layer_tests/infinite_map_b64/map.json @@ -0,0 +1,51 @@ +{ "compressionlevel":-1, + "height":6, + "infinite":true, + "layers":[ + { + "chunks":[ + { + "data":"AQAAAAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAKAAAACwAAAAwAAAANAAAADgAAAA8AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQAAABoAAAAbAAAAHAAAAB0AAAAeAAAAHwAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACEAAAAiAAAAIwAAACQAAAAlAAAAJgAAACcAAAAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApAAAAKgAAACsAAAAsAAAALQAAAC4AAAAvAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "height":16, + "width":16, + "x":0, + "y":0 + }], + "compression":"", + "encoding":"base64", + "height":16, + "id":1, + "name":"Tile Layer 1", + "offsetx":1, + "offsety":3, + "opacity":1, + "properties":[ + { + "name":"test", + "type":"string", + "value":"test property" + }], + "startx":0, + "starty":0, + "type":"tilelayer", + "visible":true, + "width":16, + "x":0, + "y":0 + }], + "nextlayerid":6, + "nextobjectid":3, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.4.1", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"..\/all_layer_types\/tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.4, + "width":8 +} \ No newline at end of file diff --git a/tests/test_layer.py b/tests/test_layer.py index 7d3e8c0..6310ca5 100644 --- a/tests/test_layer.py +++ b/tests/test_layer.py @@ -19,6 +19,8 @@ ALL_LAYER_TESTS = [ LAYER_TESTS / "b64_gzip", LAYER_TESTS / "b64_zlib", LAYER_TESTS / "no_layers", + LAYER_TESTS / "infinite_map", + LAYER_TESTS / "infinite_map_b64", ] From 3cd4e73d5f582761eb4bba74191c414f2e86e6cc Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 22:57:38 -0400 Subject: [PATCH 176/198] feat(embedded tilesets): Updates to support tilesets embedded in maps --- pytiled_parser/map.py | 51 ++++++++++++++++++++------------------- pytiled_parser/tileset.py | 21 ++++++++++------ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/pytiled_parser/map.py b/pytiled_parser/map.py index 2187b10..701a298 100644 --- a/pytiled_parser/map.py +++ b/pytiled_parser/map.py @@ -59,7 +59,7 @@ class Map: tiled_version: str tile_size: Size tilesets: TilesetDict - version: str + version: float background_color: Optional[Color] = None properties: Optional[Properties] = None @@ -100,32 +100,11 @@ class _RawTiledMap(TypedDict): tilesets: List[_RawTilesetMapping] tilewidth: int type: str - version: str + version: float width: int -def _cast_raw_tilesets(raw_tilesets: List[_RawTilesetMapping]) -> TilesetDict: - """ Cast a list of raw tileset mappings to a Tileset dictionary. - - Args: - raw_tilesets: the list of Tileset mappings to be cast into a TilesetDict - - Returns: - TilesetDict: containing all tilesets by `firstgid` - """ - - tilesets: TilesetDict = {} - - for raw_tileset_mapping in raw_tilesets: - with open(Path(raw_tileset_mapping["source"])) as raw_tileset_file: - raw_tileset = typing_cast(RawTileSet, json.load(raw_tileset_file)) - - tilesets[raw_tileset_mapping["firstgid"]] = tileset.cast(raw_tileset) - - return tilesets - - -def cast(raw_tiled_map: _RawTiledMap) -> Map: +def cast(file: Path) -> Map: """ Cast the raw Tiled map into a pytiled_parser type Args: @@ -135,6 +114,28 @@ def cast(raw_tiled_map: _RawTiledMap) -> Map: TileSet: a properly typed TileSet. """ + with open(file) as map_file: + raw_tiled_map = json.load(map_file) + + parent_dir = file.parent + + raw_tilesets: List[Union[RawTileSet, _RawTilesetMapping]] = raw_tiled_map[ + "tilesets" + ] + tilesets: TilesetDict = {} + + for raw_tileset in raw_tilesets: + if raw_tileset.get("source") is not None: + # Is an external Tileset + with open(parent_dir / raw_tileset["source"]) as raw_tileset_file: + tilesets[raw_tileset["firstgid"]] = tileset.cast( + json.load(raw_tileset_file) + ) + else: + # Is an embedded Tileset + raw_tileset = typing_cast(RawTileSet, raw_tileset) + tilesets[raw_tileset["firstgid"]] = tileset.cast(raw_tileset) + # `map` is a built-in function map_ = Map( infinite=raw_tiled_map["infinite"], @@ -146,7 +147,7 @@ def cast(raw_tiled_map: _RawTiledMap) -> Map: render_order=raw_tiled_map["renderorder"], tiled_version=raw_tiled_map["tiledversion"], tile_size=Size(raw_tiled_map["tilewidth"], raw_tiled_map["tileheight"]), - tilesets=_cast_raw_tilesets(raw_tiled_map["tilesets"]), + tilesets=tilesets, version=raw_tiled_map["version"], ) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index d2bf9a4..e7b211d 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -139,19 +139,20 @@ class TileSet: """ name: str - type: str tile_width: int tile_height: int tile_count: int columns: int - tiled_version: str - version: float - spacing: int = 0 margin: int = 0 + type: Optional[str] = None + + tiled_version: Optional[str] = None + version: Optional[float] = None + image: Optional[Path] = None image_width: Optional[int] = None image_height: Optional[int] = None @@ -370,11 +371,17 @@ def cast(raw_tileset: RawTileSet) -> TileSet: columns=raw_tileset["columns"], spacing=raw_tileset["spacing"], margin=raw_tileset["margin"], - version=raw_tileset["version"], - tiled_version=raw_tileset["tiledversion"], - type=raw_tileset["type"], ) + if raw_tileset.get("type") is not None: + tileset.type = raw_tileset["type"] + + if raw_tileset.get("version") is not None: + tileset.version = raw_tileset["version"] + + if raw_tileset.get("tiledversion") is not None: + tileset.tiled_version = raw_tileset["tiledversion"] + if raw_tileset.get("image") is not None: tileset.image = Path(raw_tileset["image"]) From c452c50b2f547490c5e04d16cf285617773b5214 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 22:58:12 -0400 Subject: [PATCH 177/198] tests(map): Expanded map test coverage --- tests/test_data/images/hexmini.png | Bin 0 -> 5784 bytes .../map_tests/embedded_tileset/expected.py | 31 ++++ .../map_tests/embedded_tileset/map.json | 36 +++++ .../test_data/map_tests/hexagonal/expected.py | 147 ++++++++++++++++++ tests/test_data/map_tests/hexagonal/map.json | 35 +++++ .../map_tests/hexagonal/tileset.json | 19 +++ .../map_tests/no_background_color/expected.py | 33 ++++ .../map_tests/no_background_color/map.json | 27 ++++ .../no_background_color/tileset_image.json | 14 ++ .../test_data/map_tests/no_layers/expected.py | 42 +++++ tests/test_data/map_tests/no_layers/map.json | 8 +- tests/test_map.py | 34 ++++ 12 files changed, 420 insertions(+), 6 deletions(-) create mode 100644 tests/test_data/images/hexmini.png create mode 100644 tests/test_data/map_tests/embedded_tileset/expected.py create mode 100644 tests/test_data/map_tests/embedded_tileset/map.json create mode 100644 tests/test_data/map_tests/hexagonal/expected.py create mode 100644 tests/test_data/map_tests/hexagonal/map.json create mode 100644 tests/test_data/map_tests/hexagonal/tileset.json create mode 100644 tests/test_data/map_tests/no_background_color/expected.py create mode 100644 tests/test_data/map_tests/no_background_color/map.json create mode 100644 tests/test_data/map_tests/no_background_color/tileset_image.json create mode 100644 tests/test_map.py diff --git a/tests/test_data/images/hexmini.png b/tests/test_data/images/hexmini.png new file mode 100644 index 0000000000000000000000000000000000000000..12d17bf0729fc6def68672a783432083df66dc5b GIT binary patch literal 5784 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 W Date: Wed, 19 Aug 2020 23:03:31 -0400 Subject: [PATCH 178/198] refactor(map): Renamed `map` to `tiled_map` to avoid redefining the built-in --- pytiled_parser/__init__.py | 2 +- pytiled_parser/{map.py => tiled_map.py} | 0 tests/test_data/map_tests/embedded_tileset/expected.py | 4 ++-- tests/test_data/map_tests/hexagonal/expected.py | 4 ++-- tests/test_data/map_tests/no_background_color/expected.py | 4 ++-- tests/test_data/map_tests/no_layers/expected.py | 4 ++-- tests/test_map.py | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) rename pytiled_parser/{map.py => tiled_map.py} (100%) diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 3ed056d..258acdd 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -4,6 +4,6 @@ from .common_types import OrderedPair, Size from .layer import Layer -from .map import Map from .properties import Properties +from .tiled_map import Map from .tileset import TileSet diff --git a/pytiled_parser/map.py b/pytiled_parser/tiled_map.py similarity index 100% rename from pytiled_parser/map.py rename to pytiled_parser/tiled_map.py diff --git a/tests/test_data/map_tests/embedded_tileset/expected.py b/tests/test_data/map_tests/embedded_tileset/expected.py index ffc69c7..ebaaddc 100644 --- a/tests/test_data/map_tests/embedded_tileset/expected.py +++ b/tests/test_data/map_tests/embedded_tileset/expected.py @@ -1,8 +1,8 @@ from pathlib import Path -from pytiled_parser import common_types, map, tileset +from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = map.Map( +EXPECTED = tiled_map.Map( infinite=False, layers=[], map_size=common_types.Size(8, 6), diff --git a/tests/test_data/map_tests/hexagonal/expected.py b/tests/test_data/map_tests/hexagonal/expected.py index a3daadc..3bf032e 100644 --- a/tests/test_data/map_tests/hexagonal/expected.py +++ b/tests/test_data/map_tests/hexagonal/expected.py @@ -1,8 +1,8 @@ from pathlib import Path -from pytiled_parser import common_types, layer, map, tileset +from pytiled_parser import common_types, layer, tiled_map, tileset -EXPECTED = map.Map( +EXPECTED = tiled_map.Map( hex_side_length=6, stagger_axis="y", stagger_index="odd", diff --git a/tests/test_data/map_tests/no_background_color/expected.py b/tests/test_data/map_tests/no_background_color/expected.py index 6e2de52..1df8bc2 100644 --- a/tests/test_data/map_tests/no_background_color/expected.py +++ b/tests/test_data/map_tests/no_background_color/expected.py @@ -1,8 +1,8 @@ from pathlib import Path -from pytiled_parser import common_types, map, tileset +from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = map.Map( +EXPECTED = tiled_map.Map( infinite=False, layers=[], map_size=common_types.Size(8, 6), diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py index b719a60..bd7a222 100644 --- a/tests/test_data/map_tests/no_layers/expected.py +++ b/tests/test_data/map_tests/no_layers/expected.py @@ -1,8 +1,8 @@ from pathlib import Path -from pytiled_parser import common_types, map, tileset +from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = map.Map( +EXPECTED = tiled_map.Map( infinite=False, layers=[], map_size=common_types.Size(8, 6), diff --git a/tests/test_map.py b/tests/test_map.py index d841e09..50363c1 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest -from pytiled_parser import map as map_ +from pytiled_parser import tiled_map TESTS_DIR = Path(os.path.dirname(os.path.abspath(__file__))) TEST_DATA = TESTS_DIR / "test_data" @@ -29,6 +29,6 @@ def test_map_integration(map_test): raw_maps_path = map_test / "map.json" - casted_map = map_.cast(raw_maps_path) + casted_map = tiled_map.cast(raw_maps_path) assert casted_map == expected.EXPECTED From 0b1348dc1b16bdad18d3fb84668f860276102240 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:04:10 -0400 Subject: [PATCH 179/198] chore(common_types): Fixed unused import --- pytiled_parser/common_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index 41c03f3..924685b 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -2,7 +2,7 @@ # pylint: disable=too-few-public-methods -from typing import NamedTuple, Union +from typing import NamedTuple import attr From e5dcb10858592ec81cdffb6af5b9affbdb2ca298 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:05:04 -0400 Subject: [PATCH 180/198] chore(layer): Removed FIXME for completed task --- pytiled_parser/layer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 72692d3..fcf057e 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -157,7 +157,6 @@ class RawChunk(TypedDict): class RawLayer(TypedDict): - # FIXME Make the layers attribute function """ The keys and their types that appear in a Layer JSON Object.""" chunks: List[RawChunk] From 659a2b7d85895cafa9f7b9561dd5266c5d085be2 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:06:31 -0400 Subject: [PATCH 181/198] chore(tiled_map): Fixed low-hanging fruit pylint errors --- pytiled_parser/tiled_map.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/tiled_map.py b/pytiled_parser/tiled_map.py index 701a298..69158d8 100644 --- a/pytiled_parser/tiled_map.py +++ b/pytiled_parser/tiled_map.py @@ -2,7 +2,7 @@ import json from pathlib import Path -from typing import Dict, List, NamedTuple, Optional, Union +from typing import Dict, List, Optional, Union from typing import cast as typing_cast import attr @@ -108,7 +108,7 @@ def cast(file: Path) -> Map: """ Cast the raw Tiled map into a pytiled_parser type Args: - raw_tiled_map: Raw JSON Formatted Tiled Map to be cast. + file: Path to the map's JSON file Returns: TileSet: a properly typed TileSet. From fb1309617828f5990011f61b3215389195cede26 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:10:00 -0400 Subject: [PATCH 182/198] tests(tileset): Removed unused tileset test --- .../tilesets/image_objects/expected.py | 0 .../tilesets/image_objects/tileset.json | 200 ------------------ 2 files changed, 200 deletions(-) delete mode 100644 tests/test_data/tilesets/image_objects/expected.py delete mode 100644 tests/test_data/tilesets/image_objects/tileset.json diff --git a/tests/test_data/tilesets/image_objects/expected.py b/tests/test_data/tilesets/image_objects/expected.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/test_data/tilesets/image_objects/tileset.json b/tests/test_data/tilesets/image_objects/tileset.json deleted file mode 100644 index f490b17..0000000 --- a/tests/test_data/tilesets/image_objects/tileset.json +++ /dev/null @@ -1,200 +0,0 @@ -{ "columns":8, - "editorsettings": - { - "export": - { - "format":"", - "target":"." - } - }, - "image":"..\/..\/images\/tmw_desert_spacing.png", - "imageheight":199, - "imagewidth":265, - "margin":1, - "name":"tile_set_image", - "spacing":1, - "tilecount":48, - "tiledversion":"1.3.5", - "tileheight":32, - "tiles":[ - { - "id":9, - "objectgroup": - { - "draworder":"index", - "name":"", - "objects":[ - { - "height":32, - "id":2, - "name":"wall", - "rotation":1, - "type":"rectangle type", - "visible":true, - "width":32, - "x":1, - "y":1 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - } - }, - { - "id":19, - "objectgroup": - { - "draworder":"index", - "name":"", - "objects":[ - { - "height":0, - "id":1, - "name":"wall corner", - "polygon":[ - { - "x":0, - "y":0 - }, - { - "x":-32, - "y":0 - }, - { - "x":-32, - "y":32 - }, - { - "x":-16, - "y":32.1818 - }, - { - "x":-15.8182, - "y":16.9091 - }, - { - "x":0.181818, - "y":17.0909 - }], - "rotation":1, - "type":"polygon type", - "visible":true, - "width":0, - "x":32, - "y":1 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - } - }, - { - "id":20, - "objectgroup": - { - "draworder":"index", - "name":"", - "objects":[ - { - "height":0, - "id":1, - "name":"polyline", - "polyline":[ - { - "x":0, - "y":0 - }, - { - "x":25.0909, - "y":21.2727 - }, - { - "x":9.63636, - "y":28.3636 - }], - "rotation":1, - "type":"polyline type", - "visible":true, - "width":0, - "x":1.45455, - "y":1.45455 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - } - }, - { - "id":31, - "objectgroup": - { - "draworder":"index", - "name":"", - "objects":[ - { - "ellipse":true, - "height":19.2727, - "id":1, - "name":"rock 1", - "rotation":1, - "type":"elipse type", - "visible":true, - "width":19.6364, - "x":5.09091, - "y":2.54545 - }, - { - "ellipse":true, - "height":8.36364, - "id":2, - "name":"rock 2", - "rotation":-1, - "type":"elipse type", - "visible":true, - "width":8.54545, - "x":16.1818, - "y":22 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - } - }, - { - "id":45, - "objectgroup": - { - "draworder":"index", - "name":"", - "objects":[ - { - "height":0, - "id":1, - "name":"sign", - "point":true, - "rotation":0, - "type":"point type", - "visible":true, - "width":0, - "x":14.7273, - "y":26.3636 - }], - "opacity":1, - "type":"objectgroup", - "visible":true, - "x":0, - "y":0 - } - }], - "tilewidth":32, - "type":"tileset", - "version":1.2 -} \ No newline at end of file From 4fb811d0392cff4203adcc75ea003863a657c26b Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:11:59 -0400 Subject: [PATCH 183/198] refactor(tileset): Renamed TileSet class to Tileset --- pytiled_parser/__init__.py | 2 +- pytiled_parser/tiled_map.py | 4 ++-- pytiled_parser/tileset.py | 10 ++++------ tests/test_data/map_tests/embedded_tileset/expected.py | 2 +- tests/test_data/map_tests/hexagonal/expected.py | 2 +- .../map_tests/no_background_color/expected.py | 2 +- tests/test_data/map_tests/no_layers/expected.py | 2 +- tests/test_data/tilesets/image/expected.py | 2 +- .../tilesets/image_background_color/expected.py | 2 +- tests/test_data/tilesets/image_grid/expected.py | 2 +- tests/test_data/tilesets/image_properties/expected.py | 2 +- tests/test_data/tilesets/image_tile_offset/expected.py | 2 +- .../tilesets/image_transparent_color/expected.py | 2 +- tests/test_data/tilesets/individual_images/expected.py | 2 +- tests/test_data/tilesets/terrain/expected.py | 2 +- 15 files changed, 19 insertions(+), 21 deletions(-) diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 258acdd..3ce0b53 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -6,4 +6,4 @@ from .common_types import OrderedPair, Size from .layer import Layer from .properties import Properties from .tiled_map import Map -from .tileset import TileSet +from .tileset import Tileset diff --git a/pytiled_parser/tiled_map.py b/pytiled_parser/tiled_map.py index 69158d8..61d9f89 100644 --- a/pytiled_parser/tiled_map.py +++ b/pytiled_parser/tiled_map.py @@ -12,9 +12,9 @@ from . import layer, properties, tileset from .common_types import Color, Size from .layer import Layer, RawLayer from .properties import Properties, RawProperty -from .tileset import RawTileSet, TileSet +from .tileset import RawTileSet, Tileset -TilesetDict = Dict[int, TileSet] +TilesetDict = Dict[int, Tileset] @attr.s(auto_attribs=True) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index e7b211d..9fc3104 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -7,7 +7,6 @@ from typing_extensions import TypedDict from . import layer from . import properties as properties_ -from . import tiled_object from .common_types import Color, OrderedPair @@ -102,15 +101,14 @@ class Tile: image_width: Optional[int] = None image_height: Optional[int] = None properties: Optional[properties_.Properties] = None - tileset: Optional["TileSet"] = None + tileset: Optional["Tileset"] = None flipped_horizontally: bool = False flipped_diagonally: bool = False flipped_vertically: bool = False @attr.s(auto_attribs=True) -class TileSet: - # FIXME: rename to Tileset +class Tileset: """Object for storing a TSX with all associated collision data. Args: @@ -353,7 +351,7 @@ def _cast_grid(raw_grid: RawGrid) -> Grid: ) -def cast(raw_tileset: RawTileSet) -> TileSet: +def cast(raw_tileset: RawTileSet) -> Tileset: """ Cast the raw tileset into a pytiled_parser type Args: @@ -363,7 +361,7 @@ def cast(raw_tileset: RawTileSet) -> TileSet: TileSet: a properly typed TileSet. """ - tileset = TileSet( + tileset = Tileset( name=raw_tileset["name"], tile_count=raw_tileset["tilecount"], tile_width=raw_tileset["tilewidth"], diff --git a/tests/test_data/map_tests/embedded_tileset/expected.py b/tests/test_data/map_tests/embedded_tileset/expected.py index ebaaddc..c64d2fb 100644 --- a/tests/test_data/map_tests/embedded_tileset/expected.py +++ b/tests/test_data/map_tests/embedded_tileset/expected.py @@ -14,7 +14,7 @@ EXPECTED = tiled_map.Map( tile_size=common_types.Size(32, 32), version=1.4, tilesets={ - 1: tileset.TileSet( + 1: tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_width=265, diff --git a/tests/test_data/map_tests/hexagonal/expected.py b/tests/test_data/map_tests/hexagonal/expected.py index 3bf032e..05a7f13 100644 --- a/tests/test_data/map_tests/hexagonal/expected.py +++ b/tests/test_data/map_tests/hexagonal/expected.py @@ -127,7 +127,7 @@ EXPECTED = tiled_map.Map( tile_size=common_types.Size(14, 12), version=1.4, tilesets={ - 1: tileset.TileSet( + 1: tileset.Tileset( columns=5, image=Path("../../images/hexmini.png"), image_width=106, diff --git a/tests/test_data/map_tests/no_background_color/expected.py b/tests/test_data/map_tests/no_background_color/expected.py index 1df8bc2..831356c 100644 --- a/tests/test_data/map_tests/no_background_color/expected.py +++ b/tests/test_data/map_tests/no_background_color/expected.py @@ -14,7 +14,7 @@ EXPECTED = tiled_map.Map( tile_size=common_types.Size(32, 32), version=1.4, tilesets={ - 1: tileset.TileSet( + 1: tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_width=265, diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py index bd7a222..febd8fa 100644 --- a/tests/test_data/map_tests/no_layers/expected.py +++ b/tests/test_data/map_tests/no_layers/expected.py @@ -15,7 +15,7 @@ EXPECTED = tiled_map.Map( version=1.4, background_color=common_types.Color("#ff0004"), tilesets={ - 1: tileset.TileSet( + 1: tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_width=265, diff --git a/tests/test_data/tilesets/image/expected.py b/tests/test_data/tilesets/image/expected.py index 29b1cfc..62577e5 100644 --- a/tests/test_data/tilesets/image/expected.py +++ b/tests/test_data/tilesets/image/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import tileset -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index 23b0cee..389681a 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_grid/expected.py b/tests/test_data/tilesets/image_grid/expected.py index 948bc13..1d58174 100644 --- a/tests/test_data/tilesets/image_grid/expected.py +++ b/tests/test_data/tilesets/image_grid/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import tileset -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index ab6aa5a..a329942 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_tile_offset/expected.py b/tests/test_data/tilesets/image_tile_offset/expected.py index 2ac339c..97e2777 100644 --- a/tests/test_data/tilesets/image_tile_offset/expected.py +++ b/tests/test_data/tilesets/image_tile_offset/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color, OrderedPair -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index 56a45ea..7d69721 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -3,7 +3,7 @@ from pathlib import Path from pytiled_parser import tileset from pytiled_parser.common_types import Color -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, image=Path("../../images/tmw_desert_spacing.png"), image_height=199, diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py index 54625d2..c6b354e 100644 --- a/tests/test_data/tilesets/individual_images/expected.py +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, layer, tiled_object, tileset -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=0, margin=0, spacing=0, diff --git a/tests/test_data/tilesets/terrain/expected.py b/tests/test_data/tilesets/terrain/expected.py index 89051ae..88db165 100644 --- a/tests/test_data/tilesets/terrain/expected.py +++ b/tests/test_data/tilesets/terrain/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, layer, tileset -EXPECTED = tileset.TileSet( +EXPECTED = tileset.Tileset( columns=8, margin=1, spacing=1, From 71c7390c00bf49396911b5dc5631167debb75eea Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Wed, 19 Aug 2020 23:12:26 -0400 Subject: [PATCH 184/198] chore(tileset): Removed FIXME for completed task --- pytiled_parser/tileset.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index 9fc3104..eb506f5 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -190,8 +190,6 @@ class RawTerrain(TypedDict): class RawTile(TypedDict): """ The keys and their types that appear in a Tile JSON Object.""" - # FIXME: Implement objectgroup, can't be done until TileLayer's are implemented - animation: List[RawFrame] id: int image: str From 2bcb1caeeabffcdd15591565a43303fc19b54cc9 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:25:17 -0400 Subject: [PATCH 185/198] docs(README): update readme --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f28d626..74e3a0a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ # PyTiled Parser -PyTiled Parser is a Python Library for parsing -[Tiled Map Editor](https://www.mapeditor.org/) (`.tmx`) files used to generate -maps and levels for 2D top-down or side-scrolling games. +PyTiled Parser is a Python Library for parsing JSON formatted +[Tiled Map Editor](https://www.mapeditor.org/) maps and tilesets to be used as maps and levels for 2D top-down (orthogonal, hexogonal, or isometric) or side-scrolling games. PyTiled Parser is not tied to any particular graphics library, and can be used with [Arcade](http://arcade.academy), @@ -10,7 +9,7 @@ with [Arcade](http://arcade.academy), [Pygame](https://www.pygame.org/news), etc. * Documentation available at: https://pytiled-parser.readthedocs.io/ -* GitHub project at: https://github.com/pvcraven/pytiled_parser +* GitHub project at: https://github.com/Beefy-Swain/pytiled_parser * PiPy: https://pypi.org/project/pytiled-parser/ The [Arcade](http://arcade.academy) library has @@ -19,4 +18,10 @@ integrate PyTiled with that 2D libary, and [example code](http://arcade.academy/examples/index.html#tmx-files-tiled-map-editor) showing its use. Original module by [Beefy-Swain](https://github.com/Beefy-Swain). -Contributions from [pvcraven](https://github.com/pvcraven). +Significant contributions from [pvcraven](https://github.com/pvcraven) and [Cleptomania](https://github.com/Cleptomania). + +## Developement +To develop pytiled parser, clone the repo, create a `venv` using a supported Python version, and activate it. Then install the package as well as all testing dependencies with the command `python -m pip install -e ".[tests]"`. + +### Testing +Run `pytest --cov=pytiled_parser` to run the test harness and report coverage. From 2cfe2e9a467f727f536e286f3d7a63d429a61a0f Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:29:36 -0400 Subject: [PATCH 186/198] chore: switch to using module-define version number https://stackoverflow.com/a/16084844/1342874 --- pytiled_parser/version.py | 3 +++ setup.cfg | 1 - setup.py | 4 +++- 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 pytiled_parser/version.py diff --git a/pytiled_parser/version.py b/pytiled_parser/version.py new file mode 100644 index 0000000..6f9d281 --- /dev/null +++ b/pytiled_parser/version.py @@ -0,0 +1,3 @@ +"""pytiled_parser version""" + +__version__ = "1.0.0" diff --git a/setup.cfg b/setup.cfg index 6c87d5f..878d5e9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,7 +1,6 @@ [metadata] name = pytiled_parser description = PongWall Server Prototype -version = 0.9.1 author = Benjamin Kirkbride author-email = BenjaminKirkbride@gmail.com license = MIT diff --git a/setup.py b/setup.py index 0496ea4..4414b8b 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ # pylint: disable-all +# type: ignore from setuptools import setup -setup() +exec(open("yourpackage/version.py").read()) +setup(version=__version__) From d101783f283364715c98d4e8d64fed02eb2b346c Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:29:59 -0400 Subject: [PATCH 187/198] chore(setup.cfg): update --- setup.cfg | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 878d5e9..89a2ebb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,8 +1,6 @@ [metadata] name = pytiled_parser -description = PongWall Server Prototype -author = Benjamin Kirkbride -author-email = BenjaminKirkbride@gmail.com +description = A library for parsing JSON formatted Tiled Map Editor maps and tilesets. license = MIT license-file = LICENSE url = https://github.com/Beefy-Swain/pytiled_parser From c95b2bd8d3c1ee0b6252aad12a9479f9cfd809e6 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:32:25 -0400 Subject: [PATCH 188/198] docs(pytiled_parser): update description --- README.md | 2 +- pytiled_parser/__init__.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 74e3a0a..9f459c2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PyTiled Parser PyTiled Parser is a Python Library for parsing JSON formatted -[Tiled Map Editor](https://www.mapeditor.org/) maps and tilesets to be used as maps and levels for 2D top-down (orthogonal, hexogonal, or isometric) or side-scrolling games. +[Tiled Map Editor](https://www.mapeditor.org/) maps and tilesets to be used as maps and levels for 2D top-down (orthogonal, hexogonal, or isometric) or side-scrolling games in a strictly typed fashion. PyTiled Parser is not tied to any particular graphics library, and can be used with [Arcade](http://arcade.academy), diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 3ce0b53..3620319 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -1,4 +1,13 @@ -"""Parse Tiled Maps and Tilesets""" +"""Parse Tiled Maps and Tilesets + +See: https://www.mapeditor.org/ + +This library is for parsing JSON formatted Tiled Map Editormaps and tilesets to be + used as maps and levels for 2D top-down (orthogonal, hexogonal, or isometric) + or side-scrolling games in a strictly typed fashion. + +PyTiled Parser is not tied to any particular graphics library or game engine. +""" # pylint: disable=too-few-public-methods @@ -7,3 +16,4 @@ from .layer import Layer from .properties import Properties from .tiled_map import Map from .tileset import Tileset +from .version import __version__ From 2b5799fa8e1e6437744ec3ba129cadf02c874dd8 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:33:05 -0400 Subject: [PATCH 189/198] docs(common_types): removed redundant "multiple" --- pytiled_parser/common_types.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index 924685b..c560bdb 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -1,4 +1,4 @@ -"""Module containing types that are common to multiple other modules.""" +"""Module containing types that are common to other modules.""" # pylint: disable=too-few-public-methods From 0de74fc9eb78714ee5f1f66dd1ab5dfa9836faeb Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:33:57 -0400 Subject: [PATCH 190/198] docs(common_types.size): clarify unit --- pytiled_parser/common_types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index c560bdb..c26c5a1 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -18,8 +18,8 @@ class Size(NamedTuple): """Size NamedTuple. Attributes: - width: The width of the object. - height: The height of the object. + width: The width of the object in pixels. + height: The height of the object in pixels. """ width: float From c98f16dcefeb281f8f9be05d9ef36b46c3b3a2c5 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 18:56:26 -0400 Subject: [PATCH 191/198] docs(layer): add module docstring --- pytiled_parser/layer.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index fcf057e..16eaf4d 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -1,3 +1,11 @@ +"""This module handles parsing all types of layers. + +See: + - https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer + - https://doc.mapeditor.org/en/stable/manual/layers/ + - https://doc.mapeditor.org/en/stable/manual/editing-tile-layers/ +""" + # pylint: disable=too-few-public-methods import base64 From d6bdf7b68462b53c97604e1e7003c52355c02626 Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Thu, 20 Aug 2020 19:32:53 -0400 Subject: [PATCH 192/198] docs(layer): update docstrings --- pytiled_parser/layer.py | 83 ++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 16eaf4d..aca7377 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -25,25 +25,21 @@ from .common_types import Color, OrderedPair, Size @attr.s(auto_attribs=True, kw_only=True) class Layer: - # FIXME:this docstring appears to be innacurate """Class that all layers inherit from. - Args: - id: Unique ID of the layer. Each layer that added to a map gets a unique id. - Even if a layer is deleted, no layer ever gets the same ID. + See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer + + Attributes: name: The name of the layer object. - tiled_objects: List of tiled_objects in the layer. - offset: Rendering offset of the layer object in pixels. opacity: Decimal value between 0 and 1 to determine opacity. 1 is completely opaque, 0 is completely transparent. + visible: If the layer is visible in the Tiled Editor. (Do not use for games) + coordinates: Where layer content starts in tiles. (For infinite maps) + id: Unique ID of the layer. Each layer that added to a map gets a unique id. + Even if a layer is deleted, no layer ever gets the same ID. + size: Ordered pair of size of map in tiles. + offset: Rendering offset of the layer object in pixels. properties: Properties for the layer. - color: The color used to display the objects in this group. - draworder: Whether the objects are drawn according to the order of the object - elements in the object group element ('manual'), or sorted by their - y-coordinate ('topdown'). Defaults to 'topdown'. - See: - https://doc.mapeditor.org/en/stable/manual/objects/#changing-stacking-order - for more info. """ name: str @@ -65,7 +61,7 @@ TileLayerGrid = List[List[int]] class Chunk: """Chunk object for infinite maps. - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#chunk + See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#chunk Attributes: coordinates: Location of chunk in tiles. @@ -78,26 +74,26 @@ class Chunk: data: List[int] -LayerData = Union[TileLayerGrid, List[Chunk]] # The tile data for one layer. # # Either a 2 dimensional array of integers representing the global tile IDs # for a TileLayerGrid, or a list of chunks for an infinite map layer. +LayerData = Union[TileLayerGrid, List[Chunk]] @attr.s(auto_attribs=True, kw_only=True) class TileLayer(Layer): - # FIXME:this docstring appears to be innacurate """Tile map layer containing tiles. - See: https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer + See: + https://doc.mapeditor.org/en/stable/reference/json-map-format/#tile-layer-example - Args: - size: The width of the layer in tiles. The same as the map width unless map is - infitite. + Attributes: + chunks: list of chunks (infinite maps) data: Either an 2 dimensional array of integers representing the global tile IDs for the map layer, or a list of chunks for an infinite map. """ + chunks: Optional[List[Chunk]] = None data: Optional[List[int]] = None @@ -108,11 +104,12 @@ class ObjectLayer(Layer): The object group is in fact a map layer, and is hence called "object layer" in Tiled. - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#objectgroup - Args: + + See: + https://doc.mapeditor.org/en/stable/reference/json-map-format/#object-layer-example + + Attributes: tiled_objects: List of tiled_objects in the layer. - offset: Rendering offset of the layer object in pixels. - color: The color used to display the objects in this group. FIXME: editor only? draworder: Whether the objects are drawn according to the order of the object elements in the object group element ('manual'), or sorted by their y-coordinate ('topdown'). Defaults to 'topdown'. See: @@ -142,20 +139,26 @@ class ImageLayer(Layer): @attr.s(auto_attribs=True, kw_only=True) class LayerGroup(Layer): - """Layer Group. - A LayerGroup can be thought of as a layer that contains layers - (potentially including other LayerGroups). + """A layer that contains layers (potentially including other LayerGroups). + Offset and opacity recursively affect child layers. - See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group + + See: + - https://doc.mapeditor.org/en/stable/reference/json-map-format/#layer + - https://doc.mapeditor.org/en/stable/manual/layers/#group-layers + Attributes: - Layers: Layers in group. + Layers: list of layers contained in the group. """ layers: Optional[List[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 + """ data: Union[List[int], str] height: int @@ -165,7 +168,10 @@ 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 + """ chunks: List[RawChunk] compression: str @@ -193,7 +199,7 @@ class RawLayer(TypedDict): def _decode_tile_layer_data(data: str, compression: str) -> List[int]: - """Decode Base64 Encoded Tile Data. Supports gzip and zlib compression. + """Decode Base64 Encoded tile data. Optionally supports gzip and zlib compression. Args: data: The base64 encoded data @@ -231,12 +237,14 @@ def _decode_tile_layer_data(data: str, compression: str) -> List[int]: def _cast_chunk( - raw_chunk: RawChunk, encoding: str = None, compression: str = None + raw_chunk: RawChunk, encoding: Optional[str] = None, compression: str = None ) -> Chunk: """ Cast the raw_chunk to a Chunk. Args: raw_chunk: RawChunk to be casted to a Chunk + encoding: Encoding type. ("base64" or None) + compression: Either zlib, gzip, or empty. If empty no decompression is done. Returns: Chunk: The Chunk created from the raw_chunk @@ -257,7 +265,10 @@ 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. Args: raw_layer: Raw Tiled object get common attributes from @@ -404,7 +415,9 @@ def _get_caster(type_: str) -> Callable[[RawLayer], Layer]: def cast(raw_layer: RawLayer) -> Layer: - """ Cast the 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. Args: raw_layer: Raw layer to be cast. From 00153d59dcc8682c46e8279da6c6a1d8857d673d Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 20 Aug 2020 21:48:31 -0400 Subject: [PATCH 193/198] refactor(tiled_map): Renamed Map class to TiledMap --- pytiled_parser/__init__.py | 2 +- pytiled_parser/tiled_map.py | 6 +++--- tests/test_data/map_tests/embedded_tileset/expected.py | 2 +- tests/test_data/map_tests/hexagonal/expected.py | 2 +- tests/test_data/map_tests/no_background_color/expected.py | 2 +- tests/test_data/map_tests/no_layers/expected.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 3ce0b53..35d672b 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -5,5 +5,5 @@ from .common_types import OrderedPair, Size from .layer import Layer from .properties import Properties -from .tiled_map import Map +from .tiled_map import TiledMap from .tileset import Tileset diff --git a/pytiled_parser/tiled_map.py b/pytiled_parser/tiled_map.py index 61d9f89..dd907fa 100644 --- a/pytiled_parser/tiled_map.py +++ b/pytiled_parser/tiled_map.py @@ -18,7 +18,7 @@ TilesetDict = Dict[int, Tileset] @attr.s(auto_attribs=True) -class Map: +class TiledMap: """Object for storing a TMX with all associated layers and properties. See: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#map @@ -104,7 +104,7 @@ class _RawTiledMap(TypedDict): width: int -def cast(file: Path) -> Map: +def cast(file: Path) -> TiledMap: """ Cast the raw Tiled map into a pytiled_parser type Args: @@ -137,7 +137,7 @@ def cast(file: Path) -> Map: tilesets[raw_tileset["firstgid"]] = tileset.cast(raw_tileset) # `map` is a built-in function - map_ = Map( + map_ = TiledMap( 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"]), diff --git a/tests/test_data/map_tests/embedded_tileset/expected.py b/tests/test_data/map_tests/embedded_tileset/expected.py index c64d2fb..cbabb9c 100644 --- a/tests/test_data/map_tests/embedded_tileset/expected.py +++ b/tests/test_data/map_tests/embedded_tileset/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = tiled_map.Map( +EXPECTED = tiled_map.TiledMap( infinite=False, layers=[], map_size=common_types.Size(8, 6), diff --git a/tests/test_data/map_tests/hexagonal/expected.py b/tests/test_data/map_tests/hexagonal/expected.py index 05a7f13..27a6741 100644 --- a/tests/test_data/map_tests/hexagonal/expected.py +++ b/tests/test_data/map_tests/hexagonal/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, layer, tiled_map, tileset -EXPECTED = tiled_map.Map( +EXPECTED = tiled_map.TiledMap( hex_side_length=6, stagger_axis="y", stagger_index="odd", diff --git a/tests/test_data/map_tests/no_background_color/expected.py b/tests/test_data/map_tests/no_background_color/expected.py index 831356c..8419d33 100644 --- a/tests/test_data/map_tests/no_background_color/expected.py +++ b/tests/test_data/map_tests/no_background_color/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = tiled_map.Map( +EXPECTED = tiled_map.TiledMap( infinite=False, layers=[], map_size=common_types.Size(8, 6), diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py index febd8fa..67a5287 100644 --- a/tests/test_data/map_tests/no_layers/expected.py +++ b/tests/test_data/map_tests/no_layers/expected.py @@ -2,7 +2,7 @@ from pathlib import Path from pytiled_parser import common_types, tiled_map, tileset -EXPECTED = tiled_map.Map( +EXPECTED = tiled_map.TiledMap( infinite=False, layers=[], map_size=common_types.Size(8, 6), From 075cf9cd7934dd9c1254010afd04148c504d4b1b Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Fri, 21 Aug 2020 21:15:12 -0400 Subject: [PATCH 194/198] fix(version.py): move to root of repo --- pytiled_parser/version.py => version.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pytiled_parser/version.py => version.py (100%) diff --git a/pytiled_parser/version.py b/version.py similarity index 100% rename from pytiled_parser/version.py rename to version.py From ed825c5b710f44dc685303991ed65e6c2f020bdb Mon Sep 17 00:00:00 2001 From: Benjamin Kirkbride Date: Fri, 21 Aug 2020 21:16:14 -0400 Subject: [PATCH 195/198] fix(version.py): actually fix it 4 real --- version.py => pytiled_parser/version.py | 0 setup.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename version.py => pytiled_parser/version.py (100%) diff --git a/version.py b/pytiled_parser/version.py similarity index 100% rename from version.py rename to pytiled_parser/version.py diff --git a/setup.py b/setup.py index 4414b8b..b5ba2af 100644 --- a/setup.py +++ b/setup.py @@ -2,5 +2,5 @@ # type: ignore from setuptools import setup -exec(open("yourpackage/version.py").read()) +exec(open("pytiled_parser/version.py").read()) setup(version=__version__) From 674b4b50c4d943949b0562f0233003f973d5289c Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 21 Feb 2021 00:58:30 -0500 Subject: [PATCH 196/198] 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. --- pytiled_parser/__init__.py | 6 +- pytiled_parser/common_types.py | 16 +- pytiled_parser/layer.py | 77 +++-- pytiled_parser/properties.py | 10 +- pytiled_parser/tiled_map.py | 13 +- pytiled_parser/tiled_object.py | 29 +- pytiled_parser/tileset.py | 34 ++- pytiled_parser/util.py | 29 ++ .../layer_tests/all_layer_types/expected.py | 114 ++++---- tests/test_data/layer_tests/b64/expected.py | 110 +++---- .../layer_tests/b64_gzip/expected.py | 110 +++---- .../layer_tests/b64_zlib/expected.py | 110 +++---- .../layer_tests/infinite_map/expected.py | 164 ++++++----- .../layer_tests/infinite_map_b64/expected.py | 276 ++---------------- .../test_data/map_tests/hexagonal/expected.py | 209 ++++++------- .../test_data/map_tests/no_layers/expected.py | 4 +- tests/test_data/test_parse_color.py | 18 ++ .../image_background_color/expected.py | 2 +- .../tilesets/image_properties/expected.py | 2 +- .../image_transparent_color/expected.py | 2 +- .../tilesets/individual_images/expected.py | 12 +- tests/test_data/tilesets/terrain/expected.py | 84 +++--- tests/test_map.py | 3 +- tests/test_tiled_object.py | 4 +- 24 files changed, 700 insertions(+), 738 deletions(-) create mode 100644 pytiled_parser/util.py create mode 100644 tests/test_data/test_parse_color.py diff --git a/pytiled_parser/__init__.py b/pytiled_parser/__init__.py index 93af445..46255ba 100644 --- a/pytiled_parser/__init__.py +++ b/pytiled_parser/__init__.py @@ -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__ diff --git a/pytiled_parser/common_types.py b/pytiled_parser/common_types.py index c26c5a1..6f53aee 100644 --- a/pytiled_parser/common_types.py +++ b/pytiled_parser/common_types.py @@ -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) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index aca7377..2796de0 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -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. diff --git a/pytiled_parser/properties.py b/pytiled_parser/properties.py index e0c8af0..e9b87b5 100644 --- a/pytiled_parser/properties.py +++ b/pytiled_parser/properties.py @@ -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 diff --git a/pytiled_parser/tiled_map.py b/pytiled_parser/tiled_map.py index dd907fa..05fc90f 100644 --- a/pytiled_parser/tiled_map.py +++ b/pytiled_parser/tiled_map.py @@ -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"] diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index fe092af..f4d95f4 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -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. diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index eb506f5..d6d337f 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -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 diff --git a/pytiled_parser/util.py b/pytiled_parser/util.py new file mode 100644 index 0000000..8db180a --- /dev/null +++ b/pytiled_parser/util.py @@ -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") diff --git a/tests/test_data/layer_tests/all_layer_types/expected.py b/tests/test_data/layer_tests/all_layer_types/expected.py index d3442ff..398a69a 100644 --- a/tests/test_data/layer_tests/all_layer_types/expected.py +++ b/tests/test_data/layer_tests/all_layer_types/expected.py @@ -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", diff --git a/tests/test_data/layer_tests/b64/expected.py b/tests/test_data/layer_tests/b64/expected.py index 9e27994..178924b 100644 --- a/tests/test_data/layer_tests/b64/expected.py +++ b/tests/test_data/layer_tests/b64/expected.py @@ -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), ), ] diff --git a/tests/test_data/layer_tests/b64_gzip/expected.py b/tests/test_data/layer_tests/b64_gzip/expected.py index 9e27994..178924b 100644 --- a/tests/test_data/layer_tests/b64_gzip/expected.py +++ b/tests/test_data/layer_tests/b64_gzip/expected.py @@ -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), ), ] diff --git a/tests/test_data/layer_tests/b64_zlib/expected.py b/tests/test_data/layer_tests/b64_zlib/expected.py index 9e27994..178924b 100644 --- a/tests/test_data/layer_tests/b64_zlib/expected.py +++ b/tests/test_data/layer_tests/b64_zlib/expected.py @@ -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), ), ] diff --git a/tests/test_data/layer_tests/infinite_map/expected.py b/tests/test_data/layer_tests/infinite_map/expected.py index e6db30c..fe93b22 100644 --- a/tests/test_data/layer_tests/infinite_map/expected.py +++ b/tests/test_data/layer_tests/infinite_map/expected.py @@ -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, + ], ], ), ], diff --git a/tests/test_data/layer_tests/infinite_map_b64/expected.py b/tests/test_data/layer_tests/infinite_map_b64/expected.py index 16be791..a907a2d 100644 --- a/tests/test_data/layer_tests/infinite_map_b64/expected.py +++ b/tests/test_data/layer_tests/infinite_map_b64/expected.py @@ -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], ], ) ], diff --git a/tests/test_data/map_tests/hexagonal/expected.py b/tests/test_data/map_tests/hexagonal/expected.py index 27a6741..09c69c5 100644 --- a/tests/test_data/map_tests/hexagonal/expected.py +++ b/tests/test_data/map_tests/hexagonal/expected.py @@ -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, + ], ], ) ], diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py index 67a5287..81152ae 100644 --- a/tests/test_data/map_tests/no_layers/expected.py +++ b/tests/test_data/map_tests/no_layers/expected.py @@ -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, diff --git a/tests/test_data/test_parse_color.py b/tests/test_data/test_parse_color.py new file mode 100644 index 0000000..fca73f4 --- /dev/null +++ b/tests/test_data/test_parse_color.py @@ -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) diff --git a/tests/test_data/tilesets/image_background_color/expected.py b/tests/test_data/tilesets/image_background_color/expected.py index 389681a..3316c75 100644 --- a/tests/test_data/tilesets/image_background_color/expected.py +++ b/tests/test_data/tilesets/image_background_color/expected.py @@ -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", ) diff --git a/tests/test_data/tilesets/image_properties/expected.py b/tests/test_data/tilesets/image_properties/expected.py index a329942..6c34158 100644 --- a/tests/test_data/tilesets/image_properties/expected.py +++ b/tests/test_data/tilesets/image_properties/expected.py @@ -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", diff --git a/tests/test_data/tilesets/image_transparent_color/expected.py b/tests/test_data/tilesets/image_transparent_color/expected.py index 7d69721..758747f 100644 --- a/tests/test_data/tilesets/image_transparent_color/expected.py +++ b/tests/test_data/tilesets/image_transparent_color/expected.py @@ -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", ) diff --git a/tests/test_data/tilesets/individual_images/expected.py b/tests/test_data/tilesets/individual_images/expected.py index c6b354e..63d766f 100644 --- a/tests/test_data/tilesets/individual_images/expected.py +++ b/tests/test_data/tilesets/individual_images/expected.py @@ -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", ), - ], + }, ) diff --git a/tests/test_data/tilesets/terrain/expected.py b/tests/test_data/tilesets/terrain/expected.py index 88db165..c5902eb 100644 --- a/tests/test_data/tilesets/terrain/expected.py +++ b/tests/test_data/tilesets/terrain/expected.py @@ -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 ), ), - ], + }, ) diff --git a/tests/test_map.py b/tests/test_map.py index 50363c1..59f367f 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -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 diff --git a/tests/test_tiled_object.py b/tests/test_tiled_object.py index 258e716..63dfd0c 100644 --- a/tests/test_tiled_object.py +++ b/tests/test_tiled_object.py @@ -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), From cf5f693da32a956f0d70d9849f9a79b8b55c4e03 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 21 Feb 2021 01:00:04 -0500 Subject: [PATCH 197/198] Update to support pep517 for building --- make.bat | 130 ------------------------------------------------- make.sh | 15 ------ pyproject.toml | 3 ++ setup.cfg | 29 ++++++++++- 4 files changed, 30 insertions(+), 147 deletions(-) delete mode 100644 make.bat delete mode 100755 make.sh create mode 100644 pyproject.toml diff --git a/make.bat b/make.bat deleted file mode 100644 index 1f857e6..0000000 --- a/make.bat +++ /dev/null @@ -1,130 +0,0 @@ -@echo off - -rem Build script for Windows - -IF "%~1"=="" GOTO printdoc -IF "%~1"=="full" GOTO makefull -IF "%~1"=="dist" GOTO makedist -IF "%~1"=="test" GOTO test -IF "%~1"=="testcov" GOTO test -IF "%~1"=="fast" GOTO makefast -IF "%~1"=="docs" GOTO makedoc -IF "%~1"=="spelling" GOTO spelling -IF "%~1"=="deploy_pypi" GOTO deploy_pypi -IF "%~1"=="clean" GOTO clean -GOTO printdoc - -:clean - -rmdir /S /Q pytiled_parser.egg-info -rmdir /S /Q build -rmdir /S /Q dist -rmdir /S /Q .pytest_cache -rmdir /S /Q doc\build - -GOTO end - -:test - -pytest -GOTO end - -:testcov - -pytest --cov=arcade -GOTO end - -:makedist - -rem Clean out old builds -del /q dist\*.* -python setup.py clean - -rem Build the python -python setup.py build -python setup.py bdist_wheel - -GOTO end - -:makefull -rem -- This builds the project, installs it, and runs unit tests - -rem Clean out old builds -rmdir /s /q "doc\build" -del /q dist\*.* -python setup.py clean - -rem Build the python -python setup.py build -python setup.py bdist_wheel - -rem Install the packages -pip uninstall -y arcade -for /r %%i in (dist\*) do pip install "%%i" - -rem Build the documentation -sphinx-build -b html doc doc/build/html - -rem Run tests and do code coverage -coverage run --source arcade setup.py test -coverage report --omit=arcade/examples/* -m - -GOTO end - -rem -- Make the documentation - -:makedoc - -rmdir /s /q "doc\build" -sphinx-build -n -b html doc doc/build/html - -GOTO end - -rem -- Make the documentation - -:spelling - -rmdir /s /q "doc\build" -sphinx-build -n -b spelling doc doc/build/html - -GOTO end - - -rem == This does a fast build and install, but no unit tests - -:makefast - -python setup.py build -python setup.py bdist_wheel -pip uninstall -y pytiled_parser -for /r %%i in (dist\*) do pip install "%%i" - -GOTO end - -rem -- Deploy - -:deploy_pypi -rem Do a "pip install twine" and set environment variables before running. - -twine upload -u %PYPI_USER% -p %PYPI_PASSWORD% -r pypi dist/* - -GOTO end - - - -rem -- Print documentation - -:printdoc - -echo make test - Runs the tests -echo make testcov - Runs the tests with coverage -echo make dist - Make the distributables -echo make full - Builds the project, installs it, builds -echo documentation, runs unit tests. -echo make docs Builds the documentation. Documentation -echo will be in doc/build/html -echo make fast - Builds and installs the library WITHOUT unit -echo tests. -echo make deploy_pypi - Deploy to PyPi (if you have environment -echo variables set up correctly.) -:end \ No newline at end of file diff --git a/make.sh b/make.sh deleted file mode 100755 index 5ae6d85..0000000 --- a/make.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -rm -rf doc/build -rm dist/* -python3 setup.py clean -python3 setup.py build -python3 setup.py bdist_wheel -pip3 uninstall -y pytiled_parser -for file in dist/* -do - pip3 install $file -done -# sphinx-build -b html doc doc/build/html -coverage run --source pytiled_parser setup.py test -coverage report -m diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..07de284 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools", "wheel"] +build-backend = "setuptools.build_meta" \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 89a2ebb..50c3441 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,7 +18,9 @@ classifiers = Topic :: Software Development :: Libraries :: Python Modules [options] -python_requires = ~=3.6 +packages = find: +include_package_data = True +python_requires = >=3.6 setup_requires = setuptools >= 40.6 pip >= 10 @@ -26,8 +28,13 @@ install_requires = attrs typing-extensions +[options.packages.find] +include = + pytiled_parser + pytiled_parser.* + [options.extras_require] -tests = +dev = pytest pytest-cov black @@ -35,6 +42,24 @@ tests = mypy isort<5,>=4.2.5 +build = + pep517 + +docs = + sphinx + sphinx_rtd_theme + +[build_sphinx] +source-dir = docs +build-dir = docs/build +all_files = 1 + +[upload-sphinx] +upload-dir = docs/build/html + +[bdist_wheel] +universal=0 + [coverage:run] branch = True From 2a5e475c93a7608a57d4657e5557d8472bbb17dd Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 21 Feb 2021 01:03:19 -0500 Subject: [PATCH 198/198] Initial docs setup --- docs/make.bat | 70 ++++++++++++++-------------- docs/source/10_ladders_and_more.png | Bin 60102 -> 0 bytes docs/source/api.rst | 68 ++++++++++++++++++++------- docs/source/conf.py | 50 +++++++++----------- docs/source/index.rst | 26 ++--------- 5 files changed, 115 insertions(+), 99 deletions(-) delete mode 100644 docs/source/10_ladders_and_more.png diff --git a/docs/make.bat b/docs/make.bat index 9534b01..6247f7e 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -1,35 +1,35 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -if "%1" == "" goto help - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/10_ladders_and_more.png b/docs/source/10_ladders_and_more.png deleted file mode 100644 index 115e0c45e69c38deaba4030cceec13e6a318a86e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60102 zcmcG#XIPWjw>OOASjL8kf`W>of^_K}MrqP(=tV&Yy+ddr%pe^^=>Y-*NJ}U}C_-q8 zfV3bb)BsWgp#%t_1d==f=bZC?IM@GrK0I$OO0w>qeeb>MZ>_!V7(E@etC!d=F)%P( zRez~$z`$^BhJoQM?c#5AioS+=8U5cMo-fUO7#LWdocx|qH+Z~7CtmPX*H*c(aPiuW z+tNC$8N#O|6;t2me!h+#-VCJ`eJ|;xE53A+vb~R;x09!@lZQJ4^B)f%(dm~?=t>@* zf!*&Eup6cCN4KL%kX5+iDW&G6M?wUANu zM&)IVK(c{k)^yrMU*ehHeisZosu-iu2IP<>adDS_ws`&3$k37-CS&f0sIJyIdvURH z=MCP%qnXb5lh^I22b_@OE{NQw(=URYAN40AwJjm|+ON;LLiu-2--T5@%sg}Y?l${> zle}oF1Jn>KU6LoS05(do;*pPk|F4hnR|l`0zH1x5{vSx%<41-xVx=){ez^8*>#&FX z7`1BvbnV#t^t)l)0}A=j)&t)S8(J~qLTE9BGN8l!?{u!JO3eS>Vcl-5uXG2`$44ul z+UUH!Pr5&IMjM;y1b@XimHvm+$L=@k`fYUS`JKFY4d;CP~Sy29oiiwbKKqRJDoUyye{lH zVG=EBO=zW2J({Rlw53X_cU0mYeeUDVwbn!G5kWEjkGqczy!ZrB*$JT$F3&Zm5A+eD zUhBJ}NMKHuyie%-xD!Y9bX4$uR8ajG#CMee**IIs(M;`>^`MUTeYgL$XXBQmX#zF9 zmE1cUK#{DEOIB^@Lr?UFOT83ZNC)q!NRXF24vciYMDQtD8L%7~KX>v(rHL_~zr8p97?YpXYyc)c-Ot{f=dbhB9>+jKW z>z1nboAR96eI@prS0U9ha>P~V8Fpg;;Lu!Jl(;_0t+;AUIReL1=Lxh~587%(J#|Hm zhQDyMV%xa8t;T87N|+n7Zuyj0fBtk<-NFQ42cJvCi{5tvw<3!YY}{M)9g5>7EmyN5 z5LX`)%-p&s57$MxbHNXLU4l7i9kbNtvBhQ^OS!g@(+L=^&F3_WCUT{JxZvT~qd36M zY5~)IC*C3_-iozc(KJh|f*X{@RyS4|*E!%?s6CbPKK?}*Yj7{{Wi#OgY$ynh9R}x(w`T=AOc0exu7BU_%=$92B*t|0V5PaBNnX zxaNG9Z#Kz-)U1wV2cMsH;rS((f@*14pjbovUH(j-T%O?8L3RpTX#JJ0sjkosjN$Ad zE1$3p{@PJ{K0m?;z+)_IER^llN=f9R?bDVDJs=C;?sv7)nN_{?P?$i?QlvB|h&qKH zFUxww=O=O;$4qq8+c4j`cjyAy2~UU`9r$FXc9hq-yL+;Q zEz=>&?fo|otF?i{N~AxpYL~B-cT;0JR|!U;tM>Z( z%7M!)Tx&KO+lXm3$bJ;-Oc0@;!^5w5h>`kc_{pT=!L;O3vm%8txV4YY>6UG@3uwBX z60X>Au;)T(CV5DB1UJxNHo-^p8&THB6vYt3nPA;b@Eb5&dgv~si8Pa?*h0A`M5S`H z@DPp%i&lVZiRVsM8(=UI8XsJJePX1mrX8jowf108D}#}gJGQ1+scW5?jqQ+M7@{BB##rtR<+y*QU(tbf0bRUT)q- zw>VHXTfu79N6oV>M{nj>AxHbx$spzC%lz9R5WH8a9AsF|IWR5A6lv&D70?+ z=gFcNewK`5yLP`1LBo|r+1V0Q5z~SNw^X3Ex9qavCPMcR*7Cs0=2x`gv3c4dc?f|s z79$nn)z{V6-9?9rdXbW~H>MZpLd8cU

qV9zO7~*`L?kw^`f$b94Z8r(tVUB5L{c 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 - -.. _Tiled Map Editor: https://www.mapeditor.org/ -.. _Arcade: http://arcade.academy -.. _Pyglet: https://pyglet.readthedocs.io/en/pyglet-1.3-maintenance/ -.. _Pygame: https://www.pygame.org/news - For More Info ------------- -* `PyTiled Parser on GitHub `_ -* `PyTiled Parser on PyPi `_ +* `PyTiled Parser on Github `_ +* `PyTiled Parser on PyPi `_ \ No newline at end of file