mirror of
https://github.com/OMGeeky/pytiled_parser.git
synced 2025-12-26 17:02:28 +01:00
re-doing everything as a caster instead of as a parser
This commit is contained in:
21
mypy.ini
21
mypy.ini
@@ -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
|
||||
@@ -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
|
||||
|
||||
38
pytiled_parser/common_types.py
Normal file
38
pytiled_parser/common_types.py
Normal file
@@ -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]
|
||||
85
pytiled_parser/layer.py
Normal file
85
pytiled_parser/layer.py
Normal file
@@ -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
|
||||
75
pytiled_parser/map.py
Normal file
75
pytiled_parser/map.py
Normal file
@@ -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
|
||||
12
pytiled_parser/properties.py
Normal file
12
pytiled_parser/properties.py
Normal file
@@ -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]
|
||||
8
pytiled_parser/template.py
Normal file
8
pytiled_parser/template.py
Normal file
@@ -0,0 +1,8 @@
|
||||
# pylint: disable=too-few-public-methods
|
||||
|
||||
import attr
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class Template:
|
||||
"""FIXME TODO"""
|
||||
231
pytiled_parser/tiled_object.py
Normal file
231
pytiled_parser/tiled_object.py
Normal file
@@ -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
|
||||
175
pytiled_parser/tileset.py
Normal file
175
pytiled_parser/tileset.py
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
552
tests/test_data/simple_objects.json
Normal file
552
tests/test_data/simple_objects.json
Normal file
@@ -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
|
||||
}
|
||||
80
tests/test_data/test_map_simple_offset.json
Normal file
80
tests/test_data/test_map_simple_offset.json
Normal file
@@ -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
|
||||
}
|
||||
82
tests/test_tiled_object.py
Normal file
82
tests/test_tiled_object.py
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user