diff --git a/pytiled_parser/tiled_map.py b/pytiled_parser/tiled_map.py index 05fc90f3..3ef206ce 100644 --- a/pytiled_parser/tiled_map.py +++ b/pytiled_parser/tiled_map.py @@ -129,9 +129,10 @@ def parse_map(file: Path) -> TiledMap: 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: + 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) + json.load(raw_tileset_file), external_path=tileset_path.parent ) else: # Is an embedded Tileset diff --git a/pytiled_parser/tileset.py b/pytiled_parser/tileset.py index d6d337f8..516d4c69 100644 --- a/pytiled_parser/tileset.py +++ b/pytiled_parser/tileset.py @@ -287,7 +287,7 @@ def _cast_terrain(raw_terrain: RawTerrain) -> Terrain: ) -def _cast_tile(raw_tile: RawTile) -> Tile: +def _cast_tile(raw_tile: RawTile, external_path: Optional[Path] = None) -> Tile: """Cast the raw_tile to a Tile object. Args: @@ -312,7 +312,10 @@ def _cast_tile(raw_tile: RawTile) -> Tile: tile.properties = properties_.cast(raw_tile["properties"]) if raw_tile.get("image") is not None: - tile.image = Path(raw_tile["image"]) + if external_path: + tile.image = Path(external_path / raw_tile["image"]).absolute().resolve() + else: + tile.image = Path(raw_tile["image"]) if raw_tile.get("imagewidth") is not None: tile.image_width = raw_tile["imagewidth"] @@ -353,7 +356,7 @@ def _cast_grid(raw_grid: RawGrid) -> Grid: ) -def cast(raw_tileset: RawTileSet) -> Tileset: +def cast(raw_tileset: RawTileSet, external_path: Optional[Path] = None) -> Tileset: """Cast the raw tileset into a pytiled_parser type Args: @@ -383,7 +386,12 @@ def cast(raw_tileset: RawTileSet) -> Tileset: tileset.tiled_version = raw_tileset["tiledversion"] if raw_tileset.get("image") is not None: - tileset.image = Path(raw_tileset["image"]) + if external_path: + tileset.image = ( + Path(external_path / raw_tileset["image"]).absolute().resolve() + ) + else: + tileset.image = Path(raw_tileset["image"]) if raw_tileset.get("imagewidth") is not None: tileset.image_width = raw_tileset["imagewidth"] @@ -418,7 +426,7 @@ def cast(raw_tileset: RawTileSet) -> Tileset: if raw_tileset.get("tiles") is not None: tiles = {} for raw_tile in raw_tileset["tiles"]: - tiles[raw_tile["id"]] = _cast_tile(raw_tile) + tiles[raw_tile["id"]] = _cast_tile(raw_tile, external_path=external_path) tileset.tiles = tiles return tileset diff --git a/tests/test_data/map_tests/external_tileset_dif_dir/expected.py b/tests/test_data/map_tests/external_tileset_dif_dir/expected.py new file mode 100644 index 00000000..98f15a3f --- /dev/null +++ b/tests/test_data/map_tests/external_tileset_dif_dir/expected.py @@ -0,0 +1,182 @@ +from pathlib import Path + +from pytiled_parser import common_types, layer, tiled_map, tiled_object, tileset + +EXPECTED = tiled_map.TiledMap( + infinite=False, + map_size=common_types.Size(8, 6), + next_layer_id=3, + next_object_id=1, + orientation="orthogonal", + render_order="right-down", + tiled_version="1.5.0", + tile_size=common_types.Size(32, 32), + version=1.5, + background_color=common_types.Color(255, 0, 4, 255), + layers=[ + layer.TileLayer( + name="Layer 1", + opacity=1, + visible=True, + id=2, + size=common_types.Size(8, 6), + data=[ + [4, 3, 2, 1, 0, 0, 0, 0], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + ], + ), + ], + tilesets={ + 1: 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", + grid=tileset.Grid(orientation="orthogonal", width=1, height=1), + tiles={ + 0: 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(Path(__file__).parent / "../../images/tile_01.png") + .absolute() + .resolve(), + image_height=32, + image_width=32, + properties={"float property": 2.2}, + type="tile", + ), + 1: tileset.Tile( + id=1, + image=Path(Path(__file__).parent / "../../images/tile_02.png") + .absolute() + .resolve(), + image_height=32, + image_width=32, + 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, + 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", + ), + 2: tileset.Tile( + id=2, + image=Path(Path(__file__).parent / "../../images/tile_03.png") + .absolute() + .resolve(), + image_height=32, + image_width=32, + properties={"bool property": True}, + type="tile", + ), + 3: tileset.Tile( + id=3, + image=Path(Path(__file__).parent / "../../images/tile_04.png") + .absolute() + .resolve(), + image_height=32, + image_width=32, + type="tile", + ), + }, + ) + }, + properties={ + "bool property - true": True, + "color property": common_types.Color(255, 73, 252, 255), + "file property": Path("../../../../../../var/log/syslog"), + "float property": 1.23456789, + "int property": 13, + "string property": "Hello, World!!", + }, +) diff --git a/tests/test_data/map_tests/external_tileset_dif_dir/map.json b/tests/test_data/map_tests/external_tileset_dif_dir/map.json new file mode 100644 index 00000000..3a4be3c8 --- /dev/null +++ b/tests/test_data/map_tests/external_tileset_dif_dir/map.json @@ -0,0 +1,66 @@ +{ "backgroundcolor":"#ff0004", + "compressionlevel":0, + "height":6, + "infinite":false, + "layers":[ + { + "compression":"zlib", + "data":"eAFjYWBgYAZiJiBmBOKhBgAIGAAL", + "encoding":"base64", + "height":6, + "id":2, + "name":"Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":8, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":1, + "orientation":"orthogonal", + "properties":[ + { + "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.5.0", + "tileheight":32, + "tilesets":[ + { + "firstgid":1, + "source":"tileset\/tileset.json" + }], + "tilewidth":32, + "type":"map", + "version":1.5, + "width":8 +} \ No newline at end of file diff --git a/tests/test_data/map_tests/external_tileset_dif_dir/tileset/tileset.json b/tests/test_data/map_tests/external_tileset_dif_dir/tileset/tileset.json new file mode 100644 index 00000000..323dca41 --- /dev/null +++ b/tests/test_data/map_tests/external_tileset_dif_dir/tileset/tileset.json @@ -0,0 +1,124 @@ +{ "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, + "type":"tile" + }], + "tilewidth":32, + "type":"tileset", + "version":1.2 + } + \ No newline at end of file diff --git a/tests/test_data/map_tests/hexagonal/expected.py b/tests/test_data/map_tests/hexagonal/expected.py index 09c69c50..38fdcb9b 100644 --- a/tests/test_data/map_tests/hexagonal/expected.py +++ b/tests/test_data/map_tests/hexagonal/expected.py @@ -138,7 +138,9 @@ tilesets={ 1: tileset.Tileset( columns=5, - image=Path("../../images/hexmini.png"), + image=Path(Path(__file__).parent / "../../images/hexmini.png") + .absolute() + .resolve(), image_width=106, image_height=72, margin=0, 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 8419d33a..4c34f58a 100644 --- a/tests/test_data/map_tests/no_background_color/expected.py +++ b/tests/test_data/map_tests/no_background_color/expected.py @@ -16,7 +16,9 @@ tilesets={ 1: tileset.Tileset( columns=8, - image=Path("../../images/tmw_desert_spacing.png"), + image=Path(Path(__file__).parent / "../../images/tmw_desert_spacing.png") + .absolute() + .resolve(), image_width=265, image_height=199, margin=1, diff --git a/tests/test_data/map_tests/no_layers/expected.py b/tests/test_data/map_tests/no_layers/expected.py index 81152ae3..1324cab3 100644 --- a/tests/test_data/map_tests/no_layers/expected.py +++ b/tests/test_data/map_tests/no_layers/expected.py @@ -17,7 +17,9 @@ tilesets={ 1: tileset.Tileset( columns=8, - image=Path("../../images/tmw_desert_spacing.png"), + image=Path(Path(__file__).parent / "../../images/tmw_desert_spacing.png") + .absolute() + .resolve(), image_width=265, image_height=199, margin=1, diff --git a/tests/test_map.py b/tests/test_map.py index 59f367f1..2d16edb9 100644 --- a/tests/test_map.py +++ b/tests/test_map.py @@ -12,6 +12,7 @@ MAP_TESTS = TEST_DATA / "map_tests" ALL_MAP_TESTS = [ + MAP_TESTS / "external_tileset_dif_dir", MAP_TESTS / "no_layers", MAP_TESTS / "no_background_color", MAP_TESTS / "hexagonal",