From 2395dd32ca0166f1d2bcc5f77a68dd2ce8413860 Mon Sep 17 00:00:00 2001 From: Darren Eberly Date: Sun, 19 Dec 2021 01:43:42 -0500 Subject: [PATCH] More 2.0/tmx parsing work. TMX is nearly done --- pytiled_parser/layer.py | 4 +- pytiled_parser/parsers/tmx/layer.py | 38 ++++++++----- pytiled_parser/parsers/tmx/properties.py | 5 +- pytiled_parser/parsers/tmx/tiled_map.py | 5 +- pytiled_parser/parsers/tmx/tiled_object.py | 63 ++++++++++++++-------- pytiled_parser/parsers/tmx/tileset.py | 29 +++++----- pytiled_parser/tiled_object.py | 7 ++- 7 files changed, 93 insertions(+), 58 deletions(-) diff --git a/pytiled_parser/layer.py b/pytiled_parser/layer.py index 8a3bc9b..a2cf80b 100644 --- a/pytiled_parser/layer.py +++ b/pytiled_parser/layer.py @@ -38,8 +38,8 @@ class Layer: """ name: str - opacity: float - visible: bool + opacity: float = 1 + visible: bool = True coordinates: OrderedPair = OrderedPair(0, 0) parallax_factor: OrderedPair = OrderedPair(1, 1) diff --git a/pytiled_parser/parsers/tmx/layer.py b/pytiled_parser/parsers/tmx/layer.py index f825d0d..3c4f0b1 100644 --- a/pytiled_parser/parsers/tmx/layer.py +++ b/pytiled_parser/parsers/tmx/layer.py @@ -144,12 +144,19 @@ def _parse_common(raw_layer: etree.Element) -> Layer: Returns: Layer: The attributes in common of all layer types """ + if raw_layer.attrib.get("name") is None: + raw_layer.attrib["name"] = "" + common = Layer( name=raw_layer.attrib["name"], - opacity=float(raw_layer.attrib["opacity"]), - visible=bool(int(raw_layer.attrib["visible"])), ) + if raw_layer.attrib.get("opacity") is not None: + common.opacity = float(raw_layer.attrib["opacity"]) + + if raw_layer.attrib.get("visible") is not None: + common.visible = bool(int(raw_layer.attrib["visible"])) + if raw_layer.attrib.get("id") is not None: common.id = int(raw_layer.attrib["id"]) @@ -159,7 +166,7 @@ def _parse_common(raw_layer: etree.Element) -> Layer: ) properties_element = raw_layer.find("./properties") - if properties_element: + if properties_element is not None: common.properties = parse_properties(properties_element) parallax = [1.0, 1.0] @@ -187,13 +194,15 @@ def _parse_tile_layer(raw_layer: etree.Element) -> TileLayer: Returns: TileLayer: The TileLayer created from raw_layer """ + common = _parse_common(raw_layer).__dict__ + del common["size"] tile_layer = TileLayer( size=Size(int(raw_layer.attrib["width"]), int(raw_layer.attrib["height"])), - **_parse_common(raw_layer).__dict__, + **common, ) - data_element = raw_layer.find("./data") - if data_element: + data_element = raw_layer.find("data") + if data_element is not None: encoding = None if data_element.attrib.get("encoding") is not None: encoding = data_element.attrib["encoding"] @@ -202,10 +211,9 @@ def _parse_tile_layer(raw_layer: etree.Element) -> TileLayer: if data_element.attrib.get("compression") is not None: compression = data_element.attrib["compression"] - raw_chunks = data_element.findall("./chunk") - + raw_chunks = data_element.findall("chunk") if not raw_chunks: - if encoding: + if encoding and encoding != "csv": tile_layer.data = _decode_tile_layer_data( data=data_element.text, # type: ignore compression=compression, @@ -213,7 +221,7 @@ def _parse_tile_layer(raw_layer: etree.Element) -> TileLayer: ) else: tile_layer.data = _convert_raw_tile_layer_data( - [int(v.strip()) for v in data_element.text], # type: ignore + [int(v.strip()) for v in data_element.text.split(",")], # type: ignore int(raw_layer.attrib["width"]), ) else: @@ -248,12 +256,16 @@ def _parse_object_layer( for object_ in raw_layer.findall("./object"): objects.append(parse_object(object_, parent_dir)) - return ObjectLayer( + object_layer = ObjectLayer( tiled_objects=objects, - draw_order=raw_layer.attrib["draworder"], **_parse_common(raw_layer).__dict__, ) + if raw_layer.attrib.get("draworder") is not None: + object_layer.draw_order = raw_layer.attrib["draworder"] + + return object_layer + def _parse_image_layer(raw_layer: etree.Element) -> ImageLayer: """Parse the raw_layer to an ImageLayer. @@ -274,6 +286,8 @@ def _parse_image_layer(raw_layer: etree.Element) -> ImageLayer: if image_element.attrib.get("trans") is not None: transparent_color = parse_color(image_element.attrib["trans"]) + common = _parse_common(raw_layer).__dict__ + del common["size"] return ImageLayer( image=source, size=Size(width, height), diff --git a/pytiled_parser/parsers/tmx/properties.py b/pytiled_parser/parsers/tmx/properties.py index b831a17..173463b 100644 --- a/pytiled_parser/parsers/tmx/properties.py +++ b/pytiled_parser/parsers/tmx/properties.py @@ -11,8 +11,9 @@ def parse(raw_properties: etree.Element) -> Properties: final: Properties = {} value: Property - for raw_property in raw_properties.findall("./property"): - type_ = raw_property.attrib["type"] + for raw_property in raw_properties.findall("property"): + + type_ = raw_property.attrib.get("type") value_ = raw_property.attrib["value"] if type_ == "file": value = Path(value_) diff --git a/pytiled_parser/parsers/tmx/tiled_map.py b/pytiled_parser/parsers/tmx/tiled_map.py index 8ecb1f8..c44e916 100644 --- a/pytiled_parser/parsers/tmx/tiled_map.py +++ b/pytiled_parser/parsers/tmx/tiled_map.py @@ -18,6 +18,7 @@ def parse(file: Path) -> TiledMap: Returns: TiledMap: A parsed TiledMap. """ + print(file) with open(file) as map_file: raw_map = etree.parse(map_file).getroot() @@ -71,10 +72,10 @@ def parse(file: Path) -> TiledMap: for my_layer in layers: for tiled_object in my_layer.tiled_objects: if hasattr(tiled_object, "new_tileset"): - if tiled_object.new_tileset: + if tiled_object.new_tileset is not None: already_loaded = None for val in map_.tilesets.values(): - if val.name == tiled_object.new_tileset["name"]: + if val.name == tiled_object.new_tileset.attrib["name"]: already_loaded = val break diff --git a/pytiled_parser/parsers/tmx/tiled_object.py b/pytiled_parser/parsers/tmx/tiled_object.py index 1cf3430..455c2c5 100644 --- a/pytiled_parser/parsers/tmx/tiled_object.py +++ b/pytiled_parser/parsers/tmx/tiled_object.py @@ -32,15 +32,25 @@ def _parse_common(raw_object: etree.Element) -> TiledObject: coordinates=OrderedPair( float(raw_object.attrib["x"]), float(raw_object.attrib["y"]) ), - visible=bool(int(raw_object.attrib["visible"])), - size=Size( - float(raw_object.attrib["width"]), float(raw_object.attrib["height"]) - ), - rotation=float(raw_object.attrib["rotation"]), - name=raw_object.attrib["name"], - type=raw_object.attrib["type"], ) + if raw_object.attrib.get("width") is not None: + common.size = Size( + float(raw_object.attrib["width"]), float(raw_object.attrib["height"]) + ) + + if raw_object.attrib.get("visible") is not None: + common.visible = bool(int(raw_object.attrib["visible"])) + + if raw_object.attrib.get("rotation") is not None: + common.rotation = float(raw_object.attrib["rotation"]) + + if raw_object.attrib.get("name") is not None: + common.name = raw_object.attrib["name"] + + if raw_object.attrib.get("type") is not None: + common.type = raw_object.attrib["type"] + properties_element = raw_object.find("./properties") if properties_element: common.properties = parse_properties(properties_element) @@ -94,9 +104,11 @@ def _parse_polygon(raw_object: etree.Element) -> Polygon: Polygon: The Polygon object created from the raw object """ polygon = [] - for raw_point in raw_object.attrib["points"].split(" "): - point = raw_point.split(",") - polygon.append(OrderedPair(float(point[0]), float(point[1]))) + polygon_element = raw_object.find("./polygon") + if polygon_element is not None: + for raw_point in polygon_element.attrib["points"].split(" "): + point = raw_point.split(",") + polygon.append(OrderedPair(float(point[0]), float(point[1]))) return Polygon(points=polygon, **_parse_common(raw_object).__dict__) @@ -204,23 +216,19 @@ def _get_parser(raw_object: etree.Element) -> Callable[[etree.Element], TiledObj Returns: Callable[[Element], Object]: The parser function. """ - if raw_object.find("./ellipse"): + if raw_object.find("./ellipse") is not None: return _parse_ellipse - if raw_object.find("./point"): + if raw_object.find("./point") is not None: return _parse_point - if raw_object.attrib.get("gid"): - # Only tile objects have the `gid` attribute - return _parse_tile - - if raw_object.find("./polygon"): + if raw_object.find("./polygon") is not None: return _parse_polygon - if raw_object.find("./polyline"): + if raw_object.find("./polyline") is not None: return _parse_polyline - if raw_object.find("./text"): + if raw_object.find("./text") is not None: return _parse_text # If it's none of the above, rectangle is the only one left. @@ -263,13 +271,22 @@ def parse(raw_object: etree.Element, parent_dir: Optional[Path] = None) -> Tiled new_tileset_path = tileset_path.parent new_object = template.find("./object") - if raw_object.attrib.get("id") and new_object: - new_object.attrib["id"] = raw_object.attrib["id"] + if new_object is not None: + if raw_object.attrib.get("id") is not None: + new_object.attrib["id"] = raw_object.attrib["id"] + + if raw_object.attrib.get("x") is not None: + new_object.attrib["x"] = raw_object.attrib["x"] + + if raw_object.attrib.get("y") is not None: + new_object.attrib["y"] = raw_object.attrib["y"] - if new_object: raw_object = new_object + if raw_object.attrib.get("gid"): + return _parse_tile(raw_object, new_tileset, new_tileset_path) + if raw_object.attrib.get("gid"): - return _parse_tile(raw_object, new_tileset, new_tileset_path) + return _parse_tile(raw_object) return _get_parser(raw_object)(raw_object) diff --git a/pytiled_parser/parsers/tmx/tileset.py b/pytiled_parser/parsers/tmx/tileset.py index 0d77b17..712d1cf 100644 --- a/pytiled_parser/parsers/tmx/tileset.py +++ b/pytiled_parser/parsers/tmx/tileset.py @@ -79,21 +79,21 @@ def _parse_tile(raw_tile: etree.Element, external_path: Optional[Path] = None) - tile.type = raw_tile.attrib["type"] animation_element = raw_tile.find("./animation") - if animation_element: + if animation_element is not None: tile.animation = [] for raw_frame in animation_element.findall("./frame"): tile.animation.append(_parse_frame(raw_frame)) object_element = raw_tile.find("./objectgroup") - if object_element: + if object_element is not None: tile.objects = parse_layer(object_element) properties_element = raw_tile.find("./properties") - if properties_element: + if properties_element is not None: tile.properties = parse_properties(properties_element) image_element = raw_tile.find("./image") - if image_element: + if image_element is not None: if external_path: tile.image = ( Path(external_path / image_element.attrib["source"]) @@ -120,8 +120,6 @@ def parse( tile_width=int(raw_tileset.attrib["tilewidth"]), tile_height=int(raw_tileset.attrib["tileheight"]), columns=int(raw_tileset.attrib["columns"]), - spacing=int(raw_tileset.attrib["spacing"]), - margin=int(raw_tileset.attrib["margin"]), firstgid=firstgid, ) @@ -134,9 +132,14 @@ def parse( if raw_tileset.attrib.get("backgroundcolor") is not None: tileset.background_color = parse_color(raw_tileset.attrib["backgroundcolor"]) + if raw_tileset.attrib.get("spacing") is not None: + tileset.spacing = int(raw_tileset.attrib["spacing"]) + + if raw_tileset.attrib.get("margin") is not None: + tileset.margin = int(raw_tileset.attrib["margin"]) + image_element = raw_tileset.find("image") if image_element is not None: - print("here") if external_path: tileset.image = ( Path(external_path / image_element.attrib["source"]) @@ -156,21 +159,21 @@ def parse( tileset.transparent_color = parse_color(my_string) tileoffset_element = raw_tileset.find("./tileoffset") - if tileoffset_element: + if tileoffset_element is not None: tileset.tile_offset = OrderedPair( int(tileoffset_element.attrib["x"]), int(tileoffset_element.attrib["y"]) ) grid_element = raw_tileset.find("./grid") - if grid_element: + if grid_element is not None: tileset.grid = _parse_grid(grid_element) properties_element = raw_tileset.find("./properties") - if properties_element: + if properties_element is not None: tileset.properties = parse_properties(properties_element) tiles = {} - for tile_element in raw_tileset.findall("./tiles"): + for tile_element in raw_tileset.findall("./tile"): tiles[int(tile_element.attrib["id"])] = _parse_tile( tile_element, external_path=external_path ) @@ -178,14 +181,14 @@ def parse( tileset.tiles = tiles wangsets_element = raw_tileset.find("./wangsets") - if wangsets_element: + if wangsets_element is not None: wangsets = [] for raw_wangset in wangsets_element.findall("./wangset"): wangsets.append(parse_wangset(raw_wangset)) tileset.wang_sets = wangsets transformations_element = raw_tileset.find("./transformations") - if transformations_element: + if transformations_element is not None: tileset.transformations = _parse_transformations(transformations_element) return tileset diff --git a/pytiled_parser/tiled_object.py b/pytiled_parser/tiled_object.py index db5c6fc..a96d65a 100644 --- a/pytiled_parser/tiled_object.py +++ b/pytiled_parser/tiled_object.py @@ -35,10 +35,9 @@ class TiledObject: coordinates: OrderedPair size: Size = Size(0, 0) rotation: float = 0 - visible: bool - - name: Optional[str] = None - type: Optional[str] = None + visible: bool = True + name: str = "" + type: str = "" properties: properties_.Properties = {}