Exemple #1
0
def _parse_object(obj):
    my_id = obj.attrib["id"]
    my_x = float(obj.attrib["x"])
    my_y = float(obj.attrib["y"])
    my_location = objects.OrderedPair(x=my_x, y=my_y)
    if "width" in obj.attrib:
        my_width = float(obj.attrib["width"])
    else:
        my_width = None
    if "height" in obj.attrib:
        my_height = float(obj.attrib["height"])
    else:
        my_height = None
    my_name = obj.attrib["name"]

    properties: Optional[objects.Properties]
    properties_element = obj.find("./properties")
    if properties_element is not None:
        properties = _parse_properties_element(properties_element)
    else:
        properties = None

    # This is where it would be nice if we could assume a walrus
    # operator was part of our Python distribution.

    my_object = None

    polygon = obj.findall("./polygon")

    if polygon and len(polygon) > 0:
        points = _parse_points(polygon[0].attrib["points"])
        my_object = objects.PolygonObject(
            id_=my_id,
            name=my_name,
            location=my_location,
            size=(my_width, my_height),
            points=points,
            properties=properties,
        )

    if my_object is None:
        polyline = obj.findall("./polyline")

        if polyline and len(polyline) > 0:
            points = _parse_points(polyline[0].attrib["points"])
            my_object = objects.PolylineObject(
                id_=my_id,
                name=my_name,
                location=my_location,
                size=(my_width, my_height),
                points=points,
                properties=properties,
            )

    if my_object is None:
        ellipse = obj.findall("./ellipse")

        if ellipse and len(ellipse):
            my_object = objects.ElipseObject(
                id_=my_id,
                name=my_name,
                location=my_location,
                size=(my_width, my_height),
                properties=properties,
            )

    if my_object is None:
        if "template" in obj.attrib:
            print("Warning, this .tmx file is using an unsupported"
                  "'template' attribute. Ignoring.")

    if my_object is None:
        point = obj.findall("./point")
        if point:
            my_object = objects.PointObject(
                id_=my_id,
                name=my_name,
                location=my_location,
                properties=properties,
            )

    if my_object is None:
        my_object = objects.RectangleObject(
            id_=my_id,
            name=my_name,
            location=my_location,
            size=(my_width, my_height),
            properties=properties,
        )

    return my_object
def _parse_tiles(
        tile_element_list: List[etree.Element]) -> Dict[int, objects.Tile]:
    """Parse a list of tile elements.

    Args:
        tile_element_list (List[etree.Element]): List of tile elements.

    Returns:
        Dict[int, objects.Tile]: Dictionary containing Tile objects by their
            ID.
    """
    tiles: Dict[int, objects.Tile] = {}
    for tile_element in tile_element_list:
        # id is not optional
        id_ = int(tile_element.attrib["id"])

        # optional attributes
        _type = None
        try:
            _type = tile_element.attrib["type"]
        except KeyError:
            pass

        terrain = None
        try:
            tile_terrain_attrib = tile_element.attrib["terrain"]
        except KeyError:
            pass
        else:
            # below is an attempt to explain how terrains are handled.
            # 'terrain' attribute is a comma seperated list of 4 values,
            # each is either an integer or blank

            # convert to list of values
            terrain_list_attrib = re.split(",", tile_terrain_attrib)
            # terrain_list is list of indexes of Tileset.terrain_types
            terrain_list: List[Optional[int]] = []
            # each index in terrain_list_attrib refers to a corner
            for corner in terrain_list_attrib:
                if not corner:
                    terrain_list.append(None)
                else:
                    terrain_list.append(int(corner))
            terrain = objects.TileTerrain(*terrain_list)

        # tile element optional sub-elements
        properties: Optional[List[objects.Property]] = None
        tile_properties_element = tile_element.find("./properties")
        if tile_properties_element:
            properties = []
            property_list = tile_properties_element.findall("./property")
            for property_ in property_list:
                name = property_.attrib["name"]
                value = property_.attrib["value"]
                obj = objects.Property(name, value)
                properties.append(obj)

        # tile element optional sub-elements
        animation: Optional[List[objects.Frame]] = None
        tile_animation_element = tile_element.find("./animation")
        if tile_animation_element:
            animation = []
            frames = tile_animation_element.findall("./frame")
            for frame in frames:
                # tileid refers to the Tile.id of the animation frame
                animated_id = int(frame.attrib["tileid"])
                # duration is in MS. Should perhaps be converted to seconds.
                # FIXME: make decision
                duration = int(frame.attrib["duration"])
                animation.append(objects.Frame(animated_id, duration))

        # tile element optional sub-elements
        objectgroup: Optional[List[objects.TiledObject]] = None
        objectgroup_element = tile_element.find("./objectgroup")
        if objectgroup_element:
            objectgroup = []
            object_list = objectgroup_element.findall("./object")
            for object in object_list:
                my_id = object.attrib["id"]
                my_x = float(object.attrib["x"])
                my_y = float(object.attrib["y"])
                if "width" in object.attrib:
                    my_width = float(object.attrib["width"])
                else:
                    my_width = None
                if "height" in object.attrib:
                    my_height = float(object.attrib["height"])
                else:
                    my_height = None

                # This is where it would be nice if we could assume a walrus
                # operator was part of our Python distribution.

                my_object = None

                polygon = object.findall("./polygon")

                if polygon and len(polygon) > 0:
                    points = _parse_points(polygon[0].attrib["points"])
                    my_object = objects.PolygonObject(id_=my_id,
                                                      location=(my_x, my_y),
                                                      size=(my_width,
                                                            my_height),
                                                      points=points)

                if my_object is None:
                    polyline = object.findall("./polyline")

                    if polyline and len(polyline) > 0:
                        points = _parse_points(polyline[0].attrib["points"])
                        my_object = objects.PolylineObject(id_=my_id,
                                                           location=(my_x,
                                                                     my_y),
                                                           size=(my_width,
                                                                 my_height),
                                                           points=points)

                if my_object is None:
                    ellipse = object.findall("./ellipse")

                    if ellipse and len(ellipse):
                        my_object = objects.ElipseObject(id_=my_id,
                                                         location=(my_x, my_y),
                                                         size=(my_width,
                                                               my_height))

                if my_object is None:
                    my_object = objects.RectangleObject(id_=my_id,
                                                        location=(my_x, my_y),
                                                        size=(my_width,
                                                              my_height))

                objectgroup.append(my_object)

        # if this is None, then the Tile is part of a spritesheet
        image = None
        image_element = tile_element.find("./image")
        if image_element is not None:
            image = _parse_image_element(image_element)

        # print(f"Adding '{id_}', {image}, {objectgroup}")

        tiles[id_] = objects.Tile(id_=id_,
                                  type_=_type,
                                  terrain=terrain,
                                  animation=animation,
                                  image=image,
                                  properties=properties,
                                  tileset=None,
                                  objectgroup=objectgroup)

    return tiles