Skip to content
Snippets Groups Projects
tile.rs 2.35 KiB
Newer Older
use std::{collections::HashMap, path::Path};
alexdevteam's avatar
alexdevteam committed

use xml::attribute::OwnedAttribute;
alexdevteam's avatar
alexdevteam committed

use crate::{
    animation::{Frame, parse_animation},
alexdevteam's avatar
alexdevteam committed
    error::TiledError,
    image::Image,
    layers::ObjectLayerData,
alexdevteam's avatar
alexdevteam committed
    properties::{parse_properties, Properties},
    util::{get_attrs, parse_tag, XmlEventResult},
alexdevteam's avatar
alexdevteam committed
};

pub type TileId = u32;

#[derive(Debug, PartialEq, Clone, Default)]
alexdevteam's avatar
alexdevteam committed
pub struct Tile {
alexdevteam's avatar
alexdevteam committed
    pub properties: Properties,
    pub collision: Option<ObjectLayerData>,
alexdevteam's avatar
alexdevteam committed
    pub animation: Option<Vec<Frame>>,
    pub tile_type: Option<String>,
    pub probability: f32,
}

impl Tile {
    pub(crate) fn new(
        parser: &mut impl Iterator<Item = XmlEventResult>,
alexdevteam's avatar
alexdevteam committed
        attrs: Vec<OwnedAttribute>,
alexdevteam's avatar
alexdevteam committed
        path_relative_to: Option<&Path>,
    ) -> Result<(TileId, Tile), TiledError> {
alexdevteam's avatar
alexdevteam committed
        let ((tile_type, probability), id) = get_attrs!(
            attrs,
            optionals: [
                ("type", tile_type, |v:String| v.parse().ok()),
                ("probability", probability, |v:String| v.parse().ok()),
            ],
            required: [
                ("id", id, |v:String| v.parse::<u32>().ok()),
            ],
            TiledError::MalformedAttributes("tile must have an id with the correct type".to_string())
        );

alexdevteam's avatar
alexdevteam committed
        let mut properties = HashMap::new();
        let mut objectgroup = None;
        let mut animation = None;
        parse_tag!(parser, "tile", {
            "image" => |attrs| {
                image = Some(Image::new(parser, attrs, path_relative_to.ok_or(TiledError::SourceRequired{object_to_parse:"Image".to_owned()})?)?);
alexdevteam's avatar
alexdevteam committed
                Ok(())
            },
            "properties" => |_| {
                properties = parse_properties(parser)?;
                Ok(())
            },
            "objectgroup" => |attrs| {
                objectgroup = Some(ObjectLayerData::new(parser, attrs, None)?.0);
alexdevteam's avatar
alexdevteam committed
                Ok(())
            },
            "animation" => |_| {
                animation = Some(parse_animation(parser)?);
                Ok(())
            },
        });
alexdevteam's avatar
alexdevteam committed
            id,
            Tile {
                image,
                properties,
                collision: objectgroup,
                animation,
                tile_type,
                probability: probability.unwrap_or(1.0),
            },
        ))
alexdevteam's avatar
alexdevteam committed
    }
}