mirror of
https://github.com/OMGeeky/pytiled_parser.git
synced 2025-12-27 14:52:15 +01:00
Fix templates for tile objects. See #41
This commit is contained in:
@@ -11,10 +11,9 @@ See:
|
||||
import base64
|
||||
import gzip
|
||||
import importlib.util
|
||||
import sys
|
||||
import zlib
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, List, Optional, Union
|
||||
from typing import Any, List, Optional, Union
|
||||
from typing import cast as type_cast
|
||||
|
||||
import attr
|
||||
@@ -284,7 +283,9 @@ def _decode_tile_layer_data(
|
||||
|
||||
|
||||
def _cast_chunk(
|
||||
raw_chunk: RawChunk, encoding: Optional[str] = None, compression: str = None
|
||||
raw_chunk: RawChunk,
|
||||
encoding: Optional[str] = None,
|
||||
compression: Optional[str] = None,
|
||||
) -> Chunk:
|
||||
"""Cast the raw_chunk to a Chunk.
|
||||
|
||||
@@ -403,7 +404,8 @@ def _cast_tile_layer(raw_layer: RawLayer) -> TileLayer:
|
||||
|
||||
|
||||
def _cast_object_layer(
|
||||
raw_layer: RawLayer, parent_dir: Optional[Path] = None
|
||||
raw_layer: RawLayer,
|
||||
parent_dir: Optional[Path] = None,
|
||||
) -> ObjectLayer:
|
||||
"""Cast the raw_layer to an ObjectLayer.
|
||||
|
||||
@@ -458,46 +460,38 @@ def _cast_group_layer(
|
||||
layers = []
|
||||
|
||||
for layer in raw_layer["layers"]:
|
||||
layers.append(cast(layer, parent_dir))
|
||||
layers.append(cast(layer, parent_dir=parent_dir))
|
||||
|
||||
return LayerGroup(layers=layers, **_get_common_attributes(raw_layer).__dict__)
|
||||
|
||||
|
||||
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,
|
||||
"imagelayer": _cast_image_layer,
|
||||
"group": _cast_group_layer,
|
||||
}
|
||||
return casters[type_]
|
||||
|
||||
|
||||
def cast(raw_layer: RawLayer, parent_dir: Optional[Path] = None) -> Layer:
|
||||
def cast(
|
||||
raw_layer: RawLayer,
|
||||
parent_dir: Optional[Path] = None,
|
||||
) -> Layer:
|
||||
"""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.
|
||||
parent_dir: The parent directory that the map file is in.
|
||||
|
||||
Returns:
|
||||
Layer: a properly typed Layer.
|
||||
"""
|
||||
caster = _get_caster(raw_layer["type"])
|
||||
|
||||
if (
|
||||
caster.__name__ == "_cast_object_layer"
|
||||
or caster.__name__ == "_cast_group_layer"
|
||||
):
|
||||
return caster(raw_layer, parent_dir)
|
||||
else:
|
||||
return caster(raw_layer)
|
||||
Raises:
|
||||
RuntimeError: For an invalid layer type being provided
|
||||
"""
|
||||
type_ = raw_layer["type"]
|
||||
|
||||
if type_ == "objectgroup":
|
||||
return _cast_object_layer(raw_layer, parent_dir)
|
||||
elif type_ == "group":
|
||||
return _cast_group_layer(raw_layer, parent_dir)
|
||||
elif type_ == "imagelayer":
|
||||
return _cast_image_layer(raw_layer)
|
||||
elif type_ == "tilelayer":
|
||||
return _cast_tile_layer(raw_layer)
|
||||
|
||||
raise RuntimeError(f"An invalid layer type of {type_} was supplied")
|
||||
|
||||
@@ -132,12 +132,16 @@ def parse_map(file: Path) -> TiledMap:
|
||||
tileset_path = Path(parent_dir / raw_tileset["source"])
|
||||
with open(tileset_path) as raw_tileset_file:
|
||||
tilesets[raw_tileset["firstgid"]] = tileset.cast(
|
||||
json.load(raw_tileset_file), external_path=tileset_path.parent
|
||||
json.load(raw_tileset_file),
|
||||
raw_tileset["firstgid"],
|
||||
external_path=tileset_path.parent,
|
||||
)
|
||||
else:
|
||||
# Is an embedded Tileset
|
||||
raw_tileset = typing_cast(RawTileSet, raw_tileset)
|
||||
tilesets[raw_tileset["firstgid"]] = tileset.cast(raw_tileset)
|
||||
tilesets[raw_tileset["firstgid"]] = tileset.cast(
|
||||
raw_tileset, raw_tileset["firstgid"]
|
||||
)
|
||||
|
||||
if isinstance(raw_tiled_map["version"], float):
|
||||
version = str(raw_tiled_map["version"])
|
||||
@@ -160,6 +164,37 @@ def parse_map(file: Path) -> TiledMap:
|
||||
version=version,
|
||||
)
|
||||
|
||||
layers = [layer for layer in map_.layers if hasattr(layer, "tiled_objects")]
|
||||
|
||||
for my_layer in layers:
|
||||
for tiled_object in my_layer.tiled_objects: # type: ignore
|
||||
if hasattr(tiled_object, "new_tileset"):
|
||||
if tiled_object.new_tileset:
|
||||
already_loaded = None
|
||||
for val in map_.tilesets.values():
|
||||
if val.name == tiled_object.new_tileset["name"]:
|
||||
already_loaded = val
|
||||
break
|
||||
|
||||
if not already_loaded:
|
||||
highest_firstgid = max(map_.tilesets.keys())
|
||||
last_tileset_count = map_.tilesets[highest_firstgid].tile_count
|
||||
new_firstgid = highest_firstgid + last_tileset_count
|
||||
map_.tilesets[new_firstgid] = tileset.cast(
|
||||
tiled_object.new_tileset,
|
||||
new_firstgid,
|
||||
tiled_object.new_tileset_path,
|
||||
)
|
||||
tiled_object.gid = tiled_object.gid + (new_firstgid - 1)
|
||||
|
||||
else:
|
||||
tiled_object.gid = tiled_object.gid + (
|
||||
already_loaded.firstgid - 1
|
||||
)
|
||||
|
||||
tiled_object.new_tileset = None
|
||||
tiled_object.new_tileset_path = None
|
||||
|
||||
if raw_tiled_map.get("backgroundcolor") is not None:
|
||||
map_.background_color = parse_color(raw_tiled_map["backgroundcolor"])
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# pylint: disable=too-few-public-methods
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Callable, Dict, List, Optional, Union
|
||||
from typing import Any, Callable, Dict, List, Optional, Union
|
||||
|
||||
import attr
|
||||
from typing_extensions import TypedDict
|
||||
@@ -148,6 +148,8 @@ class Tile(TiledObject):
|
||||
"""
|
||||
|
||||
gid: int
|
||||
new_tileset: Optional[Dict[str, Any]] = None
|
||||
new_tileset_path: Optional[Path] = None
|
||||
|
||||
|
||||
class RawTextDict(TypedDict):
|
||||
@@ -257,7 +259,11 @@ def _cast_point(raw_tiled_object: RawTiledObject) -> Point:
|
||||
return Point(**_get_common_attributes(raw_tiled_object).__dict__)
|
||||
|
||||
|
||||
def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile:
|
||||
def _cast_tile(
|
||||
raw_tiled_object: RawTiledObject,
|
||||
new_tileset: Optional[Dict[str, Any]] = None,
|
||||
new_tileset_path: Optional[Path] = None,
|
||||
) -> Tile:
|
||||
"""Cast the raw_tiled_object to a Tile object.
|
||||
|
||||
Args:
|
||||
@@ -268,7 +274,12 @@ def _cast_tile(raw_tiled_object: RawTiledObject) -> Tile:
|
||||
"""
|
||||
gid = raw_tiled_object["gid"]
|
||||
|
||||
return Tile(gid=gid, **_get_common_attributes(raw_tiled_object).__dict__)
|
||||
return Tile(
|
||||
gid=gid,
|
||||
new_tileset=new_tileset,
|
||||
new_tileset_path=new_tileset_path,
|
||||
**_get_common_attributes(raw_tiled_object).__dict__
|
||||
)
|
||||
|
||||
|
||||
def _cast_polygon(raw_tiled_object: RawTiledObject) -> Polygon:
|
||||
@@ -393,16 +404,24 @@ def _get_caster(
|
||||
|
||||
|
||||
def cast(
|
||||
raw_tiled_object: RawTiledObject, parent_dir: Optional[Path] = None
|
||||
raw_tiled_object: RawTiledObject,
|
||||
parent_dir: Optional[Path] = None,
|
||||
) -> TiledObject:
|
||||
"""Cast the raw tiled object into a pytiled_parser type
|
||||
|
||||
Args:
|
||||
raw_tiled_object: Raw Tiled object that is to be cast.
|
||||
parent_dir: The parent directory that the map file is in.
|
||||
|
||||
Returns:
|
||||
TiledObject: a properly typed Tiled object.
|
||||
|
||||
Raises:
|
||||
RuntimeError: When a required parameter was not sent based on a condition.
|
||||
"""
|
||||
new_tileset = None
|
||||
new_tileset_path = None
|
||||
|
||||
if raw_tiled_object.get("template"):
|
||||
if not parent_dir:
|
||||
raise RuntimeError(
|
||||
@@ -410,12 +429,21 @@ def cast(
|
||||
)
|
||||
template_path = Path(parent_dir / raw_tiled_object["template"])
|
||||
with open(template_path) as raw_template_file:
|
||||
loaded_template = json.load(raw_template_file)["object"]
|
||||
template = json.load(raw_template_file)
|
||||
if "tileset" in template:
|
||||
tileset_path = Path(
|
||||
template_path.parent / template["tileset"]["source"]
|
||||
)
|
||||
with open(tileset_path) as raw_tileset_file:
|
||||
new_tileset = json.load(raw_tileset_file)
|
||||
new_tileset_path = tileset_path.parent
|
||||
|
||||
loaded_template = template["object"]
|
||||
for key in loaded_template:
|
||||
if key != "id":
|
||||
raw_tiled_object[key] = loaded_template[key] # type: ignore
|
||||
|
||||
caster = _get_caster(raw_tiled_object)
|
||||
if raw_tiled_object.get("gid"):
|
||||
return _cast_tile(raw_tiled_object, new_tileset, new_tileset_path)
|
||||
|
||||
tiled_object = caster(raw_tiled_object)
|
||||
return tiled_object
|
||||
return _get_caster(raw_tiled_object)(raw_tiled_object)
|
||||
|
||||
@@ -130,6 +130,8 @@ class Tileset:
|
||||
tile_count: int
|
||||
columns: int
|
||||
|
||||
firstgid: int
|
||||
|
||||
type: str = "tileset"
|
||||
|
||||
spacing: int = 0
|
||||
@@ -144,7 +146,6 @@ class Tileset:
|
||||
|
||||
transformations: Optional[Transformations] = None
|
||||
|
||||
firstgid: Optional[int] = None
|
||||
background_color: Optional[Color] = None
|
||||
tile_offset: Optional[OrderedPair] = None
|
||||
transparent_color: Optional[Color] = None
|
||||
@@ -329,11 +330,16 @@ def _cast_grid(raw_grid: RawGrid) -> Grid:
|
||||
)
|
||||
|
||||
|
||||
def cast(raw_tileset: RawTileSet, external_path: Optional[Path] = None) -> Tileset:
|
||||
def cast(
|
||||
raw_tileset: RawTileSet,
|
||||
firstgid: int,
|
||||
external_path: Optional[Path] = None,
|
||||
) -> Tileset:
|
||||
"""Cast the raw tileset into a pytiled_parser type
|
||||
|
||||
Args:
|
||||
raw_tileset: Raw Tileset to be cast.
|
||||
firstgid: GID corresponding the first tile in the set.
|
||||
external_path: The path to the tileset if it is not an embedded one.
|
||||
|
||||
Returns:
|
||||
@@ -348,6 +354,7 @@ def cast(raw_tileset: RawTileSet, external_path: Optional[Path] = None) -> Tiles
|
||||
columns=raw_tileset["columns"],
|
||||
spacing=raw_tileset["spacing"],
|
||||
margin=raw_tileset["margin"],
|
||||
firstgid=firstgid,
|
||||
)
|
||||
|
||||
if raw_tileset.get("version") is not None:
|
||||
@@ -373,9 +380,6 @@ def cast(raw_tileset: RawTileSet, external_path: Optional[Path] = None) -> Tiles
|
||||
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"]
|
||||
|
||||
if raw_tileset.get("backgroundcolor") is not None:
|
||||
tileset.background_color = parse_color(raw_tileset["backgroundcolor"])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user