From d3fe310d7ff75f64d3007d5337d7595c30fa9d6b Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Tue, 2 Jun 2020 20:45:33 -0400 Subject: [PATCH 1/3] 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 f658e763ebfb99f972ecfdd20c448530ea58447f Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 20:15:07 -0400 Subject: [PATCH 2/3] 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 e9999ad9fe5cc6e0a22553418161245f04655ca1 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Thu, 4 Jun 2020 20:44:53 -0400 Subject: [PATCH 3/3] 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: