nze_tiled 0.1.0

Loads maps made with the map editor Tiled
Documentation
use super::{Properties, error::TiledError, helper::*, Colour};
use nze_geometry::*;

use quick_xml::reader::Reader;
use quick_xml::events::{BytesStart, BytesText};
use quick_xml::events::attributes::Attribute;



pub struct LayerData {
    pub id: u32,
    pub name: String,
    pub visible: bool,
    pub locked: bool,
    pub opacity: f64,
    pub colour : Colour,
    pub tint : Colour,
    pub index_draw_order: bool,
    pub parallax: Vec2,
    pub offset: Vec2,
    pub layer_position: u32,
} 

pub type LayerTiles = Vec<u32>;

pub struct Layer {
    pub props : Properties,
    pub tiles : LayerTiles,
    pub width : i64,
    pub height: i64,
    pub info: LayerData,
}


impl Layer {
    fn blank() -> Layer {
        Layer {
            props: Properties::blank(),
            tiles: Vec::new(),
            width: 0,
            height: 0,
            info: LayerData::new(),
        }
    }
    pub(crate) fn new(attribs : Vec<Attribute>, reader: &mut Reader<&[u8]>, layer_index: u32) -> Result<Layer, TiledError> {
        let mut layer = Layer::blank();
        layer.parse_attribs(attribs)?;
        parse_xml(&mut layer, reader)?;
        layer.info.layer_position = layer_index;
        Ok(layer)
    }
    fn parse_attribs(&mut self, attribs : Vec<Attribute>) -> Result<(), TiledError> {
        for a in attribs {
            if let Some(()) = self.info.handle_attrib(&a)? {
                match a.key.as_ref() {
                    b"width" => self.width = get_value(&a.value)?,
                    b"height" => self.height = get_value(&a.value)?,
                    _ => println!("warning: unrecognized atrribute {:?}", a.key),
                }
            }
        }
        Ok(())
    }
}

impl HandleXml for Layer {
    fn start(&mut self, e : &BytesStart, reader: &mut Reader<&[u8]>) -> Result<(), TiledError> {
        match e.name().as_ref() {
            b"data" => parse_xml(&mut self.tiles, reader)?,
            b"properties" => parse_xml(&mut self.props, reader)?,
            _ => println!("unrecognized tag {:?}", e.name()),
        }
        Ok(())
    }
    fn self_tag() -> &'static str {
        "layer"
    }
    
 }

impl HandleXml for LayerTiles {
    fn text(&mut self, e : &BytesText) -> Result<(), TiledError> {
        let data = match e.unescape() {
            Ok(s) => s,
            Err(_) => { return Err(TiledError::ParseError(String::from("tile data in layer could not be retrieved"))); },
        };
        for num in data.split(",") {
            self.push( match num.trim().parse() {
                Ok(n) => n,
                Err(_) => {
                    return Err(TiledError::ParseError(
                        String::from("tile data could not be parsed to an integer: ") + num)
                    );
                },
            });
        }
        Ok(())
    }
    
    fn self_tag() -> &'static str {
        "data"
    }
}

impl LayerData {
    pub(crate) fn new() -> LayerData {
        LayerData {
            id: 0,
            name: String::from(""),
            visible: true,
            locked: false,
            opacity: 1.0,
            colour: Colour{r: 255, g: 255, b: 255, a: 255 },
            tint: Colour { r: 255, g: 255, b: 255, a: 255 },
            index_draw_order: false,
            parallax: Vec2::new(1.0, 1.0),
            offset: Vec2::new(0.0, 0.0),
            layer_position: 0,
        }
    }
    pub(crate) fn handle_attrib(&mut self, a : &Attribute) -> Result<Option<()>, TiledError> {
        match a.key.as_ref() {
            b"id" => self.id = get_value(&a.value)?,
            b"name" => self.name = get_string(&a.value)?.to_string(),
            b"visible" => self.visible = get_value::<i32>(&a.value)? == 1,
            b"locked" => self.locked = get_value::<i32>(&a.value)? == 1,
            b"opacity" => self.opacity = get_value(&a.value)?,
            b"color" => self.colour = get_colour(&a.value)?,
            b"tintcolor" => self.tint = get_colour(&a.value)?,
            b"draworder" => self.index_draw_order = get_string(&a.value)? == "index",
            b"offsetx" => self.offset.x = get_value(&a.value)?,
            b"offsety" => self.offset.y = get_value(&a.value)?,
            b"parallaxx" => self.parallax.x = get_value(&a.value)?,
            b"parallaxy" => self.parallax.y = get_value(&a.value)?,
            _ => { return Ok(Some(())); }
        }
        Ok(None)
    }
}