Skip to content

Commit

Permalink
typehints
Browse files Browse the repository at this point in the history
  • Loading branch information
JaskRendix committed Jan 24, 2024
1 parent b8f6d69 commit a41a47c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 37 deletions.
44 changes: 25 additions & 19 deletions pytmx/pytmx.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from itertools import chain, product
from math import cos, radians, sin
from operator import attrgetter
from typing import DefaultDict, Optional, Union
from typing import Any, Optional, Union
from xml.etree import ElementTree

# for type hinting
Expand Down Expand Up @@ -518,7 +518,9 @@ def __init__(
# only used tiles are actually loaded, so there will be a difference
# between the GIDs in the Tiled map data (tmx) and the data in this
# object and the layers. This dictionary keeps track of that.
self.gidmap: DefaultDict[int, list[tuple[int, TileFlags]]] = defaultdict(list)
self.gidmap: defaultdict[
int, list[tuple[int, Optional[TileFlags]]]
] = defaultdict(list)
# mapping of gid and trans flags to real gids
self.imagemap: dict[tuple[int, TileFlags], tuple[int, TileFlags]] = {}
# mapping of tiledgid to pytmx gid
Expand Down Expand Up @@ -546,7 +548,7 @@ def __init__(
self.custom_types = dict()

# initialize the gid mapping
self.imagemap[(0, TileFlags(0, 0, 0))] = (0, TileFlags(0, 0, 0))
self.imagemap[(0, empty_flags)] = (0, empty_flags)

if custom_property_filename:
self.parse_json(json.load(open(custom_property_filename)))
Expand Down Expand Up @@ -655,7 +657,7 @@ def reload_images(self) -> None:
# skip tilesets without a source
if ts.source is None:
continue

assert self.filename
path = os.path.join(os.path.dirname(self.filename), ts.source)
colorkey = getattr(ts, "trans", None)
loader = self.image_loader(path, colorkey, tileset=ts)
Expand Down Expand Up @@ -699,7 +701,7 @@ def reload_images(self) -> None:
# load image layer images
for layer in (i for i in self.layers if isinstance(i, TiledImageLayer)):
source = getattr(layer, "source", None)
if source:
if source and self.filename:
colorkey = getattr(layer, "trans", None)
real_gid = len(self.images)
gid = self.register_gid(real_gid)
Expand All @@ -714,7 +716,7 @@ def reload_images(self) -> None:
# was loaded from the tileset
for real_gid, props in self.tile_properties.items():
source = props.get("source", None)
if source:
if source and self.filename:
colorkey = props.get("trans", None)
path = os.path.join(os.path.dirname(self.filename), source)
loader = self.image_loader(path, colorkey)
Expand Down Expand Up @@ -1109,7 +1111,7 @@ def register_gid(
"""
if flags is None:
flags = TileFlags(0, 0, 0)
flags = empty_flags

if tiled_gid:
try:
Expand Down Expand Up @@ -1148,7 +1150,9 @@ def register_gid_check_flags(
else:
return self.register_gid(*decode_gid(tiled_gid))

def map_gid(self, tiled_gid: int) -> Optional[list[tuple[int, TileFlags]]]:
def map_gid(
self, tiled_gid: int
) -> Optional[list[tuple[int, Optional[TileFlags]]]]:
"""Used to lookup a GID read from a TMX file's data.
Args:
Expand Down Expand Up @@ -1199,8 +1203,8 @@ def __init__(self, parent: TiledMap, node: ElementTree.Element) -> None:

# defaults from the specification
self.firstgid = 0
self.source = None
self.name = None
self.source: Optional[str] = None
self.name: Optional[str] = None
self.tilewidth = 0
self.tileheight = 0
self.spacing = 0
Expand Down Expand Up @@ -1231,7 +1235,7 @@ def parse_xml(self, node: ElementTree.Element) -> TiledTileset:
# if true, then node references an external tileset
source = node.get("source", None)
if source:
if source[-4:].lower() == ".tsx":
if source[-4:].lower() == ".tsx" and self.parent.filename:
# external tilesets don't save this, store it for later
self.firstgid = int(node.get("firstgid", 0))

Expand All @@ -1253,6 +1257,7 @@ def parse_xml(self, node: ElementTree.Element) -> TiledTileset:
logger.error(msg.format(path))
raise Exception(msg.format(path)) from io
else:
assert self.source
msg = "Found external tileset, but cannot handle type: {0}"
logger.error(msg.format(self.source))
raise Exception(msg.format(self.source))
Expand All @@ -1278,18 +1283,18 @@ def parse_xml(self, node: ElementTree.Element) -> TiledTileset:
p["width"] = str(self.tilewidth)
p["height"] = str(self.tileheight)
else:
tile_source = image.get("source")
tile_source = image.get("source", "")
# images are listed as relative to the .tsx file, not the .tmx file:
if source and tile_source:
tile_source = os.path.join(os.path.dirname(source), tile_source)
p["source"] = tile_source
p["trans"] = image.get("trans", None)
p["trans"] = image.get("trans", "")
p["width"] = image.get("width", "0")
p["height"] = image.get("height", "0")

# handle tiles with animations
anim = child.find("animation")
frames = list()
frames: list[AnimationFrame] = []
p["frames"] = frames
if anim is not None:
for frame in anim.findall("frame"):
Expand Down Expand Up @@ -1339,7 +1344,7 @@ def __init__(self, parent: TiledMap, node: ElementTree.Element) -> None:
"""
TiledElement.__init__(self)
self.parent = parent
self.name = None
self.name: Optional[str] = None
self.visible = True
self.parse_xml(node)

Expand Down Expand Up @@ -1372,7 +1377,7 @@ def __init__(self, parent: TiledMap, node: ElementTree.Element) -> None:
self.data: list[list[int]] = []

# defaults from the specification
self.name = None
self.name: Optional[str] = None
self.width = 0
self.height = 0
self.opacity = 1.0
Expand Down Expand Up @@ -1444,6 +1449,7 @@ def parse_xml(self, node: ElementTree.Element) -> TiledTileLayer:
"XML tile elements are no longer supported. Must use base64 or csv map formats."
)

assert data_node.text
temp = [
self.parent.register_gid_check_flags(gid)
for gid in unpack_gids(
Expand Down Expand Up @@ -1535,7 +1541,7 @@ def __init__(
self.parse_xml(node)

@property
def image(self):
def image(self) -> Optional[Any]:
"""Image for the object, if assigned.
Returns:
Expand Down Expand Up @@ -1634,14 +1640,14 @@ def __init__(self, parent: TiledMap, node: ElementTree.Element) -> None:
self.gid = 0

# defaults from the specification
self.name = None
self.name: Optional[str] = None
self.opacity = 1
self.visible = True

self.parse_xml(node)

@property
def image(self):
def image(self) -> Optional[Any]:
"""Image for the object, if assigned.
Returns:
Expand Down
38 changes: 20 additions & 18 deletions pytmx/util_pygame.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
"""
import itertools
import logging
from typing import Optional, Union
from collections.abc import Callable
from typing import Any, Optional, Union

import pytmx
from pytmx.pytmx import ColorLike, PointLike
from pytmx.pytmx import ColorLike, TileFlags

logger = logging.getLogger(__name__)

Expand All @@ -37,8 +38,7 @@


def handle_transformation(
tile: pygame.Surface,
flags: pytmx.TileFlags,
tile: pygame.Surface, flags: pytmx.TileFlags
) -> pygame.Surface:
"""
Transform tile according to the flags and return a new one
Expand Down Expand Up @@ -112,7 +112,9 @@ def smart_convert(
return tile


def pygame_image_loader(filename: str, colorkey: Optional[ColorLike], **kwargs):
def pygame_image_loader(
filename: str, colorkey: Optional[ColorLike], **kwargs: Any
) -> Callable[[Optional[pygame.Rect], Optional[TileFlags]], pygame.Surface]:
"""
pytmx image loader for pygame
Expand All @@ -130,7 +132,9 @@ def pygame_image_loader(filename: str, colorkey: Optional[ColorLike], **kwargs):
pixelalpha = kwargs.get("pixelalpha", True)
image = pygame.image.load(filename)

def load_image(rect=None, flags=None):
def load_image(
rect: Optional[pygame.Rect] = None, flags: Optional[TileFlags] = None
) -> pygame.Surface:
if rect:
try:
tile = image.subsurface(rect)
Expand All @@ -149,11 +153,7 @@ def load_image(rect=None, flags=None):
return load_image


def load_pygame(
filename: str,
*args,
**kwargs,
) -> pytmx.TiledMap:
def load_pygame(filename: str, *args: Any, **kwargs: Any) -> pytmx.TiledMap:
"""Load a TMX file, images, and return a TiledMap class
PYGAME USERS: Use me.
Expand Down Expand Up @@ -208,15 +208,15 @@ def build_rects(
"""
if isinstance(tileset, int):
try:
tileset = tmxmap.tilesets[tileset]
_tileset = tmxmap.tilesets[tileset]
except IndexError:
msg = "Tileset #{0} not found in map {1}."
logger.debug(msg.format(tileset, tmxmap))
raise IndexError

elif isinstance(tileset, str):
try:
tileset = [t for t in tmxmap.tilesets if t.name == tileset].pop()
_tileset = [t for t in tmxmap.tilesets if t.name == tileset].pop()
except IndexError:
msg = 'Tileset "{0}" not found in map {1}.'
logger.debug(msg.format(tileset, tmxmap))
Expand All @@ -230,7 +230,9 @@ def build_rects(
gid = None
if real_gid:
try:
gid, flags = tmxmap.map_gid(real_gid)[0]
_map_gid = tmxmap.map_gid(real_gid)
if _map_gid:
gid, flags = _map_gid[0]
except IndexError:
msg = "GID #{0} not found"
logger.debug(msg.format(real_gid))
Expand All @@ -240,7 +242,7 @@ def build_rects(
layer_data = tmxmap.get_layer_data(layer)
elif isinstance(layer, str):
try:
_layer = [l for l in tmxmap.layers if l.name == layer].pop()
_layer = [l for l in tmxmap.layers if l.name and l.name == layer].pop()
layer_data = _layer.data
except IndexError:
msg = 'Layer "{0}" not found in map {1}.'
Expand All @@ -258,7 +260,7 @@ def build_rects(


def simplify(
all_points: list[PointLike],
all_points: list[tuple[int, int]],
tilewidth: int,
tileheight: int,
) -> list[pygame.Rect]:
Expand Down Expand Up @@ -304,7 +306,7 @@ def simplify(
making a list of rects, one for each tile on the map!
"""

def pick_rect(points, rects) -> None:
def pick_rect(points: list[tuple[int, int]], rects: list[pygame.Rect]) -> None:
ox, oy = sorted([(sum(p), p) for p in points])[0][1]
x = ox
y = oy
Expand Down Expand Up @@ -345,7 +347,7 @@ def pick_rect(points, rects) -> None:
if points:
pick_rect(points, rects)

rect_list = []
rect_list: list[pygame.Rect] = []
while all_points:
pick_rect(all_points, rect_list)

Expand Down

0 comments on commit a41a47c

Please sign in to comment.